diff --git a/Tests/p4rseTests/ArrayTests.swift b/Tests/p4rseTests/ArrayTests.swift new file mode 100644 index 0000000..2d2d6bc --- /dev/null +++ b/Tests/p4rseTests/ArrayTests.swift @@ -0,0 +1,255 @@ +// 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 . + +import Common +import Foundation +import Macros +import P4Runtime +import P4Lang +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_types = LexicalScopes().enter() + test_types = test_types.declare(identifier: Identifier(name: "ta"), withValue: P4Array(withValueType: P4Int())) + var test_values = ValueScopes().enter() + test_values = test_values.declare( + identifier: Identifier(name: "ta"), + withValue: P4ArrayValue(withType: P4Int(), withValue: [ + P4IntValue(withValue: 1), P4IntValue(withValue: 2), P4IntValue(withValue: 3), + ])) + let program = try #UseOkResult( + Program.Compile(simple_parser_declaration, withGlobalTypes: test_types)) + let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program, withInitialValues: 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_types = LexicalScopes().enter() + test_types = test_types.declare(identifier: Identifier(name: "ta"), withValue: P4Int()) + #expect( + #RequireErrorResult( + Error( + withMessage: "{49, 22}: Failed to parse a statement element: {65, 2}: ta does not name an array type" + ), + Program.Compile(simple_parser_declaration, withGlobalTypes: test_types)) + ) +} + +@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_types = LexicalScopes().enter() + test_types = test_types.declare(identifier: Identifier(name: "ta"), withValue: P4Array(withValueType: P4Int())) + var test_values = ValueScopes().enter() + test_values = test_values.declare( + identifier: Identifier(name: "ta"), + withValue: P4ArrayValue(withType: P4Int(), withValue: [ + P4IntValue(withValue: 1), P4IntValue(withValue: 2), P4IntValue(withValue: 3), + ])) + let program = try #UseOkResult( + Program.Compile(simple_parser_declaration, withGlobalTypes: test_types)) + let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program, withInitialValues: 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_types = LexicalScopes().enter() + test_types = test_types.declare(identifier: Identifier(name: "ta"), withValue: P4Array(withValueType: P4Int())) + var test_values = ValueScopes().enter() + test_values = test_values.declare( + identifier: Identifier(name: "ta"), + withValue: P4ArrayValue(withType: P4Int(), withValue: [ + P4IntValue(withValue: 1), P4IntValue(withValue: 2), P4IntValue(withValue: 3), + ])) + let program = try #UseOkResult( + Program.Compile(simple_parser_declaration, withGlobalTypes: test_types)) + let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program, withInitialValues: 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_types = LexicalScopes().enter() + test_types = test_types.declare(identifier: Identifier(name: "ta"), withValue: P4Array(withValueType: P4Int())) + var test_values = ValueScopes().enter() + test_values = test_values.declare( + identifier: Identifier(name: "ta"), + withValue: P4ArrayValue(withType: P4Int(), withValue: [ + P4IntValue(withValue: 1), P4IntValue(withValue: 2), P4IntValue(withValue: 3), + ])) + let program = try #UseOkResult( + Program.Compile(simple_parser_declaration, withGlobalTypes: test_types)) + let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program, withInitialValues: 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_types = LexicalScopes().enter() + test_types = test_types.declare(identifier: Identifier(name: "ta"), withValue: P4Array(withValueType: P4Array(withValueType: P4Int()))) + var test_values = ValueScopes().enter() + + let nested = P4ArrayValue( + withType: P4Int(), + withValue: [P4IntValue(withValue: 5), P4IntValue(withValue: 2), P4IntValue(withValue: 3)]) + + test_values = test_values.declare( + identifier: Identifier(name: "ta"), + withValue: P4ArrayValue(withType: P4Array(withValueType: P4Int()), withValue: [nested])) + + let program = try #UseOkResult( + Program.Compile(simple_parser_declaration, withGlobalTypes: test_types)) + let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program, withInitialValues: 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_types = LexicalScopes().enter() + test_types = test_types.declare(identifier: Identifier(name: "ta"), withValue: P4Array(withValueType: P4Int())) + var test_values = ValueScopes().enter() + test_values = test_values.declare( + identifier: Identifier(name: "ta"), + withValue: P4ArrayValue(withType: P4Int(), withValue: [ + P4IntValue(withValue: 1), P4IntValue(withValue: 2), P4IntValue(withValue: 3), + ])) + let program = try #UseOkResult( + Program.Compile(simple_parser_declaration, withGlobalTypes: test_types)) + let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program, withInitialValues: 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_types = LexicalScopes().enter() + test_types = test_types.declare(identifier: Identifier(name: "ta"), withValue: P4Array(withValueType: P4Array(withValueType: P4Int()))) + var test_values = ValueScopes().enter() + + let nested = P4ArrayValue( + withType: P4Int(), + withValue: [P4IntValue(withValue: 1), P4IntValue(withValue: 2), P4IntValue(withValue: 3)]) + + test_values = test_values.declare( + identifier: Identifier(name: "ta"), + withValue: P4ArrayValue(withType: P4Array(withValueType: P4Int()), withValue: [nested])) + + let program = try #UseOkResult( + Program.Compile(simple_parser_declaration, withGlobalTypes: test_types)) + let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program, withInitialValues: test_values)) + let (state_result, _) = try! #UseOkResult(runtime.run()) + + #expect(state_result == P4Lang.accept) +} diff --git a/Tests/p4rseTests/BinaryOperators.swift b/Tests/p4rseTests/BinaryOperators.swift new file mode 100644 index 0000000..53836ff --- /dev/null +++ b/Tests/p4rseTests/BinaryOperators.swift @@ -0,0 +1,126 @@ +// 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 . + +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_binary_operator_equal() async throws { + let simple = """ + parser main_parser() { + state start { + transition select (true == true) { + true: accept; + false: reject; + }; + } + }; + """ + + let program = try #UseOkResult(Program.Compile(simple)) + let runtime = try #UseOkResult(P4Runtime.ParserRuntime.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() async throws { + let simple = """ + parser main_parser() { + state start { + transition select (true == false) { + true: accept; + false: reject; + }; + } + }; + """ + + let program = try #UseOkResult(Program.Compile(simple)) + let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program)) + let (state_result, _) = try! #UseOkResult(runtime.run()) + + #expect(state_result == P4Lang.reject) +} + +@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(Program.Compile(simple)) + let runtime = try #UseOkResult(P4Runtime.ParserRuntime.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(Program.Compile(simple)) + let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program)) + let (state_result, _) = try! #UseOkResult(runtime.run()) + + #expect(state_result == P4Lang.reject) +} + +@Test func test_simple_parser_binary_operator_equal_invalid_types() async throws { + let simple = """ + parser main_parser() { + state start { + transition select (5 == true) { + true: accept; + false: reject; + }; + } + }; + """ + + let program = try #UseOkResult(Program.Compile(simple)) + let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program)) + let (state_result, _) = try! #UseOkResult(runtime.run()) + + + // TODO: This test should throw an error. + + #expect(state_result == P4Lang.reject) +} \ No newline at end of file diff --git a/Tests/p4rseTests/ConditionalTests.swift b/Tests/p4rseTests/ConditionalTests.swift new file mode 100644 index 0000000..8101a9c --- /dev/null +++ b/Tests/p4rseTests/ConditionalTests.swift @@ -0,0 +1,82 @@ +// 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 . + +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(Program.Compile(simple_parser_declaration)) + let runtime = try #UseOkResult(P4Runtime.ParserRuntime.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(Program.Compile(simple_parser_declaration)) + let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program)) + let (state_result, _) = try! #UseOkResult(runtime.run()) + + #expect(state_result == P4Lang.accept) + +} diff --git a/Tests/p4rseTests/ParserTests.swift b/Tests/p4rseTests/ParserCompilerTests.swift similarity index 91% rename from Tests/p4rseTests/ParserTests.swift rename to Tests/p4rseTests/ParserCompilerTests.swift index bf13c9d..4e8c2b8 100644 --- a/Tests/p4rseTests/ParserTests.swift +++ b/Tests/p4rseTests/ParserCompilerTests.swift @@ -41,7 +41,7 @@ import P4Lang Program.Compile(simple_parser_declaration))) } -@Test func test_simple_parser_with_statement() async throws { +@Test func test_simple_compilation_with_statement() async throws { let simple_parser_declaration = """ parser main_parser() { state start { @@ -61,7 +61,7 @@ import P4Lang #expect(state.statements.count == 1) } -@Test func test_simple_parser_with_instantiation() async throws { +@Test func test_simple_compilation_with_instantiation() async throws { let simple_parser_declaration = """ parser main_parser() { state start { @@ -95,7 +95,7 @@ import P4Lang #expect(compilation_error.msg.contains("asdf")) } -@Test func test_simple_parser_macro_nodetype_test() async throws { +@Test func test_simple_compiler_macro_nodetype_test() async throws { let simple = """ parser main_parser() { state start { @@ -113,6 +113,6 @@ import P4Lang #expect( #RequireErrorResult<(EvaluatableStatement, CompilerContext)>( Error(withMessage: "{2, 154}: Did not find assignment statement"), - ParserAssignmentStatement.Compile( + ParserAssignmentStatement.Compile( // Note: Calling ParserAssignmentStatement compilation directly. node: result.rootNode!, withContext: CompilerContext(withNames: LexicalScopes())))) } diff --git a/Tests/p4rseTests/RuntimeTests.swift b/Tests/p4rseTests/RuntimeTests.swift index 26c61b4..8e37aa0 100644 --- a/Tests/p4rseTests/RuntimeTests.swift +++ b/Tests/p4rseTests/RuntimeTests.swift @@ -80,218 +80,3 @@ import TreeSitterP4 Error(withMessage: "Could not find the start state"), runtime.run())) } - -@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(Program.Compile(simple_parser_declaration)) - let parser = try #UseOkResult(program.find_parser(withName: Identifier(name: "main_parser"))) - let runtime = try #UseOkResult(P4Runtime.ParserRuntime.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(Program.Compile(simple_parser_declaration)) - let parser = try #UseOkResult(program.find_parser(withName: Identifier(name: "main_parser"))) - let runtime = try #UseOkResult(P4Runtime.ParserRuntime.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_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(Program.Compile(simple_parser_declaration)) - let runtime = try #UseOkResult(P4Runtime.ParserRuntime.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(Program.Compile(simple_parser_declaration)) - let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program)) - let (state_result, _) = try! #UseOkResult(runtime.run()) - - #expect(state_result == P4Lang.accept) - -} - -@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(Program.Compile(simple_parser_declaration)) - let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program)) - - #expect( - #RequireErrorResult<(ParserState, ProgramExecution)>( - Error(withMessage: "No key matched the selector"), - runtime.run())) -} - -@Test func test_simple_parser_binary_operator_equal() async throws { - let simple = """ - parser main_parser() { - state start { - transition select (true == true) { - true: accept; - false: reject; - }; - } - }; - """ - - let program = try #UseOkResult(Program.Compile(simple)) - let runtime = try #UseOkResult(P4Runtime.ParserRuntime.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() async throws { - let simple = """ - parser main_parser() { - state start { - transition select (true == false) { - true: accept; - false: reject; - }; - } - }; - """ - - let program = try #UseOkResult(Program.Compile(simple)) - let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program)) - let (state_result, _) = try! #UseOkResult(runtime.run()) - - #expect(state_result == P4Lang.reject) -} - -@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(Program.Compile(simple)) - let runtime = try #UseOkResult(P4Runtime.ParserRuntime.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(Program.Compile(simple)) - let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program)) - let (state_result, _) = try! #UseOkResult(runtime.run()) - - #expect(state_result == P4Lang.reject) -} - -@Test func test_simple_parser_binary_operator_equal_invalid_types() async throws { - let simple = """ - parser main_parser() { - state start { - transition select (5 == true) { - true: accept; - false: reject; - }; - } - }; - """ - - let program = try #UseOkResult(Program.Compile(simple)) - let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program)) - let (state_result, _) = try! #UseOkResult(runtime.run()) - - - // TODO: This test should throw an error. - - #expect(state_result == P4Lang.reject) -} \ No newline at end of file diff --git a/Tests/p4rseTests/StructTests.swift b/Tests/p4rseTests/StructTests.swift new file mode 100644 index 0000000..039673e --- /dev/null +++ b/Tests/p4rseTests/StructTests.swift @@ -0,0 +1,406 @@ +// 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 . + +import Common +import Foundation +import Macros +import P4Runtime +import P4Lang +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_types = LexicalScopes().enter() + let fields = P4StructFields([ + P4StructFieldIdentifier(name: "yesno", withType: P4Boolean()), + P4StructFieldIdentifier(name: "count", withType: P4Int()), + ]) + let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields) + test_types = test_types.declare(identifier: Identifier(name: "ts"), withValue: struct_type) + + var test_values = ValueScopes().enter() + test_values = test_values.declare( + identifier: Identifier(name: "ts"), + withValue: P4StructValue(withType: struct_type, andInitializers: [ + P4BooleanValue(withValue: true), + P4IntValue(withValue: 5), + ])) + + let program = try #UseOkResult( + Program.Compile(simple_parser_declaration, withGlobalTypes: test_types)) + let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program, withInitialValues: test_values)) + 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_types = LexicalScopes().enter() + let fields = P4StructFields([ + P4StructFieldIdentifier(name: "yesno", withType: P4Boolean()), + P4StructFieldIdentifier(name: "count", withType: P4Int()), + ]) + let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields) + test_types = test_types.declare(identifier: Identifier(name: "ts"), withValue: struct_type) + + var test_values = ValueScopes().enter() + test_values = test_values.declare( + identifier: Identifier(name: "ts"), + withValue: P4StructValue(withType: struct_type, andInitializers: [ + P4BooleanValue(withValue: false), + P4IntValue(withValue: 5), + ])) + + let program = try #UseOkResult( + Program.Compile(simple_parser_declaration, withGlobalTypes: test_types)) + let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program, withInitialValues: 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_types = LexicalScopes().enter() + let fields = P4StructFields([ + P4StructFieldIdentifier(name: "yesno", withType: P4Boolean()), + P4StructFieldIdentifier(name: "count", withType: P4Int()), + ]) + let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields) + test_types = test_types.declare(identifier: Identifier(name: "ts"), withValue: struct_type) + + var test_values = ValueScopes().enter() + test_values = test_values.declare( + identifier: Identifier(name: "ts"), + withValue: P4StructValue(withType: struct_type, andInitializers: [ + P4BooleanValue(withValue: true), + P4IntValue(withValue: 5), + ])) + + let program = try #UseOkResult( + Program.Compile(simple_parser_declaration, withGlobalTypes: test_types)) + let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program, withInitialValues: 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_types = LexicalScopes().enter() + let fields = P4StructFields([ + P4StructFieldIdentifier(name: "yesno", withType: P4Boolean()), + P4StructFieldIdentifier(name: "count", withType: P4Int()), + ]) + let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields) + test_types = test_types.declare(identifier: Identifier(name: "ts"), withValue: struct_type) + + var test_values = ValueScopes().enter() + test_values = test_values.declare( + identifier: Identifier(name: "ts"), + withValue: P4StructValue(withType: struct_type, andInitializers: [ + P4BooleanValue(withValue: true), + P4IntValue(withValue: 8), + ])) + + let program = try #UseOkResult( + Program.Compile(simple_parser_declaration, withGlobalTypes: test_types)) + let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program, withInitialValues: 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_types = LexicalScopes().enter() + + let ty_fields = P4StructFields([ + P4StructFieldIdentifier(name: "yesno", withType: P4Boolean()), + P4StructFieldIdentifier(name: "count", withType: P4Int()), + ]) + let ty_struct_type = P4Struct(withName: Identifier(name: "nested"), andFields: ty_fields) + + let ts_fields = P4StructFields([P4StructFieldIdentifier(name: "ty", withType: ty_struct_type)]) + let ts_struct_type = P4Struct(withName: Identifier(name: "outer"), andFields: ts_fields) + + test_types = test_types.declare(identifier: Identifier(name: "ts"), withValue: ts_struct_type) + + var test_values = ValueScopes().enter() + + test_values = test_values.declare( + identifier: Identifier(name: "ts"), + withValue: P4StructValue( + withType: ts_struct_type, + andInitializers: [ + P4StructValue( + withType: ty_struct_type, + andInitializers: [ + P4BooleanValue(withValue: true), + P4IntValue(withValue: 5), + ]) + ])) + let program = try #UseOkResult( + Program.Compile(simple_parser_declaration, withGlobalTypes: test_types)) + let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program, withInitialValues: 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_types = LexicalScopes().enter() + let fields = P4StructFields([ + P4StructFieldIdentifier(name: "yesno", withType: P4Boolean()), + P4StructFieldIdentifier(name: "count", withType: P4Int()), + ]) + let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields) + test_types = test_types.declare(identifier: Identifier(name: "ts"), withValue: struct_type) + + var test_values = ValueScopes().enter() + test_values = test_values.declare( + identifier: Identifier(name: "ts"), + withValue: P4StructValue(withType: struct_type, andInitializers: [ + P4BooleanValue(withValue: false), + P4IntValue(withValue: 5), + ])) + + let program = try #UseOkResult( + Program.Compile(simple_parser_declaration, withGlobalTypes: test_types)) + let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program, withInitialValues: 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_types = LexicalScopes().enter() + let fields = P4StructFields([ + P4StructFieldIdentifier(name: "yesno", withType: P4Boolean()), + P4StructFieldIdentifier(name: "count", withType: P4Int()), + ]) + let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields) + test_types = test_types.declare(identifier: Identifier(name: "ts"), withValue: struct_type) + + #expect( + #RequireErrorResult( + Error( + withMessage: "{49, 13}: Failed to parse a statement element: {49, 8}: Cannot assign value of type Int to field with type Boolean" + ), + Program.Compile(simple_parser_declaration, withGlobalTypes: test_types)) + ) +} + +@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_types = LexicalScopes().enter() + + let ty_fields = P4StructFields([ + P4StructFieldIdentifier(name: "yesno", withType: P4Boolean()), + P4StructFieldIdentifier(name: "count", withType: P4Int()), + ]) + let ty_struct_type = P4Struct(withName: Identifier(name: "nested"), andFields: ty_fields) + + let ts_fields = P4StructFields([P4StructFieldIdentifier(name: "ty", withType: ty_struct_type)]) + let ts_struct_type = P4Struct(withName: Identifier(name: "outer"), andFields: ts_fields) + + test_types = test_types.declare(identifier: Identifier(name: "ts"), withValue: ts_struct_type) + + var test_values = ValueScopes().enter() + + test_values = test_values.declare( + identifier: Identifier(name: "ts"), + withValue: P4StructValue( + withType: ts_struct_type, + andInitializers: [ + P4StructValue( + withType: ty_struct_type, + andInitializers: [ + P4BooleanValue(withValue: true), + P4IntValue(withValue: 7), + ]) + ])) + let program = try #UseOkResult( + Program.Compile(simple_parser_declaration, withGlobalTypes: test_types)) + let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program, withInitialValues: 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_types = LexicalScopes().enter() + + let ty_fields = P4StructFields([ + P4StructFieldIdentifier(name: "yesno", withType: P4Boolean()), + P4StructFieldIdentifier(name: "count", withType: P4Int()), + ]) + let ty_struct_type = P4Struct(withName: Identifier(name: "nested"), andFields: ty_fields) + + let ts_fields = P4StructFields([P4StructFieldIdentifier(name: "ty", withType: ty_struct_type)]) + let ts_struct_type = P4Struct(withName: Identifier(name: "outer"), andFields: ts_fields) + + test_types = test_types.declare(identifier: Identifier(name: "ts"), withValue: ts_struct_type) + + var test_values = ValueScopes().enter() + + test_values = test_values.declare( + identifier: Identifier(name: "ts"), + withValue: P4StructValue( + withType: ts_struct_type, + andInitializers: [ + P4StructValue( + withType: ty_struct_type, + andInitializers: [ + P4BooleanValue(withValue: true), + P4IntValue(withValue: 7), + ]) + ])) + let program = try #UseOkResult( + Program.Compile(simple_parser_declaration, withGlobalTypes: test_types)) + let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program, withInitialValues: 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_types = LexicalScopes().enter() + + let ty_fields = P4StructFields([ + P4StructFieldIdentifier(name: "yesno", withType: P4Boolean()), + P4StructFieldIdentifier(name: "count", withType: P4Int()), + ]) + let ty_struct_type = P4Struct(withName: Identifier(name: "nested"), andFields: ty_fields) + + let ts_fields = P4StructFields([P4StructFieldIdentifier(name: "ty", withType: ty_struct_type)]) + let ts_struct_type = P4Struct(withName: Identifier(name: "outer"), andFields: ts_fields) + + test_types = test_types.declare(identifier: Identifier(name: "ts"), withValue: ts_struct_type) + + #expect( + #RequireErrorResult( + Error( + withMessage: "{49, 20}: Failed to parse a statement element: {49, 11}: Cannot assign value of type Boolean to field with type Int" + ), + Program.Compile(simple_parser_declaration, withGlobalTypes: test_types)) + ) + +} diff --git a/Tests/p4rseTests/TransitionTests.swift b/Tests/p4rseTests/TransitionTests.swift new file mode 100644 index 0000000..591a944 --- /dev/null +++ b/Tests/p4rseTests/TransitionTests.swift @@ -0,0 +1,91 @@ +// 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 . + +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(Program.Compile(simple_parser_declaration)) + let parser = try #UseOkResult(program.find_parser(withName: Identifier(name: "main_parser"))) + let runtime = try #UseOkResult(P4Runtime.ParserRuntime.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(Program.Compile(simple_parser_declaration)) + let parser = try #UseOkResult(program.find_parser(withName: Identifier(name: "main_parser"))) + let runtime = try #UseOkResult(P4Runtime.ParserRuntime.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(Program.Compile(simple_parser_declaration)) + let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program)) + + #expect( + #RequireErrorResult<(ParserState, ProgramExecution)>( + Error(withMessage: "No key matched the selector"), + runtime.run())) +} \ No newline at end of file diff --git a/Tests/p4rseTests/TypeTests.swift b/Tests/p4rseTests/TypeTests.swift index 780e80b..5d18f90 100644 --- a/Tests/p4rseTests/TypeTests.swift +++ b/Tests/p4rseTests/TypeTests.swift @@ -16,14 +16,13 @@ // along with this program. If not, see . import Foundation -import Common import Macros import SwiftTreeSitter import Testing import TreeSitter import TreeSitterP4 -@testable import P4Compiler +@testable import Common @Test func test_simple_struct() async throws { let fields = P4StructFields([ diff --git a/Tests/p4rseTests/ValueTypeParserTests.swift b/Tests/p4rseTests/ValueTypeParserTests.swift index 4af3ffd..bc5d49b 100644 --- a/Tests/p4rseTests/ValueTypeParserTests.swift +++ b/Tests/p4rseTests/ValueTypeParserTests.swift @@ -52,7 +52,7 @@ import TreeSitterP4 #RequireErrorResult( Error( withMessage: - "{112, 16}: Failed to parse a statement element: {112, 16}: Cannot assign value of type Boolean to where_to (with type String)" + "{112, 16}: Failed to parse a statement element: {112, 8}: Cannot assign value with type Boolean to identifier where_to with type String" ), Program.Compile(simple_parser_declaration))) } @@ -73,7 +73,7 @@ import TreeSitterP4 #RequireErrorResult( Error( withMessage: - "{114, 22}: Failed to parse a statement element: {114, 22}: Cannot assign value of type String to where_to (with type Boolean)" + "{114, 22}: Failed to parse a statement element: {114, 8}: Cannot assign value with type String to identifier where_to with type Boolean" ), Program.Compile(simple_parser_declaration))) } @@ -252,354 +252,3 @@ import TreeSitterP4 ), Program.Compile(simple_parser_declaration, withGlobalTypes: test_types))) } - - -@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_types = LexicalScopes().enter() - test_types = test_types.declare(identifier: Identifier(name: "ta"), withValue: P4Array(withValueType: P4Int())) - var test_values = ValueScopes().enter() - test_values = test_values.declare( - identifier: Identifier(name: "ta"), - withValue: P4ArrayValue(withType: P4Int(), withValue: [ - P4IntValue(withValue: 1), P4IntValue(withValue: 2), P4IntValue(withValue: 3), - ])) - let program = try #UseOkResult( - Program.Compile(simple_parser_declaration, withGlobalTypes: test_types)) - let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program, withInitialValues: 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_types = LexicalScopes().enter() - test_types = test_types.declare(identifier: Identifier(name: "ta"), withValue: P4Int()) - #expect( - #RequireErrorResult( - Error( - withMessage: "{49, 22}: Failed to parse a statement element: {65, 2}: ta does not name an array type" - ), - Program.Compile(simple_parser_declaration, withGlobalTypes: test_types)) - ) -} - -@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_types = LexicalScopes().enter() - test_types = test_types.declare(identifier: Identifier(name: "ta"), withValue: P4Array(withValueType: P4Int())) - var test_values = ValueScopes().enter() - test_values = test_values.declare( - identifier: Identifier(name: "ta"), - withValue: P4ArrayValue(withType: P4Int(), withValue: [ - P4IntValue(withValue: 1), P4IntValue(withValue: 2), P4IntValue(withValue: 3), - ])) - let program = try #UseOkResult( - Program.Compile(simple_parser_declaration, withGlobalTypes: test_types)) - let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program, withInitialValues: 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_types = LexicalScopes().enter() - test_types = test_types.declare(identifier: Identifier(name: "ta"), withValue: P4Array(withValueType: P4Int())) - var test_values = ValueScopes().enter() - test_values = test_values.declare( - identifier: Identifier(name: "ta"), - withValue: P4ArrayValue(withType: P4Int(), withValue: [ - P4IntValue(withValue: 1), P4IntValue(withValue: 2), P4IntValue(withValue: 3), - ])) - let program = try #UseOkResult( - Program.Compile(simple_parser_declaration, withGlobalTypes: test_types)) - let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program, withInitialValues: 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_types = LexicalScopes().enter() - test_types = test_types.declare(identifier: Identifier(name: "ta"), withValue: P4Array(withValueType: P4Int())) - var test_values = ValueScopes().enter() - test_values = test_values.declare( - identifier: Identifier(name: "ta"), - withValue: P4ArrayValue(withType: P4Int(), withValue: [ - P4IntValue(withValue: 1), P4IntValue(withValue: 2), P4IntValue(withValue: 3), - ])) - let program = try #UseOkResult( - Program.Compile(simple_parser_declaration, withGlobalTypes: test_types)) - let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program, withInitialValues: 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_types = LexicalScopes().enter() - test_types = test_types.declare(identifier: Identifier(name: "ta"), withValue: P4Array(withValueType: P4Array(withValueType: P4Int()))) - var test_values = ValueScopes().enter() - - let nested = P4ArrayValue( - withType: P4Int(), - withValue: [P4IntValue(withValue: 5), P4IntValue(withValue: 2), P4IntValue(withValue: 3)]) - - test_values = test_values.declare( - identifier: Identifier(name: "ta"), - withValue: P4ArrayValue(withType: P4Array(withValueType: P4Int()), withValue: [nested])) - - let program = try #UseOkResult( - Program.Compile(simple_parser_declaration, withGlobalTypes: test_types)) - let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program, withInitialValues: test_values)) - let (state_result, _) = try! #UseOkResult(runtime.run()) - - #expect(state_result == P4Lang.accept) -} - -@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_types = LexicalScopes().enter() - let fields = P4StructFields([ - P4StructFieldIdentifier(name: "yesno", withType: P4Boolean()), - P4StructFieldIdentifier(name: "count", withType: P4Int()), - ]) - let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields) - test_types = test_types.declare(identifier: Identifier(name: "ts"), withValue: struct_type) - - var test_values = ValueScopes().enter() - test_values = test_values.declare( - identifier: Identifier(name: "ts"), - withValue: P4StructValue(withType: struct_type, andInitializers: [ - P4BooleanValue(withValue: true), - P4IntValue(withValue: 5), - ])) - - let program = try #UseOkResult( - Program.Compile(simple_parser_declaration, withGlobalTypes: test_types)) - let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program, withInitialValues: test_values)) - 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_types = LexicalScopes().enter() - let fields = P4StructFields([ - P4StructFieldIdentifier(name: "yesno", withType: P4Boolean()), - P4StructFieldIdentifier(name: "count", withType: P4Int()), - ]) - let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields) - test_types = test_types.declare(identifier: Identifier(name: "ts"), withValue: struct_type) - - var test_values = ValueScopes().enter() - test_values = test_values.declare( - identifier: Identifier(name: "ts"), - withValue: P4StructValue(withType: struct_type, andInitializers: [ - P4BooleanValue(withValue: false), - P4IntValue(withValue: 5), - ])) - - let program = try #UseOkResult( - Program.Compile(simple_parser_declaration, withGlobalTypes: test_types)) - let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program, withInitialValues: 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_types = LexicalScopes().enter() - let fields = P4StructFields([ - P4StructFieldIdentifier(name: "yesno", withType: P4Boolean()), - P4StructFieldIdentifier(name: "count", withType: P4Int()), - ]) - let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields) - test_types = test_types.declare(identifier: Identifier(name: "ts"), withValue: struct_type) - - var test_values = ValueScopes().enter() - test_values = test_values.declare( - identifier: Identifier(name: "ts"), - withValue: P4StructValue(withType: struct_type, andInitializers: [ - P4BooleanValue(withValue: true), - P4IntValue(withValue: 5), - ])) - - let program = try #UseOkResult( - Program.Compile(simple_parser_declaration, withGlobalTypes: test_types)) - let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program, withInitialValues: 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_types = LexicalScopes().enter() - let fields = P4StructFields([ - P4StructFieldIdentifier(name: "yesno", withType: P4Boolean()), - P4StructFieldIdentifier(name: "count", withType: P4Int()), - ]) - let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields) - test_types = test_types.declare(identifier: Identifier(name: "ts"), withValue: struct_type) - - var test_values = ValueScopes().enter() - test_values = test_values.declare( - identifier: Identifier(name: "ts"), - withValue: P4StructValue(withType: struct_type, andInitializers: [ - P4BooleanValue(withValue: true), - P4IntValue(withValue: 8), - ])) - - let program = try #UseOkResult( - Program.Compile(simple_parser_declaration, withGlobalTypes: test_types)) - let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program, withInitialValues: 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_types = LexicalScopes().enter() - - let ty_fields = P4StructFields([ - P4StructFieldIdentifier(name: "yesno", withType: P4Boolean()), - P4StructFieldIdentifier(name: "count", withType: P4Int()), - ]) - let ty_struct_type = P4Struct(withName: Identifier(name: "nested"), andFields: ty_fields) - - let ts_fields = P4StructFields([P4StructFieldIdentifier(name: "ty", withType: ty_struct_type)]) - let ts_struct_type = P4Struct(withName: Identifier(name: "outer"), andFields: ts_fields) - - test_types = test_types.declare(identifier: Identifier(name: "ts"), withValue: ts_struct_type) - - var test_values = ValueScopes().enter() - - test_values = test_values.declare( - identifier: Identifier(name: "ts"), - withValue: P4StructValue( - withType: ts_struct_type, - andInitializers: [ - P4StructValue( - withType: ty_struct_type, - andInitializers: [ - P4BooleanValue(withValue: true), - P4IntValue(withValue: 5), - ]) - ])) - let program = try #UseOkResult( - Program.Compile(simple_parser_declaration, withGlobalTypes: test_types)) - let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program, withInitialValues: test_values)) - let (state_result, _) = try! #UseOkResult(runtime.run()) - #expect(state_result == P4Lang.accept) -} \ No newline at end of file