Files
n8n-openai-adapter/lib/elixir/src/elixir_def_defaults.erl
T
José Valim 89cbe93bba The AST now allows metadata to be attached to each node
This means the second item in the AST is no longer an integer
(representing the line), but a keywords list. Code that relies
on the line information from AST or that manually generate AST
nodes need to be properly updated.
2013-01-21 15:42:03 -07:00

58 lines
2.0 KiB
Erlang

% Handle default clauses for function definitions.
-module(elixir_def_defaults).
-export([unpack/4]).
-include("elixir.hrl").
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:assigns(fun elixir_translator:translate/2, Base ++ Args, S),
{ InvokeArgs, _ } = elixir_translator:translate_args(Base ++ Invoke, SA),
Call = { call, Line,
{ atom, Line, name_for_kind(Kind, Name) },
InvokeArgs
},
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 = { ?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 = { ?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_macro(Name);
name_for_kind(_Kind, Name) -> Name.