74 lines
2.2 KiB
Elixir
74 lines
2.2 KiB
Elixir
import Kernel, except: [destructure: 2, defdelegate: 2, defstruct: 2]
|
|
|
|
defmodule Kernel.Utils do
|
|
@moduledoc false
|
|
|
|
def destructure(list, count) when is_list(list), do: destructure_list(list, count)
|
|
def destructure(nil, count), do: destructure_nil(count)
|
|
|
|
defp destructure_list(_, 0), do: []
|
|
defp destructure_list([], count), do: destructure_nil(count)
|
|
defp destructure_list([h|t], count), do: [h|destructure_list(t, count - 1)]
|
|
|
|
defp destructure_nil(0), do: []
|
|
defp destructure_nil(count), do: [nil|destructure_nil(count - 1)]
|
|
|
|
def defdelegate(fun, opts, env) do
|
|
append_first = Keyword.get(opts, :append_first, false)
|
|
|
|
{name, args} =
|
|
case Macro.decompose_call(fun) do
|
|
{_, _} = pair -> pair
|
|
_ -> raise ArgumentError, "invalid syntax in defdelegate #{Macro.to_string(fun)}"
|
|
end
|
|
|
|
:ok = check_defdelegate_args(args, env)
|
|
|
|
as_args =
|
|
case append_first and args != [] do
|
|
true -> tl(args) ++ [hd(args)]
|
|
false -> args
|
|
end
|
|
|
|
as = Keyword.get(opts, :as, name)
|
|
{name, args, as, as_args}
|
|
end
|
|
|
|
# TODO: Convert this to an error on 1.3
|
|
defp check_defdelegate_args([], _env),
|
|
do: :ok
|
|
defp check_defdelegate_args([{var, _, mod}|rest], env) when is_atom(var) and is_atom(mod),
|
|
do: check_defdelegate_args(rest, env)
|
|
defp check_defdelegate_args([code|_], env) do
|
|
:elixir_errors.warn(env.line, env.file,
|
|
"defdelegate/2 will only accept variable names in upcoming versions, " <>
|
|
"got: #{Macro.to_string(code)}")
|
|
end
|
|
|
|
def defstruct(module, fields) do
|
|
case fields do
|
|
fs when is_list(fs) -> :ok
|
|
other ->
|
|
raise ArgumentError, "struct fields definition must be list, got: #{inspect other}"
|
|
end
|
|
|
|
fields = :lists.map(fn
|
|
{key, val} when is_atom(key) ->
|
|
try do
|
|
Macro.escape(val)
|
|
rescue
|
|
e in [ArgumentError] ->
|
|
raise ArgumentError, "invalid value for struct field #{key}, " <> Exception.message(e)
|
|
else
|
|
_ -> {key, val}
|
|
end
|
|
key when is_atom(key) ->
|
|
{key, nil}
|
|
other ->
|
|
raise ArgumentError, "struct field names must be atoms, got: #{inspect other}"
|
|
end, fields)
|
|
|
|
:maps.put(:__struct__, module, :maps.from_list(fields))
|
|
end
|
|
end
|