diff --git a/lib/elixir/lib/macro.ex b/lib/elixir/lib/macro.ex index 3c77fe70044..dab63948e94 100644 --- a/lib/elixir/lib/macro.ex +++ b/lib/elixir/lib/macro.ex @@ -2641,16 +2641,8 @@ defmodule Macro do # Logic operators. defp dbg_ast_to_debuggable({op, _meta, [_left, _right]} = ast, _env) when op in unquote(dbg_decomposed_binary_operators) do - acc_var = unique_var(:acc, __MODULE__) result_var = unique_var(:result, __MODULE__) - - [ - quote do - unquote(acc_var) = [] - unquote(dbg_boolean_tree(ast, acc_var, result_var)) - {:logic_op, Enum.reverse(unquote(acc_var)), unquote(result_var)} - end - ] + dbg_boolean_tree(ast, result_var, []) end defp dbg_ast_to_debuggable({:__block__, _meta, exprs} = ast, _env) when exprs != [] do @@ -2818,30 +2810,27 @@ defmodule Macro do end # This is a binary operator. We replace the left side with a recursive call to - # this function to decompose it, and then execute the operation and add it to the acc. - defp dbg_boolean_tree({op, _meta, [left, right]} = ast, acc_var, result_var) + # this function to decompose it + defp dbg_boolean_tree({op, _meta, [left, right]} = ast, result_var, nodes) when op in unquote(dbg_decomposed_binary_operators) do - replaced_left = dbg_boolean_tree(left, acc_var, result_var) + tag = if nodes == [], do: :value, else: :multi_value - quote do - unquote(result_var) = unquote(op)(unquote(replaced_left), unquote(right)) - - unquote(acc_var) = [ - {unquote(escape(ast)), unquote(result_var)} | unquote(acc_var) - ] + node = + quote do + unquote(result_var) = unquote(op)(unquote(result_var), unquote(right)) + {unquote(tag), unquote(escape(ast)), unquote(result_var)} + end - unquote(result_var) - end + dbg_boolean_tree(left, result_var, [node | nodes]) end - # This is finally an expression, so we assign "result = expr", add it to the acc, and - # return the result. - defp dbg_boolean_tree(ast, acc_var, result_var) do - quote do - unquote(result_var) = unquote(ast) - unquote(acc_var) = [{unquote(escape(ast)), unquote(result_var)} | unquote(acc_var)] - unquote(result_var) - end + defp dbg_boolean_tree(ast, result_var, nodes) do + node = + quote do + {:multi_value, unquote(escape(ast)), unquote(result_var) = unquote(ast)} + end + + [node | nodes] end defp dbg_block({:__block__, meta, exprs}, acc_var, result_var) do @@ -2895,15 +2884,6 @@ defmodule Macro do {[first_formatted | rest_formatted], result} end - defp dbg_format_ast_to_debug({:logic_op, components, value}, options) do - formatted = - Enum.map(components, fn {ast, value} -> - [dbg_format_ast(to_string_with_colors(ast, options)), " ", inspect(value, options), ?\n] - end) - - {formatted, value} - end - defp dbg_format_ast_to_debug({:block, components, value}, options) do formatted = [ @@ -2994,12 +2974,20 @@ defmodule Macro do {formatted, result} end + defp dbg_format_ast_to_debug({:multi_value, code_ast, value}, options) do + {dbg_format_ast_with_value_no_newline(code_ast, value, options), value} + end + defp dbg_format_ast_to_debug({:value, code_ast, value}, options) do {dbg_format_ast_with_value(code_ast, value, options), value} end + defp dbg_format_ast_with_value_no_newline(ast, value, options) do + [dbg_format_ast(to_string_with_colors(ast, options)), " ", inspect(value, options)] + end + defp dbg_format_ast_with_value(ast, value, options) do - [dbg_format_ast(to_string_with_colors(ast, options)), " ", inspect(value, options), ?\n] + [dbg_format_ast_with_value_no_newline(ast, value, options), ?\n] end defp to_string_with_colors(ast, options) do diff --git a/lib/elixir/test/elixir/macro_test.exs b/lib/elixir/test/elixir/macro_test.exs index d32bc200ed5..e3230f1d4da 100644 --- a/lib/elixir/test/elixir/macro_test.exs +++ b/lib/elixir/test/elixir/macro_test.exs @@ -325,16 +325,22 @@ defmodule MacroTest do end describe "dbg/3" do + defmacrop dbg_format_no_newline(ast, options \\ quote(do: [syntax_colors: []])) do + quote do + ExUnit.CaptureIO.with_io(fn -> + try do + unquote(Macro.dbg(ast, options, __CALLER__)) + rescue + e -> e + end + end) + end + end + defmacrop dbg_format(ast, options \\ quote(do: [syntax_colors: []])) do quote do {result, formatted} = - ExUnit.CaptureIO.with_io(fn -> - try do - unquote(Macro.dbg(ast, options, __CALLER__)) - rescue - e -> e - end - end) + dbg_format_no_newline(unquote(ast), unquote(options)) # Make sure there's an empty line after the output. assert String.ends_with?(formatted, "\n\n") or @@ -469,6 +475,22 @@ defmodule MacroTest do """ end + test "boolean expressions that raise" do + falsy = length([]) != 0 + x = 0 + + {result, formatted} = dbg_format_no_newline((falsy || x) && 1 / x) + + assert %ArithmeticError{} = result + + assert formatted =~ "macro_test.exs" + + assert formatted =~ """ + falsy #=> false + falsy || x #=> 0 + """ + end + test "block of code" do {result, formatted} = dbg_format(