forked from elixirscript/elixirscript
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathelixir_script.ex
More file actions
128 lines (107 loc) · 3.37 KB
/
Copy pathelixir_script.ex
File metadata and controls
128 lines (107 loc) · 3.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
defmodule ElixirScript do
alias ElixirScript.Translator.JSModule
@doc """
Parses Elixir code string into JavaScript AST
"""
@spec parse_elixir(binary) :: {binary, ESTree.Node.t}
def parse_elixir(elixir_code) do
elixir_code
|> Code.string_to_quoted!
|> parse_quoted
end
@doc """
Parses Elixir code in it's quoted form into JavaScript AST
"""
@spec parse_quoted(Macro.t) :: {binary, ESTree.Node.t}
def parse_quoted(quoted) do
ElixirScript.Translator.translate(quoted)
end
@doc """
Parses Elixir code files into JavaScript AST
"""
@spec parse_elixir_files(binary) :: [{binary, ESTree.Node.t}]
def parse_elixir_files(path) do
path
|> Path.wildcard
|> Enum.map(fn(x) ->
File.read!(x)
|> Code.string_to_quoted!
|> ElixirScript.Translator.translate
end)
|> List.flatten
end
def process_module(module, root) do
file_path = create_file_name(module)
program = ElixirScript.Translator.Module.create_standard_lib_imports(module.stdlibs, root) ++ module.body
|> ESTree.Builder.program
{ file_path, program }
end
defp create_file_name(%ElixirScript.Translator.JSModule{ name: module_list }) do
"#{ElixirScript.Translator.Import.make_file_path(module_list)}.js"
end
@doc """
Converts JavaScript AST into JavaScript code
"""
@spec javascript_ast_to_code(ESTree.Node.t) :: {:ok, binary} | {:error, binary}
def javascript_ast_to_code(js_ast) do
js_ast = case js_ast do
modules when is_list(modules) ->
Enum.reduce(modules, [], fn(x, list) -> list ++ x.body end)
|> ESTree.Builder.program
%ElixirScript.Translator.Group{body: body} ->
ESTree.Builder.program(body)
_ ->
js_ast
end
js_ast = Poison.encode!(js_ast)
path = "#{operating_path}/code_generator.js"
case System.cmd("node", [path, js_ast]) do
{js_code, 0} ->
{:ok, js_code }
{error, _} ->
{:error, error}
end
end
@doc """
Same as javascript_ast_to_code but throws an error
"""
@spec javascript_ast_to_code!(ESTree.Node.t) :: binary
def javascript_ast_to_code!(js_ast) do
case javascript_ast_to_code(js_ast) do
{:ok, js_code } ->
js_code
{:error, error } ->
raise ElixirScript.ParseError, message: error
end
end
@doc """
Writes output to file
"""
def write_to_file({ file_path, js_code }, destination) do
file_name = Path.join([destination, file_path])
if !File.exists?(Path.dirname(file_name)) do
File.mkdir_p!(Path.dirname(file_name))
end
File.write!(file_name, js_code)
end
def copy_standard_libs_to_destination(destination) do
File.cp_r!(operating_path <> "/lib", destination <> "/__lib")
end
def operating_path() do
try do
Mix.Project.build_path <> "/lib/elixir_script/priv/javascript"
rescue
UndefinedFunctionError ->
split_path = Path.split(Application.app_dir(:ex2js))
replaced_path = List.delete_at(split_path, length(split_path) - 1)
replaced_path = List.delete_at(replaced_path, length(replaced_path) - 1)
Path.join(replaced_path)
end
end
def post_process_js_ast(modules, root) when is_list(modules) do
Enum.map(modules, &process_module(&1, root))
end
def post_process_js_ast(js_ast) do
js_ast
end
end