compiler, runtime, testing, common: Centralize Execution/Evaluation

Centralize the execution of statements and evaluation of expressions
so that the user can specify a debugging "callback" after every
execution/evaluation.

The callback can be used for myriad things, but it seems likely that
it will be useful for implementing:
1. Testing
2. Debugger

Signed-off-by: Will Hawkins <hawkinsw@obs.cr>
This commit is contained in:
Will Hawkins
2026-04-20 05:48:09 -04:00
parent c6f086f67f
commit d33066c543
13 changed files with 346 additions and 115 deletions
+22 -13
View File
@@ -30,14 +30,14 @@ extension SelectCaseExpression: EvaluatableExpression {
extension SelectExpression: EvaluatableExpression {
public func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution) {
switch self.selector.evaluate(execution: execution) {
switch EvaluateExpression(self.selector, inExecution: execution) {
case (.Ok(let selector_value), let updated_execution):
for sce in self.case_expressions {
if case (.Ok(let kse), let updated_execution) = sce.key.evaluate(
execution: updated_execution),
if case (.Ok(let kse), let updated_execution) = EvaluateExpression(sce.key, inExecution: updated_execution),
kse.eq(selector_value)
{
let result = sce.evaluate(execution: updated_execution)
//let result = sce.evaluate(execution: updated_execution)
let result = EvaluateExpression(sce, inExecution: updated_execution)
return result
}
}
@@ -210,12 +210,14 @@ public func binary_int_math_operator_checker(
extension BinaryOperatorExpression: EvaluatableExpression {
public func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution) {
let updated_execution = execution
let maybe_evaluated_left = self.left.evaluate(execution: updated_execution)
//let maybe_evaluated_left = self.left.evaluate(execution: updated_execution)
let maybe_evaluated_left = EvaluateExpression(self.left, inExecution: updated_execution)
guard case (.Ok(let evaluated_left), let updated_execution) = maybe_evaluated_left else {
return maybe_evaluated_left
}
let maybe_evaluated_right = self.right.evaluate(execution: updated_execution)
//let maybe_evaluated_right = self.right.evaluate(execution: updated_execution)
let maybe_evaluated_right = EvaluateExpression(self.right, inExecution: updated_execution)
guard case (.Ok(let evaluated_right), let updated_execution) = maybe_evaluated_right else {
return maybe_evaluated_right
}
@@ -231,12 +233,14 @@ extension BinaryOperatorExpression: EvaluatableExpression {
extension ArrayAccessExpression: EvaluatableExpression {
public func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution) {
let updated_execution = execution
let maybe_name = self.name.evaluate(execution: updated_execution)
//let maybe_name = self.name.evaluate(execution: updated_execution)
let maybe_name = EvaluateExpression(self.name, inExecution: updated_execution)
guard case (.Ok(let name), let updated_execution) = maybe_name else {
return maybe_name
}
let maybe_indexor = self.indexor.evaluate(execution: updated_execution)
//let maybe_indexor = self.indexor.evaluate(execution: updated_execution)
let maybe_indexor = EvaluateExpression(self.indexor, inExecution: updated_execution)
guard case (.Ok(let indexor), let updated_execution) = maybe_indexor else {
return maybe_indexor
}
@@ -265,7 +269,8 @@ extension ArrayAccessExpression: EvaluatableLValueExpression {
) -> Common.Result<(Common.VarValueScopes, P4Value)> {
let updated_execution = execution
let maybe_value = self.name.evaluate(execution: updated_execution)
//let maybe_value = self.name.evaluate(execution: updated_execution)
let maybe_value = EvaluateExpression(self.name, inExecution: updated_execution)
guard case (.Ok(let value), let updated_execution) = maybe_value else {
return .Error(
Error(withMessage: "\(self.name) cannot be evaluated: \(maybe_value.0.error()!)"))
@@ -275,7 +280,8 @@ extension ArrayAccessExpression: EvaluatableLValueExpression {
}
// Now, get the indexor!
let maybe_indexor_value = self.indexor.evaluate(execution: updated_execution)
//let maybe_indexor_value = self.indexor.evaluate(execution: updated_execution)
let maybe_indexor_value = EvaluateExpression(self.indexor, inExecution: updated_execution)
guard case (.Ok(let indexor_value), let updated_execution) = maybe_indexor_value else {
return Result.Error(
Error(withMessage: "\(self.indexor) cannot be evaluated: \(maybe_indexor_value.0.error()!)")
@@ -341,7 +347,8 @@ extension FieldAccessExpression: EvaluatableExpression {
public func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution) {
let updated_execution = execution
let maybe_struct = self.strct.evaluate(execution: updated_execution)
//let maybe_struct = self.strct.evaluate(execution: updated_execution)
let maybe_struct = EvaluateExpression(self.strct, inExecution: updated_execution)
guard case (.Ok(let strct), let updated_execution) = maybe_struct else {
return maybe_struct
}
@@ -375,7 +382,8 @@ extension FieldAccessExpression: EvaluatableLValueExpression {
let updated_execution = execution
// First, evaluate strct_id and make sure that it names a struct.
let maybe_value = self.strct.evaluate(execution: updated_execution)
//let maybe_value = self.strct.evaluate(execution: updated_execution)
let maybe_value = EvaluateExpression(self.strct, inExecution: updated_execution)
guard case (.Ok(let value), let updated_execution) = maybe_value else {
return .Error(
Error(withMessage: "\(self.strct) cannot be evaluated: \(maybe_value.0.error()!)"))
@@ -444,7 +452,8 @@ extension FieldAccessExpression: EvaluatableLValueExpression {
extension KeysetExpression: EvaluatableExpression {
public func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution) {
return self.key.evaluate(execution: execution)
//return self.key.evaluate(execution: execution)
return EvaluateExpression(self.key, inExecution: execution)
}
public func type() -> P4Type {