Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 93 additions & 24 deletions lib/elixir_script/passes/translate/forms/match.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,53 @@ defmodule ElixirScript.Translate.Forms.Match do
alias ElixirScript.Translate.Forms.Pattern

def compile({:=, _, [left, right]}, state) do
build_matches(left, right, %{patterns: []})
|> compile_match(state)
end

defp make_list_ref(array_pattern, params) do
{ref, params} = make_params(params)
ref_declaration = Helpers.declare(ref, J.array_expression(params))

[array_pattern, ref_declaration]
end

defp make_tuple_ref(array_pattern, params) do
{ref, params} = make_params(params)

ref_declaration = Helpers.declare(ref, Helpers.new(
Helpers.tuple(),
params
))
[array_pattern, ref_declaration]
end


Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should be no more than 1 consecutive blank lines.

defp make_params(params) do
ref = J.identifier("_ref#{:rand.uniform(10000000)}")

params = Enum.map(params, fn
(nil) -> J.identifier(:undefined)
(x) -> x
end)

{ ref, params }
end

defp build_matches(pattern, {:=, _, [left, right]}, parts) do
parts = parts
|> Map.update!(:patterns, fn(x) -> x ++ [pattern] end)

build_matches(left, right, parts)
end

defp build_matches(left, right, parts) do
parts
|> Map.update!(:patterns, fn(x) -> x ++ [left] end)
|> Map.put(:expression, right)
end

defp compile_match(%{patterns: [left], expression: right}, state) do

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function is too complex (ABC size is 38, max is 30).

{ right_ast, state } = Form.compile(right, state)

{var_dec, right_ast} = case right_ast do
Expand Down Expand Up @@ -47,34 +94,56 @@ defmodule ElixirScript.Translate.Forms.Match do
{ js_ast, state }
end

defp compile_match(%{patterns: lefts, expression: right}, state) do

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function is too complex (ABC size is 43, max is 30).

{ right_ast, state } = Form.compile(right, state)

defp make_list_ref(array_pattern, params) do
{ref, params} = make_params(params)
ref_declaration = Helpers.declare(ref, J.array_expression(params))

[array_pattern, ref_declaration]
end

defp make_tuple_ref(array_pattern, params) do
{ref, params} = make_params(params)

ref_declaration = Helpers.declare(ref, Helpers.new(
Helpers.tuple(),
params
))
[array_pattern, ref_declaration]
end


defp make_params(params) do
ref = J.identifier("_ref#{:rand.uniform(10000000)}")
{var_dec, right_ast} = case right_ast do
[variable_declaration, x] ->
{variable_declaration, x}
x ->
{nil, x}
end

params = Enum.map(params, fn
(nil) -> J.identifier(:undefined)
(x) -> x
intermediate_assign = Helpers.assign(
J.identifier("__intermediate__"),
right_ast
)

{js_ast, state} = Enum.map_reduce(lefts, state, fn(left, state) ->
{ patterns, params, state } = Pattern.compile([left], state)

array_pattern = Helpers.declare(params, Helpers.call(
J.member_expression(
Helpers.patterns(),
J.identifier("match")
),
[hd(patterns), J.identifier("__intermediate__")]
))

js_ast = case left do
list when is_list(list) ->
make_list_ref(array_pattern, params)
{ _, _ } ->
make_tuple_ref(array_pattern, params)
{:{}, _, _ } ->
make_tuple_ref(array_pattern, params)
_ ->
List.wrap(array_pattern)
end

js_ast = case var_dec do
nil ->
js_ast
x ->
[x] ++ js_ast
end

{ js_ast, state }
end)

{ ref, params }
js_ast = [intermediate_assign] ++ List.flatten(js_ast)

{js_ast, state}
end

end
2 changes: 2 additions & 0 deletions lib/elixir_script/passes/translate/function.ex
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,14 @@ defmodule ElixirScript.Translate.Function do
clauses = compile_clauses(clauses, state)

arg_matches_declaration = Helpers.declare_let("__arg_matches__", J.identifier("null"))
intermediate_declaration = Helpers.declare_let("__intermediate__", J.identifier("null"))

function_recur_dec = Helpers.function(
"recur",
[J.rest_element(J.identifier("__function_args__"))],
J.block_statement([
arg_matches_declaration,
intermediate_declaration,
clauses,
J.throw_statement(
Helpers.new(
Expand Down
5 changes: 5 additions & 0 deletions test/integration/integration_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,9 @@ defmodule ElixirScript.Integration.Test do
val = call_compiled_function Integration, :tuple_get, []
assert val == 5
end

test "multi_bind" do
val = call_compiled_function Integration, :multi_bind, []
assert val == [1, 2, 3, 4, 5]
end
end
14 changes: 13 additions & 1 deletion test/passes/translate/form_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ defmodule ElixirScript.Translate.Forms.Test do
{:ok, pid} = ElixirScript.State.start_link()

state = %{
pid: pid
pid: pid,
vars: %{}
}

[state: state]
Expand Down Expand Up @@ -178,4 +179,15 @@ defmodule ElixirScript.Translate.Forms.Test do
{js_ast, _} = Form.compile(ast, state)
assert hd(js_ast.arguments).name === "has__qmark__0"
end

test "multi bind", %{state: state} do
ast =
{:=, [line: 35],
[[{:|, [line: 35], [{:a, [line: 35], nil}, {:_, [line: 35], nil}]}],
{:=, [line: 35], [{:b, [line: 35], nil}, [1, 2, 3, 4, 5]]}]}

{js_ast, _} = Form.compile(ast, state)

assert length(js_ast) > 1
end
end
4 changes: 4 additions & 0 deletions test/support/integration.ex
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ defmodule Integration do
end
end

def multi_bind do
[a | _] = b = [1, 2, 3, 4, 5]
end

def tuple_get do
map = %{{1} => 5}
Map.get(map, {1})
Expand Down