Expression.V2.Compile (expression v2.33.0)

An compiler for AST returned by Expression.V2.Parser.

This reads the AST output returned by Expression.V2.parse/1 and compiles it to Elixir code.

It does this by emitting valid Elixir AST, mimicking what quote/2 does.

The Elixir AST is then supplied to Code.eval_quoted_with_env/3 without any variable binding. What is returned is an anonymous function that accepts an Expression.V2.Context.t struct and evaluates the code against that context.

Any function calls are applied to the callback module referenced in the context. So if an expression uses a function called foo(1, 2, 3) then the callback's callback/3 function will be called as follows:

apply(context.callback_module, :callback, ["foo", [1, 2, 3]])

There is some special handling of some functions that have specific Elixir AST syntax requirements.

These are documented in the to_quoted/2 function.

All variables referenced by the expression are scoped to context.vars. However the full context is supplied to any function calls, giving functions the privilege of doing more than the context.vars scope alone would allow them to do.

Summary

Functions

Accepts AST as emitted by Expression.V2.parse/1 and returns an anonymous function that accepts a Context.t as an argument and returns the result of the expression against the given Context.

Convert the AST returned from Expression.V2.parse/1 into valid Elixir AST that can be used by Code.eval_quoted_with_env/3.

Wrap an AST block into an anonymous function that accepts a single argument called context.

Functions

@spec compile([any()]) :: (Expression.V2.Context.t() -> any())

Accepts AST as emitted by Expression.V2.parse/1 and returns an anonymous function that accepts a Context.t as an argument and returns the result of the expression against the given Context.

If the callback functions defined in the callback module are pure then this function is also pure and is suitable for caching.

@spec to_quoted([term()] | term()) :: Macro.t()

Convert the AST returned from Expression.V2.parse/1 into valid Elixir AST that can be used by Code.eval_quoted_with_env/3.

There is some special handling here:

  1. Lists are recursed to ensure that all list items are properly quoted.
  2. ""Quoted strings"" are unquoted and returned as regular strings to the AST.
  3. "Normal strings" are converted into Atoms and treated as such during eval.
  4. Literals such as numbers & booleans are left as is.
  5. Range.t items are converted to valid Elixir AST.
  6. & and &1 captures are generated into valid Elixir AST captures.
  7. Any functions are generated as being function calls for the given callback module.
Link to this function

wrap_in_context(quoted)

@spec wrap_in_context(Macro.t()) :: Macro.t()

Wrap an AST block into an anonymous function that accepts a single argument called context.

This happens after all the code generation completes. The code generated expects a variable called context to exist, wrapping it in this function ensures that it does.

This is the anonymous function that is returned to the caller. The caller is then responsible to call it with the correct context variables.