runtime: Refactor ExecutionEvaluator

Move as much of the common functionality of executing a block
of statements into a common area as possible.

Signed-off-by: Will Hawkins <hawkinsw@obs.cr>
This commit is contained in:
Will Hawkins
2026-04-23 06:05:35 -04:00
parent 99d3d2bace
commit a2d6aa0e28
3 changed files with 74 additions and 67 deletions
+37 -36
View File
@@ -15,21 +15,23 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
public typealias ExecuteStatementResultHandler = (ControlFlow, ProgramExecution) -> ( public typealias ExecuteStatementResultHandlerT = (ControlFlow, ProgramExecution) -> (
ControlFlow, ProgramExecution ControlFlow, ProgramExecution
) )
public struct ClassicEvaluator: ProgramExecutionEvaluator { public typealias ExecuteStatementT = (EvaluatableStatement, ProgramExecution) -> (
public func ExecuteStatement( ControlFlow, ProgramExecution
_ statements: [EvaluatableStatement], handleResult handler: ExecuteStatementResultHandler, )
inExecution execution: ProgramExecution,
) -> (ControlFlow, ProgramExecution) {
func CanonicalExecuteStatements(
_ statements: [EvaluatableStatement], inExecution execution: ProgramExecution,
_ executor: ExecuteStatementT
) -> (ControlFlow, ProgramExecution) {
var execution = execution var execution = execution
for s in statements { for s in statements {
let (control_flow, next_execution) = s.evaluate(execution: execution) // Execute the statement with the user-provided statement executor.
switch executor(s, execution) {
switch handler(control_flow, next_execution) { // And decide what to do next!
case (ControlFlow.Next, let handled_next_execution): execution = handled_next_execution case (ControlFlow.Next, let handled_next_execution): execution = handled_next_execution
case (ControlFlow.Return(let value), let handled_next_execution): case (ControlFlow.Return(let value), let handled_next_execution):
return (ControlFlow.Return(value), handled_next_execution) return (ControlFlow.Return(value), handled_next_execution)
@@ -40,11 +42,20 @@ public struct ClassicEvaluator: ProgramExecutionEvaluator {
return (ControlFlow.Next, execution) return (ControlFlow.Next, execution)
} }
public func ExecuteStatement( public struct ClassicEvaluator: ProgramExecutionEvaluator {
_ statement: EvaluatableStatement, handleResult handler: ExecuteStatementResultHandler, public func ExecuteStatements(
inExecution execution: ProgramExecution _ statements: [EvaluatableStatement], inExecution execution: ProgramExecution,
_ handler: ExecuteStatementResultHandlerT?
) -> (ControlFlow, ProgramExecution) { ) -> (ControlFlow, ProgramExecution) {
return ExecuteStatement([statement], handleResult: handler, inExecution: execution)
return CanonicalExecuteStatements(statements, inExecution: execution) { statement, execution in
let (cf, value) = statement.evaluate(execution: execution)
// Apply the user-specified handler before continuing.
guard let handler = handler else {
return (cf, value)
}
return handler(cf, value)
}
} }
public func EvaluateExpression( public func EvaluateExpression(
@@ -84,9 +95,9 @@ public struct InterloperEvaluator: ProgramExecutionEvaluator {
return pe return pe
} }
public func ExecuteStatement( public func ExecuteStatements(
_ statements: [EvaluatableStatement], handleResult handler: ExecuteStatementResultHandler, _ statements: [EvaluatableStatement], inExecution execution: ProgramExecution,
inExecution execution: ProgramExecution, _ handler: ExecuteStatementResultHandlerT?
) -> (ControlFlow, ProgramExecution) { ) -> (ControlFlow, ProgramExecution) {
var debugger: StatementInterloper? = .none var debugger: StatementInterloper? = .none
@@ -96,31 +107,21 @@ public struct InterloperEvaluator: ProgramExecutionEvaluator {
hasDebugInterloper = true hasDebugInterloper = true
} }
var execution = execution return CanonicalExecuteStatements(statements, inExecution: execution) { statement, execution in
for s in statements { let (cf, value) = statement.evaluate(execution: execution)
let (control_flow, next_execution) = s.evaluate(execution: execution) let (handled_cf, handled_value) =
if let handler = handler {
handler(cf, value)
} else {
(cf, value)
}
if hasDebugInterloper { if hasDebugInterloper {
debugger!(s, control_flow, next_execution) debugger!(statement, handled_cf, handled_value)
} }
return (handled_cf, handled_value)
switch handler(control_flow, next_execution) {
case (ControlFlow.Next, let handled_next_execution): execution = handled_next_execution
case (ControlFlow.Return(let value), let handled_next_execution):
return (ControlFlow.Return(value), handled_next_execution)
case (let handled_control_flow, let handled_next_execution):
return (handled_control_flow, handled_next_execution)
} }
} }
return (ControlFlow.Next, execution)
}
public func ExecuteStatement(
_ statement: EvaluatableStatement, handleResult handler: ExecuteStatementResultHandler,
inExecution execution: ProgramExecution
) -> (ControlFlow, ProgramExecution) {
return ExecuteStatement([statement], handleResult: handler, inExecution: execution)
}
public func EvaluateExpression( public func EvaluateExpression(
_ expression: EvaluatableExpression, inExecution execution: ProgramExecution, _ expression: EvaluatableExpression, inExecution execution: ProgramExecution,
+13 -6
View File
@@ -56,17 +56,24 @@ public protocol EvaluatableLValueExpression: EvaluatableExpression {
} }
public protocol ProgramExecutionEvaluator { public protocol ProgramExecutionEvaluator {
func ExecuteStatement( func ExecuteStatements(
_ statements: [EvaluatableStatement], handleResult handler: ExecuteStatementResultHandler, _ statements: [EvaluatableStatement], inExecution execution: ProgramExecution,
inExecution execution: ProgramExecution, _ handler: ExecuteStatementResultHandlerT?
) -> (ControlFlow, ProgramExecution) ) -> (ControlFlow, ProgramExecution)
func ExecuteStatement( func ExecuteStatements(
_ statement: EvaluatableStatement, handleResult handler: ExecuteStatementResultHandler, _ statements: [EvaluatableStatement], inExecution execution: ProgramExecution
inExecution execution: ProgramExecution
) -> (ControlFlow, ProgramExecution) ) -> (ControlFlow, ProgramExecution)
func EvaluateExpression( func EvaluateExpression(
_ expression: EvaluatableExpression, inExecution execution: ProgramExecution, _ expression: EvaluatableExpression, inExecution execution: ProgramExecution,
) -> (Result<P4Value>, ProgramExecution) ) -> (Result<P4Value>, ProgramExecution)
} }
extension ProgramExecutionEvaluator {
public func ExecuteStatements(
_ statements: [EvaluatableStatement], inExecution execution: ProgramExecution
) -> (ControlFlow, ProgramExecution) {
return ExecuteStatements(statements, inExecution: execution, .none)
}
}
+4 -5
View File
@@ -20,9 +20,9 @@ import P4Lang
extension BlockStatement: EvaluatableStatement { extension BlockStatement: EvaluatableStatement {
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) { public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
return execution.evaluator.ExecuteStatement( return execution.evaluator.ExecuteStatements(
self.statements, self.statements, inExecution: execution
handleResult: { (cf, execution) in ) { (cf, execution) in
switch cf { switch cf {
case ControlFlow.Return(let value): return (ControlFlow.Return(value), execution) case ControlFlow.Return(let value): return (ControlFlow.Return(value), execution)
case ControlFlow.Next: return (cf, execution) case ControlFlow.Next: return (cf, execution)
@@ -34,8 +34,7 @@ extension BlockStatement: EvaluatableStatement {
error: Error(withMessage: "Invalid control flow \(cf) in block statement")) error: Error(withMessage: "Invalid control flow \(cf) in block statement"))
) )
} }
}, }
inExecution: execution)
} }
} }