compiler, runtime: Begin Runtime Refactor
Ultimately, the goal is to completely separate the compilation from the runtime to make it possible to have the interpreter/evaluator be "just another" entity that can perform meaningful work when given a parsed GP4 program. Signed-off-by: Will Hawkins <hawkinsw@obs.cr>
This commit is contained in:
@@ -22,14 +22,20 @@ import SwiftTreeSitter
|
||||
import TreeSitterExtensions
|
||||
import TreeSitterP4
|
||||
|
||||
protocol AnyCompilable {
|
||||
static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(Any, CompilerContext)>
|
||||
}
|
||||
|
||||
public struct SpecialCompilers {
|
||||
public struct TransitionStatement {
|
||||
static func Compile(
|
||||
node: Node, forState state_identifier: Common.Identifier,
|
||||
withStatements stmts: [EvaluatableStatement], withContext context: CompilerContext
|
||||
) -> Result<(ParserState, CompilerContext)> {
|
||||
withStatements stmts: [P4Statement], withContext context: CompilerContext
|
||||
) -> Result<ParserState> {
|
||||
|
||||
#RequireNodeType<Node, (EvaluatableStatement, CompilerContext)>(
|
||||
#RequireNodeType<Node, P4Statement>(
|
||||
node: node, type: "parserTransitionStatement", nice_type_name: "parser transition statement"
|
||||
)
|
||||
|
||||
@@ -58,19 +64,18 @@ public struct SpecialCompilers {
|
||||
switch next_state {
|
||||
case (_, .some(let instance)):
|
||||
return .Ok(
|
||||
(
|
||||
ParserStateDirectTransition(
|
||||
name: state_identifier,
|
||||
withNextState: instance.dataValue() as! InstantiatedParserState,
|
||||
withStatements: stmts), context
|
||||
))
|
||||
ParserStateDirectTransition(
|
||||
name: state_identifier,
|
||||
withNextState: instance.dataValue() as! InstantiatedParserState,
|
||||
withStatements: stmts,
|
||||
)
|
||||
)
|
||||
case (_, .none):
|
||||
return .Ok(
|
||||
(
|
||||
ParserStateDirectTransition(
|
||||
name: state_identifier,
|
||||
withNextStateIdentifier: next_state_id, withStatements: stmts), context
|
||||
))
|
||||
ParserStateDirectTransition(
|
||||
name: state_identifier,
|
||||
withNextStateIdentifier: next_state_id, withStatements: stmts)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -95,12 +100,11 @@ public struct SpecialCompilers {
|
||||
{
|
||||
case .Ok(let tse):
|
||||
.Ok(
|
||||
(
|
||||
ParserStateSelectTransition(
|
||||
name: state_identifier, withTransitionExpression: tse as! SelectExpression,
|
||||
withStatements: stmts,
|
||||
), context
|
||||
))
|
||||
ParserStateSelectTransition(
|
||||
name: state_identifier, withTransitionExpression: tse as! SelectExpression,
|
||||
withStatements: stmts,
|
||||
)
|
||||
)
|
||||
case .Error(let e): .Error(e)
|
||||
}
|
||||
}
|
||||
@@ -109,7 +113,7 @@ public struct SpecialCompilers {
|
||||
public struct Statements {
|
||||
static func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<([EvaluatableStatement], CompilerContext)> {
|
||||
) -> Result<[P4Statement]> {
|
||||
if node.nodeType != "statements" && node.nodeType != "parserStatements" {
|
||||
return Result.Error(
|
||||
ErrorWithLocation(
|
||||
@@ -118,15 +122,15 @@ public struct SpecialCompilers {
|
||||
|
||||
var errors: (any Errorable)? = .none
|
||||
var current_context = context
|
||||
var parsed_s: [EvaluatableStatement] = Array()
|
||||
var parsed_s: [P4Statement] = Array()
|
||||
|
||||
node.enumerateNamedChildren { node in
|
||||
switch Statement.Compile(
|
||||
node: node, withContext: current_context)
|
||||
{
|
||||
case .Ok((let parsed_statement, let updated_context)):
|
||||
current_context = updated_context
|
||||
case .Ok(let parsed_statement):
|
||||
parsed_s.append(parsed_statement)
|
||||
current_context = parsed_statement.effect(context: current_context)
|
||||
case .Error(let e):
|
||||
errors =
|
||||
if let errors = errors {
|
||||
@@ -141,11 +145,20 @@ public struct SpecialCompilers {
|
||||
return .Error(errors)
|
||||
}
|
||||
|
||||
return Result.Ok((parsed_s, current_context))
|
||||
return Result.Ok(parsed_s)
|
||||
}
|
||||
|
||||
static func effect(statements: [P4Statement], context: CompilerContext) -> CompilerContext {
|
||||
var current = context
|
||||
for s in statements {
|
||||
current = s.effect(context: current)
|
||||
}
|
||||
return current
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static func Compile(
|
||||
static func CompileParserBody(
|
||||
withName name: Common.Identifier, withParameters parameters: ParameterList, node: Node,
|
||||
withContext context: CompilerContext
|
||||
) -> Result<(P4Lang.Parser, CompilerContext)> {
|
||||
@@ -167,9 +180,10 @@ public struct SpecialCompilers {
|
||||
node: parser_state,
|
||||
withContext: context.update(newInstances: current_context.instances.enter()))
|
||||
{
|
||||
case Result.Ok(let (state, updated_context)):
|
||||
case Result.Ok(let state):
|
||||
let statement = state as P4Statement
|
||||
current_context = statement.effect(context: current_context)
|
||||
parser.states = parser.states.append(state: state)
|
||||
current_context = updated_context
|
||||
case Result.Error(let e): error = e
|
||||
}
|
||||
}
|
||||
@@ -245,43 +259,35 @@ public struct SpecialCompilers {
|
||||
|
||||
// Try to parse all top-level declarations.
|
||||
result?.rootNode?.enumerateNamedChildren { (declaration_node: Node) in
|
||||
let specific_declaration_node = declaration_node.child(at: 0)!
|
||||
|
||||
let declaration_parsers: [CompilableDeclaration.Type] = [
|
||||
Declaration.self, P4Lang.Parser.self,
|
||||
let declaration_parsers: [String: CompilableStatement.Type] = [
|
||||
"declaration": Declaration.self,
|
||||
"instantiation": Instantiation.self,
|
||||
]
|
||||
var found_parser = false
|
||||
|
||||
for parser in declaration_parsers {
|
||||
switch parser.Compile(node: specific_declaration_node, withContext: compilation_context) {
|
||||
case .Ok(.none): {}()
|
||||
case .Ok(.some((_, let updated_context))):
|
||||
found_parser = true
|
||||
compilation_context = updated_context
|
||||
break
|
||||
if let parser = declaration_parsers[declaration_node.nodeType!] {
|
||||
let r = parser.CompileStatement(node: declaration_node, withContext: compilation_context)
|
||||
switch r {
|
||||
case .Ok(let compiled):
|
||||
compilation_context = compiled.effect(context: compilation_context)
|
||||
case .Error(let e):
|
||||
found_parser = true
|
||||
errors =
|
||||
if let errors = errors {
|
||||
errors.append(error: e)
|
||||
} else {
|
||||
e
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// If none of the declaration parsers chose to parse, that's an error, too!
|
||||
if !found_parser {
|
||||
let no_parser_error = ErrorWithLocation(
|
||||
sourceLocation: specific_declaration_node.toSourceLocation(),
|
||||
withError: "Could not find parser for declaration node"
|
||||
)
|
||||
}
|
||||
} else {
|
||||
let e = ErrorWithLocation(
|
||||
sourceLocation: declaration_node.toSourceLocation(),
|
||||
withError:
|
||||
"\(declaration_node.nodeType!) cannot be at a P4 program top level")
|
||||
errors =
|
||||
if let errors = errors {
|
||||
errors.append(error: no_parser_error)
|
||||
errors.append(error: e)
|
||||
} else {
|
||||
no_parser_error
|
||||
e
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -313,4 +319,5 @@ public struct SpecialCompilers {
|
||||
return Result.Ok(program)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user