From 7faa258df540362cb8ec7b1e4d6332c2551fd2b9 Mon Sep 17 00:00:00 2001 From: Paul Guyot Date: Sun, 22 Sep 2024 16:07:23 +0200 Subject: [PATCH] Add Elixir List.Chars protocol. https://github.com/elixir-lang/elixir/blob/v1.17.2/lib/elixir/lib/list/chars.ex Split into several source files because of how our CMakeLists.txt is built Signed-off-by: Paul Guyot --- CHANGELOG.md | 1 + libs/exavmlib/lib/CMakeLists.txt | 7 ++++ libs/exavmlib/lib/List.Chars.Atom.ex | 26 +++++++++++++++ libs/exavmlib/lib/List.Chars.BitString.ex | 36 +++++++++++++++++++++ libs/exavmlib/lib/List.Chars.Float.ex | 27 ++++++++++++++++ libs/exavmlib/lib/List.Chars.Integer.ex | 26 +++++++++++++++ libs/exavmlib/lib/List.Chars.List.ex | 25 +++++++++++++++ libs/exavmlib/lib/List.Chars.ex | 39 +++++++++++++++++++++++ 8 files changed, 187 insertions(+) create mode 100644 libs/exavmlib/lib/List.Chars.Atom.ex create mode 100644 libs/exavmlib/lib/List.Chars.BitString.ex create mode 100644 libs/exavmlib/lib/List.Chars.Float.ex create mode 100644 libs/exavmlib/lib/List.Chars.Integer.ex create mode 100644 libs/exavmlib/lib/List.Chars.List.ex create mode 100644 libs/exavmlib/lib/List.Chars.ex diff --git a/CHANGELOG.md b/CHANGELOG.md index 97522e883..da99ca8d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ also non string parameters (e.g. `Enum.join([1, 2], ",")` - Support for `lists:last/1` and `lists:mapfoldl/3` - Add support to Elixir for `Process.send/2` `Process.send_after/3/4` and `Process.cancel_timer/1` - Add support for `handle_continue` callback in `gen_server` +- Support for Elixir `List.Chars` protocol ### Changed diff --git a/libs/exavmlib/lib/CMakeLists.txt b/libs/exavmlib/lib/CMakeLists.txt index 70749cfef..c55498e80 100644 --- a/libs/exavmlib/lib/CMakeLists.txt +++ b/libs/exavmlib/lib/CMakeLists.txt @@ -75,6 +75,13 @@ set(ELIXIR_MODULES Collectable.Map Collectable.MapSet + List.Chars + List.Chars.Atom + List.Chars.BitString + List.Chars.Float + List.Chars.Integer + List.Chars.List + String.Chars String.Chars.Atom String.Chars.BitString diff --git a/libs/exavmlib/lib/List.Chars.Atom.ex b/libs/exavmlib/lib/List.Chars.Atom.ex new file mode 100644 index 000000000..e187e4992 --- /dev/null +++ b/libs/exavmlib/lib/List.Chars.Atom.ex @@ -0,0 +1,26 @@ +# +# This file is part of elixir-lang. +# +# Copyright 2013-2023 Elixir Contributors +# https://github.com/elixir-lang/elixir/commits/v1.17.2/lib/elixir/lib/list/chars.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 List.Chars, for: Atom do + def to_charlist(nil), do: ~c"" + + def to_charlist(atom), do: Atom.to_charlist(atom) +end diff --git a/libs/exavmlib/lib/List.Chars.BitString.ex b/libs/exavmlib/lib/List.Chars.BitString.ex new file mode 100644 index 000000000..53fb74d76 --- /dev/null +++ b/libs/exavmlib/lib/List.Chars.BitString.ex @@ -0,0 +1,36 @@ +# +# This file is part of elixir-lang. +# +# Copyright 2013-2023 Elixir Contributors +# https://github.com/elixir-lang/elixir/commits/v1.17.2/lib/elixir/lib/list/chars.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 List.Chars, for: BitString do + @doc """ + Returns the given binary `term` converted to a charlist. + """ + def to_charlist(term) when is_binary(term) do + String.to_charlist(term) + end + + def to_charlist(term) do + raise Protocol.UndefinedError, + protocol: @protocol, + value: term, + description: "cannot convert a bitstring to a charlist" + end +end diff --git a/libs/exavmlib/lib/List.Chars.Float.ex b/libs/exavmlib/lib/List.Chars.Float.ex new file mode 100644 index 000000000..5331b88a7 --- /dev/null +++ b/libs/exavmlib/lib/List.Chars.Float.ex @@ -0,0 +1,27 @@ +# +# This file is part of elixir-lang. +# +# Copyright 2013-2023 Elixir Contributors +# https://github.com/elixir-lang/elixir/commits/v1.17.2/lib/elixir/lib/list/chars.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 List.Chars, for: Float do + def to_charlist(term) do + # TODO: :short option not yet supported right now, so :decimals+:compact should be replaced + :erlang.float_to_list(term, [{:decimals, 17}, :compact]) + end +end diff --git a/libs/exavmlib/lib/List.Chars.Integer.ex b/libs/exavmlib/lib/List.Chars.Integer.ex new file mode 100644 index 000000000..74f8dfa86 --- /dev/null +++ b/libs/exavmlib/lib/List.Chars.Integer.ex @@ -0,0 +1,26 @@ +# +# This file is part of elixir-lang. +# +# Copyright 2013-2023 Elixir Contributors +# https://github.com/elixir-lang/elixir/commits/v1.17.2/lib/elixir/lib/list/chars.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 List.Chars, for: Integer do + def to_charlist(term) do + Integer.to_charlist(term) + end +end diff --git a/libs/exavmlib/lib/List.Chars.List.ex b/libs/exavmlib/lib/List.Chars.List.ex new file mode 100644 index 000000000..bb666bbaf --- /dev/null +++ b/libs/exavmlib/lib/List.Chars.List.ex @@ -0,0 +1,25 @@ +# +# This file is part of elixir-lang. +# +# Copyright 2013-2023 Elixir Contributors +# https://github.com/elixir-lang/elixir/commits/v1.17.2/lib/elixir/lib/list/chars.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 List.Chars, for: List do + # Note that same inlining is used for the rewrite rule. + def to_charlist(list), do: list +end diff --git a/libs/exavmlib/lib/List.Chars.ex b/libs/exavmlib/lib/List.Chars.ex new file mode 100644 index 000000000..a2dafa7ca --- /dev/null +++ b/libs/exavmlib/lib/List.Chars.ex @@ -0,0 +1,39 @@ +# +# This file is part of elixir-lang. +# +# Copyright 2013-2023 Elixir Contributors +# https://github.com/elixir-lang/elixir/commits/v1.17.2/lib/elixir/lib/list/chars.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 +# + +defprotocol List.Chars do + @moduledoc ~S""" + The `List.Chars` protocol is responsible for + converting a structure to a charlist (only if applicable). + + The only function that must be implemented is + `to_charlist/1` which does the conversion. + + The `to_charlist/1` function automatically imported + by `Kernel` invokes this protocol. + """ + + @doc """ + Converts `term` to a charlist. + """ + @spec to_charlist(t) :: charlist + def to_charlist(term) +end