Skip to content

Commit 0fbec6e

Browse files
committed
Began working on allowing macros
1 parent f7ba5c4 commit 0fbec6e

17 files changed

Lines changed: 267 additions & 219 deletions

lib/elixir_script/translator.ex

Lines changed: 120 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -27,70 +27,70 @@ defmodule ElixirScript.Translator do
2727
@doc """
2828
Translates Elixir AST to JavaScript AST
2929
"""
30-
def translate(ast) do
31-
do_translate(ast)
30+
def translate(ast, env \\ __ENV__) do
31+
do_translate(ast, env)
3232
end
3333

34-
defp do_translate(ast) when is_number(ast) or is_binary(ast) or is_boolean(ast) or is_nil(ast) do
34+
defp do_translate(ast, env) when is_number(ast) or is_binary(ast) or is_boolean(ast) or is_nil(ast) do
3535
Primitive.make_literal(ast)
3636
end
3737

38-
defp do_translate(ast) when is_atom(ast) do
38+
defp do_translate(ast, env) when is_atom(ast) do
3939
Primitive.make_atom(ast)
4040
end
4141

42-
defp do_translate(ast) when is_list(ast) do
43-
Primitive.make_list(ast)
42+
defp do_translate(ast, env) when is_list(ast) do
43+
Primitive.make_list(ast, env)
4444
end
4545

46-
defp do_translate({ one, two }) do
47-
Primitive.make_tuple({one, two})
46+
defp do_translate({ one, two }, env) do
47+
Primitive.make_tuple({one, two}, env)
4848
end
4949

50-
defp do_translate({:&, [], [number]}) when is_number(number) do
50+
defp do_translate({:&, [], [number]}, env) when is_number(number) do
5151
Primitive.make_identifier(String.to_atom("__#{number}"))
5252
end
5353

54-
defp do_translate({:&, _, [{:/, _, [{{:., _, [{:__aliases__, _, module_name}, function_name]}, _, []}, arity]}]}) do
54+
defp do_translate({:&, _, [{:/, _, [{{:., _, [{:__aliases__, _, module_name}, function_name]}, _, []}, arity]}]}, env) do
5555
function_name = Utils.filter_name(function_name)
56-
Capture.make_capture(List.last(module_name), function_name, arity)
56+
Capture.make_capture(List.last(module_name), function_name, arity, env)
5757
end
5858

59-
defp do_translate({:&, _, [{:/, _, [{function_name, _, _}, arity]}]}) do
59+
defp do_translate({:&, _, [{:/, _, [{function_name, _, _}, arity]}]}, env) do
6060
function_name = Utils.filter_name(function_name)
61-
Capture.make_capture(function_name, arity)
61+
Capture.make_capture(function_name, arity, env)
6262
end
6363

64-
defp do_translate({:&, _, body}) do
64+
defp do_translate({:&, _, body}, env) do
6565
params = Capture.find_value_placeholders(body) |> List.flatten
66-
Function.make_anonymous_function([{:->, [], [params, body]}])
66+
Function.make_anonymous_function([{:->, [], [params, body]}], env)
6767
end
6868

69-
defp do_translate({:@, _, [{name, _, [value]}]}) do
69+
defp do_translate({:@, _, [{name, _, [value]}]}, env) do
7070
name = Utils.filter_name(name)
71-
Module.make_attribute(name, value)
71+
Module.make_attribute(name, value, env)
7272
end
7373

74-
defp do_translate({:@, _, [{name, _, _}]}) do
74+
defp do_translate({:@, _, [{name, _, _}]}, env) do
7575
name = Utils.filter_name(name)
7676
Primitive.make_identifier(name)
7777
end
7878

79-
defp do_translate({:%, _, [alias_info, data]}) do
79+
defp do_translate({:%, _, [alias_info, data]}, env) do
8080
{_, _, name} = alias_info
8181
{_, _, data} = data
8282
Struct.make_struct(name, data)
8383
end
8484

85-
defp do_translate({:%{}, _, [{:|, _, [map, data]}]}) do
85+
defp do_translate({:%{}, _, [{:|, _, [map, data]}]}, env) do
8686
Map.make_map_update(map, data);
8787
end
8888

89-
defp do_translate({:%{}, _, properties}) do
89+
defp do_translate({:%{}, _, properties}, env) do
9090
Map.make_object(properties)
9191
end
9292

