diff --git a/Sources/Common/Execution.swift b/Sources/Common/Execution.swift
index a5e138f..a4f932a 100644
--- a/Sources/Common/Execution.swift
+++ b/Sources/Common/Execution.swift
@@ -15,6 +15,137 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
+
+
+public typealias ExecuteStatementResultHandler = (ControlFlow, ProgramExecution) -> (
+ ControlFlow, ProgramExecution
+)
+
+public struct ClassicEvaluator: ProgramExecutionEvaluator {
+ public func ExecuteStatement(
+ _ statements: [EvaluatableStatement], handleResult handler: ExecuteStatementResultHandler,
+ inExecution execution: 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)
+ }
+ }
+ 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(
+ _ expression: EvaluatableExpression, inExecution execution: ProgramExecution,
+ ) -> (Result, ProgramExecution) {
+ return expression.evaluate(execution: execution)
+ }
+}
+
+public struct InterloperEvaluator: ProgramExecutionEvaluator {
+ var statement_interloper: StatementInterloper?
+ var expression_interloper: ExpressionInterloper?
+
+ public init() {}
+
+ public func getStatementInterloper() -> StatementInterloper? {
+ return self.statement_interloper
+ }
+
+ public func setStatementInterloper(
+ _ interloper: @escaping StatementInterloper
+ ) -> InterloperEvaluator {
+ var pe = self
+ pe.statement_interloper = interloper
+ return pe
+ }
+
+ public func getExpressionInterloper() -> ExpressionInterloper? {
+ return self.expression_interloper
+ }
+
+ public func setExpressionInterloper(
+ _ interloper: @escaping ExpressionInterloper
+ ) -> InterloperEvaluator {
+ var pe = self
+ pe.expression_interloper = interloper
+ return pe
+ }
+
+ public func ExecuteStatement(
+ _ statements: [EvaluatableStatement], handleResult handler: ExecuteStatementResultHandler,
+ inExecution execution: ProgramExecution,
+ ) -> (ControlFlow, ProgramExecution) {
+
+ var debugger: StatementInterloper? = .none
+ var hasDebugInterloper = false
+ if let found_deb = self.getStatementInterloper() {
+ debugger = found_deb
+ hasDebugInterloper = true
+ }
+
+ var execution = execution
+ for s in statements {
+ let (control_flow, next_execution) = s.evaluate(execution: execution)
+
+ 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)
+ }
+ }
+ 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(
+ _ expression: EvaluatableExpression, inExecution execution: ProgramExecution,
+ ) -> (Result, ProgramExecution) {
+
+ var debugger: ExpressionInterloper? = .none
+ var hasDebugInterloper = false
+ if let found_deb = self.getExpressionInterloper() {
+ debugger = found_deb
+ hasDebugInterloper = true
+ }
+
+ let (result, execution) = expression.evaluate(execution: execution)
+
+ if hasDebugInterloper {
+ debugger!(expression, result, execution)
+ }
+
+ return (result, execution)
+
+ }
+}
+
public typealias StatementInterloper = (EvaluatableStatement, ControlFlow, ProgramExecution) -> Void
public typealias ExpressionInterloper = (EvaluatableExpression, Result, ProgramExecution)
-> Void
@@ -24,24 +155,24 @@ open class ProgramExecution: CustomStringConvertible {
var globalValues: VarValueScopes?
var error: Error?
var debug: DebugLevel = DebugLevel.Error
- var statement_interloper: StatementInterloper?
- var expression_interloper: ExpressionInterloper?
+ public let evaluator: ProgramExecutionEvaluator
init(copy: ProgramExecution) {
self.scopes = copy.scopes
self.globalValues = copy.globalValues
self.error = copy.error
self.debug = copy.debug
- self.statement_interloper = copy.statement_interloper
- self.expression_interloper = copy.expression_interloper
+ self.evaluator = copy.evaluator
}
public init() {
globalValues = .none
+ evaluator = ClassicEvaluator()
}
- public init(withGlobalValues values: VarValueScopes) {
- globalValues = values
+ public init(_ evaluator: ProgramExecutionEvaluator) {
+ globalValues = .none
+ self.evaluator = evaluator
}
open var description: String {
@@ -72,30 +203,6 @@ open class ProgramExecution: CustomStringConvertible {
return pe
}
- public func getStatementInterloper() -> StatementInterloper? {
- return self.statement_interloper
- }
-
- public func setStatementInterloper(
- _ interloper: @escaping StatementInterloper
- ) -> ProgramExecution {
- let pe = ProgramExecution(copy: self)
- pe.statement_interloper = interloper
- return pe
- }
-
- public func getExpressionInterloper() -> ExpressionInterloper? {
- return self.expression_interloper
- }
-
- public func setExpressionInterloper(
- _ interloper: @escaping ExpressionInterloper
- ) -> ProgramExecution {
- let pe = ProgramExecution(copy: self)
- pe.expression_interloper = interloper
- return pe
- }
-
open func isDone() -> Bool {
return false
}
diff --git a/Sources/Common/Protocols.swift b/Sources/Common/Protocols.swift
index 03a5f2a..2f9c1ad 100644
--- a/Sources/Common/Protocols.swift
+++ b/Sources/Common/Protocols.swift
@@ -54,3 +54,19 @@ public protocol EvaluatableLValueExpression: EvaluatableExpression {
) -> Result<(VarValueScopes, P4Value)>
func check(to: EvaluatableExpression, inScopes scopes: VarTypeScopes) -> Result<()>
}
+
+public protocol ProgramExecutionEvaluator {
+ func ExecuteStatement(
+ _ statements: [EvaluatableStatement], handleResult handler: ExecuteStatementResultHandler,
+ inExecution execution: ProgramExecution,
+ ) -> (ControlFlow, ProgramExecution);
+
+ func ExecuteStatement(
+ _ statement: EvaluatableStatement, handleResult handler: ExecuteStatementResultHandler,
+ inExecution execution: ProgramExecution
+ ) -> (ControlFlow, ProgramExecution);
+
+ func EvaluateExpression(
+ _ expression: EvaluatableExpression, inExecution execution: ProgramExecution,
+ ) -> (Result, ProgramExecution)
+}
\ No newline at end of file
diff --git a/Sources/P4Runtime/Common.swift b/Sources/P4Runtime/Common.swift
index de70e3d..8926de9 100644
--- a/Sources/P4Runtime/Common.swift
+++ b/Sources/P4Runtime/Common.swift
@@ -33,7 +33,7 @@ public func Call(
let arg_idx = argument.index
let arg_value = argument.argument
//let maybe_argument_value = arg_value.evaluate(execution: called_execution)
- let maybe_argument_value = EvaluateExpression(arg_value, inExecution: called_execution)
+ let maybe_argument_value = called_execution.evaluator.EvaluateExpression(arg_value, inExecution: called_execution)
guard case (.Ok(let argument_value), let updated_execution) = maybe_argument_value else {
return (
.Error(Error(withMessage: "Cannot evaluate argument \(arg_idx): \(argument)")),
@@ -84,65 +84,3 @@ public func Call(
return (.Ok(call_result), updated_execution.replaceScopes(inout_scopes))
}
-public typealias ExecuteStatementResultHandler = (ControlFlow, ProgramExecution) -> (
- ControlFlow, ProgramExecution
-)
-
-public func ExecuteStatement(
- _ statements: [EvaluatableStatement], handleResult handler: ExecuteStatementResultHandler,
- inExecution execution: ProgramExecution,
-) -> (ControlFlow, ProgramExecution) {
-
- var debugger: StatementInterloper? = .none
- var hasDebugInterloper = false
- if let found_deb = execution.getStatementInterloper() {
- debugger = found_deb
- hasDebugInterloper = true
- }
-
- var execution = execution
- for s in statements {
- let (control_flow, next_execution) = s.evaluate(execution: execution)
-
- 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)
- }
- }
- 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(
- _ expression: EvaluatableExpression, inExecution execution: ProgramExecution,
-) -> (Result, ProgramExecution) {
-
- var debugger: ExpressionInterloper? = .none
- var hasDebugInterloper = false
- if let found_deb = execution.getExpressionInterloper() {
- debugger = found_deb
- hasDebugInterloper = true
- }
-
- let (result, execution) = expression.evaluate(execution: execution)
-
- if hasDebugInterloper {
- debugger!(expression, result, execution)
- }
-
- return (result, execution)
-
-}
diff --git a/Sources/P4Runtime/Expressions.swift b/Sources/P4Runtime/Expressions.swift
index db6946e..bc4cf51 100644
--- a/Sources/P4Runtime/Expressions.swift
+++ b/Sources/P4Runtime/Expressions.swift
@@ -30,15 +30,15 @@ extension SelectCaseExpression: EvaluatableExpression {
extension SelectExpression: EvaluatableExpression {
public func evaluate(execution: ProgramExecution) -> (Result, ProgramExecution) {
- switch EvaluateExpression(self.selector, inExecution: execution) {
+ switch execution.evaluator.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) = EvaluateExpression(
+ if case (.Ok(let kse), let updated_execution) = updated_execution.evaluator.EvaluateExpression(
sce.key, inExecution: updated_execution),
kse.eq(selector_value)
{
//let result = sce.evaluate(execution: updated_execution)
- let result = EvaluateExpression(sce, inExecution: updated_execution)
+ let result = updated_execution.evaluator.EvaluateExpression(sce, inExecution: updated_execution)
return result
}
}
@@ -212,13 +212,13 @@ extension BinaryOperatorExpression: EvaluatableExpression {
public func evaluate(execution: ProgramExecution) -> (Result, ProgramExecution) {
let updated_execution = execution
//let maybe_evaluated_left = self.left.evaluate(execution: updated_execution)
- let maybe_evaluated_left = EvaluateExpression(self.left, inExecution: updated_execution)
+ let maybe_evaluated_left = updated_execution.evaluator.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 = EvaluateExpression(self.right, inExecution: updated_execution)
+ let maybe_evaluated_right = updated_execution.evaluator.EvaluateExpression(self.right, inExecution: updated_execution)
guard case (.Ok(let evaluated_right), let updated_execution) = maybe_evaluated_right else {
return maybe_evaluated_right
}
@@ -235,13 +235,13 @@ extension ArrayAccessExpression: EvaluatableExpression {
public func evaluate(execution: ProgramExecution) -> (Result, ProgramExecution) {
let updated_execution = execution
//let maybe_name = self.name.evaluate(execution: updated_execution)
- let maybe_name = EvaluateExpression(self.name, inExecution: updated_execution)
+ let maybe_name = updated_execution.evaluator.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 = EvaluateExpression(self.indexor, inExecution: updated_execution)
+ let maybe_indexor = updated_execution.evaluator.EvaluateExpression(self.indexor, inExecution: updated_execution)
guard case (.Ok(let indexor), let updated_execution) = maybe_indexor else {
return maybe_indexor
}
@@ -271,7 +271,7 @@ extension ArrayAccessExpression: EvaluatableLValueExpression {
let updated_execution = execution
//let maybe_value = self.name.evaluate(execution: updated_execution)
- let maybe_value = EvaluateExpression(self.name, inExecution: updated_execution)
+ let maybe_value = updated_execution.evaluator.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()!)"))
@@ -282,7 +282,7 @@ extension ArrayAccessExpression: EvaluatableLValueExpression {
// Now, get the indexor!
//let maybe_indexor_value = self.indexor.evaluate(execution: updated_execution)
- let maybe_indexor_value = EvaluateExpression(self.indexor, inExecution: updated_execution)
+ let maybe_indexor_value = updated_execution.evaluator.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()!)")
@@ -349,7 +349,7 @@ extension FieldAccessExpression: EvaluatableExpression {
let updated_execution = execution
//let maybe_struct = self.strct.evaluate(execution: updated_execution)
- let maybe_struct = EvaluateExpression(self.strct, inExecution: updated_execution)
+ let maybe_struct = updated_execution.evaluator.EvaluateExpression(self.strct, inExecution: updated_execution)
guard case (.Ok(let strct), let updated_execution) = maybe_struct else {
return maybe_struct
}
@@ -384,7 +384,7 @@ 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 = EvaluateExpression(self.strct, inExecution: updated_execution)
+ let maybe_value = updated_execution.evaluator.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()!)"))
@@ -454,7 +454,7 @@ extension FieldAccessExpression: EvaluatableLValueExpression {
extension KeysetExpression: EvaluatableExpression {
public func evaluate(execution: ProgramExecution) -> (Result, ProgramExecution) {
//return self.key.evaluate(execution: execution)
- return EvaluateExpression(self.key, inExecution: execution)
+ return execution.evaluator.EvaluateExpression(self.key, inExecution: execution)
}
public func type() -> P4Type {
diff --git a/Sources/P4Runtime/Parser.swift b/Sources/P4Runtime/Parser.swift
index 8223c8c..e03bcb5 100644
--- a/Sources/P4Runtime/Parser.swift
+++ b/Sources/P4Runtime/Parser.swift
@@ -22,7 +22,7 @@ extension ParserAssignmentStatement: EvaluatableStatement {
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
let updated_execution = execution
//let result = self.value.evaluate(execution: updated_execution)
- let result = EvaluateExpression(self.value, inExecution: updated_execution)
+ let result = updated_execution.evaluator.EvaluateExpression(self.value, inExecution: updated_execution)
guard case (.Ok(let value), let updated_execution) = result else {
return (ControlFlow.Error, execution.setError(error: result.0.error()!))
}
@@ -44,7 +44,7 @@ extension ParserStateDirectTransition: EvaluatableParserState {
) -> (any EvaluatableParserState, Common.ProgramExecution) {
var program = program.enter_scope()
- let (control_flow, next_execution) = ExecuteStatement(
+ let (control_flow, next_execution) = program.evaluator.ExecuteStatement(
statements,
handleResult: { (control_flow, execution) in
return (control_flow, execution)
@@ -105,7 +105,7 @@ extension ParserStateSelectTransition: EvaluatableParserState {
) -> (any EvaluatableParserState, Common.ProgramExecution) {
var program = program.enter_scope()
- let (control_flow, next_execution) = ExecuteStatement(
+ let (control_flow, next_execution) = program.evaluator.ExecuteStatement(
statements,
handleResult: { (control_flow, execution) in
return (control_flow, execution)
@@ -123,7 +123,7 @@ extension ParserStateSelectTransition: EvaluatableParserState {
}
//switch self.selectExpression.evaluate(execution: program) {
- switch EvaluateExpression(self.selectExpression, inExecution: program) {
+ switch program.evaluator.EvaluateExpression(self.selectExpression, inExecution: program) {
case (.Ok(let value), let program):
if value.type().dataType().eq(rhs: self) {
return (value.dataValue() as! EvaluatableParserState, program.exit_scope())
diff --git a/Sources/P4Runtime/Runtime.swift b/Sources/P4Runtime/Runtime.swift
index 64e2fd1..fc54dc1 100644
--- a/Sources/P4Runtime/Runtime.swift
+++ b/Sources/P4Runtime/Runtime.swift
@@ -59,7 +59,7 @@ public struct ParserRuntime: CustomStringConvertible {
{
let pe =
if let initial = initialValues {
- ProgramExecution(withGlobalValues: initial)
+ ProgramExecution().setGlobalValues(initial)
} else {
ProgramExecution()
}
diff --git a/Sources/P4Runtime/Statements.swift b/Sources/P4Runtime/Statements.swift
index 8bdc051..05ef20d 100644
--- a/Sources/P4Runtime/Statements.swift
+++ b/Sources/P4Runtime/Statements.swift
@@ -20,7 +20,7 @@ import P4Lang
extension BlockStatement: EvaluatableStatement {
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
- return ExecuteStatement(
+ return execution.evaluator.ExecuteStatement(
self.statements,
handleResult: { (cf, execution) in
switch cf {
@@ -43,7 +43,7 @@ extension VariableDeclarationStatement: EvaluatableStatement {
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
guard
//case (.Ok(let initial_value), let execution) = self.initializer.evaluate(execution: execution)
- case (.Ok(let initial_value), let execution) = EvaluateExpression(
+ case (.Ok(let initial_value), let execution) = execution.evaluator.EvaluateExpression(
self.initializer, inExecution: execution)
else {
return (
@@ -61,7 +61,7 @@ extension ConditionalStatement: EvaluatableStatement {
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
guard
//case (.Ok(let evaluated_condition), let execution) = self.condition.evaluate(execution: execution)
- case (.Ok(let evaluated_condition), let execution) = EvaluateExpression(
+ case (.Ok(let evaluated_condition), let execution) = execution.evaluator.EvaluateExpression(
self.condition, inExecution: execution)
else {
return (
@@ -111,7 +111,7 @@ extension ExpressionStatement: EvaluatableStatement {
// Evaluate, there might be side effects!
//return switch self.expression.evaluate(execution: execution) {
- return switch EvaluateExpression(self.expression, inExecution: execution) {
+ return switch execution.evaluator.EvaluateExpression(self.expression, inExecution: execution) {
case (.Ok(_), let updated_context): (ControlFlow.Next, updated_context)
case (.Error(let e), let updated_context):
(ControlFlow.Next, updated_context.setError(error: e))
@@ -122,7 +122,7 @@ extension ExpressionStatement: EvaluatableStatement {
extension ReturnStatement: EvaluatableStatement {
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
//return switch self.value.evaluate(execution: execution) {
- return switch EvaluateExpression(self.value, inExecution: execution) {
+ return switch execution.evaluator.EvaluateExpression(self.value, inExecution: execution) {
case (.Ok(let v), let execution): (ControlFlow.Return(v), execution)
case (.Error(let e), let execution): (ControlFlow.Error, execution.setError(error: e))
}
diff --git a/Tests/p4rseTests/InterloperTests.swift b/Tests/p4rseTests/InterloperTests.swift
index f6f3640..da19c87 100644
--- a/Tests/p4rseTests/InterloperTests.swift
+++ b/Tests/p4rseTests/InterloperTests.swift
@@ -51,11 +51,11 @@ import TreeSitterP4
var statements_executed: [String] = Array()
- let pe = ProgramExecution().setStatementInterloper({ (statement, cf, execution) in
+ let ev = InterloperEvaluator().setStatementInterloper() { (statement, cf, execution) in
statements_executed.append("\(statement)")
- })
+ }
- let (state_result, _) = try! #UseOkResult(runtime.run(withArguments: ArgumentList(), inExecution: pe))
+ let (state_result, _) = try! #UseOkResult(runtime.run(withArguments: ArgumentList(), inExecution: ProgramExecution(ev)))
#expect(AsInstantiatedParserState(state_result) == P4Lang.accept)
@@ -90,12 +90,11 @@ import TreeSitterP4
var expressions_evaluated: [String] = Array()
- let pe = ProgramExecution().setExpressionInterloper() { expression, result, execution in
- print("Expression: \(expression)")
+ let ev = InterloperEvaluator().setExpressionInterloper() { expression, result, execution in
expressions_evaluated.append("\(expression)")
}
- let (state_result, _) = try! #UseOkResult(runtime.run(withArguments: ArgumentList(), inExecution: pe))
+ let (state_result, _) = try! #UseOkResult(runtime.run(withArguments: ArgumentList(), inExecution: ProgramExecution(ev)))
#expect(AsInstantiatedParserState(state_result) == P4Lang.accept)