Module: lib/compiler/ir/lower

Lowers the template IR to a render program.

What a program is now

A skeleton, a list of ops, and a list of blocks. A block has the same shape as the root -- skeleton, ops, marker counts -- and control flow refers to blocks by index. <@if> becomes one op naming its arms; <@for> becomes one op naming its body block, its list expression and its key.

That is the whole difference from the previous design, and it is what lets a list compile at all. Before, a loop body had no representation: the compiler rewrote it into a <template data-ax-for> element and the runtime parsed the body's markup again on every pass. A block is that body, parsed once and cloned per item, with its own ops addressing its own nodes.

Expressions are indices, not source

An op carries x: 3, not x: "cart.total". The sources are interned into an array this function returns beside the program, the caller compiles them positionally into the component's expression table, and the array itself never reaches the bundle.

The previous design keyed the compiled table by the expression's source text, so every expression shipped twice -- once as a key and once as compiled code -- and the contract between compiler and runtime was string identity, which nothing could check. An index is checkable, smaller, and means a program is self-contained: the runtime never needs the template source to work out what a binding meant.

Scope inside a block

A loop body reads names the enclosing component does not declare. The op records the binding names (as, ix); the runtime derives a scope holding them and evaluates the block's expressions against it. The compiler does not rewrite item.qty into anything else, because the name is what the author wrote and what every diagnostic, Atlas edge and trace entry has to keep calling it.

Source:

Classes

BlockBuilder
Interner

Members

(inner, constant) ELEMENT_MARKER :string

Attribute the runtime resolves bound elements by, before it is stripped.

Type:
  • string
Source:

(inner, constant) RESERVED_TRIGGERS :Set:.<string:>

<@defer when="..."> values that name a subscription rather than a condition.

Read from the previous implementation rather than redesigned: timer(1500) and 1500ms are both documented and both in use. Anything else compiles as an expression, so <@defer when="rows.length"> works without new syntax.

Type:
  • Set:.<string:>
Source:

Methods

(static) lowerToProgram(ir, optionsopt) → {Object}

Lowers an IR tree to a render program.

Parameters:
Name Type Attributes Description
ir object

The root fragment from module:lib/compiler/ir/build.

options object <optional>

Lowering options.

Properties
Name Type Attributes Description
voidTags Array:.<string:> <optional>

Project-specific void tag names.

Source:
Returns:

The program plus the sources its indices refer to, or the refusal.

Type
Object

(inner) isPurelyStatic(nodes) → {boolean}

Whether a subtree contains nothing that needs an op.

The static mark is applied by an earlier pass, and a mark that turns out to wrap control flow is a disagreement between two passes rather than something to render around. Checking here means the disagreement costs an ordinary compile of that subtree instead of refusing the whole template.

Parameters:
Name Type Description
nodes Array:.<object:>

IR nodes.

Source:
Returns:

True when every node is literal markup.

Type
boolean

(inner) isSubscriptionTrigger(when) → {boolean}

Whether a trigger names a subscription rather than a reactive condition.

Parameters:
Name Type Description
when string

The trigger as written.

Source:
Returns:

True when the runtime subscribes rather than evaluates.

Type
boolean

(inner) literalPropExpression(value) → {string}

Renders a literal prop value as the expression source the mounter expects.

The component mounter evaluates data-props-* as an expression, so a literal has to arrive quoted -- except for the four literals that mean themselves.

Parameters:
Name Type Description
value string

The attribute value as written.

Source:
Returns:

An expression source.

Type
string