Skip to content

Commit

Permalink
Merge pull request #1237 from bettio/increase-elixir-support
Browse files Browse the repository at this point in the history
Increase Elixir support

Increases Elixir support by adding support to Enumerable and Collectable
protocols, and to a number of Exceptions.

Fixes #1174

These changes are made under both the "Apache 2.0" and the "GNU Lesser General
Public License 2.1 or later" license terms (dual license).

SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
  • Loading branch information
bettio committed Aug 15, 2024
2 parents 2c0f5d0 + 0b9591f commit abf59d8
Show file tree
Hide file tree
Showing 41 changed files with 3,535 additions and 0 deletions.
10 changes: 10 additions & 0 deletions .github/workflows/build-and-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,16 @@ jobs:
./src/AtomVM ./tests/libs/alisp/test_alisp.avm
valgrind ./src/AtomVM ./tests/libs/alisp/test_alisp.avm
- name: "Test: Tests.avm (Elixir)"
timeout-minutes: 10
working-directory: build
run: |
if command -v elixirc &> /dev/null
then
./src/AtomVM ./tests/libs/exavmlib/Tests.avm
valgrind ./src/AtomVM ./tests/libs/exavmlib/Tests.avm
fi
- name: "Install and smoke test"
working-directory: build
run: |
Expand Down
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Implement `gpio:init/1` on esp32 to initialize pins for GPIO usage, which some pins
require depending on default function and bootloader code
- Implement missing opcode 161 (raw_raise), that looks more likely to be generated with Elixir code
- Support for Elixir `Map.replace/3` and `Map.replace!/3`
- Support for Elixir `Kernel.struct` and `Kernel.struct!`
- Support for Elixir `IO.iodata_to_binary/1`
- Support for Elixir exceptions: `Exception` module and the other error related modules such as
`ArgumentError`, `UndefinedFunctionError`, etc...
- Support for Elixir `Enumerable` and `Collectable` protocol
- Support for Elixir `Enum` functions: `split_with`, `join`, `map_join`, `into`, `reverse`,
`slice` and `to_list`
- Support for Elixir `MapSet` module
- Support for Elixir `Range` module
- Support for Elixir `Kernel.min` and `Kernel.max`

## [0.6.3] - 20-07-2024

Expand Down
27 changes: 27 additions & 0 deletions libs/exavmlib/lib/ArgumentError.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#
# This file is part of elixir-lang.
#
# Copyright 2012-2018 Elixir Contributors
# https://github.com/elixir-lang/elixir/tree/v1.7.4/lib/elixir/lib/exception.ex
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#

defmodule ArgumentError do
# This avoids crashing the compiler at build time
@compile {:autoload, false}

defexception message: "argument error"
end
27 changes: 27 additions & 0 deletions libs/exavmlib/lib/ArithmeticError.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#
# This file is part of elixir-lang.
#
# Copyright 2012-2018 Elixir Contributors
# https://github.com/elixir-lang/elixir/tree/v1.7.4/lib/elixir/lib/exception.ex
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#

defmodule ArithmeticError do
# This avoids crashing the compiler at build time
@compile {:autoload, false}

defexception message: "bad argument in arithmetic expression"
end
42 changes: 42 additions & 0 deletions libs/exavmlib/lib/BadArityError.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#
# This file is part of elixir-lang.
#
# Copyright 2012-2018 Elixir Contributors
# https://github.com/elixir-lang/elixir/tree/v1.7.4/lib/elixir/lib/exception.ex
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#

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)
# TODO: enable as soon as :erlang.fun_info and Function.info are implemented
# {:arity, arity} = Function.info(fun, :arity)
# "#{inspect(fun)} with arity #{arity} called with #{count(length(args), insp)}"
"#{inspect(fun)} 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
32 changes: 32 additions & 0 deletions libs/exavmlib/lib/BadBooleanError.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#
# This file is part of elixir-lang.
#
# Copyright 2012-2018 Elixir Contributors
# https://github.com/elixir-lang/elixir/tree/v1.7.4/lib/elixir/lib/exception.ex
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#

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
32 changes: 32 additions & 0 deletions libs/exavmlib/lib/BadFunctionError.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#
# This file is part of elixir-lang.
#
# Copyright 2012-2018 Elixir Contributors
# https://github.com/elixir-lang/elixir/tree/v1.7.4/lib/elixir/lib/exception.ex
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#

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
32 changes: 32 additions & 0 deletions libs/exavmlib/lib/BadMapError.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#
# This file is part of elixir-lang.
#
# Copyright 2012-2018 Elixir Contributors
# https://github.com/elixir-lang/elixir/tree/v1.7.4/lib/elixir/lib/exception.ex
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#

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
32 changes: 32 additions & 0 deletions libs/exavmlib/lib/BadStructError.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#
# This file is part of elixir-lang.
#
# Copyright 2012-2018 Elixir Contributors
# https://github.com/elixir-lang/elixir/tree/v1.7.4/lib/elixir/lib/exception.ex
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#

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
33 changes: 33 additions & 0 deletions libs/exavmlib/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,47 @@ set(ELIXIR_MODULES
LEDC
Access
Enum
Enumerable
Enumerable.List
Enumerable.Map
Enumerable.MapSet
Enumerable.Range
Exception
IO
List
Map
MapSet
Module
Keyword
Kernel
Process
Protocol.UndefinedError
Range
Tuple

ArithmeticError
ArgumentError
BadFunctionError
BadStructError
RuntimeError
SystemLimitError
BadMapError
BadBooleanError
MatchError
CaseClauseError
WithClauseError
CondClauseError
TryClauseError
BadArityError
UndefinedFunctionError
FunctionClauseError
KeyError
ErlangError

Collectable
Collectable.List
Collectable.Map
Collectable.MapSet
)

pack_archive(exavmlib ${ELIXIR_MODULES})
32 changes: 32 additions & 0 deletions libs/exavmlib/lib/CaseClauseError.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#
# This file is part of elixir-lang.
#
# Copyright 2012-2018 Elixir Contributors
# https://github.com/elixir-lang/elixir/tree/v1.7.4/lib/elixir/lib/exception.ex
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#

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
32 changes: 32 additions & 0 deletions libs/exavmlib/lib/Collectable.List.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#
# This file is part of elixir-lang.
#
# Copyright 2012-2018 Elixir Contributors
# https://github.com/elixir-lang/elixir/commits/v1.7.4/lib/elixir/lib/collectable.ex
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#

defimpl Collectable, for: List do
def into(original) do
fun = fn
list, {:cont, x} -> [x | list]
list, :done -> original ++ :lists.reverse(list)
_, :halt -> :ok
end

{[], fun}
end
end
Loading

0 comments on commit abf59d8

Please sign in to comment.