From c6f086f67f9acbd508a280c67d2fcfe71e2e734f Mon Sep 17 00:00:00 2001 From: Will Hawkins Date: Mon, 20 Apr 2026 03:35:55 -0400 Subject: [PATCH] compiler, runtime: Control Declarations Have Apply Statements Signed-off-by: Will Hawkins --- Sources/P4Compiler/Declarations.swift | 29 ++++++++++++++++++--- Sources/P4Compiler/Statement.swift | 16 ++++++++++++ Sources/P4Lang/Statement.swift | 9 +++++++ Sources/P4Runtime/Statements.swift | 6 +++++ Tests/p4rseTests/ControlCompilerTests.swift | 14 +++++++++- 5 files changed, 70 insertions(+), 4 deletions(-) diff --git a/Sources/P4Compiler/Declarations.swift b/Sources/P4Compiler/Declarations.swift index ff834ba..638c641 100644 --- a/Sources/P4Compiler/Declarations.swift +++ b/Sources/P4Compiler/Declarations.swift @@ -452,6 +452,7 @@ extension Control: CompilableDeclaration { var actions: [Action] = Array() var tables: [Table] = Array() + var apply: ApplyStatement? = .none // Because the final child // is the '}'. @@ -478,6 +479,20 @@ extension Control: CompilableDeclaration { } tables.append(table_declaration) local_context = updated_context + } else if currentChild.nodeType == "apply_statement" { + // When we see an apply, that is it for the actions and the tables. + let maybe_apply_statement = ApplyStatement.Compile( + node: currentChild, withContext: local_context) + guard + case .Ok((let apply_statement, let updated_context)) = maybe_apply_statement + else { + return .Error(maybe_apply_statement.error()!) + } + local_context = updated_context + apply = (apply_statement as! ApplyStatement) + + // The apply is the last thing in a control declaration. + break; } else { return .Error( ErrorOnNode(node: currentChild, withError: "Uknown node type in control declaration")) @@ -494,10 +509,16 @@ extension Control: CompilableDeclaration { ErrorOnNode(node: node, withError: "More than one table in control declaration")) } + // Check to make sure that there is an apply. + guard let apply = apply else { + return .Error( + ErrorOnNode(node: node, withError: "Missing apply in control declaration")) + } + let declared_control = (Control( named: control_name, withParameters: control_parameters, withTable: tables[0], - withActions: Actions(withActions: actions)) + withActions: Actions(withActions: actions), withApply: apply) as P4DataType) // Don't forget to add the newly declared Control to the instance that we were given @@ -572,15 +593,17 @@ extension Action: Compilable { identifier: parameter.name, withValue: parameter.type) } - let maybe_action_body = Parser.Statement.Compile( + let maybe_action_body = BlockStatement.Compile( node: currentChild!, withContext: context.update(newInstances: function_scope)) guard case .Ok((let action_body, _)) = maybe_action_body else { return .Error(maybe_action_body.error()!) } + // TODO: Actions cannot contain switches! + return .Ok( ( - Action(named: action_name, withParameters: action_parameters, withBody: action_body), + Action(named: action_name, withParameters: action_parameters, withBody: (action_body as! BlockStatement)), current_context )) } diff --git a/Sources/P4Compiler/Statement.swift b/Sources/P4Compiler/Statement.swift index d855699..301a180 100644 --- a/Sources/P4Compiler/Statement.swift +++ b/Sources/P4Compiler/Statement.swift @@ -329,3 +329,19 @@ extension ReturnStatement: CompilableStatement { } } } + +extension ApplyStatement: CompilableStatement { + public static func Compile( + node: SwiftTreeSitter.Node, withContext context: CompilerContext + ) -> Common.Result<(any Common.EvaluatableStatement, CompilerContext)> { + #RequireNodeType( + node: node, type: "apply_statement", nice_type_name: "apply statement") + + let expression_node = node.child(at: 1)! + + return switch BlockStatement.Compile(node: expression_node, withContext: context) { + case .Ok((let statement, let updated_context)): .Ok((ApplyStatement(statement as! BlockStatement), updated_context)) + case .Error(let e): .Error(e) + } + } +} diff --git a/Sources/P4Lang/Statement.swift b/Sources/P4Lang/Statement.swift index 15c1b3d..059bb2f 100644 --- a/Sources/P4Lang/Statement.swift +++ b/Sources/P4Lang/Statement.swift @@ -63,3 +63,12 @@ public struct ReturnStatement { self.value = value } } + +public struct ApplyStatement { + public let body: BlockStatement? + + public init() { self.body = .none } + public init(_ body: BlockStatement) { + self.body = body + } +} diff --git a/Sources/P4Runtime/Statements.swift b/Sources/P4Runtime/Statements.swift index 252bf5e..16af979 100644 --- a/Sources/P4Runtime/Statements.swift +++ b/Sources/P4Runtime/Statements.swift @@ -123,3 +123,9 @@ extension ReturnStatement: EvaluatableStatement { } } } + +extension ApplyStatement: EvaluatableStatement { + public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) { + return (ControlFlow.Next, execution) + } +} diff --git a/Tests/p4rseTests/ControlCompilerTests.swift b/Tests/p4rseTests/ControlCompilerTests.swift index 2c12240..ca72f41 100644 --- a/Tests/p4rseTests/ControlCompilerTests.swift +++ b/Tests/p4rseTests/ControlCompilerTests.swift @@ -37,6 +37,8 @@ import P4Lang true: exact; } } + apply { + } }; """ let x = { (tipe: P4Type) -> Bool in @@ -61,6 +63,8 @@ import P4Lang true: exact; } } + apply { + } }; control complex() { action b() { @@ -70,6 +74,8 @@ import P4Lang true: exact; } } + apply { + } }; """ @@ -94,6 +100,8 @@ import P4Lang y: exact; } } + apply { + } }; """ #expect(#RequireOkResult(Program.Compile(simple_parser_declaration))) @@ -111,6 +119,8 @@ import P4Lang y: exact; } } + apply { + } }; """ #expect(#RequireOkResult(Program.Compile(simple_parser_declaration))) @@ -128,13 +138,15 @@ import P4Lang y: exact; } } + apply { + } }; """ #expect( #RequireErrorResult( Error( withMessage: - "{51, 20}: Failed to parse a statement element: {57, 10}: Failed to parse a statement element: {57, 1}: Cannot assign value with type Boolean to identifier z with type Int" + "{57, 10}: Failed to parse a statement element: {57, 1}: Cannot assign value with type Boolean to identifier z with type Int" ), Program.Compile(simple_parser_declaration)) )