93-
defp do_translate({:<<>>, _, elements}) do
93+
defp do_translate({:<<>>, _, elements}, env) do
9494
is_interpolated_string = Enum.all?(elements, fn(x) ->
9595
case x do
9696
b when is_binary(b) ->
@@ -110,181 +110,202 @@ defmodule ElixirScript.Translator do
110110
end
111111
end
112112

113-
defp do_translate({{:., _, [Access, :get]}, _, [target, property]}) do
113+
defp do_translate({{:., _, [Access, :get]}, _, [target, property]}, env) do
114114
Map.make_get_property(target, property)
115115
end
116116

117-
defp do_translate({:., _, [module_name, function_name]}) do
118-
Function.make_function_or_property_call(module_name, function_name)
117+
defp do_translate({:., _, [module_name, function_name]} = ast, env) do
118+
expanded_ast = Macro.expand(ast, env)
119+
if expanded_ast == ast do
120+
Function.make_function_or_property_call(module_name, function_name, env)
121+
else
122+
translate(expanded_ast, env)
123+
end
119124
end
120125

121-
defp do_translate({{:., _, [module_name, function_name]}, _, [] }) do
122-
Function.make_function_or_property_call(module_name, function_name)
126+
defp do_translate({{:., _, [module_name, function_name]}, _, [] } = ast, env) do
127+
expanded_ast = Macro.expand(ast, env)
128+
if expanded_ast == ast do
129+
Function.make_function_or_property_call(module_name, function_name, env)
130+
else
131+
translate(expanded_ast, env)
132+
end
123133
end
124134

125-
defp do_translate({{:., _, [{:__aliases__, _, module_name}]}, _, params}) do
126-
Function.make_function_call(hd(module_name), params)
135+
defp do_translate({{:., _, [{:__aliases__, _, module_name}]}, _, params} = ast, env) do
136+
expanded_ast = Macro.expand(ast, env)
137+
if expanded_ast == ast do
138+
Function.make_function_call(hd(module_name), params, env)
139+
else
140+
translate(expanded_ast, env)
141+
end
127142
end
128143

129-
defp do_translate({{:., _, [module_name, function_name]}, _, params }) do
130-
Function.make_function_call(module_name, function_name, params)
144+
defp do_translate({{:., _, [module_name, function_name]}, _, params } = ast, env) do
145+
expanded_ast = Macro.expand(ast, env)
146+
if expanded_ast == ast do
147+
Function.make_function_call(module_name, function_name, params, env)
148+
else
149+
translate(expanded_ast, env)
150+
end
131151
end
132152

133-
defp do_translate({:_, _, _}) do
153+
defp do_translate({:_, _, _}, env) do
134154
Primitive.make_identifier(:undefined)
135155
end
136156

137-
defp do_translate({:__aliases__, _, aliases}) do
157+
defp do_translate({:__aliases__, _, aliases}, env) do
138158
Primitive.make_identifier(aliases)
139159
end
140160

141-
defp do_translate({:__block__, _, expressions }) do
161+
defp do_translate({:__block__, _, expressions }, env) do
142162
Block.make_block(expressions)
143163
end
144164

145-
defp do_translate({:__DIR__, _, _expressions }) do
165+
defp do_translate({:__DIR__, _, _expressions }, env) do
146166
ExKernel.make___DIR__()
147167
end
148168

149-
defp do_translate({:try, _, [ blocks ]}) do
150-
Try.make_try(blocks)
169+
defp do_translate({:try, _, [ blocks ]}, env) do
170+
Try.make_try(blocks, env)
151171
end
152172

153-
defp do_translate({:receive, _, [expressions] }) do
154-
Receive.make_receive(expressions);
173+
defp do_translate({:receive, _, [expressions] }, env) do
174+
Receive.make_receive(expressions, env);
155175
end
156176

157-
defp do_translate({:super, _, _expressions }) do
177+
defp do_translate({:super, _, _expressions }, env) do
158178
raise ElixirScript.UnsupportedError, :super
159179
end
160180

161-
defp do_translate({:__CALLER__, _, _expressions }) do
181+
defp do_translate({:__CALLER__, _, _expressions }, env) do
162182
raise ElixirScript.UnsupportedError, :__CALLER__
163183
end
164184

165-
defp do_translate({:__ENV__, _, _expressions }) do
185+
defp do_translate({:__ENV__, _, _expressions }, env) do
166186
raise ElixirScript.UnsupportedError, :__ENV__
167187
end
168188

169-
defp do_translate({:quote, _, [[do: expr]]}) do
189+
defp do_translate({:quote, _, [[do: expr]]}, env) do
170190
Quote.make_quote([], expr)
171191
end
172192

173-
defp do_translate({:quote, _, [opts, [do: expr]]}) do
193+
defp do_translate({:quote, _, [opts, [do: expr]]}, env) do
174194
Quote.make_quote(opts, expr)
175195
end
176196

177-
defp do_translate({:import, _, [{:__aliases__, _, module_name_list}]}) do
197+
defp do_translate({:import, _, [{:__aliases__, _, module_name_list}]}, env) do
178198
Import.make_import(module_name_list, [])
179199
end
180200

181-
defp do_translate({:import, _, [{:__aliases__, _, module_name_list}, options ]}) do
201+
defp do_translate({:import, _, [{:__aliases__, _, module_name_list}, options ]}, env) do
182202
Import.make_import(module_name_list, options)
183203
end
184204

185-
defp do_translate({:alias, _, [alias_info, options]}) do
205+
defp do_translate({:alias, _, [alias_info, options]}, env) do
186206
Import.make_alias_import(alias_info, options)
187207
end
188208

189-
defp do_translate({:alias, _, [alias_info]}) do
209+
defp do_translate({:alias, _, [alias_info]}, env) do
190210
Import.make_alias_import(alias_info, [])
191211
end
192212

193-
defp do_translate({:require, _, [alias_info, options]}) do
213+
defp do_translate({:require, _, [alias_info, options]}, env) do
194214
Import.make_alias_import(alias_info, options)
195215
end
196216

197-
defp do_translate({:require, _, [alias_info]}) do
217+
defp do_translate({:require, _, [alias_info]}, env) do
198218
Import.make_alias_import(alias_info, [])
199219
end
200220

201-
defp do_translate({:case, _, [condition, [do: clauses]]}) do
202-
Case.make_case(condition, clauses)
221+
defp do_translate({:case, _, [condition, [do: clauses]]}, env) do
222+
Case.make_case(condition, clauses, env)
203223
end
204224

205-
defp do_translate({:cond, _, [[do: clauses]]}) do
225+
defp do_translate({:cond, _, [[do: clauses]]}, env) do
206226
Cond.make_cond(clauses)
207227
end
208228

209-
defp do_translate({:for, _, generators}) do
210-
For.make_for(generators)
229+
defp do_translate({:for, _, generators}, env) do
230+
For.make_for(generators, env)
211231
end
212232

213-
defp do_translate({:fn, _, clauses}) do
214-
Function.make_anonymous_function(clauses)
233+
defp do_translate({:fn, _, clauses}, env) do
234+
Function.make_anonymous_function(clauses, env)
215235
end
216236

217-
defp do_translate({:.., _, [first, last]}) do
237+
defp do_translate({:.., _, [first, last]}, env) do
218238
ExKernel.make_range(first, last)
219239
end
220240

221-
defp do_translate({:{}, _, elements}) do
222-
Primitive.make_tuple(elements)
241+
defp do_translate({:{}, _, elements}, env) do
242+
Primitive.make_tuple(elements, env)
223243
end
224244

225-
defp do_translate({operator, _, [value]}) when operator in [:-, :!] do
226-
Expression.make_unary_expression(operator, value)
245+
defp do_translate({operator, _, [value]}, env) when operator in [:-, :!] do
246+
Expression.make_unary_expression(operator, value, env)
227247
end
228248

229-
defp do_translate({:=, _, [left, right]}) do
230-
Assignment.make_assignment(left, right)
249+
defp do_translate({:=, _, [left, right]}, env) do
250+
Assignment.make_assignment(left, right, env)
231251
end
232252

233-
defp do_translate({:<>, _, [left, right]}) do
234-
Expression.make_binary_expression(:+, left, right)
253+
defp do_translate({:<>, _, [left, right]}, env) do
254+
Expression.make_binary_expression(:+, left, right, env)
235255
end
236256

237-
defp do_translate({:++, _, [left, right]}) do
257+
defp do_translate({:++, _, [left, right]}, env) do
238258
ExKernel.concat_lists(left, right)
239259
end
240260

241-
defp do_translate({operator, _, [left, right]}) when operator in [:+, :-, :/, :*, :==, :!=, :&&, :||, :>, :<, :>=, :<=, :===] do
242-
Expression.make_binary_expression(operator, left, right)
261+
defp do_translate({operator, _, [left, right]}, env) when operator in [:+, :-, :/, :*, :==, :!=, :&&, :||, :>, :<, :>=, :<=, :===] do
262+
Expression.make_binary_expression(operator, left, right, env)
243263
end
244264

245-
defp do_translate({:and, _, [left, right]}) do
246-
Expression.make_binary_expression(:&&, left, right)
265+
defp do_translate({:and, _, [left, right]}, env) do
266+
Expression.make_binary_expression(:&&, left, right, env)
247267
end
248268

249-
defp do_translate({:or, _, [left, right]}) do
250-
Expression.make_binary_expression(:||, left, right)
269+
defp do_translate({:or, _, [left, right]}, env) do
270+
Expression.make_binary_expression(:||, left, right, env)
251271
end
252272

253-
defp do_translate({function, _, [{:when, _, [{name, _, _params} | _guards] }, [do: _body]] } = ast) when function in [:def, :defp] do
254-
Function.process_function(Utils.filter_name(name), [ast])
273+
defp do_translate({function, _, [{:when, _, [{name, _, _params} | _guards] }, [do: _body]] } = ast, env) when function in [:def, :defp] do
274+
Function.process_function(Utils.filter_name(name), [ast], env)
255275
end
256276

257-
defp do_translate({function, _, [{name, _, _params}, [do: _body]]} = ast) when function in [:def, :defp] do
258-
Function.process_function(Utils.filter_name(name), [ast])
277+
defp do_translate({function, _, [{name, _, _params}, [do: _body]]} = ast, env) when function in [:def, :defp] do
278+
Function.process_function(Utils.filter_name(name), [ast], env)
259279
end
260280

261-
defp do_translate({:defstruct, _, attributes}) do
281+
defp do_translate({:defstruct, _, attributes}, env) do
262282
Struct.make_defstruct(attributes)
263283
end
264284

265-
defp do_translate({:defexception, _, attributes}) do
285+
defp do_translate({:defexception, _, attributes}, env) do
266286
Struct.make_defexception(attributes)
267287
end
268288

269-
defp do_translate({:raise, _, [alias_info, attributes]}) do
289+
defp do_translate({:raise, _, [alias_info, attributes]}, env) do
270290
{_, _, name} = alias_info
271291

272292
Raise.throw_error(name, attributes)
273293
end
274294

275-
defp do_translate({:raise, _, [message]}) do
295+
defp do_translate({:raise, _, [message]}, env) do
276296
Raise.throw_error(message)
277297
end
278298

279-
defp do_translate({:if, _, [test, blocks]}) do
280-
If.make_if(test, blocks)
299+
defp do_translate({:if, _, _} = ast, env) do
300+
Macro.expand(ast, env)
301+
|> translate
281302
end
282303

283-
defp do_translate({:defmodule, _, [{:__aliases__, _, module_name_list}, [do: body]]}) do
284-
Module.make_module(module_name_list, body)
304+
defp do_translate({:defmodule, _, [{:__aliases__, _, module_name_list}, [do: body]]}, env) do
305+
Module.make_module(module_name_list, body, env)
285306
end
286307

287-
defp do_translate({:|>, _, [left, right]}) do
308+
defp do_translate({:|>, _, [left, right]}, env) do
288309
case right do
289310
{{:., meta, [module, fun]}, meta2, params} ->
290311
translate({{:., meta, [module, fun]}, meta2, [left] ++ params})
@@ -293,18 +314,23 @@ defmodule ElixirScript.Translator do
293314
end
294315
end
295316

296-
defp do_translate({name, metadata, params}) when is_list(params) do
297-
name = Utils.filter_name(name)
317+
defp do_translate({name, metadata, params} = ast, env) when is_list(params) do
318+
expanded_ast = Macro.expand(ast, env)
319+
if expanded_ast == ast do
320+
name = Utils.filter_name(name)
298321

299-
case metadata[:import] do
300-
Kernel ->
301-
Function.make_function_call(:Kernel, name, params)
302-
_ ->
303-
Function.make_function_call(name, params)
322+
case metadata[:import] do
323+
Kernel ->
324+
Function.make_function_call(:Kernel, name, params, env)
325+
_ ->
326+
Function.make_function_call(name, params, env)
327+
end
328+
else
329+
translate(expanded_ast)
304330
end
305331
end
306332

307-
defp do_translate({ name, _, _ }) do
333+
defp do_translate({ name, _, _ }, env) do
308334
name = Utils.filter_name(name)
309335
Primitive.make_identifier(name)
310336
end

0 commit comments

Comments
 (0)