Programs of a typed language (where supplying declarations such as members with type expressions allow for compile-time verifications) have to be verified and have references resolved before tasks such as compilation (be it bytecode generation or some other target).
I’ve several times implemented node verification in a phase-based distribution for my dialect, but it always were mostly the same. Every node (like a top declaration) is visited with a phase parameter (preferably inside a context object). Nodes are, eventually, partially solved according to the phase parameter.
For example, here’s a VB dialect being solved (simplified). Given a sequence of statements:
phase1: For every class C, define into the lexical frame the name C as a new class symbol if C is not defined. Throw a verify error if the name C is already defined. For every member declaration M, define into the lexical frame the name M as a new variable slot symbol (with the associated type currently empty) if M is not defiined. Throw a verify error if the name M is already defined.
phase2: For every member declaration, resolve the corresponding type expression if any and if resolved, update the member associated type. For every class with a
Inherits clause, resolve the
Inherits type expression. For every class C with substatement sequence cs, apply phase1 to every substatement and then phase2.
Class SomeType Inherits Object ' Member associated type is not resolved until phase 2 Public Embedded As SomeType? End Class
That’s kind of how my symbol solver works. I’m going to rewrite my last symbol solver to work for a VB dialect (before it was syntatically ECMAScript).
I’d like to know if I could improve my terminology. I appreciate any feedback.