Existing issue
Elixir and Erlang/OTP versions
Erlang/OTP 29 [erts-17.0.6] [source] [32-bit] [smp:2:2] [ds:2:2:10] [async-threads:1]
Elixir 1.20.4 (compiled with Erlang/OTP 29)
Operating system
Alpine Linux
Current behavior
Hi! I tried searching by "unary" and did find some issues but none seemed related. I work on a project that relies heavily on metaprogramming, I have some configuration files which compile to runtime modules, but for extra weirdness, we first build each module AST, then write it to a file using Macro.to_string/1, and finally load the module using Code.compile_file/1, we do this to ease debugging. Is there a cleaner way to do this?
While working on this project I found a boolean expression wasn't returning the expected value, so after a long debugging session I noticed the re-parsed AST is not correct.
# unary.exs
quote do
!(if a do
b
end) ||
!(if b do
c
end)
end
|> IO.inspect(label: "original")
|> Macro.to_string
|> tap(&IO.puts/1)
|> Code.string_to_quoted!
|> IO.inspect(label: "reparsed")
|> Macro.to_string
|> tap(&IO.puts/1)
$ elixir unary.exs
original: {:||, [context: Elixir, imports: [{2, Kernel}]],
[
{:!, [context: Elixir, imports: [{1, Kernel}]],
[
{:if, [context: Elixir, imports: [{2, Kernel}]],
[{:a, [], Elixir}, [do: {:b, [], Elixir}]]}
]},
{:!, [context: Elixir, imports: [{1, Kernel}]],
[
{:if, [context: Elixir, imports: [{2, Kernel}]],
[{:b, [], Elixir}, [do: {:c, [], Elixir}]]}
]}
]}
!if a do
b
end ||
!if b do
c
end
reparsed: {:!, [line: 1],
[
{:||, [line: 3],
[
{:if, [line: 1], [{:a, [line: 1], nil}, [do: {:b, [line: 2], nil}]]},
{:!, [line: 4],
[{:if, [line: 4], [{:b, [line: 4], nil}, [do: {:c, [line: 5], nil}]]}]}
]}
]}
!(if a do
b
end ||
!if b do
c
end)
See how first expression printed is very different from the other one.
Expected behavior
I'm not really sure if the problem is Macro.to_string/1 or the parser itself, but I think the expression should be parsed as the one with parentheses.
iex(1)> quote do
!if a do
b
end ||
!if b do
c
end
end
{:!, [context: Elixir, imports: [{1, Kernel}]],
[
{:||, [context: Elixir, imports: [{2, Kernel}]],
[
{:if, [context: Elixir, imports: [{2, Kernel}]],
[
{:a, [], Elixir},
[do: {:b, [context: Elixir, imports: [{1, IEx.Helpers}]], Elixir}]
]},
{:!, [context: Elixir, imports: [{1, Kernel}]],
[
{:if, [context: Elixir, imports: [{2, Kernel}]],
[
{:b, [context: Elixir, imports: [{1, IEx.Helpers}]], Elixir},
[
do: {:c,
[
if_undefined: :apply,
context: Elixir,
imports: [{0, IEx.Helpers}, {1, IEx.Helpers}, {2, IEx.Helpers}]
], Elixir}
]
]}
]}
]}
]}
Existing issue
Elixir and Erlang/OTP versions
Operating system
Alpine Linux
Current behavior
Hi! I tried searching by "unary" and did find some issues but none seemed related. I work on a project that relies heavily on metaprogramming, I have some configuration files which compile to runtime modules, but for extra weirdness, we first build each module AST, then write it to a file using
Macro.to_string/1, and finally load the module usingCode.compile_file/1, we do this to ease debugging. Is there a cleaner way to do this?While working on this project I found a boolean expression wasn't returning the expected value, so after a long debugging session I noticed the re-parsed AST is not correct.
See how first expression printed is very different from the other one.
Expected behavior
I'm not really sure if the problem is
Macro.to_string/1or the parser itself, but I think the expression should be parsed as the one with parentheses.