Skip to content

Commit

Permalink
Elixir library: add Exception and a number of Errors
Browse files Browse the repository at this point in the history
Code has been taken from:
https://github.com/elixir-lang/elixir/tree/v1.7.4/lib/elixir/lib

Signed-off-by: Davide Bettio <davide@uninstall.it>
  • Loading branch information
bettio committed Aug 3, 2024
1 parent c9220bb commit 7a07499
Show file tree
Hide file tree
Showing 19 changed files with 1,056 additions and 0 deletions.
40 changes: 40 additions & 0 deletions libs/exavmlib/lib/ArgumentError.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
defmodule ArgumentError do
# This avoids crashing the compiler at build time
@compile {:autoload, false}

defexception message: "argument error"

@impl true
def blame(
%{message: "argument error"} = exception,
[{:erlang, :apply, [module, function, args], _} | _] = stacktrace
) do
message =
cond do
# Note that args may be an empty list even if they were supplied
not is_atom(module) and is_atom(function) and args == [] ->
"you attempted to apply #{inspect(function)} on #{inspect(module)}. " <>
"If you are using apply/3, make sure the module is an atom. " <>
"If you are using the dot syntax, such as map.field or module.function, " <>
"make sure the left side of the dot is an atom or a map"

not is_atom(module) ->
"you attempted to apply a function on #{inspect(module)}. " <>
"Modules (the first argument of apply) must always be an atom"

not is_atom(function) ->
"you attempted to apply #{inspect(function)} on module #{inspect(module)}. " <>
"Functions (the second argument of apply) must always be an atom"

not is_list(args) ->
"you attempted to apply #{inspect(function)} on module #{inspect(module)} " <>
"with arguments #{inspect(args)}. Arguments (the third argument of apply) must always be a list"
end

{%{exception | message: message}, stacktrace}
end

def blame(exception, stacktrace) do
{exception, stacktrace}
end
end
42 changes: 42 additions & 0 deletions libs/exavmlib/lib/ArithmeticError.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
defmodule ArithmeticError do
# This avoids crashing the compiler at build time
@compile {:autoload, false}

defexception message: "bad argument in arithmetic expression"

@unary_ops [:+, :-]
@binary_ops [:+, :-, :*, :/]
@binary_funs [:div, :rem]
@bitwise_binary_funs [:band, :bor, :bxor, :bsl, :bsr]

@impl true
def blame(%{message: message} = exception, [{:erlang, fun, args, _} | _] = stacktrace) do
message =
message <>
case {fun, args} do
{op, [a]} when op in @unary_ops ->
": #{op}(#{inspect(a)})"

{op, [a, b]} when op in @binary_ops ->
": #{inspect(a)} #{op} #{inspect(b)}"

{fun, [a, b]} when fun in @binary_funs ->
": #{fun}(#{inspect(a)}, #{inspect(b)})"

{fun, [a, b]} when fun in @bitwise_binary_funs ->
": Bitwise.#{fun}(#{inspect(a)}, #{inspect(b)})"

{:bnot, [a]} ->
": Bitwise.bnot(#{inspect(a)})"

_ ->
""
end

{%{exception | message: message}, stacktrace}
end

def blame(exception, stacktrace) do
{exception, stacktrace}
end
end
19 changes: 19 additions & 0 deletions libs/exavmlib/lib/BadArityError.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
defmodule BadArityError do
# This avoids crashing the compiler at build time
@compile {:autoload, false}

defexception [:function, :args]

@impl true
def message(exception) do
fun = exception.function
args = exception.args
insp = Enum.map_join(args, ", ", &inspect/1)
{:arity, arity} = Function.info(fun, :arity)
"#{inspect(fun)} with arity #{arity} called with #{count(length(args), insp)}"
end

defp count(0, _insp), do: "no arguments"
defp count(1, insp), do: "1 argument (#{insp})"
defp count(x, insp), do: "#{x} arguments (#{insp})"
end
11 changes: 11 additions & 0 deletions libs/exavmlib/lib/BadBooleanError.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
defmodule BadBooleanError do
# This avoids crashing the compiler at build time
@compile {:autoload, false}

defexception [:term, :operator]

@impl true
def message(exception) do
"expected a boolean on left-side of \"#{exception.operator}\", got: #{inspect(exception.term)}"
end
end
11 changes: 11 additions & 0 deletions libs/exavmlib/lib/BadFunctionError.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
defmodule BadFunctionError do
# This avoids crashing the compiler at build time
@compile {:autoload, false}

defexception [:term]

@impl true
def message(exception) do
"expected a function, got: #{inspect(exception.term)}"
end
end
11 changes: 11 additions & 0 deletions libs/exavmlib/lib/BadMapError.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
defmodule BadMapError do
# This avoids crashing the compiler at build time
@compile {:autoload, false}

defexception [:term]

@impl true
def message(exception) do
"expected a map, got: #{inspect(exception.term)}"
end
end
11 changes: 11 additions & 0 deletions libs/exavmlib/lib/BadStructError.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
defmodule BadStructError do
# This avoids crashing the compiler at build time
@compile {:autoload, false}

defexception [:struct, :term]

@impl true
def message(exception) do
"expected a struct named #{inspect(exception.struct)}, got: #{inspect(exception.term)}"
end
end
23 changes: 23 additions & 0 deletions libs/exavmlib/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ set(ELIXIR_MODULES
LEDC
Access
Enum
Exception
IO
List
Map
Expand All @@ -41,6 +42,28 @@ set(ELIXIR_MODULES
Kernel
Process
Tuple

ArithmeticError
ArgumentError
BadFunctionError
BadStructError
RuntimeError
SystemLimitError

BadMapError
BadBooleanError
MatchError
CaseClauseError
WithClauseError
CondClauseError

TryClauseError
BadArityError
UndefinedFunctionError
FunctionClauseError
KeyError

ErlangError
)

pack_archive(exavmlib ${ELIXIR_MODULES})
11 changes: 11 additions & 0 deletions libs/exavmlib/lib/CaseClauseError.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
defmodule CaseClauseError do
# This avoids crashing the compiler at build time
@compile {:autoload, false}

defexception [:term]

@impl true
def message(exception) do
"no case clause matching: #{inspect(exception.term)}"
end
end
11 changes: 11 additions & 0 deletions libs/exavmlib/lib/CondClauseError.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
defmodule CondClauseError do
# This avoids crashing the compiler at build time
@compile {:autoload, false}

defexception []

@impl true
def message(_exception) do
"no cond clause evaluated to a true value"
end
end
Loading

0 comments on commit 7a07499

Please sign in to comment.