Current section

Files

Jump to
elixir_script lib elixir_script translator for.ex
Raw

lib/elixir_script/translator/for.ex

defmodule ElixirScript.Translator.For do
@moduledoc false
alias ESTree.Tools.Builder, as: JS
alias ElixirScript.Translator
alias ElixirScript.Translator.PatternMatching
alias ElixirScript.Translator.Primitive
alias ElixirScript.Translator.Function
def make_for(generators, env) do
args = handle_args(generators, env)
collections = Primitive.make_list_no_translate(args.collections)
into = args.into || Primitive.make_list_no_translate([])
filter = args.filter || JS.function_expression([], [], JS.block_statement([JS.return_statement(JS.identifier("true"))]))
fun = args.fun
js_ast = JS.call_expression(
JS.member_expression(
Primitive.special_forms(),
JS.identifier("_for")
),
[collections, fun, filter, into]
)
{ js_ast, env }
end
defp handle_args(generators, env) do
Enum.reduce(generators, %{collections: [], args: [], filter: nil, fun: nil, into: nil}, fn
({:<<>>, [], body}, state) ->
{ bs_parts, collection } = Enum.map_reduce(body, nil, fn
{:::, _, _} = ast, state ->
{ast, state}
{:<-, [], [var, collection]}, state ->
{ var, collection }
end)
{ patterns, params, env } = PatternMatching.process_match([{:<<>>, [], bs_parts}], env)
list = Primitive.make_list_no_translate([hd(patterns), Translator.translate!(collection, env)])
%{state | collections: state.collections ++ [list], args: state.args ++ params }
({:<-, _, [identifier, enum]}, state) ->
{ patterns, params, env } = PatternMatching.process_match([identifier], env)
list = Primitive.make_list_no_translate([hd(patterns), Translator.translate!(enum, env)])
%{state | collections: state.collections ++ [list], args: state.args ++ params }
([into: expression], state) ->
%{ state | into: Translator.translate(expression, env) }
([into: expression, do: expression2], state) ->
fun = create_function_expression(expression2, env, state)
%{ state | into: Translator.translate!(expression, env), fun: fun }
([do: expression], state) ->
fun = create_function_expression(expression, env, state)
%{ state | fun: fun }
(filter, state) ->
fun = create_function_expression(filter, env, state)
%{ state | filter: fun }
end)
end
defp create_function_expression(ast, env, state) do
{ ast, _ } = Function.make_function_body(ast, env)
JS.function_expression(
state.args,
[],
ast
)
end
end