compiler, runtime: Begin Runtime Refactor
Continuous Integration / Grammar Tests (push) Failing after 39s
Continuous Integration / Library Format Tests (push) Successful in 1m46s
Continuous Integration / Library Tests (push) Successful in 4m38s

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:
Will Hawkins
2026-05-29 08:41:49 -04:00
parent 18461a9215
commit 44e93e4cda
30 changed files with 1264 additions and 854 deletions
+54 -57
View File
@@ -24,30 +24,30 @@ import TreeSitterP4
func parameter_list_compiler(
node: SwiftTreeSitter.Node, withContext context: CompilerContext
) -> Common.Result<(ParameterList, CompilerContext)> {
) -> Common.Result<ParameterList> {
var walker = Walker(node: node)
var current_node: Node? = .none
if node.text == ")" {
// There are no parameters!
return Result.Ok((ParameterList([]), context))
return Result.Ok(ParameterList([]))
}
#RequireNodeType<Node, (ParameterList, CompilerContext)>(
#RequireNodeType<Node, ParameterList>(
node: node, type: "parameter_list", nice_type_name: "Parameter List")
var parameters: ParameterList = ParameterList([])
#MustOr(
result: current_node, thing: walker.getNext(),
or: Result<(ParameterList, CompilerContext)>.Error(
or: Result<ParameterList>.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(), withError: "Missing parameter list component")))
if current_node?.nodeType == "parameter_list" {
switch parameter_list_compiler(node: current_node!, withContext: context) {
case .Ok(let (ps, _)):
case .Ok(let ps):
parameters = ps
case .Error(let e): return Result.Error(e)
}
@@ -56,13 +56,13 @@ func parameter_list_compiler(
#MustOr(
result: current_node, thing: walker.getNext(),
or: Result<(ParameterList, CompilerContext)>.Error(
or: Result<ParameterList>.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(), withError: "Missing parameter list component")))
// If this is a ')', we are done.
if current_node?.text == ")" {
return Result.Ok((parameters, context))
return Result.Ok(parameters)
}
// If this is a comma, we skip it!
@@ -72,26 +72,26 @@ func parameter_list_compiler(
#MustOr(
result: current_node, thing: walker.getNext(),
or: Result<(ParameterList, CompilerContext)>.Error(
or: Result<ParameterList>.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(), withError: "Missing parameter list component")))
// Otherwise, there should be one parameter left!
switch Parameter.Compile(node: current_node!, withContext: context) {
case .Ok(let (parsed_parameter, updated_context)):
return Result.Ok((parameters.addParameter(parsed_parameter), updated_context))
case .Ok(let parsed_parameter):
return Result.Ok(parameters.addParameter(parsed_parameter))
case .Error(let e): return Result.Error(e)
}
}
extension ParameterList: Compilable {
public typealias T = ParameterList
public typealias C = ParameterList
public static func Compile(
node: SwiftTreeSitter.Node, withContext context: CompilerContext
) -> Common.Result<(ParameterList, CompilerContext)> {
) -> Common.Result<ParameterList> {
let parameter_node = node
#RequireNodeType<Node, (ParameterList, CompilerContext)>(
#RequireNodeType<Node, ParameterList>(
node: parameter_node, type: "parameters", nice_type_name: "Parameters")
var walker = Walker(node: parameter_node)
@@ -100,7 +100,7 @@ extension ParameterList: Compilable {
#MustOr(
result: current_node, thing: walker.getNext(),
or: Result<(ParameterList, CompilerContext)>.Error(
or: Result<ParameterList>.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(),
withError: "Missing '(' in parameter list component")))
@@ -108,7 +108,7 @@ extension ParameterList: Compilable {
walker.next()
#MustOr(
result: current_node, thing: walker.getNext(),
or: Result<(ParameterList, CompilerContext)>.Error(
or: Result<ParameterList>.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(), withError: "Missing parameter list component")))
@@ -117,12 +117,12 @@ extension ParameterList: Compilable {
}
extension Direction: Compilable {
public typealias T = Direction
public typealias C = Direction
public static func Compile(
node: Node, withContext context: CompilerContext
) -> Result<(Direction, CompilerContext)> {
) -> Result<Direction> {
let direction_node = node
#RequireNodeType<Node, (Direction, CompilerContext)>(
#RequireNodeType<Node, Direction>(
node: direction_node, type: "direction", nice_type_name: "direction")
let directions = [
"in": Direction.In,
@@ -137,17 +137,17 @@ extension Direction: Compilable {
withError: "\(direction_node.text!) is not a valid direction"))
}
return .Ok((parsed_direction, context))
return .Ok(parsed_direction)
}
}
extension Parameter: Compilable {
public typealias T = Parameter
public typealias C = Parameter
public static func Compile(
node: Node, withContext context: CompilerContext
) -> Result<(Parameter, CompilerContext)> {
) -> Result<Parameter> {
#RequireNodeType<Node, (EvaluatableStatement, CompilerContext)>(
#RequireNodeType<Node, P4Statement>(
node: node, type: "parameter", nice_type_name: "parameter")
var walker = Walker(node: node)
@@ -155,7 +155,7 @@ extension Parameter: Compilable {
#MustOr(
result: current_node, thing: walker.getNext(),
or: Result<(Parameter, CompilerContext)>.Error(
or: Result<Parameter>.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(),
withError: "Missing parameter declaration component")))
@@ -171,7 +171,7 @@ extension Parameter: Compilable {
#MustOr(
result: current_node, thing: walker.getNext(),
or: Result<(Parameter, CompilerContext)>.Error(
or: Result<Parameter>.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(),
withError: "Missing parameter declaration component")))
@@ -181,7 +181,7 @@ extension Parameter: Compilable {
if current_node!.nodeType == "direction" {
let maybe_parsed_direction = Direction.Compile(node: current_node!, withContext: context)
guard case .Ok((let parsed_direction, _)) = maybe_parsed_direction else {
guard case .Ok(let parsed_direction) = maybe_parsed_direction else {
return .Error(maybe_parsed_direction.error()!)
}
direction = parsed_direction
@@ -191,7 +191,7 @@ extension Parameter: Compilable {
#MustOr(
result: current_node, thing: walker.getNext(),
or: Result<(Parameter, CompilerContext)>.Error(
or: Result<Parameter>.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(),
withError: "Missing parameter declaration component")))
@@ -213,7 +213,7 @@ extension Parameter: Compilable {
walker.next()
#MustOr(
result: current_node, thing: walker.getNext(),
or: Result<(Parameter, CompilerContext)>.Error(
or: Result<Parameter>.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(),
withError: "Missing parameter declaration component")))
@@ -233,43 +233,41 @@ extension Parameter: Compilable {
}
return Result.Ok(
(
Parameter(
identifier: parameter_name,
withType: direction != nil
? parameter_type.update(addAttribute: P4TypeQualifier.Direction(direction!))
: parameter_type),
context
))
Parameter(
identifier: parameter_name,
withType: direction != nil
? parameter_type.update(addAttribute: P4TypeQualifier.Direction(direction!))
: parameter_type),
)
}
}
func argument_list_compiler(
node: SwiftTreeSitter.Node, withContext context: CompilerContext
) -> Common.Result<(ArgumentList, CompilerContext)> {
) -> Common.Result<ArgumentList> {
var walker = Walker(node: node)
var current_node: Node? = .none
if node.text == ")" {
// There are no arguments!
return Result.Ok((ArgumentList([]), context))
return Result.Ok(ArgumentList([]))
}
#RequireNodeType<Node, (ArgumentList, CompilerContext)>(
#RequireNodeType<Node, ArgumentList>(
node: node, type: "argument_list", nice_type_name: "argument List")
var arguments: ArgumentList = ArgumentList([])
#MustOr(
result: current_node, thing: walker.getNext(),
or: Result<(ArgumentList, CompilerContext)>.Error(
or: Result<ArgumentList>.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(), withError: "Missing argument list component")))
if current_node?.nodeType == "argument_list" {
switch argument_list_compiler(node: current_node!, withContext: context) {
case .Ok(let (ps, _)):
case .Ok(let ps):
arguments = ps
case .Error(let e): return Result.Error(e)
}
@@ -280,13 +278,13 @@ func argument_list_compiler(
// We may have moved nodes, check/reset current_node.
#MustOr(
result: current_node, thing: walker.getNext(),
or: Result<(ArgumentList, CompilerContext)>.Error(
or: Result<ArgumentList>.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(), withError: "Missing argument list component")))
// If this is a ')', we are done.
if current_node?.text == ")" {
return Result.Ok((arguments, context))
return Result.Ok(arguments)
}
// If this is a comma, we skip it!
@@ -296,27 +294,27 @@ func argument_list_compiler(
#MustOr(
result: current_node, thing: walker.getNext(),
or: Result<(ArgumentList, CompilerContext)>.Error(
or: Result<ArgumentList>.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(), withError: "Missing argument list component")))
// Otherwise, there should be one argument left!
switch Argument.Compile(node: current_node!, withContext: context) {
case .Ok(let (ce, updated_context)):
case .Ok(let ce):
return Result.Ok(
(arguments.addArgument(Argument(ce, atIndex: arguments.count() + 1)), updated_context))
arguments.addArgument(Argument(ce, atIndex: arguments.count() + 1)))
case .Error(let e): return Result.Error(e)
}
}
extension ArgumentList: Compilable {
public typealias T = ArgumentList
public typealias C = ArgumentList
public static func Compile(
node: SwiftTreeSitter.Node, withContext context: CompilerContext
) -> Common.Result<(ArgumentList, CompilerContext)> {
) -> Common.Result<ArgumentList> {
let argument_node = node
#RequireNodeType<Node, (ArgumentList, CompilerContext)>(
#RequireNodeType<Node, ArgumentList>(
node: argument_node, type: "arguments", nice_type_name: "arguments")
var walker = Walker(node: argument_node)
@@ -324,7 +322,7 @@ extension ArgumentList: Compilable {
#MustOr(
result: current_node, thing: walker.getNext(),
or: Result<(ArgumentList, CompilerContext)>.Error(
or: Result<ArgumentList>.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(),
withError: "Missing '(' in argument list component")))
@@ -333,7 +331,7 @@ extension ArgumentList: Compilable {
#MustOr(
result: current_node, thing: walker.getNext(),
or: Result<(ArgumentList, CompilerContext)>.Error(
or: Result<ArgumentList>.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(), withError: "Missing argument list component")))
@@ -342,25 +340,25 @@ extension ArgumentList: Compilable {
}
extension Argument: Compilable {
public typealias T = EvaluatableExpression
public typealias C = P4Expression
public static func Compile(
node: SwiftTreeSitter.Node, withContext context: CompilerContext
) -> Common.Result<(EvaluatableExpression, CompilerContext)> {
) -> Common.Result<P4Expression> {
let argument_node = node
#RequireNodeType<Node, (EvaluatableExpression, CompilerContext)>(
#RequireNodeType<Node, P4Expression>(
node: argument_node, type: "argument", nice_type_name: "argument")
let expression_node = node.child(at: 0)!
return switch Expression.Compile(node: expression_node, withContext: context) {
case .Ok(let compiled_expression): .Ok((compiled_expression, context))
case .Ok(let compiled_expression): .Ok(compiled_expression)
case .Error(let e): .Error(e)
}
}
}
func ContainsInvalidStatements(
statement: EvaluatableStatement, invalids: [EvaluatableStatement.Type]
statement: P4Statement, invalids: [P4Statement.Type]
) -> Bool {
for es in invalids {
if type(of: statement) == es {
@@ -370,8 +368,7 @@ func ContainsInvalidStatements(
return false
}
func ContainsInvalidStatements(block: BlockStatement, invalids: [EvaluatableStatement.Type]) -> Bool
{
func ContainsInvalidStatements(block: BlockStatement, invalids: [P4Statement.Type]) -> Bool {
return block.statements.contains { statement in
for es in invalids {
if type(of: statement) == es {