Skip to content

Commit e03df89

Browse files
committed
Add ffi module info to manifest. Add diagnostic info as well
1 parent 2faa3f3 commit e03df89

File tree

10 files changed

+711
-495
lines changed

10 files changed

+711
-495
lines changed

lib/elixir_script/compiler.ex

Lines changed: 70 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -29,33 +29,39 @@ defmodule ElixirScript.Compiler do
2929
Translate,
3030
FindUsedModules,
3131
FindUsedFunctions,
32-
Output,
32+
Output
3333
}
34+
3435
alias ElixirScript.ModuleSystems.ES
3536
alias Kernel.ParallelCompiler
3637

37-
@spec compile(atom | [atom] | binary, []) :: map
38+
@type compiler_input ::
39+
atom
40+
| [atom]
41+
| binary
42+
43+
@spec compile(compiler_input, []) :: map
3844
def compile(path, opts \\ [])
3945

4046
def compile(path, opts) when is_binary(path) do
4147
opts = build_compiler_options(opts)
4248
{:ok, pid} = State.start_link(opts)
4349

44-
path = if String.ends_with?(path, [".ex", ".exs"]) do
45-
path
46-
else
47-
Path.join([path, "**", "*.{ex,exs}"])
48-
end
50+
path =
51+
if String.ends_with?(path, [".ex", ".exs"]) do
52+
path
53+
else
54+
Path.join([path, "**", "*.{ex,exs}"])
55+
end
4956

5057
files = Path.wildcard(path)
5158

52-
ParallelCompiler.files(files, [
53-
each_module: &on_module_compile(pid, &1, &2, &3)
54-
])
59+
ParallelCompiler.files(files, each_module: &on_module_compile(pid, &1, &2, &3))
5560

56-
entry_modules = pid
57-
|> State.get_in_memory_modules
58-
|> Keyword.keys
61+
entry_modules =
62+
pid
63+
|> State.get_in_memory_modules()
64+
|> Keyword.keys()
5965

6066
do_compile(entry_modules, pid, opts)
6167
end
@@ -90,11 +96,12 @@ defmodule ElixirScript.Compiler do
9096
defp build_compiler_options(opts) do
9197
remove_used_functions? = Keyword.get(opts, :remove_unused_functions, true)
9298

93-
default_options = Map.new
94-
|> Map.put(:output, Keyword.get(opts, :output))
95-
|> Map.put(:format, :es)
96-
|> Map.put(:root, Keyword.get(opts, :root, "."))
97-
|> Map.put(:remove_unused_functions, remove_used_functions?)
99+
default_options =
100+
Map.new()
101+
|> Map.put(:output, Keyword.get(opts, :output))
102+
|> Map.put(:format, :es)
103+
|> Map.put(:root, Keyword.get(opts, :root, "."))
104+
|> Map.put(:remove_unused_functions, remove_used_functions?)
98105

99106
options = default_options
100107
Map.put(options, :module_formatter, ES)
@@ -105,23 +112,51 @@ defmodule ElixirScript.Compiler do
105112
end
106113

