Skip to content

Commit

Permalink
Forward port changes from v0.6 release branch
Browse files Browse the repository at this point in the history
Merge into main a number of changes, such as fixes and libraries
improvements, aimed to enabling Erlang and Elixir REPL on a browser.
  • Loading branch information
bettio committed Oct 1, 2024
2 parents 22c0da4 + 7d63dc0 commit 1bedd1c
Show file tree
Hide file tree
Showing 37 changed files with 14,506 additions and 87 deletions.
14 changes: 13 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,31 @@ also non string parameters (e.g. `Enum.join([1, 2], ",")`
- Add support for `handle_continue` callback in `gen_server`
- Support for Elixir `List.Chars` protocol
- Support for `gen_server:start_monitor/3,4`
- Support for `code:ensure_loaded/1`
- Support for `io_lib:latin1_char_list/1`
- Add support to Elixir for `Keyword.split/2`
- Support for `binary:split/3` and `string:find/2,3`
- Support for large tuples (more than 255 elements) in external terms.
- Support for `io:put_chars/2`
- Support for `lists:nthtail/2`
- Support for Elixir `IO.chardata_to_string/1`
- Support for Elixir `List.duplicate/2`
- Support for `binary:copy/1,2`

### Changed

- ESP32: Elixir library is not shipped anymore with `esp32boot.avm`. Use `elixir_esp32boot.avm`
instead
- `Enum.find_index` and `Enum.find_value` support Enumerable and not just lists
- Install AtomVM libraries source code and binaries for better dialyzer integration
- Made the `device_config` properties list in `spi:open/1` optional (defaults to `[]`), so you can use the function with only a `bus_config`

### Fixed

- ESP32: content of `boot.avm` partition is not truncated anymore
- ESP32: `Fixed gpio:set_int` to accept any pin, not only pin 2
- Fix memory corruption in `unicode:characters_to_binary`
- Fix handling of large literal indexes
- Fix handling of large literal indexes and large extended literal indexes
- `unicode:characters_to_list`: fixed bogus out_of_memory error on some platforms such as ESP32
- Fix crash in Elixir library when doing `inspect(:atom)`
- General inspect() compliance with Elixir behavior (but there are still some minor differences)
Expand Down
4 changes: 2 additions & 2 deletions doc/src/programmers-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -1531,10 +1531,10 @@ The [`spi` module](./apidocs/erlang/eavmlib/spi.md) encapsulates functionality a
Information about the ESP32 SPI leader mode interface can be found in the IDF SDK [SPI Documentation](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/spi_master.html).
```
The AtomVM SPI implementation uses the AtomVM Port mechanism and must be initialized using the [`spi:open/1`](./apidocs/erlang/eavmlib/spi.md#open1) function. The single parameter to this function is a properties list containing two elements:
The AtomVM SPI implementation uses the AtomVM Port mechanism and must be initialized using the [`spi:open/1`](./apidocs/erlang/eavmlib/spi.md#open1) function. The single parameter to this function is a properties list containing:
* [`bus_config`](./apidocs/erlang/eavmlib/spi.md#bus_config) -- a properties list containing entries for the SPI bus
* [`device_config`](./apidocs/erlang/eavmlib/spi.md#device_config) -- a properties list containing entries for each device attached to the SPI Bus
* [`device_config`](./apidocs/erlang/eavmlib/spi.md#device_config) -- an optional properties list containing entries for each device attached to the SPI Bus
The `bus_config` properties list contains the following entries:
Expand Down
21 changes: 21 additions & 0 deletions libs/alisp/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,24 @@ set(ERLANG_MODULES
)

pack_archive(alisp ${ERLANG_MODULES})

include(../../../version.cmake)

set(ALISP_VERSION ${ATOMVM_BASE_VERSION})

install(
DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/beams/
DESTINATION lib/atomvm/lib/alisp-${ALISP_VERSION}/ebin
FILES_MATCHING PATTERN "*.beam"
)

install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/alisp.avm
DESTINATION lib/atomvm/lib/alisp-${ALISP_VERSION}/ebin/
)

install(
DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/
DESTINATION lib/atomvm/lib/alisp-${ALISP_VERSION}/src
FILES_MATCHING PATTERN "*.erl"
)
21 changes: 21 additions & 0 deletions libs/eavmlib/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,24 @@ set(ERLANG_MODULES
)

pack_archive(eavmlib ${ERLANG_MODULES})

include(../../../version.cmake)

set(EAVMLIB_VERSION ${ATOMVM_BASE_VERSION})

install(
DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/beams/
DESTINATION lib/atomvm/lib/eavmlib-${EAVMLIB_VERSION}/ebin
FILES_MATCHING PATTERN "*.beam"
)

install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/eavmlib.avm
DESTINATION lib/atomvm/lib/eavmlib-${EAVMLIB_VERSION}/ebin/
)

install(
DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/
DESTINATION lib/atomvm/lib/eavmlib-${EAVMLIB_VERSION}/src
FILES_MATCHING PATTERN "*.erl"
)
14 changes: 9 additions & 5 deletions libs/eavmlib/src/spi.erl
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,14 @@
| {command_len_bits, 0..16}
].
-type device_name() :: atom().
-type params() :: [
{bus_config, bus_config()}
| {device_config, [{device_name(), device_config()}]}
].
-type params() ::
[
{bus_config, bus_config()}
]
| [
{bus_config, bus_config()}
| {device_config, [{device_name(), device_config()}]}
].

-type spi() :: pid().
-type address() :: non_neg_integer().
Expand Down Expand Up @@ -294,7 +298,7 @@ write_read(SPI, DeviceName, Transaction) when
validate_params(Params) when is_map(Params) orelse is_list(Params) ->
#{
bus_config => validate_bus_config(get_value(bus_config, Params, undefined)),
device_config => validate_device_config(get_value(device_config, Params, undefined))
device_config => validate_device_config(get_value(device_config, Params, []))
};
validate_params(Params) ->
throw({error, {not_a_map_or_list, Params}}).
Expand Down
21 changes: 21 additions & 0 deletions libs/esp32devmode/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,24 @@ project(esp32devmode)
include(BuildErlang)

pack_archive(esp32devmode esp32devmode)

include(../../../version.cmake)

set(ESP32DEVMODE_VERSION ${ATOMVM_BASE_VERSION})

install(
DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/beams/
DESTINATION lib/atomvm/lib/esp32devmode-${ESP32DEVMODE_VERSION}/ebin
FILES_MATCHING PATTERN "*.beam"
)

install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/esp32devmode.avm
DESTINATION lib/atomvm/lib/esp32devmode-${ESP32DEVMODE_VERSION}/ebin/
)

install(
DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/
DESTINATION lib/atomvm/lib/esp32devmode-${ESP32DEVMODE_VERSION}/src
FILES_MATCHING PATTERN "*.erl"
)
21 changes: 21 additions & 0 deletions libs/estdlib/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,24 @@ set(ERLANG_MODULES
)

pack_archive(estdlib ${ERLANG_MODULES})

include(../../../version.cmake)

set(ESTDLIB_VERSION ${ATOMVM_BASE_VERSION})

install(
DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/beams/
DESTINATION lib/atomvm/lib/estdlib-${ESTDLIB_VERSION}/ebin
FILES_MATCHING PATTERN "*.beam"
)

install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/estdlib.avm
DESTINATION lib/atomvm/lib/estdlib-${ESTDLIB_VERSION}/ebin/
)

install(
DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/
DESTINATION lib/atomvm/lib/estdlib-${ESTDLIB_VERSION}/src
FILES_MATCHING PATTERN "*.erl"
)
18 changes: 17 additions & 1 deletion libs/estdlib/src/binary.erl
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
%%-----------------------------------------------------------------------------
-module(binary).

-export([at/2, part/3, split/2]).
-export([at/2, part/3, split/2, split/3]).

%%-----------------------------------------------------------------------------
%% @param Binary binary to get a byte from
Expand All @@ -51,6 +51,7 @@ part(_Binary, _Pos, _Len) ->
erlang:nif_error(undefined).

%%-----------------------------------------------------------------------------
%% @equiv split(Binary, Pattern, [])
%% @param Binary binary to split
%% @param Pattern pattern to perform the split
%% @return a list composed of one or two binaries
Expand All @@ -62,3 +63,18 @@ part(_Binary, _Pos, _Len) ->
-spec split(Binary :: binary(), Pattern :: binary()) -> [binary()].
split(_Binary, _Pattern) ->
erlang:nif_error(undefined).

%%-----------------------------------------------------------------------------
%% @param Binary binary to split
%% @param Pattern pattern to perform the split
%% @param Options options for the split
%% @return a list composed of one or two binaries
%% @doc Split a binary according to pattern.
%% If pattern is not found, returns a singleton list with the passed binary.
%% Unlike Erlang/OTP, pattern must be a binary.
%% Only implemented option is `global'
%% @end
%%-----------------------------------------------------------------------------
-spec split(Binary :: binary(), Pattern :: binary(), Option :: [global]) -> [binary()].
split(_Binary, _Pattern, _Option) ->
erlang:nif_error(undefined).
18 changes: 17 additions & 1 deletion libs/estdlib/src/code.erl
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
all_available/0,
all_loaded/0,
load_abs/1,
load_binary/3
load_binary/3,
ensure_loaded/1
]).

