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:
@@ -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)
|
||||||
@@ -38,13 +40,22 @@ 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,
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user