@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
+23
-24
@@ -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))))
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
}
|
||||
@@ -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))
|
||||
)
|
||||
}
|
||||
@@ -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))))
|
||||
}
|
||||
@@ -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"
|
||||
)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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"))
|
||||
}
|
||||
@@ -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)))
|
||||
}
|
||||
@@ -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)))
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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()))
|
||||
}
|
||||
@@ -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))
|
||||
)
|
||||
}
|
||||
@@ -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]))
|
||||
}
|
||||
@@ -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))
|
||||
}
|
||||
@@ -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()))
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)))
|
||||
}
|
||||
@@ -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)))
|
||||
}
|
||||
Reference in New Issue
Block a user