From a2d6aa0e280eca16659f0bb89f45bdebaee0d492 Mon Sep 17 00:00:00 2001 From: Will Hawkins Date: Thu, 23 Apr 2026 06:05:35 -0400 Subject: [PATCH] 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 --- Sources/Common/Execution.swift | 91 +++++++++++++++--------------- Sources/Common/Protocols.swift | 19 +++++-- Sources/P4Runtime/Statements.swift | 31 +++++----- 3 files changed, 74 insertions(+), 67 deletions(-) diff --git a/Sources/Common/Execution.swift b/Sources/Common/Execution.swift index 6ff030e..80a49c7 100644 --- a/Sources/Common/Execution.swift +++ b/Sources/Common/Execution.swift @@ -15,36 +15,47 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -public typealias ExecuteStatementResultHandler = (ControlFlow, ProgramExecution) -> ( +public typealias ExecuteStatementResultHandlerT = (ControlFlow, ProgramExecution) -> ( ControlFlow, ProgramExecution ) -public struct ClassicEvaluator: ProgramExecutionEvaluator { - public func ExecuteStatement( - _ statements: [EvaluatableStatement], handleResult handler: ExecuteStatementResultHandler, - inExecution execution: ProgramExecution, - ) -> (ControlFlow, ProgramExecution) { +public typealias ExecuteStatementT = (EvaluatableStatement, ProgramExecution) -> ( + ControlFlow, ProgramExecution +) - var execution = execution - for s in statements { - let (control_flow, next_execution) = s.evaluate(execution: execution) - - 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) - } +func CanonicalExecuteStatements( + _ statements: [EvaluatableStatement], inExecution execution: ProgramExecution, + _ executor: ExecuteStatementT +) -> (ControlFlow, ProgramExecution) { + var execution = execution + for s in statements { + // Execute the statement with the user-provided statement executor. + switch executor(s, execution) { + // And decide what to do next! + 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) } + return (ControlFlow.Next, execution) +} - public func ExecuteStatement( - _ statement: EvaluatableStatement, handleResult handler: ExecuteStatementResultHandler, - inExecution execution: ProgramExecution +public struct ClassicEvaluator: ProgramExecutionEvaluator { + public func ExecuteStatements( + _ statements: [EvaluatableStatement], inExecution execution: ProgramExecution, + _ handler: ExecuteStatementResultHandlerT? ) -> (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( @@ -84,9 +95,9 @@ public struct InterloperEvaluator: ProgramExecutionEvaluator { return pe } - public func ExecuteStatement( - _ statements: [EvaluatableStatement], handleResult handler: ExecuteStatementResultHandler, - inExecution execution: ProgramExecution, + public func ExecuteStatements( + _ statements: [EvaluatableStatement], inExecution execution: ProgramExecution, + _ handler: ExecuteStatementResultHandlerT? ) -> (ControlFlow, ProgramExecution) { var debugger: StatementInterloper? = .none @@ -96,30 +107,20 @@ public struct InterloperEvaluator: ProgramExecutionEvaluator { hasDebugInterloper = true } - var execution = execution - for s in statements { - let (control_flow, next_execution) = s.evaluate(execution: execution) + return CanonicalExecuteStatements(statements, inExecution: execution) { statement, execution in + let (cf, value) = statement.evaluate(execution: execution) + let (handled_cf, handled_value) = + if let handler = handler { + handler(cf, value) + } else { + (cf, value) + } if hasDebugInterloper { - debugger!(s, control_flow, next_execution) - } - - 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) + debugger!(statement, handled_cf, handled_value) } + return (handled_cf, handled_value) } - 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( diff --git a/Sources/Common/Protocols.swift b/Sources/Common/Protocols.swift index 3cee68b..41a22b2 100644 --- a/Sources/Common/Protocols.swift +++ b/Sources/Common/Protocols.swift @@ -56,17 +56,24 @@ public protocol EvaluatableLValueExpression: EvaluatableExpression { } public protocol ProgramExecutionEvaluator { - func ExecuteStatement( - _ statements: [EvaluatableStatement], handleResult handler: ExecuteStatementResultHandler, - inExecution execution: ProgramExecution, + func ExecuteStatements( + _ statements: [EvaluatableStatement], inExecution execution: ProgramExecution, + _ handler: ExecuteStatementResultHandlerT? ) -> (ControlFlow, ProgramExecution) - func ExecuteStatement( - _ statement: EvaluatableStatement, handleResult handler: ExecuteStatementResultHandler, - inExecution execution: ProgramExecution + func ExecuteStatements( + _ statements: [EvaluatableStatement], inExecution execution: ProgramExecution ) -> (ControlFlow, ProgramExecution) func EvaluateExpression( _ expression: EvaluatableExpression, inExecution execution: ProgramExecution, ) -> (Result, ProgramExecution) } + +extension ProgramExecutionEvaluator { + public func ExecuteStatements( + _ statements: [EvaluatableStatement], inExecution execution: ProgramExecution + ) -> (ControlFlow, ProgramExecution) { + return ExecuteStatements(statements, inExecution: execution, .none) + } +} diff --git a/Sources/P4Runtime/Statements.swift b/Sources/P4Runtime/Statements.swift index 05ef20d..4749346 100644 --- a/Sources/P4Runtime/Statements.swift +++ b/Sources/P4Runtime/Statements.swift @@ -20,22 +20,21 @@ import P4Lang extension BlockStatement: EvaluatableStatement { public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) { - return execution.evaluator.ExecuteStatement( - self.statements, - handleResult: { (cf, execution) in - switch cf { - case ControlFlow.Return(let value): return (ControlFlow.Return(value), execution) - case ControlFlow.Next: return (cf, execution) - case ControlFlow.Error: return (ControlFlow.Error, execution) - default: - return ( - ControlFlow.Error, - execution.setError( - error: Error(withMessage: "Invalid control flow \(cf) in block statement")) - ) - } - }, - inExecution: execution) + return execution.evaluator.ExecuteStatements( + self.statements, inExecution: execution + ) { (cf, execution) in + switch cf { + case ControlFlow.Return(let value): return (ControlFlow.Return(value), execution) + case ControlFlow.Next: return (cf, execution) + case ControlFlow.Error: return (ControlFlow.Error, execution) + default: + return ( + ControlFlow.Error, + execution.setError( + error: Error(withMessage: "Invalid control flow \(cf) in block statement")) + ) + } + } } }