Skip to content

Commit 030fb4d

Browse files
committed
Switch to ava for JavaScript testing.
Add some implementations and tests for erlang compat. Add new pass to compiler for handling output
1 parent 73f3135 commit 030fb4d

35 files changed

+2803
-843
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,5 @@ src/elixirscript
1919
priv/**/*.js
2020
stdlib_state.bin
2121
*.log
22+
.nyc_output
2223
test/app/build

lib/elixir_script/compile_error.ex

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
defmodule ElixirScript.CompileError do
2+
defexception [:message]
3+
end

lib/elixir_script/elixir_script_compile_error.ex

Lines changed: 0 additions & 3 deletions
This file was deleted.

lib/elixir_script/next/beam.ex

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ defmodule ElixirScript.Beam do
99
"""
1010
@spec debug_info(atom) :: {:ok | :error, map | binary}
1111
def debug_info(module) when is_atom(module) do
12-
with {_, beam, _} <- :code.get_object_code(module),
12+
#TODO: Get modified date from _beam_path to check for cached version?
13+
with {_, beam, _beam_path} <- :code.get_object_code(module),
1314
{:ok, {^module, [debug_info: {:debug_info_v1, backend, data}]}} <- :beam_lib.chunks(beam, [:debug_info]),
1415
{:ok, {^module, attribute_info}} = :beam_lib.chunks(beam, [:attributes]) do
1516

lib/elixir_script/next/compiler.ex

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ defmodule ElixirScript.Compiler do
55

66
@spec compile([atom], []) :: nil
77
def compile(entry_modules, opts \\ []) do
8-
opts = build_compiler_options(opts)
8+
opts = build_compiler_options(opts, entry_modules)
99
{:ok, pid} = ElixirScript.State.start_link(opts)
1010

1111
IO.puts "Finding used modules and functions"
@@ -15,19 +15,24 @@ defmodule ElixirScript.Compiler do
1515

1616
IO.puts "Compiling"
1717
modules = ElixirScript.State.list_modules(pid)
18-
1918
ElixirScript.Translate.execute(modules, pid)
19+
20+
IO.puts "Building Output"
21+
modules = ElixirScript.State.list_modules(pid)
22+
ElixirScript.Output.execute(modules, pid)
2023

2124
ElixirScript.State.stop(pid)
2225
end
2326

24-
defp build_compiler_options(opts) do
27+
defp build_compiler_options(opts, entry_modules) do
2528
default_options = Map.new
26-
|> Map.put(:output, nil)
27-
|> Map.put(:format, :es)
29+
|> Map.put(:output, Keyword.get(opts, :output))
30+
|> Map.put(:format, Keyword.get(opts, :format, :es))
2831
|> Map.put(:js_modules, Keyword.get(opts, :js_modules, []))
32+
|> Map.put(:entry_modules, entry_modules)
2933

3034
options = default_options
35+
IO.inspect options
3136
Map.put(options, :module_formatter, get_module_formatter(options[:format]))
3237
end
3338

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
defmodule ElixirScript.Output do
2+
@moduledoc false
3+
4+
alias ElixirScript.State, as: ModuleState
5+
alias ESTree.Tools.{Builder, Generator}
6+
@generated_name "Elixir.App.js"
7+
8+
@doc """
9+
Takes outputs the JavaScript code in the specified output
10+
"""
11+
@spec execute([atom], pid) :: nil
12+
def execute(modules, pid) do
13+
modules = Enum.filter_map(modules, fn {_, info} -> Map.has_key?(info, :js_ast) end,
14+
fn {_module, info} ->
15+
info.js_ast
16+
end
17+
)
18+
19+
opts = ModuleState.get_compiler_opts(pid)
20+
21+
bundle(modules, opts)
22+
|> output(Map.get(opts, :output))
23+
end
24+
25+
defp bundle(modules, opts) do
26+
ElixirScript.Passes.CreateJSModules.compile(modules, opts)
27+
28+
js_code = modules
29+
|> ElixirScript.Passes.CreateJSModules.compile(opts)
30+
|> List.wrap
31+
|> Builder.program
32+
|> prepare_js_ast
33+
|> Generator.generate
34+
35+
concat(js_code)
36+
end
37+
38+
defp concat(code) do
39+
"'use strict';\n" <> ElixirScript.get_bootstrap_js("iife") <> "\n" <> code
40+
end
41+
42+
defp prepare_js_ast(js_ast) do
43+
case js_ast do
44+
modules when is_list(modules) ->
45+
modules
46+
|> Enum.reduce([], &(&2 ++ &1.body))
47+
|> Builder.program
48+
%ElixirScript.Translator.Group{body: body} ->
49+
Builder.program(body)
50+
%ElixirScript.Translator.Empty{} ->
51+
Builder.program([])
52+
_ ->
53+
js_ast
54+
end
55+
end
56+
57+
defp output(code, nil), do: code
58+
defp output(code, :stdout), do: IO.puts(code)
59+
60+
defp output(code, path) do
61+
file_name = case Path.extname(path) do
62+
".js" ->
63+
path
64+
_ ->
65+
Path.join([path, @generated_name])
66+
end
67+
68+
if !File.exists?(Path.dirname(file_name)) do
69+
File.mkdir_p!(Path.dirname(file_name))
70+
end
71+
72+
File.write!(file_name, code)
73+
end
74+
end

lib/elixir_script/next/passes/translate.ex

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -14,51 +14,5 @@ defmodule ElixirScript.Translate do
1414
Enum.each(modules, fn({module, info}) ->
1515
ElixirScript.Translate.Module.compile(module, info, pid)
1616
end)
17-
18-
modules = ElixirScript.State.list_modules(pid)
19-
20-
modules = Enum.filter_map(modules,
21-
fn {_, info} -> Map.has_key?(info, :js_ast) end,
22-
fn {_module, info} ->
23-
info.js_ast
24-
end
25-
)
26-
27-
opts = ModuleState.get_compiler_opts(pid)
28-
29-
bundle(modules, opts)
30-
end
31-
32-
defp bundle(modules, opts) do
33-
ElixirScript.Passes.CreateJSModules.compile(modules, opts)
34-
35-
js_code = modules
36-
|> ElixirScript.Passes.CreateJSModules.compile(opts)
37-
|> List.wrap
38-
|> Builder.program
39-
|> prepare_js_ast
40-
|> Generator.generate
41-
42-
concat(js_code)
43-
#|> IO.puts
44-
end
45-
46-
defp concat(code) do
47-
"'use strict';\n" <> ElixirScript.get_bootstrap_js("iife") <> "\n" <> code
48-
end
49-
50-
defp prepare_js_ast(js_ast) do
51-
case js_ast do
52-
modules when is_list(modules) ->
53-
modules
54-
|> Enum.reduce([], &(&2 ++ &1.body))
55-
|> Builder.program
56-
%ElixirScript.Translator.Group{body: body} ->
57-
Builder.program(body)
58-
%ElixirScript.Translator.Empty{} ->
59-
Builder.program([])
60-
_ ->
61-
js_ast
62-
end
6317
end
6418
end
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
defmodule Example do
2-
def new() do
3-
Base.encode16("hello")
2+
def start(_, _) do
3+
Atom.to_string(:gravity)
44
end
55

66
end

lib/elixir_script/next/passes/translate/form.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ defmodule ElixirScript.Translate.Form do
122122

123123
def compile({:receive, context, _}, _state) do
124124
line = Keyword.get(context, :line, 1)
125-
raise ElixirScriptCompileError, message: "Line: #{line} receive not supported"
125+
raise ElixirScript.CompileError, message: "Line: #{line} receive not supported"
126126
end
127127

128128
def compile({:try, _, [blocks]}, state) do
@@ -149,7 +149,7 @@ defmodule ElixirScript.Translate.Form do
149149
),
150150
J.identifier(module)
151151
),
152-
J.identifier(function)
152+
ElixirScript.Translator.Identifier.make_function_name(function, length(params))
153153
),
154154
Enum.map(params, &compile(&1, state))
155155
)

lib/elixir_script/next/passes/translate/module.ex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ defmodule ElixirScript.Translate.Module do
3434
_ -> true
3535
end)
3636
|> Enum.filter(fn
37+
{ {:start, 2}, _, _, _ } -> true
3738
{ name, _, _, _} -> name in used
3839
_ -> false
3940
end)

0 commit comments

Comments
 (0)