Current section

Files

Jump to
durango lib dsl function function.ex
Raw

lib/dsl/function/function.ex

defmodule Durango.Dsl.Function do
@moduledoc """
Listed at https://docs.arangodb.com/3.3/AQL/Functions/
This module parses and renders functions.
"""
def validate!({_name, low..high}, args) when length(args) >= low and length(args) <= high do
nil
end
def validate!({name, count}, args) when is_integer(count) do
validate!({name, count..count}, args)
end
def validate!({name, count..count}, args) do
msg = "Durango.Function error - function #{inspect name} requires #{count} arguments. Got #{length(args)} arguments."
raise CompileError, description: msg
end
def validate!({name, low..high}, args) do
msg = "Durango.Function error - function #{inspect name} requires between #{low} and #{high} arguments. Got #{length(args)} arguments."
raise CompileError, description: msg
end
def suffix(index, limit) when index >= limit do
""
end
def suffix(_, _) do
","
end
def render_func_name(func_name) when is_atom(func_name) do
func_name
|> to_string
|> String.upcase
end
defmacro inject_parser() do
quote do
alias Durango.Query
alias Durango.Dsl.Function
alias Durango.Dsl
@function_names Function.Names.names_list()
@functions Function.Names.functions()
def parse_expr(%Query{} = q, {func_name, _, args}) when func_name in @function_names do
arity = Keyword.fetch!(@functions, func_name)
Function.validate!({func_name, arity}, args)
# args_query =
# %Query{bound_variables: q.bound_variables}
# |> Dsl.parse_expr(args)
args_query =
Enum.reduce(args, %Query{bound_variables: q.bound_variables}, fn arg, q_acc ->
new_q =
%Query{bound_variables: q_acc.bound_variables}
|> Dsl.parse_expr(arg)
%{ q_acc |
bound_variables: new_q.bound_variables,
}
|> Query.append_tokens(Enum.join(new_q.tokens, " "))
end)
func_token =
[
Function.render_func_name(func_name),
"(",
Enum.join(args_query.tokens, ", "),
")",
]
|> Enum.join("")
q
|> Map.put(:bound_variables, args_query.bound_variables)
|> Query.append_tokens(func_token)
end
end
end
end