compiler: Refactor Transition Statement Compilation

Make it follow the standard protocol(s). Unfortunately that means
that some additional information will have to be carried in
the compilation context. It seems like a decent tradeoff -- but
it may be revisited in the future.

Signed-off-by: Will Hawkins <hawkinsw@obs.cr>
This commit is contained in:
Will Hawkins
2026-05-29 17:33:19 -04:00
parent 297288e2b0
commit 4f6de341cc
3 changed files with 146 additions and 77 deletions
+61 -7
View File
@@ -43,6 +43,8 @@ public struct CompilerContext {
public let ffis: [P4FFI]
public let expected_type: P4QualifiedType?
public let extern_context: Bool
public let lexical_context_name: Identifier?
public let lexical_context_statements: [P4Statement]?
public init() {
instances = StaticVarValueScopes().enter()
@@ -51,6 +53,8 @@ public struct CompilerContext {
expected_type = .none
extern_context = false
ffis = Array()
lexical_context_name = .none
lexical_context_statements = .none
}
public init(withInstances _instances: StaticVarValueScopes, withTypes _types: TypeTypeScopes) {
@@ -60,12 +64,16 @@ public struct CompilerContext {
expected_type = .none
extern_context = false
ffis = Array()
lexical_context_name = .none
lexical_context_statements = .none
}
public init(
withInstances _instances: StaticVarValueScopes, withTypes _types: TypeTypeScopes,
withExpectation expectation: P4QualifiedType?, withExtern extern: Bool,
withExterns externs: TypeTypeScopes, withFFIs foreigns: [P4FFI]
withExterns externs: TypeTypeScopes, withFFIs foreigns: [P4FFI],
withLexicalContextName lexical_context_name: Identifier?,
withLexicalContextStatements lexical_context_statements: [P4Statement]?
) {
instances = _instances
types = _types
@@ -73,6 +81,8 @@ public struct CompilerContext {
extern_context = extern
self.externs = externs
ffis = foreigns
self.lexical_context_name = lexical_context_name
self.lexical_context_statements = lexical_context_statements
}
/// Update a compiler context
@@ -84,7 +94,9 @@ public struct CompilerContext {
public func update(newInstances instances: StaticVarValueScopes) -> CompilerContext {
return CompilerContext(
withInstances: instances, withTypes: self.types, withExpectation: self.expected_type,
withExtern: self.extern_context, withExterns: self.externs, withFFIs: self.ffis)
withExtern: self.extern_context, withExterns: self.externs, withFFIs: self.ffis,
withLexicalContextName: self.lexical_context_name,
withLexicalContextStatements: self.lexical_context_statements)
}
/// Update a compiler context
@@ -96,7 +108,9 @@ public struct CompilerContext {
public func update(newTypes types: TypeTypeScopes) -> CompilerContext {
return CompilerContext(
withInstances: self.instances, withTypes: types, withExpectation: self.expected_type,
withExtern: self.extern_context, withExterns: self.externs, withFFIs: self.ffis)
withExtern: self.extern_context, withExterns: self.externs, withFFIs: self.ffis,
withLexicalContextName: self.lexical_context_name,
withLexicalContextStatements: self.lexical_context_statements)
}
/// Update a compiler context
@@ -108,7 +122,9 @@ public struct CompilerContext {
public func update(newExpectation expectation: P4QualifiedType?) -> CompilerContext {
return CompilerContext(
withInstances: self.instances, withTypes: self.types, withExpectation: expectation,
withExtern: self.extern_context, withExterns: self.externs, withFFIs: self.ffis)
withExtern: self.extern_context, withExterns: self.externs, withFFIs: self.ffis,
withLexicalContextName: self.lexical_context_name,
withLexicalContextStatements: self.lexical_context_statements)
}
/// Update a compiler context
@@ -120,7 +136,9 @@ public struct CompilerContext {
public func update(newExtern extern: Bool) -> CompilerContext {
return CompilerContext(
withInstances: self.instances, withTypes: self.types, withExpectation: self.expected_type,
withExtern: extern, withExterns: self.externs, withFFIs: self.ffis)
withExtern: extern, withExterns: self.externs, withFFIs: self.ffis,
withLexicalContextName: self.lexical_context_name,
withLexicalContextStatements: self.lexical_context_statements)
}
/// Update a compiler context
@@ -132,7 +150,9 @@ public struct CompilerContext {
public func update(newExterns externs: TypeTypeScopes) -> CompilerContext {
return CompilerContext(
withInstances: self.instances, withTypes: self.types, withExpectation: self.expected_type,
withExtern: self.extern_context, withExterns: externs, withFFIs: self.ffis)
withExtern: self.extern_context, withExterns: externs, withFFIs: self.ffis,
withLexicalContextName: self.lexical_context_name,
withLexicalContextStatements: self.lexical_context_statements)
}
/// Update a compiler context
@@ -144,6 +164,40 @@ public struct CompilerContext {
public func update(newFFIs foreigns: [P4FFI]) -> CompilerContext {
return CompilerContext(
withInstances: self.instances, withTypes: self.types, withExpectation: self.expected_type,
withExtern: self.extern_context, withExterns: externs, withFFIs: foreigns)
withExtern: self.extern_context, withExterns: externs, withFFIs: foreigns,
withLexicalContextName: self.lexical_context_name,
withLexicalContextStatements: self.lexical_context_statements)
}
/// Update a compiler context
///
/// Create a new compiler context based on the current but with a new lexical context name.
///
/// - Parameter new_lexical_context_name: an optional new lexical context name; passing `.none` resets.
/// - Returns: A new compiler context based on the current but with a new lexical context name.
public func update(newLexicalContextName new_lexical_context_name: Identifier?) -> CompilerContext
{
return CompilerContext(
withInstances: self.instances, withTypes: self.types, withExpectation: self.expected_type,
withExtern: self.extern_context, withExterns: externs, withFFIs: self.ffis,
withLexicalContextName: new_lexical_context_name,
withLexicalContextStatements: self.lexical_context_statements)
}
/// Update a compiler context
///
/// Create a new compiler context based on the current but with a new set of lexical context statements.
///
/// - Parameter new_lexical_context_statements: an optional new set of lexical context statements; passing `.none` resets.
/// - Returns: A new compiler context based on the current but with a new set of lexical context statements.
public func update(
newLexicalContextStatements new_lexical_context_statements: [P4Statement]?
) -> CompilerContext {
return CompilerContext(
withInstances: self.instances, withTypes: self.types, withExpectation: self.expected_type,
withExtern: self.extern_context, withExterns: externs, withFFIs: self.ffis,
withLexicalContextName: self.lexical_context_name,
withLexicalContextStatements: new_lexical_context_statements)
}
}
+4 -3
View File
@@ -178,8 +178,9 @@ extension ParserState: Compilable {
sourceLocation: node.toSourceLocation(),
withError: "Missing transition statement of state declaration")))
return SpecialCompilers.TransitionStatement.Compile(
node: current_node!, forState: state_identifier, withStatements: parsed_s,
withContext: SpecialCompilers.Statements.effect(statements: parsed_s, context: context))
let updated_context = SpecialCompilers.Statements.effect(statements: parsed_s, context: context)
.update(newLexicalContextName: state_identifier).update(newLexicalContextStatements: parsed_s)
return TransitionStatement.Compile(node: current_node!, withContext: updated_context)
}
}
+19 -5
View File
@@ -28,13 +28,26 @@ protocol AnyCompilable {
) -> Common.Result<(Any, CompilerContext)>
}
public struct SpecialCompilers {
public struct TransitionStatement {
static func Compile(
node: Node, forState state_identifier: Common.Identifier,
withStatements stmts: [P4Statement], withContext context: CompilerContext
extension TransitionStatement: Compilable {
public static func Compile(
node: Node, withContext context: CompilerContext
) -> Result<ParserState> {
guard let state_identifier = context.lexical_context_name else {
return .Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(),
withError: "Cannot parse a transition statement without the name of the containing state."))
}
guard let stmts = context.lexical_context_statements else {
return .Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(),
withError: "Cannot parse a transition statement without statements of the containing state."))
}
#RequireNodeType<Node, P4Statement>(
node: node, type: "parserTransitionStatement", nice_type_name: "parser transition statement"
)
@@ -110,6 +123,7 @@ public struct SpecialCompilers {
}
}
public struct SpecialCompilers {
public struct Statements {
static func Compile(
node: Node, withContext context: CompilerContext