Collapse expressions to improve trace debugging
This commit is contained in:
@@ -261,7 +261,8 @@ defmodule Module.Types.Helpers do
|
||||
Converts the given expression to a string,
|
||||
translating inlined Erlang calls back to Elixir.
|
||||
|
||||
We also undo some macro expressions done by the Kernel module.
|
||||
We also undo some macro expressions done by the Kernel module
|
||||
and collapse complex expressions.
|
||||
|
||||
## Options
|
||||
|
||||
@@ -352,9 +353,69 @@ defmodule Module.Types.Helpers do
|
||||
|
||||
{:&, amp_meta, [{:/, slash_meta, [{{:., dot_meta, [mod, fun]}, call_meta, []}, arity]}]}
|
||||
|
||||
{:case, meta, [expr, [do: clauses]]} = case ->
|
||||
{:case, meta, [expr, [do: clauses]]} ->
|
||||
if meta[:type_check] == :expr do
|
||||
case clauses do
|
||||
[
|
||||
{:->, _,
|
||||
[
|
||||
[
|
||||
{:when, _,
|
||||
[
|
||||
{var, _, Kernel},
|
||||
{{:., _, [:erlang, :orelse]}, _,
|
||||
[
|
||||
{{:., _, [:erlang, :"=:="]}, _, [{var, _, Kernel}, false]},
|
||||
{{:., _, [:erlang, :"=:="]}, _, [{var, _, Kernel}, nil]}
|
||||
]}
|
||||
]}
|
||||
],
|
||||
true
|
||||
]},
|
||||
{:->, _, [[{:_, _, Kernel}], false]}
|
||||
] ->
|
||||
{:!, meta, [expr]}
|
||||
|
||||
[
|
||||
{:->, _,
|
||||
[
|
||||
[
|
||||
{:when, _,
|
||||
[
|
||||
{var, _, Kernel},
|
||||
{{:., _, [:erlang, :orelse]}, _,
|
||||
[
|
||||
{{:., _, [:erlang, :"=:="]}, _, [{var, _, Kernel}, false]},
|
||||
{{:., _, [:erlang, :"=:="]}, _, [{var, _, Kernel}, nil]}
|
||||
]}
|
||||
]}
|
||||
],
|
||||
right_side
|
||||
]},
|
||||
{:->, _, [[{var, _, Kernel}], {var, _, Kernel}]}
|
||||
] ->
|
||||
{:||, meta, [expr, right_side]}
|
||||
|
||||
[
|
||||
{:->, _,
|
||||
[
|
||||
[
|
||||
{:when, _,
|
||||
[
|
||||
{var, _, Kernel},
|
||||
{{:., _, [:erlang, :orelse]}, _,
|
||||
[
|
||||
{{:., _, [:erlang, :"=:="]}, _, [{var, _, Kernel}, false]},
|
||||
{{:., _, [:erlang, :"=:="]}, _, [{var, _, Kernel}, nil]}
|
||||
]}
|
||||
]}
|
||||
],
|
||||
{var, _, Kernel}
|
||||
]},
|
||||
{:->, _, [[{:_, _, Kernel}], right_side]}
|
||||
] ->
|
||||
{:&&, meta, [expr, right_side]}
|
||||
|
||||
[
|
||||
{:->, _,
|
||||
[
|
||||
@@ -382,12 +443,21 @@ defmodule Module.Types.Helpers do
|
||||
{:if, meta, [expr, [do: do_block, else: else_block]]}
|
||||
|
||||
_ ->
|
||||
case
|
||||
{:case, meta, [expr, [do: {:..., [], []}]]}
|
||||
end
|
||||
else
|
||||
case
|
||||
{:case, meta, [expr, [do: {:..., [], []}]]}
|
||||
end
|
||||
|
||||
{:try, meta, [[do: _] ++ _]} ->
|
||||
{:try, meta, [[do: {:..., [], []}]]}
|
||||
|
||||
{:cond, meta, [[do: _]]} ->
|
||||
{:cond, meta, [[do: {:..., [], []}]]}
|
||||
|
||||
{:receive, meta, [[do: _] ++ _]} ->
|
||||
{:receive, meta, [[do: {:..., [], []}]]}
|
||||
|
||||
{var, meta, context} = expr when is_atom(var) and is_atom(context) ->
|
||||
if is_integer(meta[:capture]) do
|
||||
{:&, meta, [meta[:capture]]}
|
||||
|
||||
@@ -495,8 +495,7 @@ defmodule Module.Types.ExprTest do
|
||||
# from: types_test.ex:LINE-9
|
||||
mod =
|
||||
cond do
|
||||
z -> x
|
||||
true -> y
|
||||
...
|
||||
end
|
||||
"""
|
||||
end
|
||||
@@ -1081,8 +1080,7 @@ defmodule Module.Types.ExprTest do
|
||||
# from: types_test.ex:LINE-9
|
||||
foo_or_bar =
|
||||
cond do
|
||||
:rand.uniform() > 0.5 -> :foo
|
||||
true -> :bar
|
||||
...
|
||||
end
|
||||
|
||||
where "x" was given the type:
|
||||
|
||||
@@ -7,15 +7,75 @@ defmodule Module.Types.HelpersTest do
|
||||
use ExUnit.Case, async: true
|
||||
import Module.Types.Helpers
|
||||
|
||||
test "expr_to_string/1" do
|
||||
assert expr_to_string({1, 2}) == "{1, 2}"
|
||||
assert expr_to_string(quote(do: Foo.bar(arg))) == "Foo.bar(arg)"
|
||||
assert expr_to_string(quote(do: :erlang.band(a, b))) == "Bitwise.band(a, b)"
|
||||
assert expr_to_string(quote(do: :erlang.orelse(a, b))) == "a or b"
|
||||
assert expr_to_string(quote(do: :erlang."=:="(a, b))) == "a === b"
|
||||
assert expr_to_string(quote(do: :erlang.list_to_atom(a))) == "List.to_atom(a)"
|
||||
assert expr_to_string(quote(do: :maps.remove(a, b))) == "Map.delete(b, a)"
|
||||
assert expr_to_string(quote(do: :erlang.element(1, a))) == "elem(a, 0)"
|
||||
assert expr_to_string(quote(do: :erlang.element(:erlang.+(a, 1), b))) == "elem(b, a)"
|
||||
describe "expr_to_string/1" do
|
||||
test "common expressions" do
|
||||
assert expr_to_string({1, 2}) == "{1, 2}"
|
||||
assert expr_to_string(quote(do: Foo.bar(arg))) == "Foo.bar(arg)"
|
||||
end
|
||||
|
||||
test "rewrites" do
|
||||
assert expr_to_string(quote(do: :erlang.band(a, b))) == "Bitwise.band(a, b)"
|
||||
assert expr_to_string(quote(do: :erlang.orelse(a, b))) == "a or b"
|
||||
assert expr_to_string(quote(do: :erlang."=:="(a, b))) == "a === b"
|
||||
assert expr_to_string(quote(do: :erlang.list_to_atom(a))) == "List.to_atom(a)"
|
||||
assert expr_to_string(quote(do: :maps.remove(a, b))) == "Map.delete(b, a)"
|
||||
assert expr_to_string(quote(do: :erlang.element(1, a))) == "elem(a, 0)"
|
||||
assert expr_to_string(quote(do: :erlang.element(:erlang.+(a, 1), b))) == "elem(b, a)"
|
||||
end
|
||||
|
||||
test "Kernel macros" do
|
||||
case = Macro.expand(quote(do: if(condition, do: :this, else: :that)), __ENV__)
|
||||
assert expr_to_string(case) == "if condition do\n :this\nelse\n :that\nend"
|
||||
|
||||
case = Macro.expand(quote(do: :this || :that), __ENV__)
|
||||
assert expr_to_string(case) == ":this || :that"
|
||||
|
||||
case = Macro.expand(quote(do: :this && :that), __ENV__)
|
||||
assert expr_to_string(case) == ":this && :that"
|
||||
|
||||
case = Macro.expand(quote(do: !expr), __ENV__)
|
||||
assert expr_to_string(case) == "!expr"
|
||||
end
|
||||
|
||||
test "case/try/receive/cond" do
|
||||
assert expr_to_string(
|
||||
quote do
|
||||
case expr do
|
||||
:this -> :this!
|
||||
:that -> :that!
|
||||
end
|
||||
end
|
||||
) == "case expr do\n ...\nend"
|
||||
|
||||
assert expr_to_string(
|
||||
quote do
|
||||
try do
|
||||
:this -> :this!
|
||||
:that -> :that!
|
||||
rescue
|
||||
_ ->
|
||||
nil
|
||||
end
|
||||
end
|
||||
) == "try do\n ...\nend"
|
||||
|
||||
assert expr_to_string(
|
||||
quote do
|
||||
cond do
|
||||
:this -> :this!
|
||||
:that -> :that!
|
||||
end
|
||||
end
|
||||
) == "cond do\n ...\nend"
|
||||
|
||||
assert expr_to_string(
|
||||
quote do
|
||||
receive do
|
||||
:this -> :this!
|
||||
:that -> :that!
|
||||
end
|
||||
end
|
||||
) == "receive do\n ...\nend"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user