Support Binary Math Operators
Signed-off-by: Will Hawkins <hawkinsw@obs.cr>
This commit is contained in:
@@ -246,8 +246,9 @@ extension SelectExpression: CompilableExpression {
|
||||
let maybe_selector = Expression.Compile(node: selector_node, withContext: context)
|
||||
guard case .Ok(let selector) = maybe_selector else {
|
||||
return .Error(
|
||||
Error(
|
||||
withMessage:
|
||||
ErrorOnNode(
|
||||
node: selector_node,
|
||||
withError:
|
||||
"Could not parse transition select expression selector expression: \(maybe_selector.error()!)"
|
||||
))
|
||||
}
|
||||
@@ -343,8 +344,8 @@ extension BinaryOperatorExpression: CompilableExpression {
|
||||
// swift-format-ignore
|
||||
#RequireNodesType<Node, EvaluatableExpression?>(
|
||||
nodes: binary_operator_expression_node,
|
||||
type: ["binaryEqualOperatorExpression", "binaryLessThanOperatorExpression", "binaryLessThanEqualOperatorExpression", "binaryGreaterThanOperatorExpression", "binaryGreaterThanEqualOperatorExpression", "binaryAndOperatorExpression", "binaryOrOperatorExpression"],
|
||||
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"])
|
||||
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"])
|
||||
|
||||
if binary_operator_expression_node.childCount < currentChildIdxSafe {
|
||||
return Result.Error(
|
||||
@@ -382,7 +383,7 @@ extension BinaryOperatorExpression: CompilableExpression {
|
||||
return Result.Error(maybe_right_hand_side.error()!)
|
||||
}
|
||||
|
||||
let evaluators = [
|
||||
let evaluators: [String: (String, P4Type, BinaryOperatorChecker?, BinaryOperatorEvaluator)] = [
|
||||
"binaryEqualOperatorExpression": (
|
||||
"Binary Equal", P4Boolean(), Optional<BinaryOperatorChecker>.none,
|
||||
binary_equal_operator_evaluator
|
||||
@@ -409,6 +410,20 @@ extension BinaryOperatorExpression: CompilableExpression {
|
||||
"binaryOrOperatorExpression": (
|
||||
"Binary And", P4Boolean(), binary_and_or_operator_checker, binary_or_operator_evaluator
|
||||
),
|
||||
"binaryAddOperatorExpression": (
|
||||
"Binary Add", P4Int(), binary_int_math_operator_checker, binary_add_operator_evaluator
|
||||
),
|
||||
"binarySubtractOperatorExpression": (
|
||||
"Binary Subtract", P4Int(), binary_int_math_operator_checker,
|
||||
binary_subtract_operator_evaluator
|
||||
),
|
||||
"binaryMultiplyOperatorExpression": (
|
||||
"Binary Multiply", P4Int(), binary_int_math_operator_checker,
|
||||
binary_multiply_operator_evaluator
|
||||
),
|
||||
"binaryDivideOperatorExpression": (
|
||||
"Binary Divide", P4Int(), binary_int_math_operator_checker, binary_divide_operator_evaluator
|
||||
),
|
||||
]
|
||||
|
||||
guard let selected_evaluator = evaluators[binary_operator_expression_node.nodeType!] else {
|
||||
@@ -600,7 +615,6 @@ extension FieldAccessExpression: CompilableLValueExpression {
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Result<EvaluatableLValueExpression?> {
|
||||
let expression = node.child(at: 0)!
|
||||
print("expression: \(expression)")
|
||||
#SkipUnlessNodeType<Node, EvaluatableExpression?>(
|
||||
node: expression, type: "fieldAccessExpression")
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ public struct SelectExpression {
|
||||
}
|
||||
|
||||
public typealias NamedBinaryOperatorEvaluator = (String, P4Type, (P4Value, P4Value) -> P4Value)
|
||||
public typealias BinaryOperatorEvaluator = (P4Value, P4Value) -> P4Value
|
||||
public struct BinaryOperatorExpression {
|
||||
public let evaluator: NamedBinaryOperatorEvaluator
|
||||
public let left: EvaluatableExpression
|
||||
|
||||
@@ -123,20 +123,6 @@ public func binary_gte_operator_evaluator(left: P4Value, right: P4Value) -> P4Va
|
||||
}
|
||||
}
|
||||
|
||||
public typealias BinaryOperatorChecker = (EvaluatableExpression, EvaluatableExpression) -> Result<
|
||||
()
|
||||
>
|
||||
|
||||
public func binary_and_or_operator_checker(
|
||||
left: EvaluatableExpression, right: EvaluatableExpression
|
||||
) -> Result<()> {
|
||||
// Check that both are Boolean-typed things!
|
||||
if !(left.type().eq(rhs: P4Boolean()) && right.type().eq(rhs: P4Boolean())) {
|
||||
return .Error(Error(withMessage: "And/Or on operands with non-bool type is not allowed"))
|
||||
}
|
||||
return .Ok(())
|
||||
}
|
||||
|
||||
public func binary_and_operator_evaluator(left: P4Value, right: P4Value) -> P4Value {
|
||||
let bleft = left as! P4BooleanValue
|
||||
let bright = right as! P4BooleanValue
|
||||
@@ -153,6 +139,62 @@ public func binary_or_operator_evaluator(left: P4Value, right: P4Value) -> P4Val
|
||||
}
|
||||
}
|
||||
|
||||
public func binary_add_operator_evaluator(left: P4Value, right: P4Value) -> P4Value {
|
||||
let ileft = left as! P4IntValue
|
||||
let iright = right as! P4IntValue
|
||||
return Map(input: ileft.access() + iright.access()) { input in
|
||||
P4IntValue(withValue: input)
|
||||
}
|
||||
}
|
||||
|
||||
public func binary_subtract_operator_evaluator(left: P4Value, right: P4Value) -> P4Value {
|
||||
let ileft = left as! P4IntValue
|
||||
let iright = right as! P4IntValue
|
||||
return Map(input: ileft.access() - iright.access()) { input in
|
||||
P4IntValue(withValue: input)
|
||||
}
|
||||
}
|
||||
|
||||
public func binary_multiply_operator_evaluator(left: P4Value, right: P4Value) -> P4Value {
|
||||
let ileft = left as! P4IntValue
|
||||
let iright = right as! P4IntValue
|
||||
return Map(input: ileft.access() * iright.access()) { input in
|
||||
P4IntValue(withValue: input)
|
||||
}
|
||||
}
|
||||
|
||||
public func binary_divide_operator_evaluator(left: P4Value, right: P4Value) -> P4Value {
|
||||
let ileft = left as! P4IntValue
|
||||
let iright = right as! P4IntValue
|
||||
return Map(input: ileft.access() / iright.access()) { input in
|
||||
P4IntValue(withValue: input)
|
||||
}
|
||||
}
|
||||
|
||||
// swift-format-ignore
|
||||
public typealias BinaryOperatorChecker = (EvaluatableExpression, EvaluatableExpression) -> Result<()>
|
||||
|
||||
public func binary_and_or_operator_checker(
|
||||
left: EvaluatableExpression, right: EvaluatableExpression
|
||||
) -> Result<()> {
|
||||
// Check that both are Boolean-typed things!
|
||||
if !(left.type().eq(rhs: P4Boolean()) && right.type().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: EvaluatableExpression, right: EvaluatableExpression
|
||||
) -> Result<()> {
|
||||
// Check that both are int-typed things!
|
||||
if !(left.type().eq(rhs: P4Int()) && right.type().eq(rhs: P4Int())) {
|
||||
return .Error(
|
||||
Error(withMessage: "Mathematical operation on operands with non-int type is not allowed"))
|
||||
}
|
||||
return .Ok(())
|
||||
}
|
||||
|
||||
extension BinaryOperatorExpression: EvaluatableExpression {
|
||||
public func evaluate(execution: Common.ProgramExecution) -> Common.Result<any Common.P4Value> {
|
||||
let maybe_evaluated_left = self.left.evaluate(execution: execution)
|
||||
|
||||
Reference in New Issue
Block a user