Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Loading Phase

Static semantics verifies that a program is well-typed and produces a typingContext as its result. Dynamic semantics takes that context and evaluates the program. The loading phase sits between them: it takes the typingContext, processes each declaration to build a loadContext, and hands the result to dynamic semantics.

Why is the loading phase necessary?

In full P4, the phase between type checking and execution is called instantiation. Parsers, controls, and externs hold stateful components such as register arrays, counter arrays, and tables. Writing MyParser() or MyControl() does not just name a declaration; it allocates a live object with its own private state. Instantiation is the pass that evaluates constructor arguments, allocates those objects, and wires them together before any packet arrives.

Nano-P4 has no stateful components, so true instantiation is unnecessary. But a lighter version of the same idea is still needed: the evaluator must know which callable bodies to invoke and which specific parser and control serve as the entry point. Type checking is concerned with what something is, not what its body looks like. By the time type checking finishes, the typingContext knows that my_parser is a parser that accepts certain parameter types, but it does not retain the body of my_parser for later execution.

The loading phase fills that gap. It walks the declarations a second time, pairs each callable body with the elaborated parameter types that type checking produced, and records which parser and control were chosen as the entry point.

What does the loading phase produce?

The loadContext holds three things that dynamic semantics needs:

  • CALLABLE: a map from callable identifiers to their elaborated definitions (callableDef). Each definition pairs a callable’s name and elaborated parameter list with its body, ready for the evaluator to invoke.
  • PARSER and CONTROL: the specific parser and control declarations that were instantiated as the entry point of the NanoSwitch. Dynamic semantics starts execution from these two.

When make_evalContext is called at the start of dynamic semantics, it receives both the typingContext (for type information) and the loadContext (for callable bodies and entry points) and combines them into the evalContext used throughout evaluation.

In this chapter