107114
defp transform_output(modules, compiled_js, opts) do
108-
output_path = if opts.output == nil or opts.output == :stdout do
109-
""
110-
else
111-
Path.dirname(opts.output)
112-
end
113-
114-
Enum.reduce(modules, %{}, fn {module, info}, current_data ->
115-
info = %{
116-
references: info.used_modules,
117-
last_modified: info.last_modified,
118-
beam_path: Map.get(info, :beam_path),
119-
source: Map.get(info, :file),
120-
js_path: Path.join(output_path, "#{module}.js"),
121-
js_code: Keyword.get(compiled_js, module)
122-
}
123-
124-
Map.put(current_data, module, info)
115+
output_path =
116+
if opts.output == nil or opts.output == :stdout do
117+
""
118+
else
119+
Path.dirname(opts.output)
120+
end
121+
122+
Enum.reduce(modules, %{}, fn
123+
{module, info}, current_data ->
124+
info = %{
125+
references: info.used_modules,
126+
last_modified: info.last_modified,
127+
beam_path: Map.get(info, :beam_path),
128+
source: Map.get(info, :file),
129+
js_path: Path.join(output_path, "#{module}.js"),
130+
js_code: Keyword.get(compiled_js, module),
131+
diagnostics: Map.get(info, :diagnostics, []),
132+
type: :module
133+
}
134+
135+
Map.put(current_data, module, info)
136+
137+
{module, js_input_path, js_output_path}, current_data ->
138+
last_modified =
139+
case File.stat(js_input_path, time: :posix) do
140+
{:ok, file_info} ->
141+
file_info.mtime
142+
143+
_ ->
144+
nil
145+
end
146+
147+
info = %{
148+
references: [],
149+
last_modified: last_modified,
150+
beam_path: nil,
151+
source: nil,
152+
js_input_path: js_input_path,
153+
js_path: js_output_path,
154+
js_code: nil,
155+
diagnostics: [],
156+
type: :ffi
157+
}
158+
159+
Map.put(current_data, module, info)
125160
end)
126161
end
127162
end

lib/elixir_script/passes/find_used_functions.ex

Lines changed: 45 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,17 @@ defmodule ElixirScript.FindUsedFunctions do
1010
@spec execute([atom], pid) :: nil
1111
def execute(entry_modules, pid) do
1212
entry_modules
13-
|> List.wrap
14-
|> Enum.each(fn
15-
module ->
16-
walk_module(module, pid)
13+
|> List.wrap()
14+
|> Enum.each(fn module ->
15+
walk_module(module, pid)
1716
end)
1817

1918
pid
20-
|> ElixirScript.State.list_modules
21-
|> Enum.each(fn
22-
{module, info} ->
23-
if get_in(info, [:attributes, :protocol_impl]) do
24-
walk_module(module, pid)
25-
end
19+
|> ElixirScript.State.list_modules()
20+
|> Enum.each(fn {module, info} ->
21+
if get_in(info, [:attributes, :protocol_impl]) do
22+
walk_module(module, pid)
23+
end
2624
end)
2725
end
2826

@@ -37,27 +35,33 @@ defmodule ElixirScript.FindUsedFunctions do
3735
unreachable: unreachable
3836
} = ModuleState.get_module(pid, module)
3937

40-
reachable_defs = Enum.filter(defs, fn
41-
{ _, type, _, _} when type in [:defmacro, :defmacrop] -> false
42-
{ name, _, _, _} ->
43-
not(name in unreachable)
44-
_ -> true
45-
end)
38+
reachable_defs =
39+
Enum.filter(defs, fn
40+
{_, type, _, _} when type in [:defmacro, :defmacrop] ->
41+
false
42+
43+
{name, _, _, _} ->
44+
name not in unreachable
45+
46+
_ ->
47+
true
48+
end)
4649

4750
state = %{
4851
pid: pid,
4952
module: module
5053
}
5154

52-
Enum.each(reachable_defs, fn({name, _type, _, _clauses}) ->
53-
ModuleState.add_used(state.pid, module, name)
55+
Enum.each(reachable_defs, fn {name, _type, _, _clauses} ->
56+
ModuleState.put_used(state.pid, module, name)
5457
end)
5558

5659
Enum.each(reachable_defs, &walk(&1, state))
5760
end
5861

5962
defp walk_module(module, function, arity, pid) do
6063
function = {function, arity}
64+
6165
unless ModuleState.has_used?(pid, module, function) do
6266
info = ModuleState.get_module(pid, module)
6367

@@ -66,13 +70,15 @@ defmodule ElixirScript.FindUsedFunctions do
6670
module: module
6771
}
6872

69-
reachable_def = Enum.find(Map.get(info, :definitions, []), fn { name, _, _, _} -> name == function end)
73+
reachable_def =
74+
Enum.find(Map.get(info, :definitions, []), fn {name, _, _, _} -> name == function end)
7075

7176
case reachable_def do
7277
nil ->
7378
nil
79+
7480
{name, _type, _, _clauses} = func ->
75-
ModuleState.add_used(state.pid, module, name)
81+
ModuleState.put_used(state.pid, module, name)
7682
walk(func, state)
7783
end
7884
end
@@ -82,13 +88,13 @@ defmodule ElixirScript.FindUsedFunctions do
8288
Enum.each(clauses, &walk(&1, state))
8389
end
8490

85-
defp walk({ _, _args, _guards, body}, state) do
91+
defp walk({_, _args, _guards, body}, state) do
8692
walk_block(body, state)
8793
end
8894

89-
defp walk({:->, _, [[{:when, _, params}], body ]}, state) do
95+
defp walk({:->, _, [[{:when, _, params}], body]}, state) do
9096
guards = List.last(params)
91-
params = params |> Enum.reverse |> tl |> Enum.reverse
97+
params = params |> Enum.reverse() |> tl |> Enum.reverse()
9298

9399
walk({[], params, guards, body}, state)
94100
end
@@ -119,11 +125,11 @@ defmodule ElixirScript.FindUsedFunctions do
119125
end
120126

121127
defp walk({:%{}, _, properties}, state) do
122-
Enum.each(properties, fn (val) -> walk(val, state) end)
128+
Enum.each(properties, fn val -> walk(val, state) end)
123129
end
124130

125131
defp walk({:<<>>, _, elements}, state) do
126-
Enum.each(elements, fn (val) -> walk(val, state) end)
132+
Enum.each(elements, fn val -> walk(val, state) end)
127133
end
128134

129135
defp walk({:=, _, [left, right]}, state) do
@@ -167,7 +173,7 @@ defmodule ElixirScript.FindUsedFunctions do
167173
end
168174

169175
defp walk({:cond, _, [[do: clauses]]}, state) do
170-
Enum.each(clauses, fn({:->, _, [clause, clause_body]}) ->
176+
Enum.each(clauses, fn {:->, _, [clause, clause_body]} ->
171177
Enum.each(List.wrap(clause_body), &walk(&1, state))
172178
walk(hd(clause), state)
173179
end)
@@ -195,9 +201,10 @@ defmodule ElixirScript.FindUsedFunctions do
195201

196202
if rescue_block do
197203
Enum.each(rescue_block, fn
198-
{:->, _, [ [{:in, _, [param, names]}], body]} ->
204+
{:->, _, [[{:in, _, [param, names]}], body]} ->
199205
walk({[], [param], [{{:., [], [Enum, :member?]}, [], [param, names]}], body}, state)
200-
{:->, _, [ [param], body]} ->
206+
207+
{:->, _, [[param], body]} ->
201208
walk({[], [param], [], body}, state)
202209
end)
203210
end
@@ -234,10 +241,10 @@ defmodule ElixirScript.FindUsedFunctions do
234241

235242
[do: expression, else: elses] ->
236243
walk_block(expression, state)
237-
Enum.each(elses, fn
238-
{:->, _, [left, right]} ->
239-
walk(left, state)
240-
walk(right, state)
244+
245+
Enum.each(elses, fn {:->, _, [left, right]} ->
246+
walk(left, state)
247+
walk(right, state)
241248
end)
242249
end)
243250
end
@@ -258,10 +265,13 @@ defmodule ElixirScript.FindUsedFunctions do
258265
cond do
259266
ElixirScript.Translate.Module.is_js_module(module, state) ->
260267
nil
268+
261269
ElixirScript.Translate.Module.is_elixir_module(module) ->
262270
walk_module(module, function, length(params), state.pid)
271+
263272
is_tuple(module) ->
264273
walk(module, state)
274+
265275
true ->
266276
nil
267277
end
@@ -292,13 +302,15 @@ defmodule ElixirScript.FindUsedFunctions do
292302
case block do
293303
nil ->
294304
nil
305+
295306
{:__block__, _, block_body} ->
296307
Enum.each(block_body, &walk(&1, state))
308+
297309
b when is_list(b) ->
298310
Enum.each(b, &walk(&1, state))
311+
299312
_ ->
300313
walk(block, state)
301314
end
302315
end
303-
304316
end

0 commit comments

Comments
 (0)