Start Rewrite
Continuous Integration / Grammar Tests (push) Successful in 3m54s
Continuous Integration / Library Format Tests (push) Failing after 4m49s
Continuous Integration / Library Tests (push) Successful in 7m40s

Signed-off-by: Will Hawkins <hawkinsw@obs.cr>
This commit is contained in:
Will Hawkins
2026-06-12 06:24:53 -04:00
parent 6908d9a91d
commit b9ff228362
73 changed files with 1779 additions and 11477 deletions
-335
View File
@@ -1,335 +0,0 @@
// 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 <https://www.gnu.org/licenses/>.
import Common
import Foundation
import Macros
import P4Lang
import P4Runtime
import SwiftTreeSitter
import Testing
import TreeSitter
import TreeSitterP4
@testable import P4Compiler
@Test func test_array_access() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
bool where_to = ta[1] == 2;
transition select (where_to) {
true: accept;
false: reject;
};
}
};
"""
var test_declarations = StaticVarValueScopes().enter()
test_declarations = test_declarations.declare(
identifier: Identifier(name: "ta"),
withValue: (P4QualifiedType(P4Array(withValueType: P4QualifiedType(P4Int()))), .none))
var test_values = VarValueScopes().enter()
test_values = test_values.declare(
identifier: Identifier(name: "ta"),
withValue: P4Value(
P4ArrayValue(
withType: P4QualifiedType(P4Int()),
withValue: [
P4Value(P4IntValue(withValue: 1)), P4Value(P4IntValue(withValue: 2)),
P4Value(P4IntValue(withValue: 3)),
])))
let program = try #UseOkResult(
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration, withGlobalInstances: test_declarations))
let runtime = try #UseOkResult(
P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(
program: program, withGlobalValues: test_values))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_array_access_invalid_type() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
bool where_to = ta[1];
transition select (where_to) {
true: accept;
false: reject;
};
}
};
"""
var test_declarations = StaticVarValueScopes().enter()
test_declarations = test_declarations.declare(
identifier: Identifier(name: "ta"), withValue: (P4QualifiedType(P4Int()), .none))
#expect(
#RequireErrorResult(
Error(
withMessage:
"{49, 22}: Failed to parse a statement element: {65, 2}: ta does not name an array type"
),
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration, withGlobalInstances: test_declarations))
)
}
@Test func test_array_access2() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
bool where_to = ta[0] == 2;
transition select (where_to) {
true: accept;
false: reject;
};
}
};
"""
var test_declarations = StaticVarValueScopes().enter()
test_declarations = test_declarations.declare(
identifier: Identifier(name: "ta"),
withValue: (P4QualifiedType(P4Array(withValueType: P4QualifiedType(P4Int()))), .none))
var test_values = VarValueScopes().enter()
test_values = test_values.declare(
identifier: Identifier(name: "ta"),
withValue: P4Value(
P4ArrayValue(
withType: P4QualifiedType(P4Int()),
withValue: [
P4Value(P4IntValue(withValue: 1)), P4Value(P4IntValue(withValue: 2)),
P4Value(P4IntValue(withValue: 3)),
])))
let program = try #UseOkResult(
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration, withGlobalInstances: test_declarations))
let runtime = try #UseOkResult(
P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(
program: program, withGlobalValues: test_values))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.reject)
}
@Test func test_array_access3() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
transition select (ta[0] == 1) {
true: accept;
false: reject;
};
}
};
"""
var test_declarations = StaticVarValueScopes().enter()
test_declarations = test_declarations.declare(
identifier: Identifier(name: "ta"),
withValue: (P4QualifiedType(P4Array(withValueType: P4QualifiedType(P4Int()))), .none))
var test_values = VarValueScopes().enter()
test_values = test_values.declare(
identifier: Identifier(name: "ta"),
withValue: P4Value(
P4ArrayValue(
withType: P4QualifiedType(P4Int()),
withValue: [
P4Value(P4IntValue(withValue: 1)), P4Value(P4IntValue(withValue: 2)),
P4Value(P4IntValue(withValue: 3)),
])))
let program = try #UseOkResult(
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration, withGlobalInstances: test_declarations))
let runtime = try #UseOkResult(
P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(
program: program, withGlobalValues: test_values))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_array_access4() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
transition select (ta[1] == 2) {
true: accept;
false: reject;
};
}
};
"""
var test_declarations = StaticVarValueScopes().enter()
test_declarations = test_declarations.declare(
identifier: Identifier(name: "ta"),
withValue: (P4QualifiedType(P4Array(withValueType: P4QualifiedType(P4Int()))), .none))
var test_values = VarValueScopes().enter()
test_values = test_values.declare(
identifier: Identifier(name: "ta"),
withValue: P4Value(
P4ArrayValue(
withType: P4QualifiedType(P4Int()),
withValue: [
P4Value(P4IntValue(withValue: 1)), P4Value(P4IntValue(withValue: 2)),
P4Value(P4IntValue(withValue: 3)),
])))
let program = try #UseOkResult(
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration, withGlobalInstances: test_declarations))
let runtime = try #UseOkResult(
P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(
program: program, withGlobalValues: test_values))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_array_access_nested() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
int where_to = ta[0][0];
transition select (where_to == 5) {
true: accept;
false: reject;
};
}
};
"""
var test_declarations = StaticVarValueScopes().enter()
test_declarations = test_declarations.declare(
identifier: Identifier(name: "ta"),
withValue: (
P4QualifiedType(
P4Array(withValueType: P4QualifiedType(P4Array(withValueType: P4QualifiedType(P4Int()))))),
.none
))
var test_values = VarValueScopes().enter()
let nested = P4Value(
P4ArrayValue(
withType: P4QualifiedType(P4Int()),
withValue: [
P4Value(P4IntValue(withValue: 5)), P4Value(P4IntValue(withValue: 2)),
P4Value(P4IntValue(withValue: 3)),
]))
test_values = test_values.declare(
identifier: Identifier(name: "ta"),
withValue: P4Value(
P4ArrayValue(
withType: P4QualifiedType(P4Array(withValueType: P4QualifiedType(P4Int()))),
withValue: [nested])))
let program = try #UseOkResult(
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration, withGlobalInstances: test_declarations))
let runtime = try #UseOkResult(
P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(
program: program, withGlobalValues: test_values))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_array_set() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
ta[1] = 3;
bool where_to = ta[1] == 3;
transition select (where_to) {
true: accept;
false: reject;
};
}
};
"""
var test_declarations = StaticVarValueScopes().enter()
test_declarations = test_declarations.declare(
identifier: Identifier(name: "ta"),
withValue: (P4QualifiedType(P4Array(withValueType: P4QualifiedType(P4Int()))), .none))
var test_values = VarValueScopes().enter()
test_values = test_values.declare(
identifier: Identifier(name: "ta"),
withValue: P4Value(
P4ArrayValue(
withType: P4QualifiedType(P4Int()),
withValue: [
P4Value(P4IntValue(withValue: 1)), P4Value(P4IntValue(withValue: 2)),
P4Value(P4IntValue(withValue: 3)),
])))
let program = try #UseOkResult(
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration, withGlobalInstances: test_declarations))
let runtime = try #UseOkResult(
P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(
program: program, withGlobalValues: test_values))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_array_set_nested() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
ta[0][0] = 5;
int where_to = ta[0][0];
transition select (where_to == 5) {
true: accept;
false: reject;
};
}
};
"""
var test_declarations = StaticVarValueScopes().enter()
test_declarations = test_declarations.declare(
identifier: Identifier(name: "ta"),
withValue: (
P4QualifiedType(
P4Array(withValueType: P4QualifiedType(P4Array(withValueType: P4QualifiedType(P4Int()))))),
.none
))
var test_values = VarValueScopes().enter()
let nested = P4Value(
P4ArrayValue(
withType: P4QualifiedType(P4Int()),
withValue: [
P4Value(P4IntValue(withValue: 1)), P4Value(P4IntValue(withValue: 2)),
P4Value(P4IntValue(withValue: 3)),
]))
test_values = test_values.declare(
identifier: Identifier(name: "ta"),
withValue: P4Value(
P4ArrayValue(
withType: P4QualifiedType(P4Array(withValueType: P4QualifiedType(P4Int()))),
withValue: [nested])))
let program = try #UseOkResult(
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration, withGlobalInstances: test_declarations))
let runtime = try #UseOkResult(
P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(
program: program, withGlobalValues: test_values))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@@ -1,220 +0,0 @@
// p4rse, Copyright 202false, 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 <https://www.gnu.org/licenses/>.
import Common
import Foundation
import Macros
import P4Lang
import P4Runtime
import SwiftTreeSitter
import Testing
import TreeSitter
import TreeSitterP4
@testable import P4Compiler
// And/Or binary operator tests ...
@Test func test_simple_parser_binary_operator_and() async throws {
let simple = """
parser main_parser() {
state start {
transition select (true && true) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_simple_parser_binary_operator_and2() async throws {
let simple = """
parser main_parser() {
state start {
transition select (false && false) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.reject)
}
@Test func test_simple_parser_binary_operator_and3() async throws {
let simple = """
parser main_parser() {
state start {
transition select (false && true) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.reject)
}
@Test func test_simple_parser_binary_operator_and4() async throws {
let simple = """
parser main_parser() {
state start {
transition select (true && false) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.reject)
}
@Test func test_simple_parser_binary_operator_or() async throws {
let simple = """
parser main_parser() {
state start {
transition select (true || true) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_simple_parser_binary_operator_or2() async throws {
let simple = """
parser main_parser() {
state start {
transition select (true || false) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_simple_parser_binary_operator_or3() async throws {
let simple = """
parser main_parser() {
state start {
transition select (false || true) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_simple_parser_binary_operator_or4() async throws {
let simple = """
parser main_parser() {
state start {
transition select (false || false) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.reject)
}
@Test func test_simple_parser_binary_operator_grouped() async throws {
let simple = """
parser main_parser() {
state start {
transition select (true && (false || true)) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_simple_parser_binary_operator_grouped2() async throws {
let simple = """
parser main_parser() {
state start {
transition select (true && (false || false)) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.reject)
}
@@ -1,296 +0,0 @@
// p4rse, Copyright 202false, 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 <https://www.gnu.org/licenses/>.
import Common
import Foundation
import Macros
import P4Lang
import P4Runtime
import SwiftTreeSitter
import Testing
import TreeSitter
import TreeSitterP4
@testable import P4Compiler
// Bool binary operator tests ...
@Test func test_simple_parser_binary_operator_equal_bool() async throws {
let simple = """
parser main_parser() {
state start {
transition select (true == true) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_simple_parser_binary_operator_equal_not_equal_bool() async throws {
let simple = """
parser main_parser() {
state start {
transition select (true == false) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.reject)
}
@Test func test_simple_parser_binary_operator_less_than_bool() async throws {
let simple = """
parser main_parser() {
state start {
transition select (false < true) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_simple_parser_binary_operator_less_than_equal_bool() async throws {
let simple = """
parser main_parser() {
state start {
transition select (false <= true) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_simple_parser_binary_operator_less_than_equal_bool2() async throws {
let simple = """
parser main_parser() {
state start {
transition select (true <= true) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_simple_parser_binary_operator_greater_than_bool() async throws {
let simple = """
parser main_parser() {
state start {
transition select (true > false) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_simple_parser_binary_operator_greater_than_equal_bool() async throws {
let simple = """
parser main_parser() {
state start {
transition select (false >= false) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_simple_parser_binary_operator_greater_than_equal_bool2() async throws {
let simple = """
parser main_parser() {
state start {
transition select (true >= false) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_simple_parser_binary_operator_less_than_bool_not() async throws {
let simple = """
parser main_parser() {
state start {
transition select (true < false) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.reject)
}
@Test func test_simple_parser_binary_operator_less_than_bool_not2() async throws {
let simple = """
parser main_parser() {
state start {
transition select (true < true) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.reject)
}
@Test func test_simple_parser_binary_operator_less_than_equal_bool_not() async throws {
let simple = """
parser main_parser() {
state start {
transition select (true <= false) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.reject)
}
@Test func test_simple_parser_binary_operator_greater_than_bool_not() async throws {
let simple = """
parser main_parser() {
state start {
transition select (false > true) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.reject)
}
@Test func test_simple_parser_binary_operator_greater_than_bool_not2() async throws {
let simple = """
parser main_parser() {
state start {
transition select (true > true) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.reject)
}
@Test func test_simple_parser_binary_operator_greater_than_equal_bool_not() async throws {
let simple = """
parser main_parser() {
state start {
transition select (false >= true) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.reject)
}
@@ -1,549 +0,0 @@
// 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 <https://www.gnu.org/licenses/>.
import Common
import Foundation
import Macros
import P4Lang
import P4Runtime
import SwiftTreeSitter
import Testing
import TreeSitter
import TreeSitterP4
@testable import P4Compiler
// Integer binary operator tests ...
@Test func test_simple_parser_binary_operator_equal_integer() async throws {
let simple = """
parser main_parser() {
state start {
transition select (5 == 5) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_simple_parser_binary_operator_equal_not_equal_integer() async throws {
let simple = """
parser main_parser() {
state start {
transition select (5 == 6) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.reject)
}
@Test func test_simple_parser_binary_operator_less_than_integer() async throws {
let simple = """
parser main_parser() {
state start {
transition select (5 < 6) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_simple_parser_binary_operator_less_than_equal_integer() async throws {
let simple = """
parser main_parser() {
state start {
transition select (5 <= 6) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_simple_parser_binary_operator_less_than_equal_integer2() async throws {
let simple = """
parser main_parser() {
state start {
transition select (6 <= 6) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_simple_parser_binary_operator_greater_than_integer() async throws {
let simple = """
parser main_parser() {
state start {
transition select (7 > 6) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_simple_parser_binary_operator_greater_than_equal_integer() async throws {
let simple = """
parser main_parser() {
state start {
transition select (6 >= 6) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_simple_parser_binary_operator_greater_than_equal_integer2() async throws {
let simple = """
parser main_parser() {
state start {
transition select (7 >= 6) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_simple_parser_binary_operator_less_than_integer_not() async throws {
let simple = """
parser main_parser() {
state start {
transition select (6 < 5) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.reject)
}
@Test func test_simple_parser_binary_operator_less_than_integer_not2() async throws {
let simple = """
parser main_parser() {
state start {
transition select (5 < 5) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.reject)
}
@Test func test_simple_parser_binary_operator_less_than_equal_integer_not() async throws {
let simple = """
parser main_parser() {
state start {
transition select (6 <= 5) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.reject)
}
@Test func test_simple_parser_binary_operator_greater_than_integer_not() async throws {
let simple = """
parser main_parser() {
state start {
transition select (5 > 6) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.reject)
}
@Test func test_simple_parser_binary_operator_greater_than_integer_not2() async throws {
let simple = """
parser main_parser() {
state start {
transition select (5 > 5) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.reject)
}
@Test func test_simple_parser_binary_operator_greater_than_equal_integer_not() async throws {
let simple = """
parser main_parser() {
state start {
transition select (5 >= 6) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.reject)
}
// Add Integers
@Test func test_simple_parser_binary_operator_add_integer() async throws {
let simple = """
parser main_parser() {
state start {
transition select (10 == (5 + 5)) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_simple_parser_binary_operator_add_non_integer() async throws {
let simple = """
parser main_parser() {
state start {
transition select (true + false) {
true: accept;
false: reject;
};
}
};
"""
#expect(
#RequireErrorResult(
Error(
withMessage:
"{72, 12}: Could not parse transition select expression selector expression: Mathematical operation on operands with non-int type is not allowed"
),
SpecialCompilers.ProgramCompiler.Compile(simple)))
}
@Test func test_simple_parser_binary_operator_add_non_integer2() async throws {
let simple = """
parser main_parser() {
state start {
transition select (5 + false) {
true: accept;
false: reject;
};
}
};
"""
#expect(
#RequireErrorResult(
Error(
withMessage:
"{72, 9}: Could not parse transition select expression selector expression: Types of values used with binary expression are not the same"
),
SpecialCompilers.ProgramCompiler.Compile(simple)))
}
// Subtract Integers
@Test func test_simple_parser_binary_operator_subtract_integer() async throws {
let simple = """
parser main_parser() {
state start {
transition select (0 == (5 - 5)) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_simple_parser_binary_operator_subtract_non_integer() async throws {
let simple = """
parser main_parser() {
state start {
transition select (true - false) {
true: accept;
false: reject;
};
}
};
"""
#expect(
#RequireErrorResult(
Error(
withMessage:
"{72, 12}: Could not parse transition select expression selector expression: Mathematical operation on operands with non-int type is not allowed"
),
SpecialCompilers.ProgramCompiler.Compile(simple)))
}
@Test func test_simple_parser_binary_operator_subtract_non_integer2() async throws {
let simple = """
parser main_parser() {
state start {
transition select (5 - false) {
true: accept;
false: reject;
};
}
};
"""
#expect(
#RequireErrorResult(
Error(
withMessage:
"{72, 9}: Could not parse transition select expression selector expression: Types of values used with binary expression are not the same"
),
SpecialCompilers.ProgramCompiler.Compile(simple)))
}
// Multiply Integers
@Test func test_simple_parser_binary_operator_multiply_integer() async throws {
let simple = """
parser main_parser() {
state start {
transition select (25 == (5 * 5)) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_simple_parser_binary_operator_multiply_non_integer() async throws {
let simple = """
parser main_parser() {
state start {
transition select (true * false) {
true: accept;
false: reject;
};
}
};
"""
#expect(
#RequireErrorResult(
Error(
withMessage:
"{72, 12}: Could not parse transition select expression selector expression: Mathematical operation on operands with non-int type is not allowed"
),
SpecialCompilers.ProgramCompiler.Compile(simple)))
}
@Test func test_simple_parser_binary_operator_multiply_non_integer2() async throws {
let simple = """
parser main_parser() {
state start {
transition select (5 * false) {
true: accept;
false: reject;
};
}
};
"""
#expect(
#RequireErrorResult(
Error(
withMessage:
"{72, 9}: Could not parse transition select expression selector expression: Types of values used with binary expression are not the same"
),
SpecialCompilers.ProgramCompiler.Compile(simple)))
}
// Divide Integers
@Test func test_simple_parser_binary_operator_divide_integer() async throws {
let simple = """
parser main_parser() {
state start {
transition select (1 == (5 / 5)) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_simple_parser_binary_operator_divide_non_integer() async throws {
let simple = """
parser main_parser() {
state start {
transition select (true / false) {
true: accept;
false: reject;
};
}
};
"""
#expect(
#RequireErrorResult(
Error(
withMessage:
"{72, 12}: Could not parse transition select expression selector expression: Mathematical operation on operands with non-int type is not allowed"
),
SpecialCompilers.ProgramCompiler.Compile(simple)))
}
@Test func test_simple_parser_binary_operator_divide_non_integer2() async throws {
let simple = """
parser main_parser() {
state start {
transition select (5 / false) {
true: accept;
false: reject;
};
}
};
"""
#expect(
#RequireErrorResult(
Error(
withMessage:
"{72, 9}: Could not parse transition select expression selector expression: Types of values used with binary expression are not the same"
),
SpecialCompilers.ProgramCompiler.Compile(simple)))
}
@@ -1,220 +0,0 @@
// 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 <https://www.gnu.org/licenses/>.
import Common
import Foundation
import Macros
import P4Lang
import P4Runtime
import SwiftTreeSitter
import Testing
import TreeSitter
import TreeSitterP4
@testable import P4Compiler
// String binary operator tests ...
@Test func test_simple_parser_binary_operator_equal_string() async throws {
let simple = """
parser main_parser() {
state start {
transition select ("five" == "five") {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_simple_parser_binary_operator_equal_not_equal_string() async throws {
let simple = """
parser main_parser() {
state start {
transition select ("five" == "six") {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.reject)
}
@Test func test_simple_parser_binary_operator_less_than_string() async throws {
let simple = """
parser main_parser() {
state start {
transition select ("five" < "six") {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_simple_parser_binary_operator_less_than_equal_string() async throws {
let simple = """
parser main_parser() {
state start {
transition select ("six" <= "six") {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_simple_parser_binary_operator_greater_than_string() async throws {
let simple = """
parser main_parser() {
state start {
transition select ("twelve" > "six") {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_simple_parser_binary_operator_greater_than_equal_string() async throws {
let simple = """
parser main_parser() {
state start {
transition select ("twelve" >= "six") {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_simple_parser_binary_operator_less_than_string_not() async throws {
let simple = """
parser main_parser() {
state start {
transition select ("six" < "five") {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.reject)
}
@Test func test_simple_parser_binary_operator_less_than_equal_string_not() async throws {
let simple = """
parser main_parser() {
state start {
transition select ("six" <= "five") {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.reject)
}
@Test func test_simple_parser_binary_operator_greater_than_string_not() async throws {
let simple = """
parser main_parser() {
state start {
transition select ("five" > "six") {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.reject)
}
@Test func test_simple_parser_binary_operator_greater_than_equal_string_not() async throws {
let simple = """
parser main_parser() {
state start {
transition select ("five" >= "six") {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.reject)
}
@@ -1,196 +0,0 @@
// 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 <https://www.gnu.org/licenses/>.
import Common
import Foundation
import Macros
import P4Lang
import P4Runtime
import SwiftTreeSitter
import Testing
import TreeSitter
import TreeSitterP4
@testable import P4Compiler
@Test func test_struct_equality_empty() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
Testing one;
Testing two;
transition select (one == two) {
true: accept;
false: reject;
};
}
};
"""
let fields = P4StructFields([
P4StructFieldIdentifier(name: "yesno", withType: P4QualifiedType(P4Boolean())),
P4StructFieldIdentifier(name: "count", withType: P4QualifiedType(P4Int())),
])
var test_types = TypeTypeScopes().enter()
let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields)
test_types = test_types.declare(identifier: Identifier(name: "Testing"), withValue: struct_type)
let program = try #UseOkResult(
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration, withGlobalInstances: .none, withGlobalTypes: test_types))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_struct_equality_one_empty() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
Testing one;
Testing two;
one.yesno = true;
transition select (one == two) {
true: accept;
false: reject;
};
}
};
"""
let fields = P4StructFields([
P4StructFieldIdentifier(name: "yesno", withType: P4QualifiedType(P4Boolean())),
P4StructFieldIdentifier(name: "count", withType: P4QualifiedType(P4Int())),
])
var test_types = TypeTypeScopes().enter()
let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields)
test_types = test_types.declare(identifier: Identifier(name: "Testing"), withValue: struct_type)
let program = try #UseOkResult(
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration, withGlobalInstances: .none, withGlobalTypes: test_types))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.reject)
}
@Test func test_struct_equality_neither_empty() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
Testing one;
Testing two;
one.yesno = true;
two.yesno = true;
transition select (one == two) {
true: accept;
false: reject;
};
}
};
"""
let fields = P4StructFields([
P4StructFieldIdentifier(name: "yesno", withType: P4QualifiedType(P4Boolean())),
P4StructFieldIdentifier(name: "count", withType: P4QualifiedType(P4Int())),
])
var test_types = TypeTypeScopes().enter()
let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields)
test_types = test_types.declare(identifier: Identifier(name: "Testing"), withValue: struct_type)
let program = try #UseOkResult(
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration, withGlobalInstances: .none, withGlobalTypes: test_types))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_struct_equality_neither_empty2() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
Testing one;
Testing two;
one.yesno = true;
two.yesno = true;
one.count = 5;
two.count = 5;
transition select (one == two) {
true: accept;
false: reject;
};
}
};
"""
let fields = P4StructFields([
P4StructFieldIdentifier(name: "yesno", withType: P4QualifiedType(P4Boolean())),
P4StructFieldIdentifier(name: "count", withType: P4QualifiedType(P4Int())),
])
var test_types = TypeTypeScopes().enter()
let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields)
test_types = test_types.declare(identifier: Identifier(name: "Testing"), withValue: struct_type)
let program = try #UseOkResult(
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration, withGlobalInstances: .none, withGlobalTypes: test_types))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_struct_equality_neither_empty3() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
Testing one;
Testing two;
one.yesno = true;
two.yesno = true;
one.count = 5;
two.count = 6;
transition select (one == two) {
true: accept;
false: reject;
};
}
};
"""
let fields = P4StructFields([
P4StructFieldIdentifier(name: "yesno", withType: P4QualifiedType(P4Boolean())),
P4StructFieldIdentifier(name: "count", withType: P4QualifiedType(P4Int())),
])
var test_types = TypeTypeScopes().enter()
let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields)
test_types = test_types.declare(identifier: Identifier(name: "Testing"), withValue: struct_type)
let program = try #UseOkResult(
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration, withGlobalInstances: .none, withGlobalTypes: test_types))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.reject)
}
-51
View File
@@ -1,51 +0,0 @@
// 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 <https://www.gnu.org/licenses/>.
import Foundation
import Testing
/// Success
///
@CliTest()
func simple_cli_test() -> [String] {
return ["p4ce", "--plain", "compile", "simple.p4", "-I", "TestData/Sources/"]
}
@CliTest()
func simple_cli_testa() -> [String] {
return ["p4ce", "--plain", "compile", "simple.p4", "-I", "TestData/Sources/"]
}
@CliTest()
func simple_cli_preprocessor_test() -> [String] {
return ["p4ce", "--plain", "preprocess", "simple.p4", "-I", "TestData/Sources/"]
}
@CliTest()
func simple_cli_preprocessor_test_file_not_found() -> [String] {
return ["p4ce", "--plain", "preprocess", "simple.p", "-I", "TestData/Sources/"]
}
@CliTest()
func simple_cli_compilation_error() -> [String] {
return ["p4ce", "--plain", "compile", "action-parameters-wrong-order.p4", "-I", "TestData/Sources/"]
}
@CliTest()
func simple_cli_compilation_error_with_includes() -> [String] {
return ["p4ce", "--plain", "compile", "file-loc-error.p4", "-I", "TestData/Sources/"]
}
@@ -1,97 +0,0 @@
// 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 <https://www.gnu.org/licenses/>.
import Common
import Foundation
import Macros
import P4Compiler
import P4Lang
import P4Runtime
import SwiftTreeSitter
import Testing
import TreeSitter
import TreeSitterP4
@testable import P4Runtime
func shrink(_ from: String) -> String {
return from.replacing(Regex(#/\n[\s]+/#), with: "").replacing("\n", with: "")
}
@Test func test_codegen_parser_state_direct_transition() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
true;
transition accept;
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let cg = try #UseOkResult(CodeGenerator().codeGen(program))
let expected = shrink(
"""
[
{
name: "main_parser",
init_state: "start",
parse_states: [
{
name: "start",
transitions: []
},
]
}
]
""")
#expect(expected == cg.getGeneratedCode())
}
@Test func test_codegen_parser_state_select_transition() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
transition select (false) {
true: reject;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let cg = try #UseOkResult(CodeGenerator().codeGen(program))
/// TODO: Fix this test.
let expected = shrink(
"""
[
{
name: "main_parser",
init_state: "start",
parse_states: [
{
name: "start",
transitions: [Select]
},
]
}
]
""")
#expect(expected == cg.getGeneratedCode())
}
@@ -18,34 +18,33 @@
import Common
import Foundation
import Macros
import P4Lang
import P4Runtime
import SwiftTreeSitter
import Testing
import TreeSitter
import TreeSitterP4
import P4CodeGen
@testable import Macros
@testable import P4Compiler
func wrapper_test_mustor() -> Int {
let x: Int? = 2
var i = 0
#MustOr(result: i, thing: x, or: 1)
return i
}
func wrapper_test_mustor_none() -> Int {
let x: Int? = .none
var i = 0
#MustOr(result: i, thing: x, or: 1)
return i
}
@Test func test_mustor() async throws {
#expect(wrapper_test_mustor() == 2)
}
@Test func test_mustor_none() async throws {
#expect(wrapper_test_mustor_none() == 1)
@Test func test_text_serializer() async throws {
let simple_parser_declaration = """
parser main_parser(inout int x) {
state start {
true;
transition accept;
}
state start {
transition select (true) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let v = TextSerializer()
let c = TextSerializerContext();
let vd = ASTVisitorDriver();
#expect(#RequireOkResult((vd.visit(program: program, visitor: v, context: c))))
}
-82
View File
@@ -1,82 +0,0 @@
// 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 <https://www.gnu.org/licenses/>.
import Common
import Foundation
import Macros
import P4Lang
import P4Runtime
import SwiftTreeSitter
import Testing
import TreeSitter
import TreeSitterP4
@testable import P4Compiler
@Test func test_simple_parser_with_conditional_statement() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
bool x = true;
string check = "Invalid";
if (x) {
x = false;
check = "valid";
}
transition select (x) {
false: reject;
true: accept;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.reject)
}
@Test func test_simple_parser_with_conditional_statement_and_else() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
bool x = false;
string check = "Invalid";
if (x) {
x = false;
check = "a";
} else {
x = true;
check = "b";
}
transition select (x) {
false: reject;
true: accept;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
-402
View File
@@ -1,402 +0,0 @@
// 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 <https://www.gnu.org/licenses/>.
import Common
import Foundation
import Macros
import P4Lang
import Runtime
import SwiftTreeSitter
import Testing
import TreeSitter
import TreeSitterP4
@testable import P4Compiler
@Test func test_simple_control_declaration() async throws {
let simple_parser_declaration = """
control simple() {
action a() {
}
table t {
key = {
true: exact;
}
}
apply {
}
};
"""
let x = { (tipe: P4Type) -> Bool in
switch tipe {
case let c as Control: c.name == "simple"
default: false
}
}
let program = try! #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
#expect(program.TypesWithTypes(x).count == 1)
}
@Test func test_simple_control_declaration2() async throws {
let simple_parser_declaration = """
struct Testing {
};
control simple() {
action a() {
}
table t {
key = {
true: exact;
}
}
apply {
}
};
control complex() {
action b() {
}
table t {
key = {
true: exact;
}
}
apply {
}
};
"""
let filter = { (tipe: P4Type) -> Bool in
switch tipe {
case let c as Control: c.name == "simple" || c.name == "complex"
default: false
}
}
let program = try! #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
#expect(program.TypesWithTypes(filter).count == 2)
}
@Test func test_simple_control_declaration_with_actions() async throws {
let simple_parser_declaration = """
control simple() {
action a() {
}
table t {
key = {
true: exact;
}
actions = {
a;
}
}
apply {
}
};
"""
let x = { (tipe: P4Type) -> Bool in
switch tipe {
case let c as Control: c.name == "simple"
default: false
}
}
let program = try! #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
#expect(program.TypesWithTypes(x).count == 1)
}
@Test func test_simple_control_declaration_with_misnamed_actions() async throws {
let simple_parser_declaration = """
control simple() {
action a() {
}
table t {
key = {
true: exact;
}
actions = {
b;
}
}
apply {
}
};
"""
#expect(
#RequireErrorResult(
Error(
withMessage:
"{54, 63}: Error(s) parsing property list: {91, 26}: Error(s) parsing table actions: Cannot find b in lexical scope."
),
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
)
}
@Test func test_simple_control_declaration_with_misnamed_actions2() async throws {
let simple_parser_declaration = """
control simple() {
action a() {
}
table t {
key = {
true: exact;
}
actions = {
a;
b;
}
}
apply {
}
};
"""
#expect(
#RequireErrorResult(
Error(
withMessage:
"{54, 72}: Error(s) parsing property list: {91, 35}: Error(s) parsing table actions: Cannot find b in lexical scope."
),
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
)
}
@Test func test_simple_control_declaration_with_mistyped_actions() async throws {
let simple_parser_declaration = """
bool a() {
return true;
};
control simple() {
table t {
key = {
true: exact;
}
actions = {
a;
}
}
apply {
}
};
"""
#expect(
#RequireErrorResult(
Error(
withMessage:
"{64, 63}: Error(s) parsing property list: {101, 26}: Error(s) parsing table actions: {101, 26}: a does not name an action"
),
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
)
}
@Test func test_simple_control_declaration_with_parameters() async throws {
let simple_parser_declaration = """
control simple(bool x, bool y) {
action a() {
}
table t {
key = {
x: exact;
y: exact;
}
}
apply {
}
};
"""
#expect(#RequireOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration)))
}
@Test func test_simple_control_declaration_with_multiple_tables() async throws {
let simple_parser_declaration = """
control simple(bool x, bool y, bool a, bool b) {
action a() {
}
table t {
key = {
x: exact;
y: exact;
}
}
table u {
key = {
a: exact;
b: exact;
}
}
apply {
}
};
"""
#expect(
#RequireErrorResult(
Error(
withMessage: "{0, 215}: More than one table in control declaration"
),
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
)
}
@Test func test_simple_control_declaration_with_action_using_parameter() async throws {
let simple_parser_declaration = """
control simple(bool x, bool y) {
action a(int z) {
z = 5;
}
table t {
key = {
x: exact;
y: exact;
}
}
apply {
}
};
"""
#expect(#RequireOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration)))
}
@Test func test_simple_control_declaration_with_action_using_parameter_wrong_type() async throws {
let simple_parser_declaration = """
control simple(bool x, bool y) {
action a(int z) {
z = false;
}
table t {
key = {
x: exact;
y: exact;
}
}
apply {
}
};
"""
#expect(
#RequireErrorResult(
Error(
withMessage:
"{57, 10}: Failed to parse a statement element: {57, 1}: Cannot assign value with type Boolean to identifier z with type Int (width: Infinite)"
),
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
)
}
@Test func test_simple_control_declaration_with_element_after_apply() async throws {
let simple_parser_declaration = """
control simple(bool x, bool y) {
action a(int z) {
z = false;
}
table t {
key = {
x: exact;
y: exact;
}
}
apply {
}
table x {
key = {
x: exact;
y: exact;
}
}
};
"""
#expect(
#RequireErrorResult(
Error(
withMessage:
"Could not compile the P4 program"
),
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
)
}
@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: P4Type) -> Bool in
switch tipe {
case let c as Control: c.name == "simple"
default: false
}
}
let program = try! #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
#expect(program.TypesWithTypes(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"),
SpecialCompilers.ProgramCompiler.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"),
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
)
}
-623
View File
@@ -1,623 +0,0 @@
// 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 <https://www.gnu.org/licenses/>.
import Common
import Foundation
import Macros
import P4Lang
import P4Runtime
import SwiftTreeSitter
import Testing
import TreeSitter
import TreeSitterP4
@testable import P4Compiler
@Test func test_control_single_key() async throws {
let simple_parser_declaration = """
control simple(inout int result, bool x) {
action a() {
result = 5;
}
action b() {
result = 7;
}
table t {
key = {
x: exact;
}
actions = {
a;
b;
}
}
apply {
}
};
"""
let program = try! #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
// Pull the control out of the compiled program.
let controls = program.TypesWithTypes { (tipe: P4Type) -> Bool in
return switch tipe {
case let c as Control: c.name == "simple"
default: false
}
}
var control = ((controls[0]) as! Control)
// Add entries to the table.
control = control.updateTable(
addEntry: (
P4Value(P4BooleanValue(withValue: true)),
TypedIdentifier(name: "a", withType: P4QualifiedType(Action()))
)
).updateTable(
addEntry: (
P4Value(P4BooleanValue(withValue: false)),
TypedIdentifier(name: "b", withType: P4QualifiedType(Action()))
))
// Set a variable in the global scope for the inout first parameter.
var global_values = VarValueScopes().enter()
global_values = global_values.declare(
identifier: Identifier(name: "result_arg"),
withValue: P4Value(
P4IntValue(withValue: 0),
P4QualifiedType(P4Int())))
let runtime = try #UseOkResult(
P4Runtime.Runtime<P4TableHitMissValue, Control>.create(
control: control, withGlobalValues: global_values))
let (hit_miss, updated_execution) = try #UseOkResult(
runtime.run(
withArguments: ArgumentList([
Argument(
TypedIdentifier(name: "result_arg", withType: P4QualifiedType(P4Int())), atIndex: 0),
Argument(P4Value(P4BooleanValue(withValue: true)), atIndex: 1),
])))
// We expect there to be a hit.
#expect(hit_miss == P4TableHitMissValue.Hit)
// And that the proper action was invoked.
let result_arg = try #UseOkResult(
updated_execution.scopes.lookup(identifier: Identifier(name: "result_arg")))
#expect(result_arg.eq(P4Value(P4IntValue(withValue: 5))))
}
@Test func test_control_single_key_false() async throws {
let simple_parser_declaration = """
control simple(inout int result, bool x) {
action a() {
result = 5;
}
action b() {
result = 7;
}
table t {
key = {
x: exact;
}
actions = {
a;
b;
}
}
apply {
}
};
"""
let program = try! #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
// Pull the control out of the compiled program.
let controls = program.TypesWithTypes { (tipe: P4Type) -> Bool in
switch tipe {
case let c as Control: c.name == "simple"
default: false
}
}
var control = ((controls[0]) as! Control)
// Add entries to the table.
control = control.updateTable(
addEntry: (
P4Value(P4BooleanValue(withValue: true)),
TypedIdentifier(name: "a", withType: P4QualifiedType(Action()))
)
).updateTable(
addEntry: (
P4Value(P4BooleanValue(withValue: false)),
TypedIdentifier(name: "b", withType: P4QualifiedType(Action()))
))
// Set a variable in the global scope for the inout first parameter.
var global_values = VarValueScopes().enter()
global_values = global_values.declare(
identifier: Identifier(name: "result_arg"),
withValue: P4Value(
P4IntValue(withValue: 0),
P4QualifiedType(P4Int())))
let runtime = try #UseOkResult(
P4Runtime.Runtime<P4TableHitMissValue, Control>.create(
control: control, withGlobalValues: global_values))
let (hit_miss, updated_execution) = try #UseOkResult(
runtime.run(
withArguments: ArgumentList([
Argument(
TypedIdentifier(name: "result_arg", withType: P4QualifiedType(P4Int())), atIndex: 0),
Argument(P4Value(P4BooleanValue(withValue: false)), atIndex: 1),
])))
// We expect there to be a hit.
#expect(hit_miss == P4TableHitMissValue.Hit)
// And that the proper action was invoked.
let result_arg = try #UseOkResult(
updated_execution.scopes.lookup(identifier: Identifier(name: "result_arg")))
#expect(result_arg.eq(P4Value(P4IntValue(withValue: 7))))
}
@Test func test_control_single_integer_key_hit() async throws {
let simple_parser_declaration = """
control simple(inout int result, int x) {
action a() {
result = 5;
}
action b() {
result = 7;
}
table t {
key = {
x: exact;
}
actions = {
a;
b;
}
}
apply {
}
};
"""
let program = try! #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
// Pull the control out of the compiled program.
let controls = program.TypesWithTypes { (tipe: P4Type) -> Bool in
switch tipe {
case let c as Control: c.name == "simple"
default: false
}
}
var control = ((controls[0]) as! Control)
// Add entries to the table.
control = control.updateTable(
addEntry: (
P4Value(P4IntValue(withValue: 5)),
TypedIdentifier(name: "a", withType: P4QualifiedType(Action()))
)
).updateTable(
addEntry: (
P4Value(P4IntValue(withValue: 2)),
TypedIdentifier(name: "b", withType: P4QualifiedType(Action()))
))
// Set a variable in the global scope for the inout first parameter.
var global_values = VarValueScopes().enter()
global_values = global_values.declare(
identifier: Identifier(name: "result_arg"),
withValue: P4Value(
P4IntValue(withValue: 0),
P4QualifiedType(P4Int())))
let runtime = try #UseOkResult(
P4Runtime.Runtime<P4TableHitMissValue, Control>.create(
control: control, withGlobalValues: global_values))
let (hit_miss, updated_execution) = try #UseOkResult(
runtime.run(
withArguments: ArgumentList([
Argument(
TypedIdentifier(name: "result_arg", withType: P4QualifiedType(P4Int())), atIndex: 0),
Argument(P4Value(P4IntValue(withValue: 5)), atIndex: 1),
])))
// We expect there to be a hit.
#expect(hit_miss == P4TableHitMissValue.Hit)
let result_arg = try #UseOkResult(
updated_execution.scopes.lookup(identifier: Identifier(name: "result_arg")))
#expect(result_arg.eq(P4Value(P4IntValue(withValue: 5))))
}
@Test func test_control_single_integer_key_miss() async throws {
let simple_parser_declaration = """
control simple(inout int result, int x) {
action a() {
result = 5;
}
action b() {
result = 7;
}
table t {
key = {
x: exact;
}
actions = {
a;
b;
}
}
apply {
}
};
"""
let program = try! #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
// Pull the control out of the compiled program.
let controls = program.TypesWithTypes { (tipe: P4Type) -> Bool in
return switch tipe {
case let c as Control: c.name == "simple"
default: false
}
}
var control = ((controls[0]) as! Control)
// Add entries to the table.
control = control.updateTable(
addEntry: (
P4Value(P4IntValue(withValue: 1)),
TypedIdentifier(name: "a", withType: P4QualifiedType(Action()))
)
).updateTable(
addEntry: (
P4Value(P4IntValue(withValue: 2)),
TypedIdentifier(name: "b", withType: P4QualifiedType(Action()))
))
// Set a variable in the global scope for the inout first parameter.
var global_values = VarValueScopes().enter()
global_values = global_values.declare(
identifier: Identifier(name: "result_arg"),
withValue: P4Value(
P4IntValue(withValue: 0),
P4QualifiedType(P4Int())))
let runtime = try #UseOkResult(
P4Runtime.Runtime<P4TableHitMissValue, Control>.create(
control: control, withGlobalValues: global_values))
let (hit_miss, updated_execution) = try #UseOkResult(
runtime.run(
withArguments: ArgumentList([
Argument(
TypedIdentifier(name: "result_arg", withType: P4QualifiedType(P4Int())), atIndex: 0),
Argument(P4Value(P4IntValue(withValue: 3)), atIndex: 1),
])))
// We expect there to be a hit.
#expect(hit_miss == P4TableHitMissValue.Miss)
let result_arg = try #UseOkResult(
updated_execution.scopes.lookup(identifier: Identifier(name: "result_arg")))
#expect(result_arg.eq(P4Value(P4IntValue(withValue: 0))))
}
@Test func test_control_multiple_keys() async throws {
let simple_parser_declaration = """
control simple(inout int result, bool x, int f) {
action a() {
result = 5;
}
action b() {
result = 7;
}
table t {
key = {
x: exact;
f: exact;
}
actions = {
a;
b;
}
}
apply {
}
};
"""
let program = try! #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
// Pull the control out of the compiled program.
let controls = program.TypesWithTypes { (tipe: P4Type) -> Bool in
return switch tipe {
case let c as Control: c.name == "simple"
default: false
}
}
var control = ((controls[0]) as! Control)
// Add entries to the table.
control = control.updateTable(
addEntry: (
P4Value(P4BooleanValue(withValue: true)),
TypedIdentifier(name: "a", withType: P4QualifiedType(Action()))
)
).updateTable(
addEntry: (
P4Value(P4IntValue(withValue: 5)),
TypedIdentifier(name: "b", withType: P4QualifiedType(Action()))
))
// Set a variable in the global scope for the inout first parameter.
var global_values = VarValueScopes().enter()
global_values = global_values.declare(
identifier: Identifier(name: "result_arg"),
withValue: P4Value(
P4IntValue(withValue: 0),
P4QualifiedType(P4Int())))
let runtime = try #UseOkResult(
P4Runtime.Runtime<P4TableHitMissValue, Control>.create(
control: control, withGlobalValues: global_values))
let (hit_miss, updated_execution) = try #UseOkResult(
runtime.run(
withArguments: ArgumentList([
Argument(
TypedIdentifier(name: "result_arg", withType: P4QualifiedType(P4Int())), atIndex: 0),
Argument(P4Value(P4BooleanValue(withValue: false)), atIndex: 1), // false will make the x key miss.
Argument(P4Value(P4IntValue(withValue: 5)), atIndex: 2),
])))
// We expect there to be a hit -- but from the second key!
#expect(hit_miss == P4TableHitMissValue.Hit)
// And that the proper action was invoked.
let result_arg = try #UseOkResult(
updated_execution.scopes.lookup(identifier: Identifier(name: "result_arg")))
#expect(result_arg.eq(P4Value(P4IntValue(withValue: 7))))
}
@Test func test_control_key_from_struct() async throws {
let simple_parser_declaration = """
struct K {
int i;
int j;
};
control simple(inout int result, K k) {
action a() {
result = 5;
}
action b() {
result = 7;
}
table t {
key = {
k.i: exact;
}
actions = {
a;
b;
}
}
apply {
}
};
"""
let program = try! #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
// Pull the control out of the compiled program.
let controls = program.TypesWithTypes { (tipe: P4Type) -> Bool in
return switch tipe {
case let c as Control: c.name == "simple"
default: false
}
}
var control = ((controls[0]) as! Control)
let k_fields = P4StructFields([
P4StructFieldIdentifier(name: "i", withType: P4QualifiedType(P4Int())),
P4StructFieldIdentifier(name: "j", withType: P4QualifiedType(P4Int())),
])
let k_type = P4Struct(withName: Identifier(name: "K"), andFields: k_fields)
let k_instance = P4StructValue(
withType: k_type,
andInitializers: [
P4Value(P4IntValue(withValue: 5)),
P4Value(P4IntValue(withValue: 1)),
])
// Add entries to the table.
control = control.updateTable(
addEntry: (
P4Value(P4IntValue(withValue: 5)),
TypedIdentifier(name: "a", withType: P4QualifiedType(Action()))
)
).updateTable(
addEntry: (
P4Value(P4IntValue(withValue: 4)),
TypedIdentifier(name: "b", withType: P4QualifiedType(Action()))
))
// Set a variable in the global scope for the inout first parameter.
var global_values = VarValueScopes().enter()
global_values = global_values.declare(
identifier: Identifier(name: "result_arg"),
withValue: P4Value(
P4IntValue(withValue: 0),
P4QualifiedType(P4Int())))
let runtime = try #UseOkResult(
P4Runtime.Runtime<P4TableHitMissValue, Control>.create(
control: control, withGlobalValues: global_values))
let (hit_miss, updated_execution) = try #UseOkResult(
runtime.run(
withArguments: ArgumentList([
Argument(
TypedIdentifier(name: "result_arg", withType: P4QualifiedType(P4Int())), atIndex: 0),
Argument(P4Value(k_instance), atIndex: 1),
])))
// We expect there to be a hit.
#expect(hit_miss == P4TableHitMissValue.Hit)
// And that the proper action was invoked.
let result_arg = try #UseOkResult(
updated_execution.scopes.lookup(identifier: Identifier(name: "result_arg")))
#expect(result_arg.eq(P4Value(P4IntValue(withValue: 5))))
// Now, check whether the b action can be invoked.
let k_instance2 = P4StructValue(
withType: k_type,
andInitializers: [
P4Value(P4IntValue(withValue: 4)),
P4Value(P4IntValue(withValue: 1)),
])
// Set a variable in the global scope for the inout first parameter.
var next_global_values = VarValueScopes().enter()
next_global_values = global_values.declare(
identifier: Identifier(name: "result_arg"),
withValue: P4Value(
P4IntValue(withValue: 0),
P4QualifiedType(P4Int())))
let runtime2 = try #UseOkResult(
P4Runtime.Runtime<P4TableHitMissValue, Control>.create(
control: control, withGlobalValues: next_global_values))
let (hit_miss2, updated_execution2) = try #UseOkResult(
runtime2.run(
withArguments: ArgumentList([
Argument(
TypedIdentifier(name: "result_arg", withType: P4QualifiedType(P4Int())), atIndex: 0),
Argument(P4Value(k_instance2), atIndex: 1),
])))
// We expect there to be a hit.
#expect(hit_miss2 == P4TableHitMissValue.Hit)
// And that the proper action was invoked.
let result_arg2 = try #UseOkResult(
updated_execution2.scopes.lookup(identifier: Identifier(name: "result_arg")))
#expect(result_arg2.eq(P4Value(P4IntValue(withValue: 7))))
}
@Test func test_control_key_from_struct_miss() async throws {
let simple_parser_declaration = """
struct K {
int i;
int j;
};
control simple(inout int result, K k) {
action a() {
result = 5;
}
action b() {
result = 7;
}
table t {
key = {
k.i: exact;
}
actions = {
a;
b;
}
}
apply {
}
};
"""
let program = try! #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
// Pull the control out of the compiled program.
let controls = program.TypesWithTypes { (tipe: P4Type) -> Bool in
return switch tipe {
case let c as Control: c.name == "simple"
default: false
}
}
var control = ((controls[0]) as! Control)
let k_fields = P4StructFields([
P4StructFieldIdentifier(name: "i", withType: P4QualifiedType(P4Int())),
P4StructFieldIdentifier(name: "j", withType: P4QualifiedType(P4Int())),
])
let k_type = P4Struct(withName: Identifier(name: "K"), andFields: k_fields)
let k_instance = P4StructValue(
withType: k_type,
andInitializers: [
P4Value(P4IntValue(withValue: 8)),
P4Value(P4IntValue(withValue: 1)),
])
// Add entries to the table.
control = control.updateTable(
addEntry: (
P4Value(P4IntValue(withValue: 5)),
TypedIdentifier(name: "a", withType: P4QualifiedType(Action()))
)
).updateTable(
addEntry: (
P4Value(P4IntValue(withValue: 4)),
TypedIdentifier(name: "b", withType: P4QualifiedType(Action()))
))
// Set a variable in the global scope for the inout first parameter.
var global_values = VarValueScopes().enter()
global_values = global_values.declare(
identifier: Identifier(name: "result_arg"),
withValue: P4Value(
P4IntValue(withValue: 0),
P4QualifiedType(P4Int())))
let runtime = try #UseOkResult(
P4Runtime.Runtime<P4TableHitMissValue, Control>.create(
control: control, withGlobalValues: global_values))
let (hit_miss, updated_execution) = try #UseOkResult(
runtime.run(
withArguments: ArgumentList([
Argument(
TypedIdentifier(name: "result_arg", withType: P4QualifiedType(P4Int())), atIndex: 0),
Argument(P4Value(k_instance), atIndex: 1),
])))
// We expect there to be a hit.
#expect(hit_miss == P4TableHitMissValue.Miss)
// And that the proper action was invoked.
let result_arg = try #UseOkResult(
updated_execution.scopes.lookup(identifier: Identifier(name: "result_arg")))
#expect(result_arg.eq(P4Value(P4IntValue(withValue: 0))))
}
-205
View File
@@ -1,205 +0,0 @@
// 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 <https://www.gnu.org/licenses/>.
import Common
import Foundation
import Macros
import P4Runtime
import P4Lang
import SwiftTreeSitter
import Testing
import TreeSitter
import TreeSitterP4
@testable import P4Compiler
@Test func test_struct_declaration_and_field_write() async throws {
let simple_parser_declaration = """
struct Testing {
bool yesno;
int count;
};
parser main_parser() {
state start {
Testing ts;
ts.yesno = true;
bool where_to = ts.yesno;
transition select (where_to) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_struct_declaration_and_field_write_field_read() async throws {
let simple_parser_declaration = """
struct Testing {
bool yesno;
int count;
};
parser main_parser() {
state start {
Testing ts;
ts.yesno = true;
ts.count = 5;
transition select (ts.count == 5) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_struct_declaration_and_field_read_defaults() async throws {
let simple_parser_declaration = """
struct Testing {
bool yesno;
int count;
};
parser main_parser() {
state start {
Testing ts;
transition select (ts.count == 0) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_struct_declaration_and_field_read_defaults_sc() async throws {
let simple_parser_declaration = """
struct Testing {
bool yesno;
int count;
};
parser main_parser() {
state start {
Testing ts;
transition select (ts.count) {
0: accept;
_: reject;
};
}
};
"""
let program = try #UseOkResult(
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_struct_declaration_and_field_read_defaults_sc2() async throws {
let simple_parser_declaration = """
struct Testing {
bool yesno;
int count;
};
parser main_parser() {
state start {
Testing ts;
ts.count = 1;
transition select (ts.count) {
0: accept;
_: reject;
};
}
};
"""
let program = try #UseOkResult(
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.reject)
}
@Test func test_function_declaration() async throws {
let simple_parser_declaration = """
bool functionb() {
int count;
};
"""
#expect(#RequireOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration)))
}
@Test func test_function_declaration_with_parameters() async throws {
let simple_parser_declaration = """
bool functionb(bool x) {
x = true;
};
"""
#expect(#RequireOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration)))
}
@Test func test_function_declaration_with_parameters_and_direction() async throws {
let simple_parser_declaration = """
bool functionb(in bool x, out string y, inout int z) {
x = true;
};
"""
#expect(
#RequireErrorResult(
Error(
withMessage:
"{63, 9}: Failed to parse a statement element: {63, 1}: Cannot assign value with type Boolean to identifier x that is in parameter"
),
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
)
}
@Test func test_function_declaration_with_parameters_and_direction_struct() async throws {
let simple_parser_declaration = """
struct Testing {
bool yesno;
int count;
};
bool functionb(in Testing x, out string y, inout int z) {
x.yesno = true;
};
"""
#expect(
#RequireErrorResult(
Error(
withMessage:
"{120, 15}: Failed to parse a statement element: {120, 7}: Cannot assign to field yesno of x that is in parameter"
),
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
)
}
@@ -1,58 +0,0 @@
// 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 <https://www.gnu.org/licenses/>.
import Common
import Foundation
import Macros
import P4Lang
import P4Runtime
import SwiftTreeSitter
import Testing
import TreeSitter
import TreeSitterP4
@testable import P4Compiler
@Test func test_error_with_location_formatting() async throws {
let formatter = FormatterAnsi()
let e = ErrorWithLocation(sourceLocation: SourceLocation(1, 5), withError: "There was an error")
let formatted = e.format(formatter)
#expect(formatted == "\u{1B}[31;1m{1, 5}\u{1B}[0m: There was an error")
}
@Test func test_errors_with_location_no_formatting() async throws {
let e = ErrorWithLocation(sourceLocation: SourceLocation(1, 5), withError: "There was an error")
let e1 = ErrorWithLocation(
sourceLocation: SourceLocation(10, 5), withError: "There was another error")
let formatted = e.append(error: e1).format(FormatterPlain())
#expect(formatted == "{1, 5}: There was an error\n{10, 5}: There was another error")
}
@Test func test_errors_with_location_ansi_formatting() async throws {
let e = ErrorWithLocation(sourceLocation: SourceLocation(1, 5), withError: "There was an error")
let e1 = ErrorWithLocation(
sourceLocation: SourceLocation(10, 5), withError: "There was another error")
let formatted = e.append(error: e1).format(FormatterAnsi())
#expect(
formatted
== "\u{1B}[31;1m{1, 5}\u{1B}[0m: There was an error\n\u{1B}[31;1m{10, 5}\u{1B}[0m: There was another error"
)
}
-88
View File
@@ -1,88 +0,0 @@
// 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 <https://www.gnu.org/licenses/>.
import Common
import Foundation
import Macros
import P4Lang
import P4Runtime
import SwiftTreeSitter
import Testing
import TreeSitter
import TreeSitterP4
@testable import P4Compiler
@Test func test_expression_grouped_equal() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
bool x = (true == (1 < 4));
transition select (x) {
false: reject;
true: accept;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_expression_grouped_or() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
bool x = (false || (1 < 4));
transition select (x) {
false: reject;
true: accept;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_expression_grouped_and() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
bool x = (false && (1 < 4));
transition select (x) {
false: reject;
true: accept;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.reject)
}
@@ -1,186 +0,0 @@
// 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 <https://www.gnu.org/licenses/>.
import Common
import Foundation
import Macros
import P4Lang
import P4Runtime
import SwiftTreeSitter
import Testing
import TreeSitter
import TreeSitterP4
@testable import P4Compiler
@Test func test_function_call_scoped_name_collision() async throws {
let simple_parser_declaration = """
bool functionb(bool c) {
return c;
};
parser main_parser() {
state start {
int c = 5;
bool b = functionb(true);
transition select (b) {
false: reject;
true: accept;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let parser = try #UseOkResult(program.find_parser(withName: Identifier(name: "main_parser")))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(parser.states.count() == 1)
#expect(state_result == P4Lang.accept)
}
@Test func test_function_call_scoped_name_collision2() async throws {
// Test whether the assignment to c leaks out of the function call scope.
let simple_parser_declaration = """
bool functionb(bool c) {
c = true;
return c;
};
parser main_parser() {
state start {
bool c = false;
bool b = functionb(true);
transition select (c) {
false: reject;
true: accept;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let parser = try #UseOkResult(program.find_parser(withName: Identifier(name: "main_parser")))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(parser.states.count() == 1)
#expect(state_result == P4Lang.reject)
}
@Test func test_function_call_scoped_name_collision_inout() async throws {
let simple_parser_declaration = """
bool functionb(inout bool c) {
c = true;
return c;
};
parser main_parser() {
state start {
bool c = false;
bool b = functionb(c);
transition select (c) {
false: reject;
true: accept;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let parser = try #UseOkResult(program.find_parser(withName: Identifier(name: "main_parser")))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(parser.states.count() == 1)
#expect(state_result == P4Lang.accept)
}
@Test func test_function_call_integer_return_value() async throws {
let simple_parser_declaration = """
int functionb(int c) {
return c;
};
parser main_parser() {
state start {
int c = 5;
transition select (5 == functionb(c)) {
false: reject;
true: accept;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let parser = try #UseOkResult(program.find_parser(withName: Identifier(name: "main_parser")))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(parser.states.count() == 1)
#expect(state_result == P4Lang.accept)
}
@Test func test_function_call_integer_return_value2() async throws {
let simple_parser_declaration = """
int functionb(int c) {
return c;
};
parser main_parser() {
state start {
int c = 5;
transition select (4 == functionb(c)) {
false: reject;
true: accept;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let parser = try #UseOkResult(program.find_parser(withName: Identifier(name: "main_parser")))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(parser.states.count() == 1)
#expect(state_result == P4Lang.reject)
}
@Test func test_function_call_invalid_return_type() async throws {
let simple_parser_declaration = """
int functionb(int c) {
return true;
};
parser main_parser() {
state start {
int c = 5;
transition select (4 == functionb(c)) {
false: reject;
true: accept;
};
}
};
"""
let error = try #UseErrorResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
#expect(error.msg().contains("{29, 12}: Type of expression in return statement (Boolean) is not compatible with function return type (Int (width: Infinite))"))
}
@@ -1,203 +0,0 @@
// 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 <https://www.gnu.org/licenses/>.
import Common
import Foundation
import Macros
import P4Lang
import P4Runtime
import SwiftTreeSitter
import Testing
import TreeSitter
import TreeSitterP4
@testable import P4Compiler
@Test func test_simple_parser_with_transition_select_case_nondefault_expressions() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
transition select (true) {
false: reject;
true: accept;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let parser = try #UseOkResult(program.find_parser(withName: Identifier(name: "main_parser")))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(parser.states.count() == 1)
#expect(state_result == P4Lang.accept)
}
@Test func test_simple_parser_with_transition_select_case_default_expression() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
transition select (5) {
5: reject;
_: accept;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let parser = try #UseOkResult(program.find_parser(withName: Identifier(name: "main_parser")))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(parser.states.count() == 1)
#expect(state_result == P4Lang.reject)
}
@Test func test_simple_parser_with_transition_select_case_default_expression2() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
transition select (1) {
5: reject;
_: accept;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let parser = try #UseOkResult(program.find_parser(withName: Identifier(name: "main_parser")))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(parser.states.count() == 1)
#expect(state_result == P4Lang.accept)
}
@Test func test_simple_parser_with_transition_select_case_default_expression3() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
transition select (6) {
5: reject;
6: reject;
_: accept;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let parser = try #UseOkResult(program.find_parser(withName: Identifier(name: "main_parser")))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(parser.states.count() == 1)
#expect(state_result == P4Lang.reject)
}
@Test func test_simple_parser_with_transition_select_case_invalid_type() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
transition select (6) {
true: reject;
6: reject;
_: accept;
};
}
};
"""
#expect(
#RequireErrorResult(
Error(
withMessage:
"Error(s) parsing select cases: {81, 4}: Key expression of type Boolean is not compatible with selector type Int (width: Infinite)"
),
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration)))
}
@Test func test_select_expression_selection_order() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
transition select (5) {
5: reject;
5: accept;
_: accept;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let parser = try #UseOkResult(program.find_parser(withName: Identifier(name: "main_parser")))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(parser.states.count() == 1)
#expect(state_result == P4Lang.reject)
}
@Test func test_select_expression_from_parser_parameters() async throws {
let simple_parser_declaration = """
parser main_parser(bool pmtr, string smtr, int imtr) {
state start {
transition select (pmtr) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let args = ArgumentList([
Argument(P4Value(P4BooleanValue(withValue: false)), atIndex: 1), Argument(P4Value(P4StringValue(withValue: "Testing")), atIndex: 2), Argument(P4Value(P4IntValue(withValue: 5)), atIndex: 3),
])
let (state_result, _) = try! #UseOkResult(runtime.run(withArguments: args))
#expect(state_result == P4Lang.reject)
}
@Test func test_select_expression_from_parser_parameters2() async throws {
let simple_parser_declaration = """
parser main_parser(bool pmtr, string smtr, int imtr) {
state start {
transition select (imtr == 5) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let args = ArgumentList([
Argument(P4Value(P4BooleanValue(withValue: false)), atIndex: 1), Argument(P4Value(P4StringValue(withValue: "Testing")), atIndex: 2), Argument(P4Value(P4IntValue(withValue: 5)), atIndex: 3),
])
let (state_result, _) = try! #UseOkResult(runtime.run(withArguments: args))
#expect(state_result == P4Lang.accept)
}
-124
View File
@@ -1,124 +0,0 @@
// 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 <https://www.gnu.org/licenses/>.
import Common
import Foundation
import Macros
import P4Lang
import P4Runtime
import SwiftTreeSitter
import Testing
import TreeSitter
import TreeSitterP4
@testable import P4Compiler
public struct Return5: P4FFI {
public func execute(execution: Common.ProgramExecution) -> (
Common.ControlFlow, Common.ProgramExecution
) {
return (ControlFlow.Return(P4Value(P4IntValue(withValue: 5))), execution)
}
public func parameters() -> ParameterList {
return ParameterList()
}
public func type() -> Common.P4QualifiedType {
return P4QualifiedType(
FunctionDeclaration(
named: Identifier(name: "externally"), ofType: P4QualifiedType(P4Int()),
withParameters: ParameterList(), withBody: .none?))
}
public init() {}
}
public struct Return6: P4FFI {
public func execute(execution: Common.ProgramExecution) -> (
Common.ControlFlow, Common.ProgramExecution
) {
return (ControlFlow.Return(P4Value(P4IntValue(withValue: 6))), execution)
}
public func parameters() -> ParameterList {
return ParameterList()
}
public func type() -> Common.P4QualifiedType {
return P4QualifiedType(
FunctionDeclaration(
named: Identifier(name: "externally"), ofType: P4QualifiedType(P4Int()),
withParameters: ParameterList(), withBody: .none?))
}
public init() {}
}
@Test func test_extern_function_declaration() async throws {
let simple_parser_declaration = """
extern int externally();
parser main_parser() {
state start {
int t = externally();
transition select (t == 5) {
true: accept;
false: reject;
};
}
};
"""
let externally = Return5()
let program = try! #UseOkResult(
SpecialCompilers.ProgramCompiler.Compile(
simple_parser_declaration, withGlobalInstances: .none, withGlobalTypes: .none,
withFFIs: [externally]))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_extern_function_declaration2() async throws {
let simple_parser_declaration = """
extern int externally();
parser main_parser() {
state start {
int t = externally();
transition select (t == 5) {
true: accept;
false: reject;
};
}
};
"""
let externally = Return6()
let program = try! #UseOkResult(
SpecialCompilers.ProgramCompiler.Compile(
simple_parser_declaration, withGlobalInstances: .none, withGlobalTypes: .none,
withFFIs: [externally]))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.reject)
}
-115
View File
@@ -1,115 +0,0 @@
// 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 <https://www.gnu.org/licenses/>.
import Common
import Foundation
import Macros
import P4Runtime
import P4Lang
import SwiftTreeSitter
import Testing
import TreeSitter
import TreeSitterP4
@testable import P4Compiler
@Test func test_statement_interloper() async throws {
let simple_parser_declaration = """
parser main_parser() {
state starts {
bool where_to = false;
int va = 5;
transition accept;
}
state start {
bool where_to = true;
where_to = true;
transition select (where_to) {
false: reject;
true: starts;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
var statements_executed: [String] = Array()
let ev = InterloperEvaluator().setStatementInterloper() { (statement, cf, execution) in
statements_executed.append("\(statement)")
}
let (state_result, _) = try! #UseOkResult(runtime.run(withArguments: ArgumentList(), inExecution: ProgramExecution(ev)))
#expect(state_result == P4Lang.accept)
print("statements_executed: \(statements_executed)")
#expect(statements_executed[0].hasPrefix("VariableDeclarationStatement"))
#expect(statements_executed[1].hasPrefix("ParserAssignmentStatement"))
// Moved into starts
#expect(statements_executed[2].hasPrefix("VariableDeclarationStatement"))
#expect(statements_executed[3].hasPrefix("VariableDeclarationStatement"))
}
@Test func test_expression_interloper() async throws {
let simple_parser_declaration = """
parser main_parser() {
state starts {
bool where_to = false;
int va = 5;
transition accept;
}
state start {
bool where_to = true;
where_to = true;
transition select (where_to) {
false: reject;
true: starts;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
var expressions_evaluated: [String] = Array()
let ev = InterloperEvaluator().setExpressionInterloper() { expression, result, execution in
expressions_evaluated.append("\(expression)")
}
let (state_result, _) = try! #UseOkResult(runtime.run(withArguments: ArgumentList(), inExecution: ProgramExecution(ev)))
#expect(state_result == P4Lang.accept)
#expect(expressions_evaluated[0].hasPrefix("Value: true of Boolean"))
#expect(expressions_evaluated[1].hasPrefix("Value: true of Boolean"))
#expect(expressions_evaluated[2].hasPrefix("where_to"))
#expect(expressions_evaluated[3].hasPrefix("Value: false of Boolean"))
#expect(expressions_evaluated[4].hasPrefix("KeysetExpression"))
#expect(expressions_evaluated[5].hasPrefix("Value: true of Boolean"))
#expect(expressions_evaluated[6].hasPrefix("KeysetExpression"))
#expect(expressions_evaluated[7].hasPrefix("SelectCaseExpression"))
#expect(expressions_evaluated[8].hasPrefix("SelectExpression"))
// Moved into starts
#expect(expressions_evaluated[9].hasPrefix("Value: false of Boolean"))
#expect(expressions_evaluated[10].hasPrefix("Value: 5 of Int"))
}
-197
View File
@@ -1,197 +0,0 @@
// 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 <https://www.gnu.org/licenses/>.
import Common
import Foundation
import Macros
import Runtime
import SwiftTreeSitter
import Testing
import TreeSitter
import TreeSitterP4
import P4Lang
@testable import P4Compiler
@Test func test_simple_parser_syntax_error() async throws {
let simple_parser_declaration = """
parser main_parser() {
state
transition start;
}
};
"""
#expect(
#RequireErrorResult(
Error(withMessage: "Could not compile the P4 program"),
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration)))
}
@Test func test_simple_compilation_with_statement() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
true;
transition accept;
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let parser = try #UseOkResult(program.find_parser(withName: Identifier(name: "main_parser")))
#expect(parser.states.count() == 1)
let state = (try! #require(parser.states.find(withIdentifier: Identifier(name: "start"))))
#expect(state.getName() == Identifier(name: "start"))
#expect(state.statements.count == 1)
}
@Test func test_invalid_transition_expression_keyset_expressions() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
transition select (false) {
asdf: reject;
asde: reject;
};
}
};
"""
let compilation_error = try #UseErrorResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
#expect(compilation_error.msg().contains("asde"))
#expect(compilation_error.msg().contains("asdf"))
}
@Test func test_simple_compiler_macro_nodetype_test() async throws {
let simple = """
parser main_parser() {
state start {
transition select (false) {
asdf: reject;
asde: reject;
};
}
};
"""
let p = try! #UseOkResult(ConfigureP4Parser())
let result = try! #require(p.parse(simple))
#expect(
#RequireErrorResult<ParserAssignmentStatement>(
ErrorWithLocation(sourceLocation: SourceLocation(2, 154), withError: "Did not find assignment statement"),
ParserAssignmentStatement.Compile( // Note: Calling ParserAssignmentStatement compilation directly.
node: result.rootNode!, withContext: CompilerContext())))
}
@Test func test_simple_compiler_parser_with_parameters() async throws {
let simple = """
parser main_parser(bool pmtr) {
state start {
transition accept;
}
};
"""
let program = try! #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let parser = try! #UseOkResult(program.find_parser(withName: Identifier(name: "main_parser")))
let parameters = parser.parameters
// Check that the parameters match.
#expect(parameters.parameters.count == 1)
#expect(parameters.parameters[0].name == Identifier(name: "pmtr"))
#expect(parameters.parameters[0].type.baseType().eq(rhs: P4Boolean()))
}
@Test func test_simple_compiler_parser_with_multiple_parameters() async throws {
let simple = """
parser main_parser(bool pmtr, string smtr) {
state start {
transition accept;
}
};
"""
let program = try! #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let parser = try! #UseOkResult(program.find_parser(withName: Identifier(name: "main_parser")))
let parameters = parser.parameters
// Check that the parameters match.
#expect(parameters.parameters.count == 2)
#expect(parameters.parameters[0].name == Identifier(name: "pmtr"))
#expect(parameters.parameters[0].type.baseType().eq(rhs: P4Boolean()))
#expect(parameters.parameters[1].name == Identifier(name: "smtr"))
#expect(parameters.parameters[1].type.baseType().eq(rhs: P4String()))
}
@Test func test_simple_compiler_parser_with_multiple_parameters2() async throws {
let simple = """
parser main_parser(bool pmtr, string smtr, int imtr) {
state start {
transition accept;
}
};
"""
let program = try! #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple))
let parser = try! #UseOkResult(program.find_parser(withName: Identifier(name: "main_parser")))
let parameters = parser.parameters
// Check that the parameters match.
#expect(parameters.parameters.count == 3)
#expect(parameters.parameters[0].name == Identifier(name: "pmtr"))
#expect(parameters.parameters[0].type.baseType().eq(rhs: P4Boolean()))
#expect(parameters.parameters[1].name == Identifier(name: "smtr"))
#expect(parameters.parameters[1].type.baseType().eq(rhs: P4String()))
#expect(parameters.parameters[2].name == Identifier(name: "imtr"))
#expect(parameters.parameters[2].type.baseType().eq(rhs: P4Int()))
}
@Test func test_simple_compiler_parser_use_parameters() async throws {
let simple = """
parser main_parser(bool pmtr, string smtr, int imtr) {
state start {
pmtr = true;
transition accept;
}
};
"""
#expect(#RequireOkResult(SpecialCompilers.ProgramCompiler.Compile(simple)))
}
@Test func test_simple_compiler_with_instantiation() async throws {
let simple_instantiation_program = """
parser MainParser() {
state start {
transition accept;
}
};
MainParser() mp;
"""
#expect(#RequireOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_instantiation_program)))
}
-173
View File
@@ -1,173 +0,0 @@
// 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 <https://www.gnu.org/licenses/>.
import Common
import Foundation
import Macros
import P4Lang
import P4Runtime
import SwiftTreeSitter
import Testing
import TreeSitter
import TreeSitterP4
@testable import P4Compiler
@Test func test_simple_runtime() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
true;
transition accept;
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
// We should be in the accept state.
#expect(state_result == P4Lang.accept)
}
@Test func test_simple_runtime_to_accept() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
true;
transition reject;
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
// We should be in the accept state.
#expect(state_result == P4Lang.reject)
}
@Test func test_simple_runtime_no_start_state() async throws {
let simple_parser_declaration = """
parser main_parser() {
state tart {
true;
transition reject;
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
#expect(
#RequireErrorResult<(InstantiatedParserState, ProgramExecution)>(
Error(withMessage: "Could not find the start state"),
runtime.run()))
}
@Test func test_simple_runtime_parser_with_parameters() async throws {
let simple_parser_declaration = """
parser main_parser(bool pmtr, string smtr, int imtr) {
state start {
transition select (pmtr) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let args = ArgumentList([
Argument(P4Value(P4BooleanValue(withValue: true)), atIndex: 1), Argument(P4Value(P4StringValue(withValue: "Testing")), atIndex: 2), Argument(P4Value(P4IntValue(withValue: 5)), atIndex: 3),
])
let (state_result, _) = try! #UseOkResult(runtime.run(withArguments: args))
// We should be in the accept state.
#expect(state_result == P4Lang.accept)
}
@Test func test_simple_runtime_parser_with_mismatched_parameter_types() async throws {
let simple_parser_declaration = """
parser main_parser(bool pmtr, string smtr, int imtr) {
state start {
transition select (pmtr) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let args = ArgumentList([
Argument(P4Value(P4BooleanValue(withValue: true)), atIndex: 1), Argument(P4Value(P4BooleanValue(withValue: false)), atIndex: 2), Argument(P4Value(P4IntValue(withValue: 5)), atIndex: 3),
])
#expect(
#RequireErrorResult<(InstantiatedParserState, ProgramExecution)>(
Error(withMessage: "Cannot call parser: Argument 2's type (Boolean) is incompatible with the parameter type (String)"),
runtime.run(withArguments: args)))
}
@Test func test_simple_runtime_parser_with_mismatched_parameter_types2() async throws {
let simple_parser_declaration = """
parser main_parser(bool pmtr, string smtr, int imtr) {
state start {
transition select (pmtr) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let args = ArgumentList([
Argument(P4Value(P4IntValue(withValue: 5)), atIndex: 1), Argument(P4Value(P4StringValue(withValue: "Testing")), atIndex: 2), Argument(P4Value(P4IntValue(withValue: 5)), atIndex: 3),
])
#expect(
#RequireErrorResult<(InstantiatedParserState, ProgramExecution)>(
Error(withMessage: "Cannot call parser: Argument 1's type (Int (width: Infinite)) is incompatible with the parameter type (Boolean)"),
runtime.run(withArguments: args)))
}
@Test func test_simple_runtime_parser_with_mismatched_parameter_counts() async throws {
let simple_parser_declaration = """
parser main_parser(bool pmtr, string smtr, int imtr) {
state start {
transition select (pmtr) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let args = ArgumentList([Argument(P4Value(P4BooleanValue(withValue: true)), atIndex: 0)])
#expect(
#RequireErrorResult<(InstantiatedParserState, ProgramExecution)>(
Error(withMessage: "Cannot call parser: 1 arguments found but 3 required"),
runtime.run(withArguments: args)))
}
-159
View File
@@ -1,159 +0,0 @@
// 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 <https://www.gnu.org/licenses/>.
import Common
import Foundation
import P4Lang
import Macros
import P4Runtime
import SwiftTreeSitter
import Testing
import TreeSitter
import TreeSitterP4
@testable import P4Compiler
@Test func test_simple_local_element_variable_declaration() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
bool b = false;
string s = "testing";
true;
false;
true;
transition reject;
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.reject)
}
@Test func test_simple_scope() async throws {
let simple_parser_declaration = """
parser main_parser() {
state starts {
bool where_to = false;
int va = 5;
transition accept;
}
state start {
bool where_to = true;
transition select (where_to) {
false: reject;
true: starts;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_simple_scope2() async throws {
let simple_parser_declaration = """
parser main_parser() {
state starts {
bool where_to = false;
int va = 5;
transition accept;
}
state start {
bool where_to = true;
where_to = false;
transition select (where_to) {
false: reject;
true: starts;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.reject)
}
@Test func test_simple_assignment() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
bool where_to = true;
string where_from = "here";
where_to = false;
where_from = "there";
transition select (where_to) {
false: reject;
true: accept;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.reject)
}
@Test func test_nested_declaration_assignment() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
bool where_to = true;
string where_from = "here";
string where_where = "here";
if (where_to) {
bool where_from = true;
if (where_from) {
where_to = false;
}
}
where_from = "there";
transition select (where_to) {
false: reject;
true: accept;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.reject)
}
-66
View File
@@ -1,66 +0,0 @@
// 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 <https://www.gnu.org/licenses/>.
import Common
import Foundation
import Macros
import P4Runtime
import SwiftTreeSitter
import Testing
import TreeSitter
import TreeSitterP4
@testable import P4Compiler
@Test func test_scope() async throws {
let s = VarTypeScope()
let s2 = s.declare(identifier: Identifier(name: "first"), withValue: P4QualifiedType(P4Int()))
let found_first = try! #require(s2.lookup(identifier: Identifier(name: "first")))
#expect(found_first.baseType().eq(rhs: P4Int()))
#expect(s2.count == 1)
}
@Test func test_scope_no_set() async throws {
var ss = VarTypeScopes().enter()
ss = ss.declare(identifier: Identifier(name: "first"), withValue: P4QualifiedType(P4Int()))
ss = ss.enter()
ss = ss.declare(identifier: Identifier(name: "second"), withValue: P4QualifiedType(P4Boolean()))
let found_first = try! #UseOkResult(ss.lookup(identifier: Identifier(name: "first")))
let found_second = try! #UseOkResult(ss.lookup(identifier: Identifier(name: "second")))
#expect(found_first.baseType().eq(rhs: P4Int()))
#expect(found_second.baseType().eq(rhs: P4Boolean()))
}
@Test func test_scope_set() async throws {
var ss = VarTypeScopes().enter()
let id = Identifier(name: "first")
let id_type = P4QualifiedType(P4Int())
ss = ss.declare(identifier: id, withValue: id_type)
ss = ss.enter()
ss = ss.declare(identifier: Identifier(name: "second"), withValue: P4QualifiedType(P4Boolean()))
// Change the value of `first`.
ss = ss.set(identifier: id, withValue: P4QualifiedType(P4String()))
// Verify the change!
let found = try! #UseOkResult(ss.lookup(identifier: id))
#expect(found.baseType().eq(rhs: P4String()))
}
-556
View File
@@ -1,556 +0,0 @@
// 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 <https://www.gnu.org/licenses/>.
import Common
import Foundation
import Macros
import P4Lang
import P4Runtime
import SwiftTreeSitter
import Testing
import TreeSitter
import TreeSitterP4
@testable import P4Compiler
@Test func test_field_access() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
bool where_to = ts.yesno;
transition select (where_to) {
true: accept;
false: reject;
};
}
};
"""
var test_declarations = StaticVarValueScopes().enter()
let fields = P4StructFields([
P4StructFieldIdentifier(name: "yesno", withType: P4QualifiedType(P4Boolean())),
P4StructFieldIdentifier(name: "count", withType: P4QualifiedType(P4Int())),
])
let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields)
test_declarations = test_declarations.declare(
identifier: Identifier(name: "ts"), withValue: (P4QualifiedType(struct_type), .none))
var test_values = VarValueScopes().enter()
test_values = test_values.declare(
identifier: Identifier(name: "ts"),
withValue: P4Value(
P4StructValue(
withType: struct_type,
andInitializers: [
P4Value(P4BooleanValue(withValue: true)),
P4Value(P4IntValue(withValue: 5)),
])))
let program = try #UseOkResult(
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration, withGlobalInstances: test_declarations))
let runtime = try #UseOkResult(
P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(
program: program, withGlobalValues: test_values))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_field_access_declared() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
Testing ts;
ts.yesno = true;
bool where_to = ts.yesno;
transition select (where_to) {
true: accept;
false: reject;
};
}
};
"""
var test_types = TypeTypeScopes().enter()
let fields = P4StructFields([
P4StructFieldIdentifier(name: "yesno", withType: P4QualifiedType(P4Boolean())),
P4StructFieldIdentifier(name: "count", withType: P4QualifiedType(P4Int())),
])
let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields)
test_types = test_types.declare(identifier: Identifier(name: "Testing"), withValue: struct_type)
let program = try #UseOkResult(
SpecialCompilers.ProgramCompiler.Compile(
simple_parser_declaration, withGlobalInstances: .none, withGlobalTypes: test_types))
let runtime = try #UseOkResult(
P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_field_access_declared2() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
Testing ts;
ts.yesno = true;
ts.count = 5;
bool where_to = ts.yesno;
transition select (ts.count == 5) {
true: accept;
false: reject;
};
}
};
"""
var test_declarations = TypeTypeScopes().enter()
let fields = P4StructFields([
P4StructFieldIdentifier(name: "yesno", withType: P4QualifiedType(P4Boolean())),
P4StructFieldIdentifier(name: "count", withType: P4QualifiedType(P4Int())),
])
let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields)
test_declarations = test_declarations.declare(
identifier: Identifier(name: "Testing"), withValue: struct_type)
let program = try #UseOkResult(
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration, withGlobalInstances: .none, withGlobalTypes: test_declarations))
let runtime = try #UseOkResult(
P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_field_access_opp() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
bool where_to = ts.yesno;
transition select (where_to) {
true: accept;
false: reject;
};
}
};
"""
var test_declarations = StaticVarValueScopes().enter()
let fields = P4StructFields([
P4StructFieldIdentifier(name: "yesno", withType: P4QualifiedType(P4Boolean())),
P4StructFieldIdentifier(name: "count", withType: P4QualifiedType(P4Int())),
])
let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields)
test_declarations = test_declarations.declare(
identifier: Identifier(name: "ts"), withValue: (P4QualifiedType(struct_type), .none))
var test_values = VarValueScopes().enter()
test_values = test_values.declare(
identifier: Identifier(name: "ts"),
withValue: P4Value(
P4StructValue(
withType: struct_type,
andInitializers: [
P4Value(P4BooleanValue(withValue: false)),
P4Value(P4IntValue(withValue: 5)),
])))
let program = try #UseOkResult(
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration, withGlobalInstances: test_declarations))
let runtime = try #UseOkResult(
P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(
program: program, withGlobalValues: test_values))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.reject)
}
@Test func test_field_access2() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
transition select (ts.count == 5) {
true: accept;
false: reject;
};
}
};
"""
var test_declarations = StaticVarValueScopes().enter()
let fields = P4StructFields([
P4StructFieldIdentifier(name: "yesno", withType: P4QualifiedType(P4Boolean())),
P4StructFieldIdentifier(name: "count", withType: P4QualifiedType(P4Int())),
])
let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields)
test_declarations = test_declarations.declare(
identifier: Identifier(name: "ts"), withValue: (P4QualifiedType(struct_type), .none))
var test_values = VarValueScopes().enter()
test_values = test_values.declare(
identifier: Identifier(name: "ts"),
withValue: P4Value(
P4StructValue(
withType: struct_type,
andInitializers: [
P4Value(P4BooleanValue(withValue: true)),
P4Value(P4IntValue(withValue: 5)),
])))
let program = try #UseOkResult(
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration, withGlobalInstances: test_declarations))
let runtime = try #UseOkResult(
P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(
program: program, withGlobalValues: test_values))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_field_access2_opp() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
transition select (ts.count == 5) {
true: accept;
false: reject;
};
}
};
"""
var test_declarations = StaticVarValueScopes().enter()
let fields = P4StructFields([
P4StructFieldIdentifier(name: "yesno", withType: P4QualifiedType(P4Boolean())),
P4StructFieldIdentifier(name: "count", withType: P4QualifiedType(P4Int())),
])
let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields)
test_declarations = test_declarations.declare(
identifier: Identifier(name: "ts"), withValue: (P4QualifiedType(struct_type), .none))
var test_values = VarValueScopes().enter()
test_values = test_values.declare(
identifier: Identifier(name: "ts"),
withValue: P4Value(
P4StructValue(
withType: struct_type,
andInitializers: [
P4Value(P4BooleanValue(withValue: true)),
P4Value(P4IntValue(withValue: 8)),
])))
let program = try #UseOkResult(
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration, withGlobalInstances: test_declarations))
let runtime = try #UseOkResult(
P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(
program: program, withGlobalValues: test_values))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.reject)
}
@Test func test_field_access_nested() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
int where_to = ts.ty.count;
transition select (where_to == 5) {
true: accept;
false: reject;
};
}
};
"""
var test_declarations = StaticVarValueScopes().enter()
let ty_fields = P4StructFields([
P4StructFieldIdentifier(name: "yesno", withType: P4QualifiedType(P4Boolean())),
P4StructFieldIdentifier(name: "count", withType: P4QualifiedType(P4Int())),
])
let ty_struct_type = P4Struct(withName: Identifier(name: "nested"), andFields: ty_fields)
let ts_fields = P4StructFields([
P4StructFieldIdentifier(name: "ty", withType: P4QualifiedType(ty_struct_type))
])
let ts_struct_type = P4Struct(withName: Identifier(name: "outer"), andFields: ts_fields)
test_declarations = test_declarations.declare(
identifier: Identifier(name: "ts"), withValue: (P4QualifiedType(ts_struct_type), .none))
var test_values = VarValueScopes().enter()
test_values = test_values.declare(
identifier: Identifier(name: "ts"),
withValue: P4Value(
P4StructValue(
withType: ts_struct_type,
andInitializers: [
P4Value(
P4StructValue(
withType: ty_struct_type,
andInitializers: [
P4Value(P4BooleanValue(withValue: true)),
P4Value(P4IntValue(withValue: 5)),
]))
])))
let program = try #UseOkResult(
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration, withGlobalInstances: test_declarations))
let runtime = try #UseOkResult(
P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(
program: program, withGlobalValues: test_values))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_field_write() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
ts.yesno = true;
bool where_to = ts.yesno;
transition select (where_to) {
true: accept;
false: reject;
};
}
};
"""
var test_declarations = StaticVarValueScopes().enter()
let fields = P4StructFields([
P4StructFieldIdentifier(name: "yesno", withType: P4QualifiedType(P4Boolean())),
P4StructFieldIdentifier(name: "count", withType: P4QualifiedType(P4Int())),
])
let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields)
test_declarations = test_declarations.declare(
identifier: Identifier(name: "ts"), withValue: (P4QualifiedType(struct_type), .none))
var test_values = VarValueScopes().enter()
test_values = test_values.declare(
identifier: Identifier(name: "ts"),
withValue: P4Value(
P4StructValue(
withType: struct_type,
andInitializers: [
P4Value(P4BooleanValue(withValue: false)),
P4Value(P4IntValue(withValue: 5)),
])))
let program = try #UseOkResult(
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration, withGlobalInstances: test_declarations))
let runtime = try #UseOkResult(
P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(
program: program, withGlobalValues: test_values))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_field_write_invalid_type() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
ts.yesno = 5;
transition accept;
}
};
"""
var test_declarations = StaticVarValueScopes().enter()
let fields = P4StructFields([
P4StructFieldIdentifier(name: "yesno", withType: P4QualifiedType(P4Boolean())),
P4StructFieldIdentifier(name: "count", withType: P4QualifiedType(P4Int())),
])
let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields)
test_declarations = test_declarations.declare(
identifier: Identifier(name: "ts"), withValue: (P4QualifiedType(struct_type), .none))
#expect(
#RequireErrorResult(
Error(
withMessage:
"{49, 13}: Failed to parse a statement element: {49, 8}: Cannot assign value of type Int (width: Infinite) to field yesno of type Boolean"
),
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration, withGlobalInstances: test_declarations))
)
}
@Test func test_field_write_nested() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
ts.ty.count = 5;
int where_to = ts.ty.count;
transition select (where_to == 5) {
true: accept;
false: reject;
};
}
};
"""
var test_declarations = StaticVarValueScopes().enter()
let ty_fields = P4StructFields([
P4StructFieldIdentifier(name: "yesno", withType: P4QualifiedType(P4Boolean())),
P4StructFieldIdentifier(name: "count", withType: P4QualifiedType(P4Int())),
])
let ty_struct_type = P4Struct(withName: Identifier(name: "nested"), andFields: ty_fields)
let ts_fields = P4StructFields([
P4StructFieldIdentifier(name: "ty", withType: P4QualifiedType(ty_struct_type))
])
let ts_struct_type = P4Struct(withName: Identifier(name: "outer"), andFields: ts_fields)
test_declarations = test_declarations.declare(
identifier: Identifier(name: "ts"), withValue: (P4QualifiedType(ts_struct_type), .none))
var test_values = VarValueScopes().enter()
test_values = test_values.declare(
identifier: Identifier(name: "ts"),
withValue: P4Value(
P4StructValue(
withType: ts_struct_type,
andInitializers: [
P4Value(
P4StructValue(
withType: ty_struct_type,
andInitializers: [
P4Value(P4BooleanValue(withValue: true)),
P4Value(P4IntValue(withValue: 7)),
]))
])))
let program = try #UseOkResult(
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration, withGlobalInstances: test_declarations))
let runtime = try #UseOkResult(
P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(
program: program, withGlobalValues: test_values))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_field_write_nested2() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
ts.ty.count = 3;
ts.ty.count = 5;
int where_to = ts.ty.count;
transition select (where_to == 5) {
true: accept;
false: reject;
};
}
};
"""
var test_declarations = StaticVarValueScopes().enter()
let ty_fields = P4StructFields([
P4StructFieldIdentifier(name: "yesno", withType: P4QualifiedType(P4Boolean())),
P4StructFieldIdentifier(name: "count", withType: P4QualifiedType(P4Int())),
])
let ty_struct_type = P4Struct(withName: Identifier(name: "nested"), andFields: ty_fields)
let ts_fields = P4StructFields([
P4StructFieldIdentifier(name: "ty", withType: P4QualifiedType(ty_struct_type))
])
let ts_struct_type = P4Struct(withName: Identifier(name: "outer"), andFields: ts_fields)
test_declarations = test_declarations.declare(
identifier: Identifier(name: "ts"), withValue: (P4QualifiedType(ts_struct_type), .none))
var test_values = VarValueScopes().enter()
test_values = test_values.declare(
identifier: Identifier(name: "ts"),
withValue: P4Value(
P4StructValue(
withType: ts_struct_type,
andInitializers: [
P4Value(
P4StructValue(
withType: ty_struct_type,
andInitializers: [
P4Value(P4BooleanValue(withValue: true)),
P4Value(P4IntValue(withValue: 7)),
]))
])))
let program = try #UseOkResult(
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration, withGlobalInstances: test_declarations))
let runtime = try #UseOkResult(
P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(
program: program, withGlobalValues: test_values))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(state_result == P4Lang.accept)
}
@Test func test_field_write_nested_invalid_type() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
ts.ty.count = false;
int where_to = ts.ty.count;
transition select (where_to == 5) {
true: accept;
false: reject;
};
}
};
"""
var test_declarations = StaticVarValueScopes().enter()
let ty_fields = P4StructFields([
P4StructFieldIdentifier(name: "yesno", withType: P4QualifiedType(P4Boolean())),
P4StructFieldIdentifier(name: "count", withType: P4QualifiedType(P4Int())),
])
let ty_struct_type = P4Struct(withName: Identifier(name: "nested"), andFields: ty_fields)
let ts_fields = P4StructFields([
P4StructFieldIdentifier(name: "ty", withType: P4QualifiedType(ty_struct_type))
])
let ts_struct_type = P4Struct(withName: Identifier(name: "outer"), andFields: ts_fields)
test_declarations = test_declarations.declare(
identifier: Identifier(name: "ts"), withValue: (P4QualifiedType(ts_struct_type), .none))
#expect(
#RequireErrorResult(
Error(
withMessage:
"{49, 20}: Failed to parse a statement element: {49, 11}: Cannot assign value of type Boolean to field count of type Int (width: Infinite)"
),
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration, withGlobalInstances: test_declarations))
)
}
@Test func test_field_read_equality_invalid_type() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
transition select (ts.yesno == "testing") {
true: accept;
false: reject;
};
}
};
"""
var test_declarations = StaticVarValueScopes().enter()
let fields = P4StructFields([
P4StructFieldIdentifier(name: "yesno", withType: P4QualifiedType(P4Boolean())),
P4StructFieldIdentifier(name: "count", withType: P4QualifiedType(P4Int())),
])
let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields)
test_declarations = test_declarations.declare(
identifier: Identifier(name: "ts"), withValue: (P4QualifiedType(struct_type), .none))
#expect(
#RequireErrorResult(
Error(
withMessage:
"{68, 21}: Could not parse transition select expression selector expression: Types of values used with binary expression are not the same"
),
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration, withGlobalInstances: test_declarations))
)
}
-57
View File
@@ -1,57 +0,0 @@
// 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 <https://www.gnu.org/licenses/>.
import Common
import Foundation
import Macros
import P4Runtime
import P4Lang
import SwiftTreeSitter
import Testing
import TreeSitter
import TreeSitterP4
@testable import P4Compiler
@Test func test_style_add_format() async throws {
let red = Style(StyleColor.Red)
let bold_red = red.update(addFormat: StyleFormat.Bold)
#expect(bold_red == Style(StyleColor.Red, [StyleFormat.Bold]))
}
@Test func test_style_add_format2() async throws {
let bold_red = Style(StyleColor.Red, [StyleFormat.Bold])
let bold_underline_red = bold_red.update(addFormat: StyleFormat.Underline)
#expect(bold_underline_red == Style(StyleColor.Red, [StyleFormat.Bold, StyleFormat.Underline]))
}
@Test func test_style_remove_format() async throws {
let bold_red = Style(StyleColor.Red, [StyleFormat.Bold])
let red = bold_red.update(removeFormat: StyleFormat.Bold)
#expect(red == Style(StyleColor.Red))
}
@Test func test_style_remove_format2() async throws {
let bold_underline_red = Style(StyleColor.Red, [StyleFormat.Bold, StyleFormat.Underline])
let underline_red = bold_underline_red.update(removeFormat: StyleFormat.Bold)
#expect(underline_red == Style(StyleColor.Red, [StyleFormat.Underline]))
}
-49
View File
@@ -1,49 +0,0 @@
// 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 <https://www.gnu.org/licenses/>.
import Foundation
import Common
import Macros
import SwiftTreeSitter
import Testing
import TreeSitter
import TreeSitterP4
@testable import P4Compiler
struct NotStringConvertible {}
struct StringConvertible: CustomStringConvertible {
public var description: String {
return "CONVERTED"
}
}
@Test func test_result_type_description_not_convertible() async throws {
let result: Result<NotStringConvertible> = Result.Ok(NotStringConvertible());
#expect("\(result)" == "Ok(Tests.NotStringConvertible())")
}
@Test func test_result_type_description_convertible() async throws {
let result: Result<StringConvertible> = Result.Ok(StringConvertible());
#expect("\(result)" == "Ok: CONVERTED")
}
@Test func test_result_type_p4value_convertible() async throws {
let result = Result.Ok(P4Value(P4IntValue(withValue: 5)))
#expect("\(result)" == "Ok: Value: 5 of Int (width: Infinite) type of type Int (width: Infinite)")
}
@@ -1,58 +0,0 @@
// 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 <https://www.gnu.org/licenses/>.
import Common
import Foundation
import Macros
import P4Lang
import P4Runtime
import SwiftTreeSitter
import Testing
import TreeSitter
import TreeSitterP4
@testable import P4Compiler
@Test func test_invalid_statements() async throws {
let ret = ReturnStatement(P4Value(P4IntValue(withValue: 5)))
let block = BlockStatement([ret])
#expect(ContainsInvalidStatements(block: block, invalids: [ReturnStatement.self]))
}
@Test func test_no_invalid_statements() async throws {
let exprs = ExpressionStatement(P4Value(P4IntValue(withValue: 5)))
let block = BlockStatement([exprs])
#expect(!ContainsInvalidStatements(block: block, invalids: [ReturnStatement.self]))
}
@Test func test_is_invalid_statement() async throws {
let ret = ReturnStatement(P4Value(P4IntValue(withValue: 5)))
#expect(ContainsInvalidStatements(statement: ret, invalids: [ReturnStatement.self]))
}
@Test func test_no_is_invalid_statement() async throws {
let exprs = ExpressionStatement(P4Value(P4IntValue(withValue: 5)))
#expect(!ContainsInvalidStatements(statement: exprs, invalids: [ReturnStatement.self]))
}
@@ -1,258 +0,0 @@
// 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 <https://www.gnu.org/licenses/>.
import Foundation
import Macros
import P4Compiler
import P4Lang
import P4Runtime
import SwiftTreeSitter
import SystemPackage
import Testing
import TreeSitter
import TreeSitterP4
@testable import Common
@Test func test_preprocessor() async throws {
let sm = SourceManager(["./TestData/Sources/"])
let prep = SourceCodePreprocessor(sm)
let file = FilePath.init(stringLiteral: "simple.p4")
let source = try! (#UseOkResult(prep.preprocess(file)))
let program = try! #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(source.getSource()))
#expect(#RequireOkResult((program.find_parser(withName: Identifier(name: "main_parser")))))
#expect(source.getLocations().getPath() == file)
}
@Test func test_preprocessor_search_for_file() async throws {
let sm = SourceManager(["./TestData/Sources/"])
let prep = SourceCodePreprocessor(sm)
let file = FilePath.init(stringLiteral: "simple.p4")
let source = try! (#UseOkResult(prep.preprocess(file)))
let program = try! #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(source.getSource()))
#expect(#RequireOkResult((program.find_parser(withName: Identifier(name: "main_parser")))))
#expect(source.getLocations().getPath() == file)
}
@Test func test_preprocessor_nested_includes() async throws {
let sm = SourceManager(["./TestData/Sources/"])
let prep = SourceCodePreprocessor(sm)
let file = FilePath.init(stringLiteral: "simple-split.p4")
#expect(#RequireOkResult(prep.preprocess(file)))
let source = try! (#UseOkResult(prep.preprocess(file)))
let program = try! #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(source.getSource()))
#expect(#RequireOkResult((program.find_parser(withName: Identifier(name: "main_parser")))))
#expect(source.getLocations().getPath() == file)
}
@Test func test_preprocessor_oneline_includes() async throws {
let sm = SourceManager(["./TestData/Sources/"])
let prep = SourceCodePreprocessor(sm)
let file = FilePath.init(stringLiteral: "simple-split-oneline.p4")
#expect(#RequireOkResult(prep.preprocess(file)))
let source = try! (#UseOkResult(prep.preprocess(file)))
let program = try! #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(source.getSource()))
#expect(#RequireOkResult((program.find_parser(withName: Identifier(name: "main_parser")))))
#expect(source.getLocations().getPath() == file)
}
@Test func test_preprocessor_missing_file() async throws {
let sm = SourceManager(["./TestData/Sources/"])
let prep = SourceCodePreprocessor(sm)
let file = FilePath.init(stringLiteral: "./TestData/Sources/unfound.p4")
#expect(
#RequireErrorResult(
Error(withMessage: "Could not open ./TestData/Sources/unfound.p4 for preprocessing"),
(prep.preprocess(file))))
}
@Test func test_preprocessor_missing_included_file() async throws {
let sm = SourceManager(["./TestData/Sources/"])
let prep = SourceCodePreprocessor(sm)
let file = FilePath.init(stringLiteral: "simple-unfound.p4")
#expect(
#RequireErrorResult(
Error(withMessage: "Could not open unfound.p4 for preprocessing"), (prep.preprocess(file))))
}
@Test func test_preprocessor_no_change_locations() async throws {
let sm = SourceManager(["./TestData/Sources/"])
let prep = SourceCodePreprocessor(sm)
let file = FilePath.init(stringLiteral: "testing.p4")
let source = try! (#UseOkResult(prep.preprocess(file)))
#expect(source.getLocations().getLocation() == SourceLocation(0..<173))
}
@Test func test_preprocessor_change_locations() async throws {
let sm = SourceManager(["./TestData/Sources/"])
let prep = SourceCodePreprocessor(sm)
let file = FilePath.init(stringLiteral: "testing-split-a.p4")
let source = try! (#UseOkResult(prep.preprocess(file)))
#expect(source.getLocations().getLocation() == SourceLocation(0..<173))
#expect(source.getLocations().getNestedLocations()[0].getLocation() == SourceLocation(48..<173))
}
@Test func test_preprocessor_oneline_includes_locations() async throws {
let sm = SourceManager(["./TestData/Sources/"])
let prep = SourceCodePreprocessor(sm)
let file = FilePath.init(stringLiteral: "simple-split-oneline.p4")
#expect(#RequireOkResult(prep.preprocess(file)))
let source = try! (#UseOkResult(prep.preprocess(file)))
#expect(source.getLocations().getLocation() == SourceLocation(0..<173))
#expect(source.getLocations().getNestedLocations()[0].getLocation() == SourceLocation(0..<70))
#expect(source.getLocations().getNestedLocations()[1].getLocation() == SourceLocation(70..<173))
}
@Test func test_preprocessor_nested_includes_locations() async throws {
let sm = SourceManager(["./TestData/Sources/"])
let prep = SourceCodePreprocessor(sm)
let file = FilePath.init(stringLiteral: "nested-split.p4")
#expect(#RequireOkResult(prep.preprocess(file)))
let source = try! (#UseOkResult(prep.preprocess(file)))
#expect(source.getLocations().getLocation() == SourceLocation(0..<173))
/*
#expect(
source.getLocations().getNestedLocations()[0].getNestedLocations()[0].getLocation()
== SourceLocation(27..<47))
#expect(
source.getLocations().getNestedLocations()[0].getNestedLocations()[1].getLocation()
== SourceLocation(48..<166))
*/
}
@Test func test_preprocessor_nested_includes_annotated_source() async throws {
let sm = SourceManager(["./TestData/Sources/"])
let prep = SourceCodePreprocessor(sm)
let file = FilePath.init(stringLiteral: "annotate.p4")
let expected = """
<struct Testing {
< bool yesno;
int count;>
};
<parser main_parser() {
< state start {
Testing ts;
ts.yesno = true;
ts.count = 5;
transition select (ts.count == 5) {
true: accept;
false: reject;
};
}
>
}>>
"""
#expect(#RequireOkResult(prep.preprocess(file)))
let source = try! (#UseOkResult(prep.preprocess(file)))
#expect(source.getSource(annotated: true) == expected)
}
@Test func test_preprocessor_nested_includes_get_file_location() async throws {
let sm = SourceManager(["./TestData/Sources/"], FileManager()) // Add a FileManager to get absolute paths.
let prep = SourceCodePreprocessor(sm)
let file = FilePath.init(stringLiteral: "file-loc.p4")
let source = try! (#UseOkResult(prep.preprocess(file)))
let expected_file = file
let expected_nested_file = FilePath(stringLiteral: "file-loc-parser.p4")
let expected_nested_nested_file = FilePath(stringLiteral: "file-loc-parser-state.p4")
let found_nested_files = try! #require(source.pathForLocation(78))
#expect(found_nested_files[0].path == expected_file)
#expect(found_nested_files[1].path == expected_nested_file)
#expect(found_nested_files[2].path == expected_nested_nested_file)
}
@Test func test_source_location_contains() async throws {
let outer = SourceLocation(0..<500)
let inner = SourceLocation(0..<499)
#expect(outer.contains(inner))
}
@Test func test_source_location_contains_a() async throws {
let outer = SourceLocation(0, 500)
let inner = SourceLocation(0, 499)
#expect(outer.contains(inner))
}
@Test func test_source_location_contains2() async throws {
let outer = SourceLocation(0..<500)
let not_inner = SourceLocation(0..<501)
#expect(!outer.contains(not_inner))
}
@Test func test_source_location_contains2_a() async throws {
let outer = SourceLocation(0, 500)
let not_inner = SourceLocation(0, 501)
#expect(!outer.contains(not_inner))
}
@Test func test_source_location_contains3() async throws {
let outer = SourceLocation(200..<500)
let inner = SourceLocation(200..<499)
#expect(outer.contains(inner))
}
@Test func test_source_location_contains3_a() async throws {
let outer = SourceLocation(200, 300)
let inner = SourceLocation(200, 299)
#expect(outer.contains(inner))
}
@Test func test_source_location_contains4() async throws {
let outer = SourceLocation(200..<500)
let inner = SourceLocation(200, 299)
#expect(outer.contains(inner))
}
@Test func test_source_location_contains5() async throws {
let outer = SourceLocation(200..<300)
let not_inner = SourceLocation(200, 101)
#expect(!outer.contains(not_inner))
}
-91
View File
@@ -1,91 +0,0 @@
// 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 <https://www.gnu.org/licenses/>.
import Common
import Foundation
import Macros
import P4Lang
import P4Runtime
import SwiftTreeSitter
import Testing
import TreeSitter
import TreeSitterP4
@testable import P4Compiler
@Test func test_simple_parser_with_transition_select_expression() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
transition select (true) {
false: reject;
true: accept;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let parser = try #UseOkResult(program.find_parser(withName: Identifier(name: "main_parser")))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(parser.states.count() == 1)
#expect(state_result == P4Lang.accept)
}
@Test func test_simple_parser_with_transition_select_expression_to_reject() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
transition select (false) {
false: reject;
true: accept;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let parser = try #UseOkResult(program.find_parser(withName: Identifier(name: "main_parser")))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
#expect(parser.states.count() == 1)
#expect(state_result == P4Lang.reject)
}
@Test func test_no_matching_key_transition() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
transition select (false) {
true: accept;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
#expect(
#RequireErrorResult<(InstantiatedParserState, ProgramExecution)>(
Error(withMessage: "No key matched the selector"),
runtime.run()))
}
-37
View File
@@ -1,37 +0,0 @@
// 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 <https://www.gnu.org/licenses/>.
import Foundation
import Macros
import SwiftTreeSitter
import Testing
import TreeSitter
import TreeSitterP4
@testable import Common
@Test func test_simple_struct() async throws {
let fields = P4StructFields([
P4StructFieldIdentifier(name: "yesno", withType: P4QualifiedType(P4Boolean())),
P4StructFieldIdentifier(name: "count", withType: P4QualifiedType(P4Int())),
])
let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields)
#expect(struct_type.fields.count() == 2)
#expect(struct_type.fields == fields)
}
-56
View File
@@ -1,56 +0,0 @@
// 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 <https://www.gnu.org/licenses/>.
import Common
import Foundation
import Macros
import P4Lang
import Runtime
import SwiftTreeSitter
import Testing
import TreeSitter
import TreeSitterP4
@testable import P4Compiler
@Test func test_unsupported_annotations() async throws {
let simple_annotated_parser_declaration = """
@testing parser main_parser() {
state start {
transition start;
}
};
"""
#expect(
#RequireErrorResult(
Error(withMessage: "{0, 8}: Annotations in parser type are not yet handled."),
SpecialCompilers.ProgramCompiler.Compile(simple_annotated_parser_declaration)))
}
@Test func test_unsupported_annotations_state() async throws {
let simple_annotated_parser_declaration = """
parser main_parser() {
@testing state start {
transition start;
}
};
"""
#expect(
#RequireErrorResult(
Error(withMessage: "{26, 8}: Annotations in parser state are not yet handled."),
SpecialCompilers.ProgramCompiler.Compile(simple_annotated_parser_declaration)))
}
-373
View File
@@ -1,373 +0,0 @@
// 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 <https://www.gnu.org/licenses/>.
import Common
import Foundation
import Macros
import P4Lang
import P4Runtime
import SwiftTreeSitter
import Testing
import TreeSitter
import TreeSitterP4
@testable import P4Compiler
@Test func test_invalid_types() async throws {
for invalid_type_name in ["boo", "str", "in"] {
let simple_parser_declaration = """
parser main_parser() {
state start {
\(invalid_type_name) v = 1;
transition reject;
}
};
"""
let err = SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration)
guard case Result.Error(let e) = err else {
assert(false, "Expected an error, but had success")
}
#expect(
e.msg().contains(
"Failed to parse a statement element: Could not parse a P4 type from \(invalid_type_name)"))
}
}
@Test func test_invalid_type_in_assignment() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
string g = "Testing";
string where_to = "Testing";
where_to = true;
transition reject;
}
};
"""
#expect(
#RequireErrorResult(
Error(
withMessage:
"{112, 16}: Failed to parse a statement element: {112, 8}: Cannot assign value with type Boolean to identifier where_to with type String"
),
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration)))
}
@Test func test_invalid_type_in_assignment2() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
bool where_to = true;
string where_from = "testing";
where_to = where_from;
transition reject;
}
};
"""
#expect(
#RequireErrorResult(
Error(
withMessage:
"{114, 22}: Failed to parse a statement element: {114, 8}: Cannot assign value with type String to identifier where_to with type Boolean"
),
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration)))
}
@Test func test_invalid_type_in_declaration() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
string where_from = "testing";
bool where_to = where_from;
transition reject;
}
};
"""
#expect(
#RequireErrorResult(
Error(
withMessage:
"{86, 27}: Failed to parse a statement element: Cannot initialize where_to (with type Boolean) from expression with type String"
),
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration)))
}
@Test func test_invalid_type_in_declaration2() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
bool where_to = true;
string where_from = where_to;
transition reject;
}
};
"""
#expect(
#RequireErrorResult(
Error(
withMessage:
"{77, 29}: Failed to parse a statement element: Cannot initialize where_from (with type String) from expression with type Boolean"
),
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration)))
}
@Test func test_invalid_type_in_declaration3() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
int<5> specific_width_int = 5;
int unspecific_width_int = specific_width_int;
transition reject;
}
};
"""
let error = try! #UseErrorResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
#expect(
error.msg().contains(
"Cannot initialize specific_width_int (with type Int (width: Width(5))) from expression with type Int (width: Infinite)"
))
}
@Test func test_valid_specific_width_int_type_in_declaration() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
int<5> specific_width_int = 5w5;
int<5> unspecific_width_int = specific_width_int;
transition reject;
}
};
"""
#expect(#RequireOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration)))
}
@Test func test_expression_in_declaration_initializer_specific_width_int_type() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
int<5> specific_width_int = 5w5;
bool where_to = 5w5 == specific_width_int == true;
transition select (where_to) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(
P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
// 5w5 == specific_width_int == true
// true == true
// true
#expect(state_result == P4Lang.accept)
}
@Test func test_expression_in_declaration_initializer_specific_width_int_type2() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
int<5> specific_width_int = 5w5;
bool where_to = 5w6 == specific_width_int == false;
transition select (where_to) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(
P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
// 5w6 == specific_width_int == false
// false == false
// true
#expect(state_result == P4Lang.accept)
}
@Test func test_expression_in_declaration_initializer() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
bool where_to = 5 == 5 == true;
transition select (where_to) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(
P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
// 5 == 5 == true
// true == true
// true
#expect(state_result == P4Lang.accept)
}
@Test func test_expression_in_declaration_initializer2() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
bool where_to = 5 == 5 == false;
transition select (where_to) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(
P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
// 5 == 5 == true
// true == false
// false
#expect(state_result == P4Lang.reject)
}
@Test func test_expression_in_declaration_initializer_false() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
bool where_to = 6 == 5 == true;
transition select (where_to) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(
P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
// 6 == 5 == true
// false == true
// false
#expect(state_result == P4Lang.reject)
}
@Test func test_expression_in_declaration_initializer_false2() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
bool where_to = 6 == 5 == false;
transition select (where_to) {
true: accept;
false: reject;
};
}
};
"""
let program = try #UseOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration))
let runtime = try #UseOkResult(
P4Runtime.Runtime<InstantiatedParserState, P4Lang.ParserValue>.create(program: program))
let (state_result, _) = try! #UseOkResult(runtime.run())
// 6 == 5 == false
// false == false
// true
#expect(state_result == P4Lang.accept)
}
@Test func test_expression_in_declaration_initializer_invalid_types() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
bool where_to = false == 5 == true;
transition select (where_to) {
true: accept;
false: reject;
};
}
};
"""
#expect(
#RequireErrorResult(
Error(
withMessage:
"{49, 35}: Failed to parse a statement element: Types of values used with binary expression are not the same"
),
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration)))
}
@Test func test_expression_in_declaration_initializer_invalid_types2() async throws {
let simple_parser_declaration = """
parser main_parser() {
state start {
bool where_to = ta[0];
transition select (where_to) {
true: accept;
false: reject;
};
}
};
"""
var test_declarations = StaticVarValueScopes().enter()
test_declarations = test_declarations.declare(
identifier: Identifier(name: "ta"),
withValue: (P4QualifiedType(P4Array(withValueType: P4QualifiedType(P4Int()))), .none))
#expect(
#RequireErrorResult(
Error(
withMessage:
"{49, 22}: Failed to parse a statement element: Cannot initialize where_to (with type Boolean) from expression with type Int (width: Infinite)"
),
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration, withGlobalInstances: test_declarations)))
}
@Test func test_simple_compiler_parser_parameters_invalid_types() async throws {
let simple_parser_declaration = """
parser main_parser(bool pmtr, string smtr, int imtr) {
state start {
pmtr = 1;
transition accept;
}
};
"""
#expect(
#RequireErrorResult(
Error(
withMessage:
"{85, 9}: Failed to parse a statement element: {85, 4}: Cannot assign value with type Int (width: Infinite) to identifier pmtr with type Boolean"
),
SpecialCompilers.ProgramCompiler.Compile(simple_parser_declaration)))
}