Support Calling Parsers With Parameters

Signed-off-by: Will Hawkins <hawkinsw@obs.cr>
This commit is contained in:
Will Hawkins
2026-04-02 01:28:43 -04:00
parent 7cdbee1999
commit d971aab1fe
12 changed files with 345 additions and 82 deletions
+30 -3
View File
@@ -117,8 +117,11 @@ extension ParserStateSelectTransition: EvaluatableParserState {
}
}
extension Parser: ParserExecution {
public func execute(execution: ProgramExecution) -> (InstantiatedParserState, ProgramExecution) {
extension Parser: CallableExecution {
public typealias T = InstantiatedParserState
public func call(
execution: Common.ProgramExecution, arguments: P4Lang.ArgumentList
) -> (P4Lang.InstantiatedParserState, Common.ProgramExecution) {
var execution = execution.enter_scope()
execution = execution.declare(
@@ -146,10 +149,34 @@ extension Parser: ParserExecution {
)
}
// Now that we are assured that there is a start state,
// let's set the arguments.
if case .Error(let e) = arguments.compatible(self.parameters) {
return (
reject, execution.setError(error: Error(withMessage: "Cannot call parser: \(e)"))
)
}
for (parameter, argument) in zip(self.parameters.parameters, arguments.arguments) {
let arg_idx = argument.0
let arg_value = argument.1
let maybe_argument_value = arg_value.evaluate(execution: execution)
guard case .Ok(let argument_value) = maybe_argument_value else {
return (
reject,
execution.setError(
error: Error(withMessage: "Cannot evaluate argument \(arg_idx): \(argument)"))
)
}
execution = execution.declare(identifier: parameter.name, withValue: argument_value)
}
// Evaluate until the state is either accept or reject.
while !current_state.done() && !execution.hasError() {
(current_state, execution) = current_state.execute(program: execution)
}
return (AsInstantiatedParserState(current_state.state()), execution)
return (AsInstantiatedParserState(current_state.state()), execution.exit_scope())
}
}
+3 -2
View File
@@ -34,6 +34,7 @@ public protocol EvaluatableParserState: P4Value {
func state() -> ParserState
}
public protocol ParserExecution {
func execute(execution: ProgramExecution) -> (InstantiatedParserState, ProgramExecution)
public protocol CallableExecution<T> {
associatedtype T
func call(execution: ProgramExecution, arguments: ArgumentList) -> (T, ProgramExecution)
}
+8 -2
View File
@@ -49,8 +49,14 @@ public struct ParserRuntime: CustomStringConvertible {
}
}
/// Run the P4 parser on a given packet
/// Run a P4 parser with no arguments
public func run() -> Result<(ParserState, ProgramExecution)> {
return self.run(withArguments: ArgumentList([]))
}
/// Run the P4 parser on a given packet
public func run(withArguments arguments: ArgumentList) -> Result<(ParserState, ProgramExecution)>
{
let pe =
if let initial = initialValues {
@@ -59,7 +65,7 @@ public struct ParserRuntime: CustomStringConvertible {
ProgramExecution()
}
let (end_state, execution) = parser.execute(execution: pe)
let (end_state, execution) = parser.call(execution: pe, arguments: arguments)
if let error = execution.getError() {
return .Error(error)
}