// p4rse, Copyright 2026, Will Hawkins // // This file is part of p4rse. // // This file is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . import Common import P4Lang extension ParserAssignmentStatement: EvaluatableStatement { public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) { let updated_execution = execution //let result = self.value.evaluate(execution: 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()!)) } let maybe_updated_scopes = self.lvalue.set( to: value, inScopes: execution.scopes, duringExecution: updated_execution) guard case Result.Ok(let updated_scopes) = maybe_updated_scopes else { return (ControlFlow.Error, execution.setError(error: maybe_updated_scopes.error()!)) } execution.scopes = updated_scopes.0 return (ControlFlow.Next, updated_execution) } } extension ParserStateDirectTransitionValue: EvaluatableParserState { public func execute( program: Common.ProgramExecution ) -> (any EvaluatableParserState, Common.ProgramExecution) { var program = program.enter_scope() let (control_flow, next_execution) = program.evaluator.ExecuteStatements( self.state.statements, inExecution: program) switch control_flow { case .Next: program = next_execution case .Error: return (reject, next_execution.exit_scope()) default: return ( reject, next_execution.exit_scope().setError( error: Error(withMessage: "Invalid control flow (\(control_flow) in parser)")) ) } return (self.next_state as! EvaluatableParserState, program.exit_scope()) } public func done() -> Bool { return false } public func state() -> ParserState { return self.state } } extension ParserStateNoTransitionValue: EvaluatableParserState { public func execute( program: Common.ProgramExecution ) -> (any EvaluatableParserState, Common.ProgramExecution) { return (self, program) } public func done() -> Bool { return true } public func state() -> ParserState { return self.state } } extension ParserStateSelectTransitionValue: EvaluatableParserState { public func execute( program: Common.ProgramExecution ) -> (any EvaluatableParserState, Common.ProgramExecution) { var program = program.enter_scope() let (control_flow, next_execution) = program.evaluator.ExecuteStatements( self.state.statements, inExecution: program) switch control_flow { case .Next: program = next_execution case .Error: return (reject, next_execution.exit_scope()) default: return ( reject, next_execution.exit_scope().setError( error: Error(withMessage: "Invalid control flow (\(control_flow) in parser)")) ) } switch program.evaluator.EvaluateExpression(self.te, inExecution: program) { case (.Ok(let value), let program): if AnyParserState.eq(rhs: value.type().baseType()) { return (value.dataValue() as! EvaluatableParserState, program.exit_scope()) } else { return ( self, program.setError( error: Error(withMessage: "Select transition transitioned to a none state")) ) } case (.Error(let e), let program): return (self, program.setError(error: e).exit_scope()) } } public func done() -> Bool { return false } public func state() -> ParserState { return self.state } } extension ParserValue: LibraryCallable { public typealias T = InstantiatedParserState public func call( execution: Common.ProgramExecution, arguments: ArgumentList ) -> (InstantiatedParserState, Common.ProgramExecution) { var execution = execution.enter_scope() execution = execution.declare( identifier: accept.state().getName(), withValue: P4Value(accept, P4QualifiedType.ReadOnly(accept.type()))) execution = execution.declare( identifier: reject.state().getName(), withValue: P4Value(reject, P4QualifiedType.ReadOnly(reject.type()))) // Add initial values to the global scope for (name, value) in execution.getGlobalValues() { execution = execution.declare(identifier: name, withValue: value) } // First, add every state to the scope! for state in self.tipe.states.states { guard let instantiated_state = state.instantiate(state.getName()) else { return ( reject, execution.setError(error: Error(withMessage: "Could not instantiate \(state.getName())")) ) } execution = execution.declare( identifier: state.getName(), withValue: P4Value(instantiated_state)) } guard let _current_state = self.tipe.findStartState(), var current_state = _current_state.instantiate(Identifier(name: "start")) as? EvaluatableParserState else { return ( reject, execution.setError(error: Error(withMessage: "Could not find the start state")) ) } let call_body: (ProgramExecution) -> (Result, ProgramExecution) = { (execution: ProgramExecution) in var current_execution = execution // Evaluate until the state is either accept or reject. while !current_state.done() && !current_execution.hasError() { (current_state, current_execution) = current_state.execute(program: current_execution) } return (.Ok(P4Value((current_state))), current_execution) } return switch Call( body: call_body, withArguments: arguments, withParameters: self.tipe.parameters, inExecution: execution) { case (.Ok(let value), let updated_execution): (value.dataValue() as! InstantiatedParserState, updated_execution) case (.Error(let e), let updated_execution): (reject, updated_execution.setError(error: Error(withMessage: "Cannot call parser: \(e)"))) } } }