runtime: Refactor Expression/Statement Evaluators

Allow the user to customize the evaluation/execution of expressions/
statements with something that implements functions that perform
those tasks. This additional functionality will make it possible for
the "classic" evaluator not to waste time checking for the presence
of interlopers and give implementers additional customization opportunities.

Signed-off-by: Will Hawkins <hawkinsw@obs.cr>
This commit is contained in:
Will Hawkins
2026-04-20 16:28:01 -04:00
parent 47cc52ea44
commit a24571222b
8 changed files with 181 additions and 121 deletions
+137 -30
View File
@@ -15,6 +15,137 @@
// 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) -> (
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<P4Value>, 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<P4Value>, 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 StatementInterloper = (EvaluatableStatement, ControlFlow, ProgramExecution) -> Void
public typealias ExpressionInterloper = (EvaluatableExpression, Result<P4Value>, ProgramExecution) public typealias ExpressionInterloper = (EvaluatableExpression, Result<P4Value>, ProgramExecution)
-> Void -> Void
@@ -24,24 +155,24 @@ open class ProgramExecution: CustomStringConvertible {
var globalValues: VarValueScopes? var globalValues: VarValueScopes?
var error: Error? var error: Error?
var debug: DebugLevel = DebugLevel.Error var debug: DebugLevel = DebugLevel.Error
var statement_interloper: StatementInterloper? public let evaluator: ProgramExecutionEvaluator
var expression_interloper: ExpressionInterloper?
init(copy: ProgramExecution) { init(copy: ProgramExecution) {
self.scopes = copy.scopes self.scopes = copy.scopes
self.globalValues = copy.globalValues self.globalValues = copy.globalValues
self.error = copy.error self.error = copy.error
self.debug = copy.debug self.debug = copy.debug
self.statement_interloper = copy.statement_interloper self.evaluator = copy.evaluator
self.expression_interloper = copy.expression_interloper
} }
public init() { public init() {
globalValues = .none globalValues = .none
evaluator = ClassicEvaluator()
} }
public init(withGlobalValues values: VarValueScopes) { public init(_ evaluator: ProgramExecutionEvaluator) {
globalValues = values globalValues = .none
self.evaluator = evaluator
} }
open var description: String { open var description: String {
@@ -72,30 +203,6 @@ open class ProgramExecution: CustomStringConvertible {
return pe 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 { open func isDone() -> Bool {
return false return false
} }
+16
View File
@@ -54,3 +54,19 @@ public protocol EvaluatableLValueExpression: EvaluatableExpression {
) -> Result<(VarValueScopes, P4Value)> ) -> Result<(VarValueScopes, P4Value)>
func check(to: EvaluatableExpression, inScopes scopes: VarTypeScopes) -> Result<()> 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<P4Value>, ProgramExecution)
}
+1 -63
View File
@@ -33,7 +33,7 @@ public func Call<T>(
let arg_idx = argument.index let arg_idx = argument.index
let arg_value = argument.argument let arg_value = argument.argument
//let maybe_argument_value = arg_value.evaluate(execution: called_execution) //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 { guard case (.Ok(let argument_value), let updated_execution) = maybe_argument_value else {
return ( return (
.Error(Error(withMessage: "Cannot evaluate argument \(arg_idx): \(argument)")), .Error(Error(withMessage: "Cannot evaluate argument \(arg_idx): \(argument)")),
@@ -84,65 +84,3 @@ public func Call<T>(
return (.Ok(call_result), updated_execution.replaceScopes(inout_scopes)) 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<P4Value>, 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)
}
+12 -12
View File
@@ -30,15 +30,15 @@ extension SelectCaseExpression: EvaluatableExpression {
extension SelectExpression: EvaluatableExpression { extension SelectExpression: EvaluatableExpression {
public func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution) { public func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution) {
switch EvaluateExpression(self.selector, inExecution: execution) { switch execution.evaluator.EvaluateExpression(self.selector, inExecution: execution) {
case (.Ok(let selector_value), let updated_execution): case (.Ok(let selector_value), let updated_execution):
for sce in self.case_expressions { 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), sce.key, inExecution: updated_execution),
kse.eq(selector_value) 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) let result = updated_execution.evaluator.EvaluateExpression(sce, inExecution: updated_execution)
return result return result
} }
} }
@@ -212,13 +212,13 @@ extension BinaryOperatorExpression: EvaluatableExpression {
public func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution) { public func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution) {
let updated_execution = execution 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) 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 { guard case (.Ok(let evaluated_left), let updated_execution) = maybe_evaluated_left else {
return maybe_evaluated_left 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) 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 { guard case (.Ok(let evaluated_right), let updated_execution) = maybe_evaluated_right else {
return maybe_evaluated_right return maybe_evaluated_right
} }
@@ -235,13 +235,13 @@ extension ArrayAccessExpression: EvaluatableExpression {
public func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution) { public func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution) {
let updated_execution = execution 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) let maybe_name = updated_execution.evaluator.EvaluateExpression(self.name, inExecution: updated_execution)
guard case (.Ok(let name), let updated_execution) = maybe_name else { guard case (.Ok(let name), let updated_execution) = maybe_name else {
return maybe_name 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) let maybe_indexor = updated_execution.evaluator.EvaluateExpression(self.indexor, inExecution: updated_execution)
guard case (.Ok(let indexor), let updated_execution) = maybe_indexor else { guard case (.Ok(let indexor), let updated_execution) = maybe_indexor else {
return maybe_indexor return maybe_indexor
} }
@@ -271,7 +271,7 @@ extension ArrayAccessExpression: EvaluatableLValueExpression {
let updated_execution = execution 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) let maybe_value = updated_execution.evaluator.EvaluateExpression(self.name, inExecution: updated_execution)
guard case (.Ok(let value), let updated_execution) = maybe_value else { guard case (.Ok(let value), let updated_execution) = maybe_value else {
return .Error( return .Error(
Error(withMessage: "\(self.name) cannot be evaluated: \(maybe_value.0.error()!)")) Error(withMessage: "\(self.name) cannot be evaluated: \(maybe_value.0.error()!)"))
@@ -282,7 +282,7 @@ extension ArrayAccessExpression: EvaluatableLValueExpression {
// Now, get the indexor! // 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) 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 { guard case (.Ok(let indexor_value), let updated_execution) = maybe_indexor_value else {
return Result.Error( return Result.Error(
Error(withMessage: "\(self.indexor) cannot be evaluated: \(maybe_indexor_value.0.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 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) let maybe_struct = updated_execution.evaluator.EvaluateExpression(self.strct, inExecution: updated_execution)
guard case (.Ok(let strct), let updated_execution) = maybe_struct else { guard case (.Ok(let strct), let updated_execution) = maybe_struct else {
return maybe_struct return maybe_struct
} }
@@ -384,7 +384,7 @@ extension FieldAccessExpression: EvaluatableLValueExpression {
let updated_execution = execution let updated_execution = execution
// First, evaluate strct_id and make sure that it names a struct. // 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) let maybe_value = updated_execution.evaluator.EvaluateExpression(self.strct, inExecution: updated_execution)
guard case (.Ok(let value), let updated_execution) = maybe_value else { guard case (.Ok(let value), let updated_execution) = maybe_value else {
return .Error( return .Error(
Error(withMessage: "\(self.strct) cannot be evaluated: \(maybe_value.0.error()!)")) Error(withMessage: "\(self.strct) cannot be evaluated: \(maybe_value.0.error()!)"))
@@ -454,7 +454,7 @@ extension FieldAccessExpression: EvaluatableLValueExpression {
extension KeysetExpression: EvaluatableExpression { extension KeysetExpression: EvaluatableExpression {
public func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution) { 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) return execution.evaluator.EvaluateExpression(self.key, inExecution: execution)
} }
public func type() -> P4Type { public func type() -> P4Type {
+4 -4
View File
@@ -22,7 +22,7 @@ extension ParserAssignmentStatement: EvaluatableStatement {
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) { public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
let updated_execution = execution let updated_execution = execution
//let result = self.value.evaluate(execution: updated_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 { guard case (.Ok(let value), let updated_execution) = result else {
return (ControlFlow.Error, execution.setError(error: result.0.error()!)) return (ControlFlow.Error, execution.setError(error: result.0.error()!))
} }
@@ -44,7 +44,7 @@ extension ParserStateDirectTransition: EvaluatableParserState {
) -> (any EvaluatableParserState, Common.ProgramExecution) { ) -> (any EvaluatableParserState, Common.ProgramExecution) {
var program = program.enter_scope() var program = program.enter_scope()
let (control_flow, next_execution) = ExecuteStatement( let (control_flow, next_execution) = program.evaluator.ExecuteStatement(
statements, statements,
handleResult: { (control_flow, execution) in handleResult: { (control_flow, execution) in
return (control_flow, execution) return (control_flow, execution)
@@ -105,7 +105,7 @@ extension ParserStateSelectTransition: EvaluatableParserState {
) -> (any EvaluatableParserState, Common.ProgramExecution) { ) -> (any EvaluatableParserState, Common.ProgramExecution) {
var program = program.enter_scope() var program = program.enter_scope()
let (control_flow, next_execution) = ExecuteStatement( let (control_flow, next_execution) = program.evaluator.ExecuteStatement(
statements, statements,
handleResult: { (control_flow, execution) in handleResult: { (control_flow, execution) in
return (control_flow, execution) return (control_flow, execution)
@@ -123,7 +123,7 @@ extension ParserStateSelectTransition: EvaluatableParserState {
} }
//switch self.selectExpression.evaluate(execution: program) { //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): case (.Ok(let value), let program):
if value.type().dataType().eq(rhs: self) { if value.type().dataType().eq(rhs: self) {
return (value.dataValue() as! EvaluatableParserState, program.exit_scope()) return (value.dataValue() as! EvaluatableParserState, program.exit_scope())
+1 -1
View File
@@ -59,7 +59,7 @@ public struct ParserRuntime: CustomStringConvertible {
{ {
let pe = let pe =
if let initial = initialValues { if let initial = initialValues {
ProgramExecution(withGlobalValues: initial) ProgramExecution().setGlobalValues(initial)
} else { } else {
ProgramExecution() ProgramExecution()
} }
+5 -5
View File
@@ -20,7 +20,7 @@ import P4Lang
extension BlockStatement: EvaluatableStatement { extension BlockStatement: EvaluatableStatement {
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) { public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
return ExecuteStatement( return execution.evaluator.ExecuteStatement(
self.statements, self.statements,
handleResult: { (cf, execution) in handleResult: { (cf, execution) in
switch cf { switch cf {
@@ -43,7 +43,7 @@ extension VariableDeclarationStatement: EvaluatableStatement {
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) { public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
guard guard
//case (.Ok(let initial_value), let execution) = self.initializer.evaluate(execution: execution) //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) self.initializer, inExecution: execution)
else { else {
return ( return (
@@ -61,7 +61,7 @@ extension ConditionalStatement: EvaluatableStatement {
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) { public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
guard guard
//case (.Ok(let evaluated_condition), let execution) = self.condition.evaluate(execution: execution) //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) self.condition, inExecution: execution)
else { else {
return ( return (
@@ -111,7 +111,7 @@ extension ExpressionStatement: EvaluatableStatement {
// Evaluate, there might be side effects! // Evaluate, there might be side effects!
//return switch self.expression.evaluate(execution: execution) { //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 (.Ok(_), let updated_context): (ControlFlow.Next, updated_context)
case (.Error(let e), let updated_context): case (.Error(let e), let updated_context):
(ControlFlow.Next, updated_context.setError(error: e)) (ControlFlow.Next, updated_context.setError(error: e))
@@ -122,7 +122,7 @@ extension ExpressionStatement: EvaluatableStatement {
extension ReturnStatement: EvaluatableStatement { extension ReturnStatement: EvaluatableStatement {
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) { public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
//return switch self.value.evaluate(execution: execution) { //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 (.Ok(let v), let execution): (ControlFlow.Return(v), execution)
case (.Error(let e), let execution): (ControlFlow.Error, execution.setError(error: e)) case (.Error(let e), let execution): (ControlFlow.Error, execution.setError(error: e))
} }
+5 -6
View File
@@ -51,11 +51,11 @@ import TreeSitterP4
var statements_executed: [String] = Array() 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)") 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) #expect(AsInstantiatedParserState(state_result) == P4Lang.accept)
@@ -90,12 +90,11 @@ import TreeSitterP4
var expressions_evaluated: [String] = Array() var expressions_evaluated: [String] = Array()
let pe = ProgramExecution().setExpressionInterloper() { expression, result, execution in let ev = InterloperEvaluator().setExpressionInterloper() { expression, result, execution in
print("Expression: \(expression)")
expressions_evaluated.append("\(expression)") 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) #expect(AsInstantiatedParserState(state_result) == P4Lang.accept)