%%-----------------------------------------------------------------------------
Expand Down Expand Up @@ -82,3 +83,18 @@ load_abs(_Filename) ->
error | {module, module()}.
load_binary(_Module, _Filename, _Binary) ->
erlang:nif_error(undefined).

%%-----------------------------------------------------------------------------
%% @param Module module to load
%% @returns Tuple `{module, Module}' if module is loaded or `{error, embedded}'
%% @doc Try to load a module if it's not already loaded. AtomVM works in
%% an embedded-like mode where modules are loaded at start-up but modules
%% can be loaded explicitely as well (especially from a binary with `load_binary/3').
%% So this function can be used to determine if a module is loaded.
%% It is called by Elixir Code module.
%% @end
%%-----------------------------------------------------------------------------
-spec ensure_loaded(Module) -> {module, Module} | {error, embedded | any()} when
Module :: atom().
ensure_loaded(_Module) ->
erlang:nif_error(undefined).
14 changes: 13 additions & 1 deletion libs/estdlib/src/io.erl
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
%%-----------------------------------------------------------------------------
-module(io).

-export([format/1, format/2, get_line/1, put_chars/1]).
-export([format/1, format/2, get_line/1, put_chars/1, put_chars/2]).

%%-----------------------------------------------------------------------------
%% @doc Equivalent to format(Format, []).
Expand Down Expand Up @@ -96,3 +96,15 @@ put_chars(Chars) ->
{io_reply, Ref, Line} -> Line
end
end.

%%-----------------------------------------------------------------------------
%% @param Chars character(s) to write to console
%% @returns ok
%% @doc Writes the given character(s) to the console.
%% @end
%%-----------------------------------------------------------------------------
-spec put_chars(Device :: any(), Chars :: list() | binary()) -> ok.
put_chars(standard_error, Chars) ->
put_chars(Chars);
put_chars(standard_output, Chars) ->
put_chars(Chars).
16 changes: 15 additions & 1 deletion libs/estdlib/src/io_lib.erl
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
%%-----------------------------------------------------------------------------
-module(io_lib).

-export([format/2]).
-export([format/2, latin1_char_list/1]).

%%-----------------------------------------------------------------------------
%% @param Format format string
Expand All @@ -50,6 +50,20 @@ format(Format, Args) ->
error(badarg)
end.

%%-----------------------------------------------------------------------------
%% @param Term term to test
%% @returns true if Term is a list of latin1 characters, false otherwise.
%% @doc Determine if passed term is a list of ISO-8859-1 characters (0-255).
%% @end
%%-----------------------------------------------------------------------------
-spec latin1_char_list(Term :: any()) -> boolean().
latin1_char_list([H | T]) when is_integer(H) andalso H >= 0 andalso H =< 255 ->
latin1_char_list(T);
latin1_char_list([]) ->
true;
latin1_char_list(_) ->
false.

%%
%% internal operations
%%
Expand Down
17 changes: 17 additions & 0 deletions libs/estdlib/src/lists.erl
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
-export([
map/2,
nth/2,
nthtail/2,
last/1,
member/2,
delete/2,
Expand Down Expand Up @@ -92,6 +93,22 @@ nth(1, [H | _T]) ->
nth(Index, [_H | T]) when Index > 1 ->
nth(Index - 1, T).

%%-----------------------------------------------------------------------------
%% @param N the index to start the sublist from
%% @param L the list from which to extract a tail
%% @returns a sublist of list starting from position N.
%% @doc Get the sublist of list L starting after the element N.
%%
%% The behavior of this function is undefined if N is outside of the
%% {0..length(L)}.
%% @end
%%-----------------------------------------------------------------------------
-spec nthtail(N :: non_neg_integer(), L :: list()) -> list().
nthtail(0, L) when is_list(L) ->
L;
nthtail(N, [_H | T]) when is_integer(N) andalso N > 0 ->
nthtail(N - 1, T).

%%-----------------------------------------------------------------------------
%% @param L the proper list from which to get the last item
%% @returns the last item of the list.
Expand Down
Loading

0 comments on commit 1bedd1c

Please sign in to comment.