Skip to content

Commit

Permalink
Better error messages for undefined functions when loading scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
davydog187 committed Mar 14, 2024
1 parent c880da9 commit 8c15b93
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 32 deletions.
3 changes: 3 additions & 0 deletions lib/lua.ex
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,9 @@ defmodule Lua do
{:ok, [], state} ->
%__MODULE__{lua | state: state}

{:lua_error, _error, _lua} = error ->
raise Lua.CompilerException, error

:error ->
raise "Cannot load lua file, #{inspect(path <> ".lua")} does not exist"
end
Expand Down
21 changes: 20 additions & 1 deletion lib/lua/compiler_exception.ex
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
defmodule Lua.CompilerException do
defexception [:message]

def exception(data) do
alias Lua.Util

def exception({:lua_error, error, state}) do
stacktrace = Luerl.New.get_stacktrace(state)

message = """
Failed to compile Lua script: #{Util.format_error(error)}
#{Util.format_stacktrace(stacktrace, state)}
"""

%__MODULE__{message: message}
end

def exception(data) when is_list(data) do
message =
data
|> Keyword.fetch!(:reason)
Expand All @@ -12,6 +26,11 @@ defmodule Lua.CompilerException do
%__MODULE__{message: "Failed to compile Lua script\n\n#{message}\n"}
end

def exception(shit) do
dbg(shit)
%__MODULE__{}
end

defp format_error(:luerl_parse), do: "failed to parse"
defp format_error(:luerl_scan), do: "failed to tokenize"

Expand Down
30 changes: 1 addition & 29 deletions lib/lua/runtime_exception.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,7 @@ defmodule Lua.RuntimeException do

@impl true
def exception({:lua_error, error, state}) do
message =
case error do
{:error_call, message} ->
Util.format_function("error", message)

{:undefined_function, nil} ->
"undefined function"

{:undefined_function, "sandboxed"} ->
"sandboxed function"

{:undefined_function, ref} ->
"undefined function #{inspect(ref)}"

{:undefined_method, nil, name} ->
"undefined method #{inspect(name)}"

{:illegal_index, _, name} ->
"invalid index #{inspect(name)}"

{:badarith, operator, values} ->
expression = values |> Enum.map(&to_string/1) |> Enum.join(" #{operator} ")

"bad arithmetic #{expression}"

error ->
"unknown error #{inspect(error)}"
end

message = Util.format_error(error)
stacktrace = Luerl.New.get_stacktrace(state)

%__MODULE__{
Expand Down
30 changes: 30 additions & 0 deletions lib/lua/util.ex
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,36 @@ defmodule Lua.Util do
|> Enum.sort(:asc)
end

def format_error(error) do
case error do
{:error_call, message} ->
format_function("error", message)

{:undefined_function, nil} ->
"undefined function"

{:undefined_function, "sandboxed"} ->
"sandboxed function"

{:undefined_function, ref} ->
"undefined function #{inspect(ref)}"

{:undefined_method, nil, name} ->
"undefined method #{inspect(name)}"

{:illegal_index, _, name} ->
"invalid index #{inspect(name)}"

{:badarith, operator, values} ->
expression = values |> Enum.map(&to_string/1) |> Enum.join(" #{operator} ")

"bad arithmetic #{expression}"

error ->
"unknown error #{inspect(error)}"
end
end

@doc """
Pretty prints a stack trace
"""
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/syntax_error.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
shisjg;alskdgjl''z'
1 change: 1 addition & 0 deletions test/fixtures/undefined_function.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bogus()
31 changes: 29 additions & 2 deletions test/lua_test.exs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
defmodule LuaTest do
use ExUnit.Case
use ExUnit.Case, async: true

alias Lua

Expand All @@ -24,7 +24,7 @@ defmodule LuaTest do

describe "load_lua_file/2" do
test "loads the lua file into the state" do
path = Path.join(["test", "fixtures", "test_api"])
path = test_file("test_api")

assert lua = Lua.load_lua_file!(Lua.new(), path)

Expand All @@ -34,6 +34,29 @@ defmodule LuaTest do
""")
end

@tag :skip
test "loading files with syntax errors returns an error" do
path = test_file("syntax_error")

assert_raise Lua.CompilerException, fn ->
Lua.load_lua_file!(Lua.new(), path)
end
end

test "loading files with undefined functions returns an error" do
path = test_file("undefined_function")

error = """
Failed to compile Lua script: undefined function
script line 1: <unknown function>()
"""

assert_raise Lua.CompilerException, error, fn ->
Lua.load_lua_file!(Lua.new(), path)
end
end

test "non-existent files are not loaded" do
assert_raise RuntimeError, "Cannot load lua file, \"bananas.lua\" does not exist", fn ->
Lua.load_lua_file!(Lua.new(), "bananas")
Expand Down Expand Up @@ -468,4 +491,8 @@ defmodule LuaTest do
end
end
end

defp test_file(name) do
Path.join(["test", "fixtures", name])
end
end

0 comments on commit 8c15b93

Please sign in to comment.