AST → Elixir AST (quoted code) translation for ~NFT sigil
bodies that contain #{...} interpolations.
This is the runtime-emit sibling of Linx.NFT.Compiler. Where
the static compiler walks the AST and calls the validator-setter
functions on Linx.Netfilter.Ruleset directly to produce a
ready-made %Ruleset{} value at compile time, the runtime
compiler walks the same AST and produces an Elixir AST that,
when evaluated at runtime, calls the same validator-setter
functions to produce the %Ruleset{}. The two paths are
semantically identical for static sigils; the runtime emit path
exists so the sigil can splice the values of interpolated
Elixir expressions into the right positions.
The macro picks which path to use based on whether any
:elixir_expr tokens were produced by the tokenizer.
Static portions vs runtime portions
AST nodes outside the value-position of a match (i.e. table
family, chain name, hook, priority, …) must be static —
the parser produces the same AST for them, and the runtime
compiler emits them as literal values via Macro.escape/1.
AST nodes at value positions inside matches CAN be :elixir_expr.
When they are, the runtime compiler:
- Parses the raw Elixir source of the interpolation with
Code.string_to_quoted!/1to recover the original AST. - Emits a call to
Linx.NFT.Runtime.cmp!/3(or one of the other encoders) passing the parsed Elixir AST + the field kind the surrounding nft syntax expects.
Result: at runtime, the Elixir expression is evaluated in the caller's scope, encoded per the typed field, and spliced into the rule's expression list.
Scope
Mirrors Linx.NFT.Compiler's scope. Anything the static
compiler rejects (limit / meta-set / named objects / flowtables
/ concat keys / includes) the runtime compiler also rejects,
with the same error message. Interpolation is supported at:
- Match RHS where the field kind is
{:int, _}/:ipv4/:ipv6/:ifname.
Interpolations in keyword positions (table name, chain name,
family, hook, etc.) raise a clear ParseError — they'd require
case-by-case wiring through each validator-setter.
Summary
Functions
Emits Elixir AST that, when evaluated, returns a
%Linx.Netfilter.Ruleset{}. Returns {:ok, quoted} or
{:error, %ParseError{}}.
Functions
@spec emit( [tuple()], keyword() ) :: {:ok, Macro.t()} | {:error, Linx.NFT.ParseError.t()}
Emits Elixir AST that, when evaluated, returns a
%Linx.Netfilter.Ruleset{}. Returns {:ok, quoted} or
{:error, %ParseError{}}.