Begin Implementation of Binary Operator Support

Signed-off-by: Will Hawkins <hawkinsw@obs.cr>
This commit is contained in:
Will Hawkins
2026-03-13 08:26:35 -04:00
parent 4a3a6bdf56
commit d323434787
6 changed files with 320 additions and 1 deletions
+1
View File
@@ -199,6 +199,7 @@ public class P4IntValue: P4Value {
self.value = value
}
public func eq(rhs: P4Value) -> Bool {
print("Int value equal.")
guard let int_rhs = rhs as? P4IntValue else {
return false
}
+65 -1
View File
@@ -19,6 +19,7 @@ import Common
import P4Lang
import SwiftTreeSitter
import TreeSitterP4
import P4Runtime
protocol CompilableExpression {
static func compile(
@@ -108,7 +109,7 @@ struct Expression {
}
let localElementsParsers: [CompilableExpression.Type] = [
P4BooleanValue.self, P4StringValue.self, P4IntValue.self, TypedIdentifier.self,
P4BooleanValue.self, P4StringValue.self, P4IntValue.self, TypedIdentifier.self, BinaryOperatorExpression.self
]
for le_parser in localElementsParsers {
@@ -242,3 +243,66 @@ extension KeysetExpression: CompilableExpression {
)
}
}
extension BinaryOperatorExpression: CompilableExpression {
static func compile(
node: SwiftTreeSitter.Node, withContext context: CompilerContext
) -> Result<(EvaluatableExpression)?> {
let expression = node.child(at: 0)!
#SkipUnlessNodeType<Node, EvaluatableExpression?>(node: expression, type: "binaryOperatorExpression")
var currentChildIdx = 0
var currentChildIdxSafe = 1
var currentChild: Node? = .none
if expression.childCount < currentChildIdxSafe {
return Result.Error(
ErrorOnNode(node: node, withError: "Malformed binary operator expression"))
}
currentChild = expression.child(at: currentChildIdx)
let binary_operator_expression_node = currentChild!
#RequireNodesType<Node, EvaluatableExpression?>(nodes: binary_operator_expression_node, type: ["binaryEqualOperatorExpression"], nice_type_names: ["binary equal operator"])
if binary_operator_expression_node.childCount < currentChildIdxSafe {
return Result.Error(
ErrorOnNode(node: node, withError: "Missing LHS for binary operator expression"))
}
currentChild = binary_operator_expression_node.child(at: currentChildIdx)
let left_hand_side_raw = currentChild!
currentChildIdx = currentChildIdx + 1
currentChildIdxSafe = currentChildIdxSafe + 1
if binary_operator_expression_node.childCount < currentChildIdxSafe {
return Result.Error(
ErrorOnNode(node: node, withError: "Missing binary operator for binary operator expression"))
}
currentChild = binary_operator_expression_node.child(at: currentChildIdx)
currentChildIdx = currentChildIdx + 1
currentChildIdxSafe = currentChildIdxSafe + 1
if binary_operator_expression_node.childCount < currentChildIdxSafe {
return Result.Error(
ErrorOnNode(node: node, withError: "Missing binary operator for binary operator expression"))
}
currentChild = binary_operator_expression_node.child(at: currentChildIdx)
let right_hand_side_raw = currentChild!
let maybe_left_hand_side = Expression.Compile(node: left_hand_side_raw, withContext: context)
guard case Result.Ok(let left_hand_side) = maybe_left_hand_side else {
return Result.Error(maybe_left_hand_side.error()!)
}
let maybe_right_hand_side = Expression.Compile(node: right_hand_side_raw, withContext: context)
guard case Result.Ok(let right_hand_side) = maybe_right_hand_side else {
return Result.Error(maybe_right_hand_side.error()!)
}
return .Ok(
BinaryOperatorExpression(
withEvaluator: ("Binary Equal", P4Boolean.create(), binary_equal_operator_evaluator),
withLhs: left_hand_side, withRhs: right_hand_side))
}
}
+16
View File
@@ -56,3 +56,19 @@ public struct SelectExpression {
withSelector: self.selector, withKeysetExpressions: new_kse)
}
}
public typealias NamedBinaryOperatorEvaluator = (String, P4Type, (P4Value, P4Value) -> P4Value)
public struct BinaryOperatorExpression {
public let evaluator: NamedBinaryOperatorEvaluator
public let left: EvaluatableExpression
public let right: EvaluatableExpression
public init(
withEvaluator evaluator: NamedBinaryOperatorEvaluator, withLhs lhs: EvaluatableExpression,
withRhs rhs: EvaluatableExpression
) {
self.evaluator = evaluator
self.left = lhs
self.right = rhs
}
}
+27
View File
@@ -86,3 +86,30 @@ extension TypedIdentifier: EvaluatableExpression {
return execution.scopes.lookup(identifier: self)
}
}
public func binary_equal_operator_evaluator(left: P4Value, right: P4Value) -> P4Value {
if left.eq(rhs: right) {
return P4BooleanValue(withValue: true)
}
return P4BooleanValue(withValue: false)
}
extension BinaryOperatorExpression: EvaluatableExpression {
public func evaluate(execution: Common.ProgramExecution) -> Common.Result<any Common.P4Value> {
let maybe_evaluated_left = self.left.evaluate(execution: execution)
guard case Result.Ok(let evaluated_left) = maybe_evaluated_left else {
return maybe_evaluated_left
}
let maybe_evaluated_right = self.right.evaluate(execution: execution)
guard case Result.Ok(let evaluated_right) = maybe_evaluated_right else {
return maybe_evaluated_right
}
return Result.Ok(self.evaluator.2(evaluated_left, evaluated_right))
}
public func type() -> any Common.P4Type {
return self.evaluator.1
}
}