Files
n8n-openai-adapter/lib/elixir/src/elixir_def_defaults.erl
T

68 lines
2.4 KiB
Erlang

% Handle default clauses for function definitions.
-module(elixir_def_defaults).
-export([expand/2, unpack/4]).
-include("elixir.hrl").
expand(Args, E) ->
lists:mapfoldl(fun
({'\\\\', Meta, [Left, Right]}, Acc) ->
{ELeft, EL} = elixir_exp:expand(Left, Acc),
{ERight, _} = elixir_exp:expand(Right, Acc#{context := nil}),
{{'\\\\', Meta, [ELeft, ERight]}, EL};
(Left, Acc) ->
elixir_exp:expand(Left, Acc)
end, E, Args).
unpack(Kind, Name, Args, S) ->
unpack_each(Kind, Name, Args, [], [], S).
%% Helpers
%% Unpack default from given args.
%% Returns the given arguments without their default
%% clauses and a list of clauses for the default calls.
unpack_each(Kind, Name, [{'\\\\', Line, [Expr, _]}|T] = List, Acc, Clauses, S) ->
Base = build_match(Acc, Line, []),
{Args, Invoke} = extract_defaults(List, Line, length(Base), [], []),
{DefArgs, SA} = elixir_clauses:match(fun elixir_translator:translate_args/2, Base ++ Args, S),
{DefInvoke, _} = elixir_translator:translate_args(Base ++ Invoke, SA),
Call = {call, Line,
{atom, Line, name_for_kind(Kind, Name)},
DefInvoke
},
Clause = {clause, Line, DefArgs, [], [Call]},
unpack_each(Kind, Name, T, [Expr|Acc], [Clause|Clauses], S);
unpack_each(Kind, Name, [H|T], Acc, Clauses, S) ->
unpack_each(Kind, Name, T, [H|Acc], Clauses, S);
unpack_each(_Kind, _Name, [], Acc, Clauses, _S) ->
{lists:reverse(Acc), lists:reverse(Clauses)}.
% Extract default values from args following the current default clause.
extract_defaults([{'\\\\', _, [_Expr, Default]}|T], Line, Counter, NewArgs, NewInvoke) ->
extract_defaults(T, Line, Counter, NewArgs, [Default|NewInvoke]);
extract_defaults([_|T], Line, Counter, NewArgs, NewInvoke) ->
H = {elixir_utils:atom_concat(["_@D", Counter]), Line, nil},
extract_defaults(T, Line, Counter + 1, [H|NewArgs], [H|NewInvoke]);
extract_defaults([], _Line, _Counter, NewArgs, NewInvoke) ->
{lists:reverse(NewArgs), lists:reverse(NewInvoke)}.
% Build matches for all the previous argument until the current default clause.
build_match([], _Line, Acc) -> Acc;
build_match([_|T], Line, Acc) ->
Var = {elixir_utils:atom_concat(["_@D", length(T)]), Line, nil},
build_match(T, Line, [Var|Acc]).
% Given the invoked function name based on the kind
name_for_kind(Kind, Name) when Kind == defmacro; Kind == defmacrop -> elixir_utils:macro_name(Name);
name_for_kind(_Kind, Name) -> Name.