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
+78 -65
View File
@@ -21,22 +21,10 @@ import P4Runtime
import SwiftTreeSitter
import TreeSitterP4
protocol CompilableExpression {
static func compile(
node: Node, withContext context: CompilerContext
) -> Result<EvaluatableExpression?>
}
protocol CompilableLValueExpression {
static func compile_as_lvalue(
node: Node, withContext context: CompilerContext
) -> Result<EvaluatableLValueExpression?>
}
extension TypedIdentifier: CompilableExpression {
static func compile(
public static func compile(
node: SwiftTreeSitter.Node, withContext context: CompilerContext
) -> Result<EvaluatableExpression?> {
) -> Result<P4Expression?> {
let node = node.child(at: 0)!
#SkipUnlessNodeType<SwiftTreeSitter.Node>(
@@ -57,9 +45,9 @@ extension TypedIdentifier: CompilableExpression {
}
extension TypedIdentifier: CompilableLValueExpression {
static func compile_as_lvalue(
public static func compile_as_lvalue(
node: SwiftTreeSitter.Node, withContext context: CompilerContext
) -> Result<EvaluatableLValueExpression?> {
) -> Result<P4LValueExpression?> {
let expression = node.child(at: 0)!
#SkipUnlessNodeType<SwiftTreeSitter.Node>(
@@ -77,9 +65,9 @@ extension TypedIdentifier: CompilableLValueExpression {
}
extension P4BooleanValue: CompilableExpression {
static func compile(
public static func compile(
node: SwiftTreeSitter.Node, withContext context: CompilerContext
) -> Result<EvaluatableExpression?> {
) -> Result<P4Expression?> {
let node = node.child(at: 0)!
#SkipUnlessNodeType<SwiftTreeSitter.Node>(
node: node, type: "booleanLiteralExpression")
@@ -98,9 +86,9 @@ extension P4BooleanValue: CompilableExpression {
}
extension P4IntValue: CompilableExpression {
static func compile(
public static func compile(
node: SwiftTreeSitter.Node, withContext context: CompilerContext
) -> Result<EvaluatableExpression?> {
) -> Result<P4Expression?> {
let node = node.child(at: 0)!
#SkipUnlessNodesTypes<SwiftTreeSitter.Node>(
@@ -147,9 +135,9 @@ extension P4IntValue: CompilableExpression {
}
extension P4StringValue: CompilableExpression {
static func compile(
public static func compile(
node: SwiftTreeSitter.Node, withContext scopes: CompilerContext
) -> Result<EvaluatableExpression?> {
) -> Result<P4Expression?> {
let node = node.child(at: 0)!
#SkipUnlessNodeType<SwiftTreeSitter.Node>(
node: node, type: "string_literal")
@@ -158,12 +146,12 @@ extension P4StringValue: CompilableExpression {
}
extension KeysetExpression: CompilableExpression {
static func compile(
public static func compile(
node: SwiftTreeSitter.Node, withContext context: CompilerContext
) -> Common.Result<(any Common.EvaluatableExpression)?> {
) -> Result<P4Expression?> {
let keyset_expression_node = node.child(at: 0)!
#RequireNodesType<Node, EvaluatableExpression>(
#RequireNodesType<Node, P4Expression>(
nodes: keyset_expression_node, type: ["expression", "default_keyset"],
nice_type_names: ["expression", "default keyset"])
@@ -186,12 +174,12 @@ extension KeysetExpression: CompilableExpression {
struct Expression {
public static func Compile(
node: Node, withContext context: CompilerContext
) -> Result<EvaluatableExpression> {
#RequireNodeType<Node, EvaluatableExpression>(
) -> Result<P4Expression> {
#RequireNodeType<Node, P4Expression>(
node: node, type: "expression", nice_type_name: "expression")
let expression_node = node.child(at: 0)!
#RequireNodesType<Node, EvaluatableExpression>(
#RequireNodesType<Node, P4Expression>(
nodes: expression_node, type: ["grouped_expression", "simple_expression"],
nice_type_names: ["grouped expression", "simple expression"])
@@ -223,12 +211,12 @@ struct Expression {
struct LValue {
public static func Compile(
node: Node, withContext context: CompilerContext
) -> Result<EvaluatableLValueExpression> {
#RequireNodeType<Node, EvaluatableExpression>(
) -> Result<P4LValueExpression> {
#RequireNodeType<Node, P4Expression>(
node: node, type: "expression", nice_type_name: "expression")
let expression_node = node.child(at: 0)!
#RequireNodesType<Node, EvaluatableExpression>(
#RequireNodesType<Node, P4Expression>(
nodes: expression_node, type: ["grouped_expression", "simple_expression"],
nice_type_names: ["grouped expression", "simple expression"])
@@ -268,9 +256,9 @@ struct Identifier {
}
extension SelectExpression: CompilableExpression {
static func compile(
public static func compile(
node: Node, withContext context: CompilerContext
) -> Result<EvaluatableExpression?> {
) -> Result<P4Expression?> {
#RequireNodeType<Node, (SelectExpression, CompilerContext)>(
node: node, type: "selectExpression", nice_type_name: "parser select expression")
@@ -330,9 +318,9 @@ extension SelectExpression: CompilableExpression {
}
extension SelectCaseExpression: CompilableExpression {
static func compile(
public static func compile(
node: Node, withContext context: CompilerContext
) -> Result<EvaluatableExpression?> {
) -> Result<P4Expression?> {
if node.nodeType != "selectCase" {
return Result.Error(Error(withMessage: "Expected select case not found"))
}
@@ -383,10 +371,35 @@ extension SelectCaseExpression: CompilableExpression {
}
}
// swift-format-ignore
public typealias BinaryOperatorChecker = (P4Expression, P4Expression) -> Result<()>
public func binary_and_or_operator_checker(
left: P4Expression, right: P4Expression
) -> Result<()> {
// Check that both are Boolean-typed things!
if !(left.type().baseType().eq(rhs: P4Boolean()) && right.type().baseType().eq(rhs: P4Boolean()))
{
return .Error(Error(withMessage: "And/Or on operands with non-bool type is not allowed"))
}
return .Ok(())
}
public func binary_int_math_operator_checker(
left: P4Expression, right: P4Expression
) -> Result<()> {
// Check that both are int-typed things!
if !(left.type().baseType().eq(rhs: P4Int()) && right.type().baseType().eq(rhs: P4Int())) {
return .Error(
Error(withMessage: "Mathematical operation on operands with non-int type is not allowed"))
}
return .Ok(())
}
extension BinaryOperatorExpression: CompilableExpression {
static func compile(
public static func compile(
node: SwiftTreeSitter.Node, withContext context: CompilerContext
) -> Result<(EvaluatableExpression)?> {
) -> Result<(P4Expression)?> {
let expression = node.child(at: 0)!
#SkipUnlessNodeType<Node>(
@@ -398,20 +411,20 @@ extension BinaryOperatorExpression: CompilableExpression {
var current_node: Node? = .none
#MustOr(
result: current_node, thing: walker.getNext(),
or: Result<EvaluatableExpression?>.Error(
or: Result<P4Expression?>.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(), withError: "Malformed binary operator expression"
)))
/// TODO: This macro cannot handle new lines in the arrays
// swift-format-ignore
#RequireNodesType<Node, EvaluatableExpression?>(
#RequireNodesType<Node, P4Expression?>(
nodes: binary_operator_expression_node,
type: ["binaryEqualOperatorExpression", "binaryLessThanOperatorExpression", "binaryLessThanEqualOperatorExpression", "binaryGreaterThanOperatorExpression", "binaryGreaterThanEqualOperatorExpression", "binaryAndOperatorExpression", "binaryOrOperatorExpression", "binaryAddOperatorExpression", "binarySubtractOperatorExpression", "binaryMultiplyOperatorExpression", "binaryDivideOperatorExpression"],
nice_type_names: [ "binary equal operator", "binary less than operator", "binary less than or equal to operator", "binary greater than operator", "binary greater than or equal to operator", "binary and operator", "binary or operator", "binary add operator", "binary subtract operator", "binary multiply operator", "binary divide operator"])
#MustOr(
result: current_node, thing: walker.getNext(),
or: Result<EvaluatableExpression?>.Error(
or: Result<P4Expression?>.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(),
withError: "Missing LHS for binary operator expression")))
@@ -421,7 +434,7 @@ extension BinaryOperatorExpression: CompilableExpression {
walker.next()
#MustOr(
result: current_node, thing: walker.getNext(),
or: Result<EvaluatableExpression?>.Error(
or: Result<P4Expression?>.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(),
withError: "Missing binary operator for binary operator expression")))
@@ -429,7 +442,7 @@ extension BinaryOperatorExpression: CompilableExpression {
walker.next()
#MustOr(
result: current_node, thing: walker.getNext(),
or: Result<EvaluatableExpression?>.Error(
or: Result<P4Expression?>.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(),
withError: "Missing RHS for binary operator expression")))
@@ -520,9 +533,9 @@ extension BinaryOperatorExpression: CompilableExpression {
}
extension ArrayAccessExpression: CompilableExpression {
static func compile(
public static func compile(
node: SwiftTreeSitter.Node, withContext context: CompilerContext
) -> Common.Result<EvaluatableExpression?> {
) -> Result<P4Expression?> {
let expression = node.child(at: 0)!
#SkipUnlessNodeType<Node>(
@@ -535,11 +548,11 @@ extension ArrayAccessExpression: CompilableExpression {
#MustOr(
result: current_node, thing: walker.getNext(),
or: Result<EvaluatableExpression?>.Error(
or: Result<P4Expression?>.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(), withError: "Malformed array access expression")))
#RequireNodeType<Node, EvaluatableExpression?>(
#RequireNodeType<Node, P4Expression?>(
node: current_node!, type: "expression",
nice_type_name: "array identifier expression")
let array_access_identifier_node = current_node!
@@ -547,7 +560,7 @@ extension ArrayAccessExpression: CompilableExpression {
walker.next()
#MustOr(
result: current_node, thing: walker.getNext(),
or: Result<EvaluatableExpression?>.Error(
or: Result<P4Expression?>.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(),
withError: "Missing [ for array access expression")))
@@ -556,12 +569,12 @@ extension ArrayAccessExpression: CompilableExpression {
#MustOr(
result: current_node, thing: walker.getNext(),
or: Result<EvaluatableExpression?>.Error(
or: Result<P4Expression?>.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(),
withError: "Missing indexor expression for array access expression")))
#RequireNodeType<Node, EvaluatableExpression?>(
#RequireNodeType<Node, P4Expression?>(
node: current_node!, type: "expression",
nice_type_name: "array indexor expression")
@@ -595,9 +608,9 @@ extension ArrayAccessExpression: CompilableExpression {
}
extension FieldAccessExpression: CompilableExpression {
static func compile(
public static func compile(
node: SwiftTreeSitter.Node, withContext context: CompilerContext
) -> Common.Result<(any Common.EvaluatableExpression)?> {
) -> Result<P4Expression?> {
let expression = node.child(at: 0)!
#SkipUnlessNodeType<Node>(
@@ -610,11 +623,11 @@ extension FieldAccessExpression: CompilableExpression {
#MustOr(
result: current_node, thing: walker.getNext(),
or: Result<EvaluatableExpression?>.Error(
or: Result<P4Expression?>.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(), withError: "Malformed field access expression")))
#RequireNodeType<Node, EvaluatableExpression?>(
#RequireNodeType<Node, P4Expression?>(
node: current_node!, type: "expression",
nice_type_name: "struct identifier expression")
let struct_identifier_node = current_node!
@@ -622,7 +635,7 @@ extension FieldAccessExpression: CompilableExpression {
walker.next()
#MustOr(
result: current_node, thing: walker.getNext(),
or: Result<EvaluatableExpression?>.Error(
or: Result<P4Expression?>.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(),
withError: "Missing . for field access expression")))
@@ -630,12 +643,12 @@ extension FieldAccessExpression: CompilableExpression {
walker.next()
#MustOr(
result: current_node, thing: walker.getNext(),
or: Result<EvaluatableExpression?>.Error(
or: Result<P4Expression?>.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(),
withError: "Missing field name for field access expression")))
#RequireNodeType<Node, EvaluatableExpression?>(
#RequireNodeType<Node, P4Expression?>(
node: current_node!, type: "identifier",
nice_type_name: "field name")
@@ -677,9 +690,9 @@ extension FieldAccessExpression: CompilableExpression {
}
extension FieldAccessExpression: CompilableLValueExpression {
static func compile_as_lvalue(
public static func compile_as_lvalue(
node: SwiftTreeSitter.Node, withContext context: CompilerContext
) -> Result<EvaluatableLValueExpression?> {
) -> Result<P4LValueExpression?> {
let expression = node.child(at: 0)!
#SkipUnlessNodeType<Node>(
node: expression, type: "fieldAccessExpression")
@@ -696,9 +709,9 @@ extension FieldAccessExpression: CompilableLValueExpression {
}
extension ArrayAccessExpression: CompilableLValueExpression {
static func compile_as_lvalue(
public static func compile_as_lvalue(
node: SwiftTreeSitter.Node, withContext context: CompilerContext
) -> Result<EvaluatableLValueExpression?> {
) -> Result<P4LValueExpression?> {
let expression = node.child(at: 0)!
#SkipUnlessNodeType<Node>(
node: expression, type: "arrayAccessExpression")
@@ -715,9 +728,9 @@ extension ArrayAccessExpression: CompilableLValueExpression {
}
extension FunctionCall: CompilableExpression {
static func compile(
public static func compile(
node: Node, withContext context: CompilerContext
) -> Result<EvaluatableExpression?> {
) -> Result<P4Expression?> {
let expression = node.child(at: 0)!
#SkipUnlessNodeType<Node>(
@@ -728,7 +741,7 @@ extension FunctionCall: CompilableExpression {
#MustOr(
result: current_node, thing: walker.getNext(),
or: Result<EvaluatableExpression?>.Error(
or: Result<P4Expression?>.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(), withError: "Missing function call component")))
@@ -780,13 +793,13 @@ extension FunctionCall: CompilableExpression {
#MustOr(
result: current_node, thing: walker.getNext(),
or: Result<EvaluatableExpression?>.Error(
or: Result<P4Expression?>.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(), withError: "Missing function call component")))
let maybe_argument_list = ArgumentList.Compile(node: current_node!, withContext: context)
guard case .Ok((let arguments, _)) = maybe_argument_list else {
guard case .Ok(let arguments) = maybe_argument_list else {
return .Error(maybe_argument_list.error()!)
}