Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

String.slice(str, 0, -1) raises FunctionClauseError #496

Open
beadsland opened this issue Aug 1, 2020 · 1 comment
Open

String.slice(str, 0, -1) raises FunctionClauseError #496

beadsland opened this issue Aug 1, 2020 · 1 comment

Comments

@beadsland
Copy link

beadsland commented Aug 1, 2020

This snippet of Elixir:

String.slice(str, 0, -1)

Started with slice/2 form of this call, but swapped to slice/3 to confirm the error wasn't being generated by the Elixir range.

Raises the following exception

** (EXIT from #PID<0.95.0>) an exception was raised:
** (FunctionClauseError) no function clause matching in ElixirScript.Translate.Form.compile/2
lib/elixir_script/passes/translate/form.ex:28: ElixirScript.Translate.Form.compile(&Inspect.inspect/2, %{anonymous_fn: false, function: {:struct, nil}, in_guard: false, module: Inspect.Opts, pid: #PID<0.200.0>, vars: %{}})
lib/elixir_script/passes/translate/form.ex:16: ElixirScript.Translate.Form.compile!/2
lib/elixir_script/passes/translate/forms/map.ex:37: anonymous fn/2 in ElixirScript.Translate.Forms.Map.compile/2
(elixir 1.10.4) lib/enum.ex:1396: Enum."-map/2-lists^map/1-0-"/2
(elixir 1.10.4) lib/enum.ex:1396: Enum."-map/2-lists^map/1-0-"/2
lib/elixir_script/passes/translate/forms/map.ex:32: ElixirScript.Translate.Forms.Map.compile/2
lib/elixir_script/passes/translate/form.ex:16: ElixirScript.Translate.Form.compile!/2
lib/elixir_script/passes/translate/function.ex:170: ElixirScript.Translate.Function.compile_block/2

Modified Transcript.Form.compile! as follows:

  @spec compile!(any, map) :: ESTree.Node.t()
  def compile!(ast, state) do
    {js_ast, _} = compile(ast, state)
    js_ast
  rescue
    e -> Logger.debug inspect({:compile!, ast, state})
         raise RuntimeError, message: inspect({"compile!/2", e})
  end

Which revealed the following debugging info:

03:45:21.580 [debug] {:compile!, &Inspect.inspect/2, %{anonymous_fn: false, function: {:struct, nil}, in_guard: false, module: Inspect.Opts, pid: #PID<0.200.0>, vars: %{}}}

03:45:21.696 [debug] {:compile!, {:%{}, [line: 74], [struct: Inspect.Opts, base: :decimal, binaries: :infer, char_lists: :infer, charlists: :infer, custom_options: [], inspect_fun: &Inspect.inspect/2, limit: 50, pretty: false, printable_limit: 4096, safe: true, structs: true, syntax_colors: [], width: 80]}, %{anonymous_fn: false, function: {:struct, nil}, in_guard: false, module: Inspect.Opts, pid: #PID<0.200.0>, vars: %{}}}

Thoughts

Not too familiar with this codebase, but I'm working from the premise that inspect_fun: &Inspect.inspect/2 might be malformed, for it to be promoted into the ast parameter of compile!.

@beadsland
Copy link
Author

beadsland commented Aug 1, 2020

Trying to build out same functionality without library function String.slice/2:

path = to_charlist str

Hit same error condition:

** (EXIT from #PID<0.95.0>) an exception was raised:
** (RuntimeError) {"compile!/2", %RuntimeError{message: "{"compile!/2", %FunctionClauseError{args: nil, arity: 2, clauses: nil, function: :compile, kind: nil, module: ElixirScript.Translate.Form}}"}}
lib/elixir_script/passes/translate/form.ex:19: ElixirScript.Translate.Form.compile!/2
lib/elixir_script/passes/translate/function.ex:170: ElixirScript.Translate.Function.compile_block/2
lib/elixir_script/passes/translate/function.ex:138: ElixirScript.Translate.Function.compile_clause/2
(elixir 1.10.4) lib/enum.ex:1396: Enum."-map/2-lists^map/1-0-"/2
lib/elixir_script/passes/translate/function.ex:100: ElixirScript.Translate.Function.compile_clauses/2
lib/elixir_script/passes/translate/function.ex:60: ElixirScript.Translate.Function.compile/2
(elixir 1.10.4) lib/enum.ex:1520: Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3
lib/elixir_script/passes/translate/module.ex:98: ElixirScript.Translate.Module.compile/3

With similar debug values:

06:15:24.282 [debug] {:compile!, &Inspect.inspect/2, %{anonymous_fn: false, function: {:struct, nil}, in_guard: false, module: Inspect.Opts, pid: #PID<0.166.0>, vars: %{}}}

06:15:24.336 [debug] {:compile!, {:%{}, [line: 74], [struct: Inspect.Opts, base: :decimal, binaries: :infer, char_lists: :infer, charlists: :infer, custom_options: [], inspect_fun: &Inspect.inspect/2, limit: 50, pretty: false, printable_limit: 4096, safe: true, structs: true, syntax_colors: [], width: 80]}, %{anonymous_fn: false, function: {:struct, nil}, in_guard: false, module: Inspect.Opts, pid: #PID<0.166.0>, vars: %{}}}

Breaking it down:

So, reducing it to bare necessary expression to break ElixirScript:

to_charlist "abc"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant