mirror of
https://github.com/livebook-dev/livebook.git
synced 2025-10-29 23:05:59 +08:00
Use unambiguous mapping between erlang and elixir variable names (#2556)
This commit is contained in:
parent
1cac107402
commit
6d994a5542
2 changed files with 74 additions and 2 deletions
|
|
@ -808,17 +808,47 @@ defmodule Livebook.Runtime.Evaluator do
|
||||||
defp elixir_to_erlang_var(name) do
|
defp elixir_to_erlang_var(name) do
|
||||||
name
|
name
|
||||||
|> :erlang.atom_to_binary()
|
|> :erlang.atom_to_binary()
|
||||||
|> Macro.camelize()
|
|> toggle_var_case()
|
||||||
|> :erlang.binary_to_atom()
|
|> :erlang.binary_to_atom()
|
||||||
end
|
end
|
||||||
|
|
||||||
defp erlang_to_elixir_var(name) do
|
defp erlang_to_elixir_var(name) do
|
||||||
name
|
name
|
||||||
|> :erlang.atom_to_binary()
|
|> :erlang.atom_to_binary()
|
||||||
|> Macro.underscore()
|
|> toggle_var_case()
|
||||||
|> :erlang.binary_to_atom()
|
|> :erlang.binary_to_atom()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Unambiguously maps variable names from camel case to underscore
|
||||||
|
# case, and vice-versa. The mapping is defined as follows:
|
||||||
|
#
|
||||||
|
# 1. The first character case is changed
|
||||||
|
#
|
||||||
|
# 2. Underscore followed by lower character maps to upper character,
|
||||||
|
# and vice-versa
|
||||||
|
#
|
||||||
|
defp toggle_var_case(<<h, t::binary>>) do
|
||||||
|
do_toggle_var_case(<<toggle_char_case(h)>>, t)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp do_toggle_var_case(acc, <<?_, h, t::binary>>) when h >= ?a and h <= ?z do
|
||||||
|
do_toggle_var_case(<<acc::binary, toggle_char_case(h)>>, t)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp do_toggle_var_case(acc, <<h, t::binary>>) when h >= ?A and h <= ?Z do
|
||||||
|
do_toggle_var_case(<<acc::binary, ?_, toggle_char_case(h)>>, t)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp do_toggle_var_case(acc, <<h, t::binary>>) do
|
||||||
|
do_toggle_var_case(<<acc::binary, h>>, t)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp do_toggle_var_case(acc, <<>>), do: acc
|
||||||
|
|
||||||
|
defp toggle_char_case(char) when char >= ?a and char <= ?z, do: char - 32
|
||||||
|
defp toggle_char_case(char) when char >= ?A and char <= ?Z, do: char + 32
|
||||||
|
defp toggle_char_case(char), do: char
|
||||||
|
|
||||||
defp filter_erlang_code_markers(code_markers) do
|
defp filter_erlang_code_markers(code_markers) do
|
||||||
Enum.reject(code_markers, &(&1.line == 0))
|
Enum.reject(code_markers, &(&1.line == 0))
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1268,6 +1268,48 @@ defmodule Livebook.Runtime.EvaluatorTest do
|
||||||
assert [{:z, 1}, {:y, 1}, {:x, 1}] == binding
|
assert [{:z, 1}, {:y, 1}, {:x, 1}] == binding
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "uses unambiguous camelization for erlang/elixir bindings", %{evaluator: evaluator} do
|
||||||
|
Evaluator.evaluate_code(evaluator, :erlang, "{JSON, JsOn, JsON} = {1, 2, 3}.", :code_1, [])
|
||||||
|
|
||||||
|
assert_receive {:runtime_evaluation_response, :code_1, terminal_text(_), metadata()}
|
||||||
|
|
||||||
|
Evaluator.evaluate_code(
|
||||||
|
evaluator,
|
||||||
|
:elixir,
|
||||||
|
"""
|
||||||
|
assertion1 = {j_s_o_n, js_on, js_o_n} == {1, 2, 3}
|
||||||
|
{j_s_o_n, js_on, js_o_n} = {11, 12, 13}
|
||||||
|
""",
|
||||||
|
:code_2,
|
||||||
|
[:code_1]
|
||||||
|
)
|
||||||
|
|
||||||
|
assert_receive {:runtime_evaluation_response, :code_2, terminal_text(_), metadata()}
|
||||||
|
|
||||||
|
Evaluator.evaluate_code(
|
||||||
|
evaluator,
|
||||||
|
:erlang,
|
||||||
|
"""
|
||||||
|
Assertion2 = {JSON, JsOn, JsON} =:= {11, 12, 13}.
|
||||||
|
""",
|
||||||
|
:code_3,
|
||||||
|
[:code_2]
|
||||||
|
)
|
||||||
|
|
||||||
|
assert_receive {:runtime_evaluation_response, :code_3, terminal_text(_), metadata()}
|
||||||
|
|
||||||
|
%{binding: binding} =
|
||||||
|
Evaluator.get_evaluation_context(evaluator, [:code_3, :code_2, :code_1])
|
||||||
|
|
||||||
|
assert [
|
||||||
|
{:assertion2, true},
|
||||||
|
{:js_on, 12},
|
||||||
|
{:js_o_n, 13},
|
||||||
|
{:j_s_o_n, 11},
|
||||||
|
{:assertion1, true}
|
||||||
|
] == binding
|
||||||
|
end
|
||||||
|
|
||||||
test "inspects erlang results using erlang format", %{evaluator: evaluator} do
|
test "inspects erlang results using erlang format", %{evaluator: evaluator} do
|
||||||
code = ~S"#{x=>1}."
|
code = ~S"#{x=>1}."
|
||||||
Evaluator.evaluate_code(evaluator, :erlang, code, :code_1, [], file: "file.ex")
|
Evaluator.evaluate_code(evaluator, :erlang, code, :code_1, [], file: "file.ex")
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue