mirror of
				https://github.com/livebook-dev/livebook.git
				synced 2025-11-01 00:06:04 +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 | ||||
|     name | ||||
|     |> :erlang.atom_to_binary() | ||||
|     |> Macro.camelize() | ||||
|     |> toggle_var_case() | ||||
|     |> :erlang.binary_to_atom() | ||||
|   end | ||||
| 
 | ||||
|   defp erlang_to_elixir_var(name) do | ||||
|     name | ||||
|     |> :erlang.atom_to_binary() | ||||
|     |> Macro.underscore() | ||||
|     |> toggle_var_case() | ||||
|     |> :erlang.binary_to_atom() | ||||
|   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 | ||||
|     Enum.reject(code_markers, &(&1.line == 0)) | ||||
|   end | ||||
|  |  | |||
|  | @ -1268,6 +1268,48 @@ defmodule Livebook.Runtime.EvaluatorTest do | |||
|       assert [{:z, 1}, {:y, 1}, {:x, 1}] == binding | ||||
|     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 | ||||
|       code = ~S"#{x=>1}." | ||||
|       Evaluator.evaluate_code(evaluator, :erlang, code, :code_1, [], file: "file.ex") | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue