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:
@@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user