diff --git a/Sources/P4Compiler/Declarations.swift b/Sources/P4Compiler/Declarations.swift index ce060ea..dc223cf 100644 --- a/Sources/P4Compiler/Declarations.swift +++ b/Sources/P4Compiler/Declarations.swift @@ -614,6 +614,17 @@ extension Action: Compilable { } current_context = updated_context + // Check whether the parameters are in the proper order. + let remaining_parameters = action_parameters.parameters.drop(while: { + $0.type.direction() != .none + }) + if remaining_parameters.contains(where: { $0.type.direction() != .none }) { + return .Error( + ErrorWithLocation( + sourceLocation: current_node!.toSourceLocation(), + withError: "All parameters with direction must precede directionless parameters")) + } + walker.next() #MustOr( result: current_node, thing: walker.getNext(), diff --git a/Tests/p4rseTests/ControlTests/Compile.swift b/Tests/p4rseTests/ControlTests/Compile.swift index 62b064e..3c29f03 100644 --- a/Tests/p4rseTests/ControlTests/Compile.swift +++ b/Tests/p4rseTests/ControlTests/Compile.swift @@ -18,12 +18,12 @@ import Common import Foundation import Macros +import P4Lang import Runtime import SwiftTreeSitter import Testing import TreeSitter import TreeSitterP4 -import P4Lang @testable import P4Compiler @@ -319,4 +319,81 @@ import P4Lang ), Program.Compile(simple_parser_declaration)) ) -} \ No newline at end of file +} + +@Test func test_simple_control_declaration_with_action_with_params_right_order() async throws { + let simple_parser_declaration = """ + control simple(int x, int y) { + action a(inout int ax, bool ay) { + ax = 5; + } + table t { + key = { + x: exact; + y: exact; + } + } + apply { + } + }; + """ + + let x = { (tipe: P4QualifiedType) -> Bool in + switch tipe.baseType() { + case let c as Control: c.name == "simple" + default: false + } + } + let program = try! #UseOkResult(Program.Compile(simple_parser_declaration)) + #expect(program.InstancesWithTypes(x).count == 1) +} + +@Test func test_simple_control_declaration_with_action_with_params_wrong_order() async throws { + let simple_parser_declaration = """ + control simple(int x, int y) { + action a(int ax, inout bool ay) { + ay = false; + } + table t { + key = { + x: exact; + y: exact; + } + } + apply { + } + }; + """ + #expect( + #RequireErrorResult( + ErrorWithLocation( + sourceLocation: SourceLocation(41, 23), + withError: "All parameters with direction must precede directionless parameters"), + Program.Compile(simple_parser_declaration)) + ) +} + +@Test func test_simple_control_declaration_with_action_with_params_wrong_order_interspersed() async throws { + let simple_parser_declaration = """ + control simple(int x, int y) { + action a(inout bool aa, int ax, inout bool ay) { + aa = false; + } + table t { + key = { + x: exact; + y: exact; + } + } + apply { + } + }; + """ + #expect( + #RequireErrorResult( + ErrorWithLocation( + sourceLocation: SourceLocation(41, 38), + withError: "All parameters with direction must precede directionless parameters"), + Program.Compile(simple_parser_declaration)) + ) +}