Current section
Files
Jump to
Current section
Files
lib/liquex/expression.ex
defmodule Liquex.Expression do
@moduledoc false
alias Liquex.Argument
alias Liquex.Context
@spec eval(maybe_improper_list | {:field, any} | {:literal, any}, Context.t()) :: any
def eval([left: left, op: op, right: right], %Context{} = context) do
do_eval({
left |> Argument.eval(context),
op,
right |> Argument.eval(context)
})
end
def eval({type, _} = argument, context) when type in [:field, :literal],
do: [argument] |> Argument.eval(context) |> do_eval()
def eval(expressions, context) when is_list(expressions) do
expressions
|> Enum.chunk_every(2)
|> Enum.reverse()
|> Enum.reduce(nil, fn
[exp, :and], acc ->
eval(exp, context) and acc
[exp, :or], acc ->
eval(exp, context) or acc
[exp], nil ->
eval(exp, context)
end)
end
defp do_eval({left, :<=, nil}) when is_number(left), do: false
defp do_eval({left, :<, nil}) when is_number(left), do: false
defp do_eval({nil, :>=, right}) when is_number(right), do: false
defp do_eval({nil, :>, right}) when is_number(right), do: false
defp do_eval({nil, :contains, _right}), do: false
defp do_eval({_, :contains, nil}), do: false
defp do_eval({left, :contains, right}) when is_list(left), do: right in left
defp do_eval({left, :contains, right}) when is_binary(left) and is_binary(right),
do: String.contains?(left, right)
defp do_eval({left, op, right}), do: apply(Kernel, op, [left, right])
# Truthy values
defp do_eval(nil), do: false
defp do_eval(false), do: false
defp do_eval(_), do: true
end