diff --git a/lib/elixir_script/module_systems/es.ex b/lib/elixir_script/module_systems/es.ex index 54d2da9f..123656c7 100644 --- a/lib/elixir_script/module_systems/es.ex +++ b/lib/elixir_script/module_systems/es.ex @@ -12,6 +12,17 @@ defmodule ElixirScript.ModuleSystems.ES do imports ++ body ++ export end + def build_imports(js_imports) do + js_imports + |> Enum.map(fn + {_module, name, _path, import_path} -> import_module(name, import_path) + end) + end + + def build_export(exports) do + if is_nil(exports), do: [], else: [export_module(exports)] + end + defp import_module(import_name, from) do js_module_name = JS.identifier(import_name) diff --git a/lib/elixir_script/passes/find_used_functions.ex b/lib/elixir_script/passes/find_used_functions.ex index 94df537f..806d0c5e 100644 --- a/lib/elixir_script/passes/find_used_functions.ex +++ b/lib/elixir_script/passes/find_used_functions.ex @@ -9,18 +9,23 @@ defmodule ElixirScript.FindUsedFunctions do """ @spec execute([atom], pid) :: nil def execute(entry_modules, pid) do - Enum.each(entry_modules, fn + entry_modules + |> List.wrap + |> Task.async_stream(fn module -> walk_module(module, pid) end) + |> Stream.run() - modules = ElixirScript.State.list_modules(pid) - Enum.each(modules, fn + pid + |> ElixirScript.State.list_modules + |> Task.async_stream(fn {module, info} -> if get_in(info, [:attributes, :protocol_impl]) do walk_module(module, pid) end end) + |> Stream.run() end defp walk_module(module, pid) do diff --git a/lib/elixir_script/passes/find_used_modules.ex b/lib/elixir_script/passes/find_used_modules.ex index 7c584775..2e9bc22f 100644 --- a/lib/elixir_script/passes/find_used_modules.ex +++ b/lib/elixir_script/passes/find_used_modules.ex @@ -8,11 +8,14 @@ defmodule ElixirScript.FindUsedModules do """ @spec execute([atom], pid) :: nil def execute(modules, pid) do - Enum.each(List.wrap(modules), fn(module) -> + modules + |> List.wrap + |> Task.async_stream(fn(module) -> if ElixirScript.State.get_module(pid, module) == nil do do_execute(module, pid) end end) + |> Stream.run() end defp do_execute(module, pid) do @@ -72,7 +75,6 @@ defmodule ElixirScript.FindUsedModules do } Enum.each(reachable_defs, &walk(&1, state)) - end defp walk_protocol(module, implementations, pid) do @@ -128,7 +130,7 @@ defmodule ElixirScript.FindUsedModules do defp walk(form, state) when is_atom(form) and form not in [BitString, Function, PID, Port, Reference, Any, Elixir] do if ElixirScript.Translate.Module.is_elixir_module(form) and !ElixirScript.Translate.Module.is_js_module(form, state) do if ModuleState.get_module(state.pid, form) == nil do - execute(form, state.pid) + do_execute(form, state.pid) end end end @@ -292,7 +294,7 @@ defmodule ElixirScript.FindUsedModules do cond do ElixirScript.Translate.Module.is_elixir_module(module) -> if ModuleState.get_module(state.pid, module) == nil do - execute(module, state.pid) + do_execute(module, state.pid) end true -> walk(module, state) diff --git a/lib/elixir_script/passes/output.ex b/lib/elixir_script/passes/output.ex index fc373936..83fec60a 100644 --- a/lib/elixir_script/passes/output.ex +++ b/lib/elixir_script/passes/output.ex @@ -35,10 +35,16 @@ defmodule ElixirScript.Output do defp bundle(modules, opts, js_modules) do modules |> ElixirScript.Output.JSModule.compile(opts, js_modules) - |> List.wrap - |> Builder.program - |> prepare_js_ast - |> Generator.generate + |> Task.async_stream(fn(js_part) -> + js_part + |> List.wrap + |> Builder.program + |> prepare_js_ast + |> Generator.generate + end) + |> Stream.map(fn {:ok, js_code} -> js_code end) + |> Enum.to_list + |> Enum.join("\n") |> concat end diff --git a/lib/elixir_script/passes/output/js_module.ex b/lib/elixir_script/passes/output/js_module.ex index af9f1b2c..3d093715 100644 --- a/lib/elixir_script/passes/output/js_module.ex +++ b/lib/elixir_script/passes/output/js_module.ex @@ -7,13 +7,10 @@ defmodule ElixirScript.Output.JSModule do def compile(body, opts, js_modules) do elixir = Helpers.declare("Elixir", J.object_expression([])) - ast = opts.module_formatter.build( - js_modules, - [elixir, create_atom_table(), start(), load()] ++ body, - J.identifier("Elixir") - ) + imports = opts.module_formatter.build_imports(js_modules) + exports = opts.module_formatter.build_export(J.identifier("Elixir")) - ast + [elixir, create_atom_table(), start(), load(), imports, body, exports] end def start do diff --git a/lib/elixir_script/passes/translate.ex b/lib/elixir_script/passes/translate.ex index 11f89339..45f29204 100644 --- a/lib/elixir_script/passes/translate.ex +++ b/lib/elixir_script/passes/translate.ex @@ -8,9 +8,12 @@ defmodule ElixirScript.Translate do """ @spec execute([atom], pid) :: nil def execute(modules, pid) do - Enum.each(modules, fn + modules + |> List.wrap() + |> Task.async_stream(fn {module, info} -> ElixirScript.Translate.Module.compile(module, info, pid) end) + |> Stream.run() end end diff --git a/lib/elixir_script/passes/translate/identifier.ex b/lib/elixir_script/passes/translate/identifier.ex index bd4664af..9d80f833 100644 --- a/lib/elixir_script/passes/translate/identifier.ex +++ b/lib/elixir_script/passes/translate/identifier.ex @@ -46,9 +46,15 @@ defmodule ElixirScript.Translate.Identifier do end defp filter_name(name) do - to_string(name) - |> String.replace("?", "__qmark__") - |> String.replace("!", "__emark__") + name = to_string(name) + + if String.contains?(name, ["?", "!"]) do + name + |> String.replace("?", "__qmark__") + |> String.replace("!", "__emark__") + else + name + end end defp make_alias([x]) do diff --git a/lib/elixir_script/state.ex b/lib/elixir_script/state.ex index 03a74fba..78c0d418 100644 --- a/lib/elixir_script/state.ex +++ b/lib/elixir_script/state.ex @@ -25,7 +25,8 @@ defmodule ElixirScript.State do def put_module(pid, module, value) do Agent.update(pid, fn(state) -> value = Map.put(value, :used, []) - %{ state | modules: Keyword.put(state.modules, module, value) } + modules = Keyword.put(state.modules, module, value) + %{ state | modules: modules } end) end @@ -41,7 +42,7 @@ defmodule ElixirScript.State do module_info = Keyword.get(state.modules, module) used = Map.get(module_info, :used, []) - used = used ++ [func] + used = [func | used] module_info = Map.put(module_info, :used, used) modules = Keyword.put(state.modules, module, module_info) @@ -53,7 +54,7 @@ defmodule ElixirScript.State do def put_javascript_module(pid, module, name, path) do Agent.update(pid, fn(state) -> js_modules = Map.get(state, :js_modules, []) - js_modules = js_modules ++ [{module, name, path}] + js_modules = [{module, name, path} | js_modules] %{ state | js_modules: js_modules } end) end