From 94086c8e171bfb27f6bf8513d3f7eb71be2be0ac Mon Sep 17 00:00:00 2001 From: Will Hawkins Date: Mon, 13 Apr 2026 23:53:31 -0400 Subject: [PATCH] compiler, runtime, common, documentation: Refactor Type System The type system (and the value system) now include attributes for each type (things like direction, const-ness). Signed-off-by: Will Hawkins --- .gitignore | 1 - Snippets/use-program-instanceswithtypes.swift | 4 +- Snippets/use-program-typeswithtypes.swift | 2 +- Sources/Common/Compiler.swift | 8 +- .../{ProgramTypes.swift => DataTypes.swift} | 254 ++++++------------ Sources/Common/P4Types.swift | 200 ++++++++++++++ Sources/Common/Protocols.swift | 28 +- Sources/P4Compiler/Common.swift | 5 +- Sources/P4Compiler/Declarations.swift | 36 +-- Sources/P4Compiler/Expression.swift | 44 +-- Sources/P4Compiler/Protocols.swift | 6 +- Sources/P4Compiler/Statement.swift | 9 +- Sources/P4Compiler/Types.swift | 10 +- Sources/P4Lang/Common.swift | 15 +- Sources/P4Lang/Control.swift | 18 +- Sources/P4Lang/Declarations.swift | 25 +- Sources/P4Lang/Expressions.swift | 17 +- Sources/P4Lang/Parser.swift | 52 ++-- Sources/P4Lang/Program.swift | 18 +- Sources/P4Lang/Types.swift | 6 +- Sources/P4Runtime/Expressions.swift | 162 +++++------ Sources/P4Runtime/Parser.swift | 23 +- Sources/P4Runtime/Protocols.swift | 2 +- Sources/P4Runtime/Statements.swift | 4 +- Tests/p4rseTests/ArrayTests.swift | 63 ++--- .../BinaryOperatorTests/Struct.swift | 20 +- Tests/p4rseTests/ControlCompilerTests.swift | 8 +- .../ExpressionTests/SelectExpression.swift | 4 +- Tests/p4rseTests/ParserCompilerTests.swift | 12 +- Tests/p4rseTests/RuntimeTests.swift | 8 +- Tests/p4rseTests/ScopeTests.swift | 20 +- Tests/p4rseTests/StructTests.swift | 152 +++++------ Tests/p4rseTests/TypeTests.swift | 4 +- Tests/p4rseTests/ValueTypeParserTests.swift | 2 +- 34 files changed, 690 insertions(+), 552 deletions(-) rename Sources/Common/{ProgramTypes.swift => DataTypes.swift} (72%) create mode 100644 Sources/Common/P4Types.swift diff --git a/.gitignore b/.gitignore index fcb85b9..58be4a0 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,3 @@ DerivedData/ .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata .netrc tree-sitter-p4/test.txt -documentation/ diff --git a/Snippets/use-program-instanceswithtypes.swift b/Snippets/use-program-instanceswithtypes.swift index aa81c4c..a494019 100644 --- a/Snippets/use-program-instanceswithtypes.swift +++ b/Snippets/use-program-instanceswithtypes.swift @@ -39,8 +39,8 @@ let p4_program_with_control_decl = """ // snippet.include -let flter = { (tipe: P4TypeAttributed) -> Bool in - switch tipe.type { +let flter = { (tipe: P4Type) -> Bool in + switch tipe.dataType(){ case let c as Control: c.name == "simple" default: false } diff --git a/Snippets/use-program-typeswithtypes.swift b/Snippets/use-program-typeswithtypes.swift index 45e8192..32231a6 100644 --- a/Snippets/use-program-typeswithtypes.swift +++ b/Snippets/use-program-typeswithtypes.swift @@ -32,7 +32,7 @@ let p4_program_with_struct_decl = """ """ // snippet.include -let flter = { (tipe: P4Type) -> Bool in +let flter = { (tipe: P4DataType) -> Bool in switch tipe { case let c as P4Struct: c.name == "agg" default: false diff --git a/Sources/Common/Compiler.swift b/Sources/Common/Compiler.swift index 5aca1e6..c9f43ea 100644 --- a/Sources/Common/Compiler.swift +++ b/Sources/Common/Compiler.swift @@ -16,13 +16,13 @@ // along with this program. If not, see . /// A scope that resolves variable identifiers to their types. -public typealias VarTypeScope = Scope +public typealias VarTypeScope = Scope /// Scopes that resolve variable identifiers to their types. -public typealias VarTypeScopes = Scopes +public typealias VarTypeScopes = Scopes /// A scope that resolves type identifiers to their types. -public typealias TypeTypeScope = Scope +public typealias TypeTypeScope = Scope /// Scopes that resolve type identifiers to their types. -public typealias TypeTypeScopes = Scopes +public typealias TypeTypeScopes = Scopes diff --git a/Sources/Common/ProgramTypes.swift b/Sources/Common/DataTypes.swift similarity index 72% rename from Sources/Common/ProgramTypes.swift rename to Sources/Common/DataTypes.swift index 3bcc55a..7df2722 100644 --- a/Sources/Common/ProgramTypes.swift +++ b/Sources/Common/DataTypes.swift @@ -69,24 +69,18 @@ public class TypedIdentifier: Identifier { /// A P4 variable public class Variable: TypedIdentifier { - var constant: Bool - var value: P4Value? + var value: P4Value public init( - name: String, withType type: P4Type, withValue value: P4Value?, isConstant constant: Bool + name: String, withValue value: P4Value ) { - self.constant = constant self.value = value - super.init(name: name, withType: type) + super.init(name: name, withType: value.type()) } public override var description: String { return - "\(super.description) = \(value?.description ?? "Missing Value") \(constant ? "(constant)" : "")" - } - - public var value_type: P4Value? { - value + "\(super.description) = \(value.description)" } } @@ -141,7 +135,7 @@ public struct P4StructFields: Sequence, CustomStringConvertible, Equatable { } /// The type for a P4 struct -public struct P4Struct: P4Type { +public struct P4Struct: P4DataType { public let name: Identifier public let fields: P4StructFields @@ -160,7 +154,7 @@ public struct P4Struct: P4Type { return "Struct \(self.name) with fields: \(self.fields)" } - public func eq(rhs: P4Type) -> Bool { + public func eq(rhs: P4DataType) -> Bool { return if let struct_rhs = rhs as? P4Struct { struct_rhs.name == self.name } else { @@ -168,19 +162,20 @@ public struct P4Struct: P4Type { } } - public func def() -> any P4Value { + public func def() -> any P4DataValue { return P4StructValue(withType: self) } } /// An instance of a P4 struct -public class P4StructValue: P4Value { - public func type() -> any P4Type { +public class P4StructValue: P4DataValue { + public func type() -> P4DataType { return self.stype } - func bin_op_impl(lhs: P4StructValue, rhs: P4StructValue, op: (P4Value?, P4Value?) -> Bool) -> Bool - { + func bin_op_impl( + lhs: P4StructValue, rhs: P4StructValue, op: (P4DataValue?, P4DataValue?) -> Bool + ) -> Bool { if lhs.stype.fields.count() != rhs.stype.fields.count() { // If there are a different number of fields, then we cannot // possibly be equal. @@ -208,14 +203,14 @@ public class P4StructValue: P4Value { } // Now that we know that the field names match, do the values match? - if !op(left_field_value, right_field_value) { + if !op(left_field_value.dataValue(), right_field_value.dataValue()) { return false } } return true } - public func eq(rhs: any P4Value) -> Bool { + public func eq(rhs: any P4DataValue) -> Bool { guard let rrhs = rhs as? P4StructValue else { return false } @@ -231,7 +226,7 @@ public class P4StructValue: P4Value { return llhs.eq(rhs: rrhs) } } - public func lt(rhs: any P4Value) -> Bool { + public func lt(rhs: any P4DataValue) -> Bool { guard let rrhs = rhs as? P4StructValue else { return false } @@ -247,7 +242,7 @@ public class P4StructValue: P4Value { return llhs.lt(rhs: rrhs) } } - public func lte(rhs: any P4Value) -> Bool { + public func lte(rhs: any P4DataValue) -> Bool { guard let rrhs = rhs as? P4StructValue else { return false } @@ -263,7 +258,7 @@ public class P4StructValue: P4Value { return llhs.lte(rhs: rrhs) } } - public func gt(rhs: any P4Value) -> Bool { + public func gt(rhs: any P4DataValue) -> Bool { guard let rrhs = rhs as? P4StructValue else { return false } @@ -280,7 +275,7 @@ public class P4StructValue: P4Value { } } - public func gte(rhs: any P4Value) -> Bool { + public func gte(rhs: any P4DataValue) -> Bool { guard let rrhs = rhs as? P4StructValue else { return false } @@ -337,7 +332,7 @@ public class P4StructValue: P4Value { for field_idx in 0.. Bool { + public func eq(rhs: P4DataType) -> Bool { return switch rhs { case is P4Boolean: true default: false } } - public func def() -> any P4Value { + public func def() -> any P4DataValue { return P4BooleanValue(withValue: false) } } /// An instance of a P4 boolean -public class P4BooleanValue: P4Value { - public func type() -> any P4Type { +public class P4BooleanValue: P4DataValue { + public func type() -> any P4DataType { return P4Boolean() } @@ -386,35 +381,35 @@ public class P4BooleanValue: P4Value { public init(withValue value: Bool) { self.value = value } - public func eq(rhs: P4Value) -> Bool { + public func eq(rhs: P4DataValue) -> Bool { guard let bool_rhs = rhs as? P4BooleanValue else { return false } return self.value == bool_rhs.value } - public func lt(rhs: P4Value) -> Bool { + public func lt(rhs: P4DataValue) -> Bool { guard let bool_rhs = rhs as? P4BooleanValue else { return false } return (self.value ? 1 : 0) < (bool_rhs.value ? 1 : 0) } - public func lte(rhs: P4Value) -> Bool { + public func lte(rhs: P4DataValue) -> Bool { guard let bool_rhs = rhs as? P4BooleanValue else { return false } return (self.value ? 1 : 0) <= (bool_rhs.value ? 1 : 0) } - public func gt(rhs: P4Value) -> Bool { + public func gt(rhs: P4DataValue) -> Bool { guard let bool_rhs = rhs as? P4BooleanValue else { return false } return (self.value ? 1 : 0) > (bool_rhs.value ? 1 : 0) } - public func gte(rhs: P4Value) -> Bool { + public func gte(rhs: P4DataValue) -> Bool { guard let bool_rhs = rhs as? P4BooleanValue else { return false } @@ -427,26 +422,26 @@ public class P4BooleanValue: P4Value { } /// A P4 int type -public struct P4Int: P4Type { +public struct P4Int: P4DataType { public init() {} public var description: String { return "Int" } - public func eq(rhs: P4Type) -> Bool { + public func eq(rhs: P4DataType) -> Bool { return switch rhs { case is P4Int: true default: false } } - public func def() -> any P4Value { + public func def() -> any P4DataValue { return P4IntValue(withValue: 0) } } /// An instance of a P4 integer -public class P4IntValue: P4Value { - public func type() -> any P4Type { +public class P4IntValue: P4DataValue { + public func type() -> P4DataType { return P4Int() } @@ -459,35 +454,35 @@ public class P4IntValue: P4Value { return self.value } - public func eq(rhs: P4Value) -> Bool { + public func eq(rhs: P4DataValue) -> Bool { guard let int_rhs = rhs as? P4IntValue else { return false } return self.value == int_rhs.value } - public func lt(rhs: P4Value) -> Bool { + public func lt(rhs: P4DataValue) -> Bool { guard let int_rhs = rhs as? P4IntValue else { return false } return self.value < int_rhs.value } - public func lte(rhs: P4Value) -> Bool { + public func lte(rhs: P4DataValue) -> Bool { guard let int_rhs = rhs as? P4IntValue else { return false } return self.value <= int_rhs.value } - public func gt(rhs: P4Value) -> Bool { + public func gt(rhs: P4DataValue) -> Bool { guard let int_rhs = rhs as? P4IntValue else { return false } return self.value > int_rhs.value } - public func gte(rhs: P4Value) -> Bool { + public func gte(rhs: P4DataValue) -> Bool { guard let int_rhs = rhs as? P4IntValue else { return false } @@ -500,24 +495,24 @@ public class P4IntValue: P4Value { } /// A P4 string type -public struct P4String: P4Type { +public struct P4String: P4DataType { public init() {} public var description: String { return "String" } - public func eq(rhs: any P4Type) -> Bool { + public func eq(rhs: any P4DataType) -> Bool { return switch rhs { case is P4String: true default: false } } - public func def() -> any P4Value { + public func def() -> any P4DataValue { return P4StringValue(withValue: "") } } /// An instance of a P4 string -public class P4StringValue: P4Value { - public func type() -> any P4Type { +public class P4StringValue: P4DataValue { + public func type() -> any P4DataType { return P4String() } @@ -525,35 +520,35 @@ public class P4StringValue: P4Value { public init(withValue value: String) { self.value = value } - public func eq(rhs: P4Value) -> Bool { + public func eq(rhs: P4DataValue) -> Bool { guard let string_rhs = rhs as? P4StringValue else { return false } return self.value == string_rhs.value } - public func lt(rhs: P4Value) -> Bool { + public func lt(rhs: P4DataValue) -> Bool { guard let string_rhs = rhs as? P4StringValue else { return false } return self.value < string_rhs.value } - public func lte(rhs: P4Value) -> Bool { + public func lte(rhs: P4DataValue) -> Bool { guard let string_rhs = rhs as? P4StringValue else { return false } return self.value <= string_rhs.value } - public func gt(rhs: P4Value) -> Bool { + public func gt(rhs: P4DataValue) -> Bool { guard let string_rhs = rhs as? P4StringValue else { return false } return self.value > string_rhs.value } - public func gte(rhs: P4Value) -> Bool { + public func gte(rhs: P4DataValue) -> Bool { guard let string_rhs = rhs as? P4StringValue else { return false } @@ -570,7 +565,7 @@ public class Packet { } /// A P4 array type -public struct P4Array: P4Type { +public struct P4Array: P4DataType { public init(withValueType vtype: P4Type) { self.vtype = vtype } @@ -585,21 +580,21 @@ public struct P4Array: P4Type { return "Array" } - public func eq(rhs: any P4Type) -> Bool { + public func eq(rhs: any P4DataType) -> Bool { return switch rhs { case is P4Array: true default: false } } - public func def() -> P4Value { - return P4ArrayValue(withType: self, withValue: []) + public func def() -> P4DataValue { + return P4ArrayValue(withType: self.vtype, withValue: []) } } /// An instance of a P4 array -public class P4ArrayValue: P4Value { - public func type() -> any P4Type { +public class P4ArrayValue: P4DataValue { + public func type() -> any P4DataType { return P4Array(withValueType: self.vtype) } @@ -622,7 +617,7 @@ public class P4ArrayValue: P4Value { return Result.Ok(P4ArrayValue(withType: self.vtype, withValue: updated_values)) } - public func eq(rhs: P4Value) -> Bool { + public func eq(rhs: P4DataValue) -> Bool { guard rhs as? P4ArrayValue != nil else { return false } @@ -630,7 +625,7 @@ public class P4ArrayValue: P4Value { return true } - public func lt(rhs: P4Value) -> Bool { + public func lt(rhs: P4DataValue) -> Bool { guard rhs as? P4ArrayValue != nil else { return false } @@ -638,7 +633,7 @@ public class P4ArrayValue: P4Value { return true } - public func lte(rhs: P4Value) -> Bool { + public func lte(rhs: P4DataValue) -> Bool { guard rhs as? P4ArrayValue != nil else { return false } @@ -646,7 +641,7 @@ public class P4ArrayValue: P4Value { return true } - public func gt(rhs: P4Value) -> Bool { + public func gt(rhs: P4DataValue) -> Bool { guard rhs as? P4ArrayValue != nil else { return false } @@ -654,7 +649,7 @@ public class P4ArrayValue: P4Value { return true } - public func gte(rhs: P4Value) -> Bool { + public func gte(rhs: P4DataValue) -> Bool { guard rhs as? P4ArrayValue != nil else { return false } @@ -668,7 +663,7 @@ public class P4ArrayValue: P4Value { } /// A P4 set type -public struct P4Set: P4Type { +public struct P4Set: P4DataType { public init(withSetType stype: P4Type) { self.stype = stype } @@ -683,30 +678,28 @@ public struct P4Set: P4Type { return "P4Set" } - public func eq(rhs: any P4Type) -> Bool { + public func eq(rhs: any P4DataType) -> Bool { return switch rhs { // If rhs is a set type, then they are the same if the types in the set are the same. - case let srhs as P4Set: srhs.eq(rhs: self.stype) + case let srhs as P4Set: srhs.eq(rhs: self.stype.dataType()) default: false } } - public func def() -> P4Value { - return P4ArrayValue(withType: self, withValue: []) + public func def() -> P4DataValue { + return P4SetValue(withValue: P4Value(self.stype.dataType().def(), self.stype)) } } /// An instance of a P4 set -public class P4SetValue: P4Value { - public func type() -> any P4Type { - return P4Set(withSetType: self.stype) +public class P4SetValue: P4DataValue { + public func type() -> any P4DataType { + return P4Set(withSetType: self.value.type()) } let value: P4Value - let stype: P4Type - public init(withType type: P4Type, withValue value: P4Value) { - self.stype = type + public init(withValue value: P4Value) { self.value = value } @@ -714,44 +707,44 @@ public class P4SetValue: P4Value { return self.value } - public func eq(rhs: P4Value) -> Bool { + public func eq(rhs: P4DataValue) -> Bool { guard let rrhs = rhs as? P4SetValue else { return false } - return rrhs.access().eq(rhs: self.value) + return rrhs.access().dataValue().eq(rhs: self.value.dataValue()) } - public func lt(rhs: P4Value) -> Bool { + public func lt(rhs: P4DataValue) -> Bool { guard let rrhs = rhs as? P4SetValue else { return false } - return rrhs.access().lt(rhs: self.value) + return rrhs.access().dataValue().lt(rhs: self.value.dataValue()) } - public func lte(rhs: P4Value) -> Bool { + public func lte(rhs: P4DataValue) -> Bool { guard let rrhs = rhs as? P4SetValue else { return false } - return rrhs.access().lte(rhs: self.value) + return rrhs.access().dataValue().lte(rhs: self.value.dataValue()) } - public func gt(rhs: P4Value) -> Bool { + public func gt(rhs: P4DataValue) -> Bool { guard let rrhs = rhs as? P4SetValue else { return false } - return rrhs.access().gt(rhs: self.value) + return rrhs.access().dataValue().gt(rhs: self.value.dataValue()) } - public func gte(rhs: P4Value) -> Bool { + public func gte(rhs: P4DataValue) -> Bool { guard let rrhs = rhs as? P4SetValue else { return false } - return rrhs.access().gte(rhs: self.value) + return rrhs.access().dataValue().gte(rhs: self.value.dataValue()) } public var description: String { - "P4Set with \(self.value) of \(self.type()) type" + "P4Set with \(self.value)" } } -public class P4SetDefaultValue: P4Value { - public func type() -> any P4Type { +public class P4SetDefaultValue: P4DataValue { + public func type() -> P4DataType { return P4Set(withSetType: self.stype) } @@ -762,19 +755,19 @@ public class P4SetDefaultValue: P4Value { } // Snarf up everything! - public func eq(rhs: P4Value) -> Bool { + public func eq(rhs: P4DataValue) -> Bool { return true } - public func lt(rhs: P4Value) -> Bool { + public func lt(rhs: P4DataValue) -> Bool { return true } - public func lte(rhs: P4Value) -> Bool { + public func lte(rhs: P4DataValue) -> Bool { return true } - public func gt(rhs: P4Value) -> Bool { + public func gt(rhs: P4DataValue) -> Bool { return true } - public func gte(rhs: P4Value) -> Bool { + public func gte(rhs: P4DataValue) -> Bool { return true } @@ -782,76 +775,3 @@ public class P4SetDefaultValue: P4Value { "Default of P4Set of \(self.type()) type" } } - -public enum Direction: Equatable, CustomStringConvertible { - case In - case Out - case InOut - - public var description: String { - return switch self { - case Direction.In: "In" - case Direction.Out: "Out" - case Direction.InOut: "InOut" - } - } - - /// Compare two optional ``Direction``s - static public func eqopt(_ lhs: Direction?, _ rhs: Direction?) -> Bool { - // If both are empty, they are the same. - if lhs == .none && rhs == .none { - return true - } - - // If one is empty, they are different - if lhs == .none || rhs == .none { - return false - } - - // Both have values -- compare them natively. - return lhs! == rhs! - } -} - -public enum P4TypeAttribute { - case Direction(Direction) - case Readonly // Not yet used -- here to keep Swift warnings at bay -} - -public struct P4TypeAttributed { - let attributes: [P4TypeAttribute] - public let type: P4Type - - public init(_ type: P4Type, _ attributes: [P4TypeAttribute]) { - self.attributes = attributes - self.type = type - } - - public func direction() -> Direction? { - let result = attributes.firstIndex { attribute in - return switch attribute { - case .Direction(_): true - default: false - } - } - return result.flatMap { index in - return switch attributes[index] { - case .Direction(let d): d - default: Optional.none - } - } - } - - public func readOnly() -> Bool { - return attributes.contains { attribute in - return switch attribute { - case .Readonly: true - default: false - } - } - } - - public static func Attributeless(_ type: P4Type) -> P4TypeAttributed { - return P4TypeAttributed(type, []) - } -} diff --git a/Sources/Common/P4Types.swift b/Sources/Common/P4Types.swift new file mode 100644 index 0000000..e3a7ea0 --- /dev/null +++ b/Sources/Common/P4Types.swift @@ -0,0 +1,200 @@ +// 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 . + +public enum Direction: Equatable, CustomStringConvertible { + case In + case Out + case InOut + + public var description: String { + return switch self { + case Direction.In: "In" + case Direction.Out: "Out" + case Direction.InOut: "InOut" + } + } + + /// Compare two optional ``Direction``s + static public func eqopt(_ lhs: Direction?, _ rhs: Direction?) -> Bool { + // If both are empty, they are the same. + if lhs == .none && rhs == .none { + return true + } + + // If one is empty, they are different + if lhs == .none || rhs == .none { + return false + } + + // Both have values -- compare them natively. + return lhs! == rhs! + } +} + +public enum P4TypeAttribute: Equatable { + case Direction(Direction) + case Readonly // Not yet used -- here to keep Swift warnings at bay +} + +public struct P4TypeAttributes: CustomStringConvertible { + let _attributes: [P4TypeAttribute] + + public init(_ attributes: [P4TypeAttribute]) { + self._attributes = attributes + } + + public func direction() -> Direction? { + let result = _attributes.firstIndex { attribute in + return switch attribute { + case .Direction(_): true + default: false + } + } + return result.flatMap { index in + return switch _attributes[index] { + case .Direction(let d): d + default: Optional.none + } + } + } + + public func readOnly() -> Bool { + return _attributes.contains { attribute in + return switch attribute { + case .Readonly: true + default: false + } + } + } + + public func update(removeAttribute attributeToRemove: P4TypeAttribute) -> P4TypeAttributes { + var new_attributes = self._attributes + new_attributes.removeAll { item in + return item == attributeToRemove + } + return P4TypeAttributes(new_attributes) + } + + public func update(addAttribute attributeToAdd: P4TypeAttribute) -> P4TypeAttributes { + return P4TypeAttributes(self._attributes + [attributeToAdd]) + } + + public var description: String { + return self._attributes.map { attribute in + return "\(attribute)" + }.joined(separator: ",") + } + + public static func ReadOnly() -> P4TypeAttributes { + return P4TypeAttributes([P4TypeAttribute.Readonly]) + } + +} + +public struct P4Type: CustomStringConvertible { + let _attributes: P4TypeAttributes + let _data_type: P4DataType + + public init(_ type: P4DataType, _ attributes: P4TypeAttributes = P4TypeAttributes([])) { + self._attributes = attributes + self._data_type = type + } + + public func update(removeAttribute attribute: P4TypeAttribute) -> P4Type { + return P4Type(self._data_type, self._attributes.update(addAttribute: attribute)) + } + + public func update(addAttribute attribute: P4TypeAttribute) -> P4Type { + return P4Type(self._data_type, self._attributes.update(removeAttribute: attribute)) + } + + public func direction() -> Direction? { + return self._attributes.direction() + } + + public func readOnly() -> Bool { + return self._attributes.readOnly() + } + + public func dataType() -> P4DataType { + return self._data_type + } + + public func def() -> P4Value { + return P4Value(self._data_type.def(), self) + } + + public func eq(_ rhs: P4Type) -> Bool { + return self.direction() == rhs.direction() && self.readOnly() == self.readOnly() + && self.dataType().eq(rhs: rhs.dataType()) + } + + public static func ReadOnly(_ type: P4DataType) -> P4Type { + return P4Type(type, P4TypeAttributes.ReadOnly()) + } + + public var description: String { + var attributes_description = "\(self._attributes)" + if !attributes_description.isEmpty { + attributes_description += " " + } + return "\(attributes_description)\(self._data_type)" + } +} + +public struct P4Value: CustomStringConvertible { + let _value: P4DataValue + let _type: P4Type + + public init(_ value: P4DataValue, _ type: P4Type? = .none) { + self._value = value + self._type = type != nil ? type! : P4Type(value.type()) + } + + public func update(withNewValue value: P4DataValue) -> Result { + // TODO: Check that the types match. + return .Ok(P4Value(value, self._type)) + } + + public var description: String { + return "Value: \(self._value) of type \(self._type)" + } + + public func type() -> P4Type { + return self._type + } + + public func dataValue() -> P4DataValue { + return self._value + } + public func eq(_ rhs: P4Value) -> Bool { + return self._value.eq(rhs: rhs.dataValue()) + } + public func lt(_ rhs: P4Value) -> Bool { + return self._value.lt(rhs: rhs.dataValue()) + } + public func lte(_ rhs: P4Value) -> Bool { + return self._value.lte(rhs: rhs.dataValue()) + } + public func gt(_ rhs: P4Value) -> Bool { + return self._value.gt(rhs: rhs.dataValue()) + } + public func gte(_ rhs: P4Value) -> Bool { + return self._value.gte(rhs: rhs.dataValue()) + } + +} diff --git a/Sources/Common/Protocols.swift b/Sources/Common/Protocols.swift index 6800ce2..bce3be1 100644 --- a/Sources/Common/Protocols.swift +++ b/Sources/Common/Protocols.swift @@ -21,7 +21,7 @@ public protocol EvaluatableExpression { /// - execution: The execution context in which to evaluate the expression /// - Returns: The value of expression func evaluate(execution: ProgramExecution) -> Result - func type() -> any P4Type + func type() -> P4Type } public protocol EvaluatableStatement { @@ -34,24 +34,18 @@ public protocol EvaluatableStatement { func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) } -public protocol P4Type: CustomStringConvertible { - func eq(rhs: any P4Type) -> Bool - func def() -> P4Value +public protocol P4DataType: CustomStringConvertible { + func eq(rhs: any P4DataType) -> Bool + func def() -> P4DataValue } -public protocol P4Value: EvaluatableExpression, CustomStringConvertible { - func type() -> any P4Type - func eq(rhs: P4Value) -> Bool - func lt(rhs: P4Value) -> Bool - func lte(rhs: P4Value) -> Bool - func gt(rhs: P4Value) -> Bool - func gte(rhs: P4Value) -> Bool -} - -extension P4Value { - public func evaluate(execution: ProgramExecution) -> Result { - return Result.Ok(self) - } +public protocol P4DataValue: CustomStringConvertible { + func type() -> any P4DataType + func eq(rhs: P4DataValue) -> Bool + func lt(rhs: P4DataValue) -> Bool + func lte(rhs: P4DataValue) -> Bool + func gt(rhs: P4DataValue) -> Bool + func gte(rhs: P4DataValue) -> Bool } public protocol EvaluatableLValueExpression: EvaluatableExpression { diff --git a/Sources/P4Compiler/Common.swift b/Sources/P4Compiler/Common.swift index b5cdc9e..2b7d92f 100644 --- a/Sources/P4Compiler/Common.swift +++ b/Sources/P4Compiler/Common.swift @@ -226,7 +226,10 @@ extension Parameter: Compilable { return Result.Ok( ( Parameter( - identifier: parameter_name, withType: parameter_type, withDirection: direction), + identifier: parameter_name, + withType: direction != nil + ? parameter_type.update(addAttribute: P4TypeAttribute.Direction(direction!)) + : parameter_type), context )) } diff --git a/Sources/P4Compiler/Declarations.swift b/Sources/P4Compiler/Declarations.swift index f501ca9..ff834ba 100644 --- a/Sources/P4Compiler/Declarations.swift +++ b/Sources/P4Compiler/Declarations.swift @@ -25,7 +25,7 @@ import TreeSitterP4 extension Declaration: CompilableDeclaration { public static func Compile( node: Node, withContext context: CompilerContext - ) -> Result<(P4Type, CompilerContext)?> { + ) -> Result<(P4DataType, CompilerContext)?> { let declaration_compilers: [String: CompilableDeclaration.Type] = [ "function_declaration": FunctionDeclaration.self, @@ -44,7 +44,7 @@ extension Declaration: CompilableDeclaration { extension FunctionDeclaration: CompilableDeclaration { public static func Compile( node: SwiftTreeSitter.Node, withContext context: CompilerContext - ) -> Common.Result<(any Common.P4Type, CompilerContext)?> { + ) -> Common.Result<(any Common.P4DataType, CompilerContext)?> { let function_declaration_node = node #RequireNodeType( node: function_declaration_node, type: "function_declaration", @@ -109,7 +109,7 @@ extension FunctionDeclaration: CompilableDeclaration { var function_scope = context.instances.enter() for parameter in function_parameters.parameters { function_scope = function_scope.declare( - identifier: parameter.name, withValue: parameter.attributedType()) + identifier: parameter.name, withValue: parameter.type) } let maybe_function_body = Parser.Statement.Compile( @@ -141,7 +141,7 @@ struct StructDeclaration {} extension StructDeclaration: CompilableDeclaration { static func Compile( node: Node, withContext context: CompilerContext - ) -> Result<(P4Type, CompilerContext)?> { + ) -> Result<(P4DataType, CompilerContext)?> { let struct_declaration_node = node.child(at: 0)! var currentChildIdx = 0 @@ -249,9 +249,9 @@ extension StructDeclaration: CompilableDeclaration { extension P4Lang.Parser: CompilableDeclaration { public static func Compile( node: Node, withContext context: CompilerContext - ) -> Result<(P4Type, CompilerContext)?> { + ) -> Result<(P4DataType, CompilerContext)?> { let parser_node = node - #SkipUnlessNodeType( + #SkipUnlessNodeType( node: parser_node, type: "parserDeclaration") var current_context = context @@ -332,7 +332,7 @@ extension P4Lang.Parser: CompilableDeclaration { for parameter in parameter_list.parameters { current_context = current_context.update( newInstances: current_context.instances.declare( - identifier: parameter.name, withValue: parameter.attributedType())) + identifier: parameter.name, withValue: parameter.type)) } currentChildIdx += 1 @@ -375,7 +375,7 @@ extension P4Lang.Parser: CompilableDeclaration { parser, context.update( newInstances: updated_context.instances.declare( - identifier: parser.name, withValue: P4TypeAttributed(parser, []))) + identifier: parser.name, withValue: P4Type(parser))) )) case Result.Error(let error): return .Error(error) } @@ -385,9 +385,9 @@ extension P4Lang.Parser: CompilableDeclaration { extension Control: CompilableDeclaration { public static func Compile( node: SwiftTreeSitter.Node, withContext context: CompilerContext - ) -> Common.Result<(any Common.P4Type, CompilerContext)?> { + ) -> Common.Result<(any Common.P4DataType, CompilerContext)?> { - #SkipUnlessNodeType( + #SkipUnlessNodeType( node: node, type: "control_declaration") var currentChildIdx = 0 @@ -438,7 +438,7 @@ extension Control: CompilableDeclaration { var control_scope = local_context.instances.enter() for parameter in control_parameters.parameters { control_scope = control_scope.declare( - identifier: parameter.name, withValue: parameter.attributedType()) + identifier: parameter.name, withValue: parameter.type) } local_context = local_context.update(newInstances: control_scope) @@ -498,7 +498,7 @@ extension Control: CompilableDeclaration { (Control( named: control_name, withParameters: control_parameters, withTable: tables[0], withActions: Actions(withActions: actions)) - as P4Type) + as P4DataType) // Don't forget to add the newly declared Control to the instance that we were given // (and not the one that we entered to do the parsing of this Control). @@ -507,7 +507,7 @@ extension Control: CompilableDeclaration { declared_control, context.update( newInstances: context.instances.declare( - identifier: control_name, withValue: P4TypeAttributed(declared_control, []))) + identifier: control_name, withValue: P4Type(declared_control))) )) } } @@ -517,7 +517,7 @@ extension Action: Compilable { public static func Compile( node: SwiftTreeSitter.Node, withContext context: CompilerContext ) -> Common.Result<(P4Lang.Action, CompilerContext)> { - #RequireNodeType( + #RequireNodeType( node: node, type: "action_declaration", nice_type_name: "Action Declaration") var currentChildIdx = 1 @@ -569,7 +569,7 @@ extension Action: Compilable { var function_scope = context.instances.enter() for parameter in action_parameters.parameters { function_scope = function_scope.declare( - identifier: parameter.name, withValue: parameter.attributedType()) + identifier: parameter.name, withValue: parameter.type) } let maybe_action_body = Parser.Statement.Compile( @@ -592,7 +592,7 @@ extension TableKeyEntry: Compilable { node: SwiftTreeSitter.Node, withContext context: CompilerContext ) -> Common.Result<(P4Lang.TableKeyEntry, CompilerContext)> { - #RequireNodeType( + #RequireNodeType( node: node, type: "table_key_entry", nice_type_name: "Table Key Entry") var currentChildIdx = 0 @@ -701,7 +701,7 @@ extension TablePropertyList: Compilable { node: SwiftTreeSitter.Node, withContext context: CompilerContext ) -> Common.Result<(P4Lang.TablePropertyList, CompilerContext)> { - #RequireNodeType( + #RequireNodeType( node: node, type: "table_property_list", nice_type_name: "Table Property List") var current_context = context @@ -756,7 +756,7 @@ extension Table: Compilable { ) -> Common.Result<(P4Lang.Table, CompilerContext)> { let table_declaration_node = node - #RequireNodeType( + #RequireNodeType( node: table_declaration_node, type: "table_declaration", nice_type_name: "Table Declaration") var currentChildIdx = 1 diff --git a/Sources/P4Compiler/Expression.swift b/Sources/P4Compiler/Expression.swift index e8d59fc..5a5bb32 100644 --- a/Sources/P4Compiler/Expression.swift +++ b/Sources/P4Compiler/Expression.swift @@ -43,13 +43,13 @@ extension TypedIdentifier: CompilableExpression { node: node, type: "identifier") guard - case Result.Ok(let attributed_type) = context.instances.lookup( + case Result.Ok(let type) = context.instances.lookup( identifier: Common.Identifier(name: node.text!)) else { return .Error(ErrorOnNode(node: node, withError: "Cannot find \(node.text!) in scope")) } - return .Ok(TypedIdentifier(name: node.text!, withType: attributed_type.type)) + return .Ok(TypedIdentifier(name: node.text!, withType: type)) } } @@ -82,9 +82,9 @@ extension P4BooleanValue: CompilableExpression { node: node, type: "booleanLiteralExpression") if node.text == "false" { - return .Ok(P4BooleanValue(withValue: false)) + return .Ok(P4Value(P4BooleanValue(withValue: false))) } else if node.text == "true" { - return .Ok(P4BooleanValue(withValue: true)) + return .Ok(P4Value(P4BooleanValue(withValue: true))) } return .Error( @@ -99,7 +99,7 @@ extension P4IntValue: CompilableExpression { let node = node.child(at: 0)! #SkipUnlessNodeType(node: node, type: "integer") if let parsed_int = Int(node.text!) { - return .Ok(P4IntValue(withValue: parsed_int)) + return .Ok(P4Value(P4IntValue(withValue: parsed_int))) } else { return .Error(ErrorOnNode(node: node, withError: "Failed to parse integer: \(node.text!)")) } @@ -113,7 +113,7 @@ extension P4StringValue: CompilableExpression { let node = node.child(at: 0)! #SkipUnlessNodeType( node: node, type: "string_literal") - return .Ok(P4StringValue(withValue: node.text!)) + return .Ok(P4Value(P4StringValue(withValue: node.text!))) } } @@ -129,7 +129,7 @@ extension KeysetExpression: CompilableExpression { // If there is a default keyset, that's easy! if keyset_expression_node.nodeType == "default_keyset" { - return .Ok(KeysetExpression(P4SetDefaultValue(withType: context.expected_type!))) + return .Ok(KeysetExpression(P4Value(P4SetDefaultValue(withType: context.expected_type!)))) } // Compile the expression: @@ -399,44 +399,48 @@ extension BinaryOperatorExpression: CompilableExpression { let evaluators: [String: (String, P4Type, BinaryOperatorChecker?, BinaryOperatorEvaluator)] = [ "binaryEqualOperatorExpression": ( - "Binary Equal", P4Boolean(), Optional.none, + "Binary Equal", P4Type(P4Boolean()), Optional.none, binary_equal_operator_evaluator ), "binaryLessThanOperatorExpression": ( - "Binary Less Than", P4Boolean(), Optional.none, + "Binary Less Than", P4Type(P4Boolean()), Optional.none, binary_lt_operator_evaluator ), "binaryLessThanEqualOperatorExpression": ( - "Binary Less Than Or Equal", P4Boolean(), Optional.none, + "Binary Less Than Or Equal", P4Type(P4Boolean()), Optional.none, binary_lte_operator_evaluator ), "binaryGreaterThanOperatorExpression": ( - "Binary Greater Than", P4Boolean(), Optional.none, + "Binary Greater Than", P4Type(P4Boolean()), Optional.none, binary_gt_operator_evaluator ), "binaryGreaterThanEqualOperatorExpression": ( - "Binary Greater Than Or Equal", P4Boolean(), Optional.none, + "Binary Greater Than Or Equal", P4Type(P4Boolean()), Optional.none, binary_gte_operator_evaluator ), "binaryAndOperatorExpression": ( - "Binary Or", P4Boolean(), binary_and_or_operator_checker, binary_and_operator_evaluator + "Binary Or", P4Type(P4Boolean()), binary_and_or_operator_checker, + binary_and_operator_evaluator ), "binaryOrOperatorExpression": ( - "Binary And", P4Boolean(), binary_and_or_operator_checker, binary_or_operator_evaluator + "Binary And", P4Type(P4Boolean()), binary_and_or_operator_checker, + binary_or_operator_evaluator ), "binaryAddOperatorExpression": ( - "Binary Add", P4Int(), binary_int_math_operator_checker, binary_add_operator_evaluator + "Binary Add", P4Type(P4Int()), binary_int_math_operator_checker, + binary_add_operator_evaluator ), "binarySubtractOperatorExpression": ( - "Binary Subtract", P4Int(), binary_int_math_operator_checker, + "Binary Subtract", P4Type(P4Int()), binary_int_math_operator_checker, binary_subtract_operator_evaluator ), "binaryMultiplyOperatorExpression": ( - "Binary Multiply", P4Int(), binary_int_math_operator_checker, + "Binary Multiply", P4Type(P4Int()), binary_int_math_operator_checker, binary_multiply_operator_evaluator ), "binaryDivideOperatorExpression": ( - "Binary Divide", P4Int(), binary_int_math_operator_checker, binary_divide_operator_evaluator + "Binary Divide", P4Type(P4Int()), binary_int_math_operator_checker, + binary_divide_operator_evaluator ), ] @@ -517,7 +521,7 @@ extension ArrayAccessExpression: CompilableExpression { } let maybe_array_type = array_identifier.type() - guard let array_type = maybe_array_type as? P4Array else { + guard let array_type = maybe_array_type.dataType() as? P4Array else { return Result.Error( ErrorOnNode( node: array_access_identifier_node, @@ -595,7 +599,7 @@ extension FieldAccessExpression: CompilableExpression { guard case Result.Ok(let struct_identifier) = maybe_struct_identifier else { return Result.Error(maybe_struct_identifier.error()!) } - guard let struct_type = struct_identifier.type() as? P4Struct else { + guard let struct_type = struct_identifier.type().dataType() as? P4Struct else { return .Error( ErrorOnNode( node: struct_identifier_node, diff --git a/Sources/P4Compiler/Protocols.swift b/Sources/P4Compiler/Protocols.swift index f9ff25f..5f5cc24 100644 --- a/Sources/P4Compiler/Protocols.swift +++ b/Sources/P4Compiler/Protocols.swift @@ -29,19 +29,19 @@ public protocol CompilableStatement { } public protocol CompilableValue { - static func CompileValue(withValue value: String) -> Result + static func CompileValue(withValue value: String) -> Result } public protocol CompilableType { static func CompileType( type: SwiftTreeSitter.Node, withContext: CompilerContext - ) -> Result + ) -> Result } public protocol CompilableDeclaration { static func Compile( node: Node, withContext context: CompilerContext - ) -> Result<(P4Type, CompilerContext)?> + ) -> Result<(P4DataType, CompilerContext)?> } public protocol Compilable { diff --git a/Sources/P4Compiler/Statement.swift b/Sources/P4Compiler/Statement.swift index df7bfc3..54cf3ce 100644 --- a/Sources/P4Compiler/Statement.swift +++ b/Sources/P4Compiler/Statement.swift @@ -214,7 +214,7 @@ extension VariableDeclarationStatement: CompilableStatement { return .Error(maybe_parsed_rvalue.error()!) } - if parsed_rvalue.type().eq(rhs: declaration_p4_type) { + if parsed_rvalue.type().eq(declaration_p4_type) { initializer = parsed_rvalue } else { return Result.Error( @@ -231,8 +231,9 @@ extension VariableDeclarationStatement: CompilableStatement { // Context with updated names to include the newly declared name. context.update( newInstances: context.instances.declare( - identifier: parsed_variablename, withValue: P4TypeAttributed(declaration_p4_type, []))) - )) + identifier: parsed_variablename, withValue: declaration_p4_type)) + ) + ) } } @@ -311,7 +312,7 @@ extension ReturnStatement: CompilableStatement { return switch Expression.Compile(node: expression_node, withContext: context) { case .Ok(let result): - if result.type().eq(rhs: context.expected_type!) { + if result.type().eq(context.expected_type!) { .Ok((ReturnStatement(result), context)) } else { .Error( diff --git a/Sources/P4Compiler/Types.swift b/Sources/P4Compiler/Types.swift index fd182ce..aec0c27 100644 --- a/Sources/P4Compiler/Types.swift +++ b/Sources/P4Compiler/Types.swift @@ -25,7 +25,7 @@ import TreeSitterP4 extension P4Boolean: CompilableType { public static func CompileType( type: SwiftTreeSitter.Node, withContext: CompilerContext - ) -> Common.Result<(any Common.P4Type)?> { + ) -> Common.Result<(any Common.P4DataType)?> { return type.text == "bool" ? .Ok(P4Boolean()) : .Ok(.none) } } @@ -33,7 +33,7 @@ extension P4Boolean: CompilableType { extension P4Int: CompilableType { public static func CompileType( type: SwiftTreeSitter.Node, withContext: CompilerContext - ) -> Common.Result<(any Common.P4Type)?> { + ) -> Common.Result<(any Common.P4DataType)?> { return type.text == "int" ? .Ok(P4Int()) : .Ok(.none) } } @@ -41,7 +41,7 @@ extension P4Int: CompilableType { extension P4String: CompilableType { public static func CompileType( type: SwiftTreeSitter.Node, withContext: CompilerContext - ) -> Common.Result<(any Common.P4Type)?> { + ) -> Common.Result<(any Common.P4DataType)?> { return type.text == "string" ? .Ok(P4String()) : .Ok(.none) } } @@ -49,7 +49,7 @@ extension P4String: CompilableType { extension P4Struct: CompilableType { public static func CompileType( type: SwiftTreeSitter.Node, withContext context: CompilerContext - ) -> Common.Result<(any Common.P4Type)?> { + ) -> Common.Result<(any Common.P4DataType)?> { let maybe_parsed_type_id = Identifier.Compile(node: type, withContext: context) guard case .Ok(let parsed_type_id) = maybe_parsed_type_id else { @@ -74,7 +74,7 @@ public struct Types { ] for type_parser in type_parsers { switch type_parser.CompileType(type: type, withContext: context) { - case .Ok(.some(let type)): return .Ok(type) + case .Ok(.some(let type)): return .Ok(P4Type(type)) case .Ok(.none): continue case .Error(let e): return .Error(e) } diff --git a/Sources/P4Lang/Common.swift b/Sources/P4Lang/Common.swift index a3b8d7e..adf0690 100644 --- a/Sources/P4Lang/Common.swift +++ b/Sources/P4Lang/Common.swift @@ -19,36 +19,29 @@ import Common public struct Parameter: CustomStringConvertible, Equatable { public static func == (lhs: Parameter, rhs: Parameter) -> Bool { - return lhs.name == rhs.name && lhs.type.eq(rhs: rhs.type) && lhs.direction == rhs.direction + return lhs.name == rhs.name && lhs.type.eq(rhs.type) } public var name: Identifier public var type: P4Type - public var direction: Direction? public init( - identifier: Identifier, withType type: P4Type, withDirection direction: Direction? = .none + identifier: Identifier, withType type: P4Type ) { self.name = identifier self.type = type - self.direction = direction } public var description: String { - let direction = self.direction != .none ? self.direction!.description : "no" - return "Parameter: \(self.name) with type \(self.type) with \(direction) direction" + return "Parameter: \(self.name) with type \(self.type)" } /// Calculate whether the `argument` is compatible with this parameter. public func compatible(_ argument: Argument) -> Bool { let arg_type = argument.argument.type() - return arg_type.eq(rhs: self.type) + return arg_type.eq(self.type) } - public func attributedType() -> P4TypeAttributed { - return P4TypeAttributed( - self.type, self.direction == .none ? [] : [P4TypeAttribute.Direction(self.direction!)]) - } } public struct ParameterList: CustomStringConvertible, Equatable { diff --git a/Sources/P4Lang/Control.swift b/Sources/P4Lang/Control.swift index fc2fb0c..4775620 100644 --- a/Sources/P4Lang/Control.swift +++ b/Sources/P4Lang/Control.swift @@ -120,53 +120,53 @@ public struct Table: CustomStringConvertible { } } -public struct Control: P4Type, P4Value, Equatable, CustomStringConvertible { +public struct Control: P4DataType, P4DataValue, Equatable, CustomStringConvertible { public static func == (lhs: Control, rhs: Control) -> Bool { // Two "bare" controls are always equal. return true } - public func eq(rhs: any Common.P4Type) -> Bool { + public func eq(rhs: any Common.P4DataType) -> Bool { return switch rhs { case is Control: true default: false } } - public func type() -> any Common.P4Type { + public func type() -> any Common.P4DataType { return self } // Any operation between two "bare" parser states is always true. - public func eq(rhs: any Common.P4Value) -> Bool { + public func eq(rhs: any Common.P4DataValue) -> Bool { return switch rhs { case is Control: true default: false } } - public func lt(rhs: any Common.P4Value) -> Bool { + public func lt(rhs: any Common.P4DataValue) -> Bool { return switch rhs { case is Control: true default: false } } - public func lte(rhs: any Common.P4Value) -> Bool { + public func lte(rhs: any Common.P4DataValue) -> Bool { return switch rhs { case is Control: true default: false } } - public func gt(rhs: any Common.P4Value) -> Bool { + public func gt(rhs: any Common.P4DataValue) -> Bool { return switch rhs { case is Control: true default: false } } - public func gte(rhs: any Common.P4Value) -> Bool { + public func gte(rhs: any Common.P4DataValue) -> Bool { return switch rhs { case is Control: true default: false @@ -200,7 +200,7 @@ public struct Control: P4Type, P4Value, Equatable, CustomStringConvertible { self.table = table } - public func def() -> any P4Value { + public func def() -> any P4DataValue { return Control( named: Identifier(name: ""), withParameters: ParameterList(), diff --git a/Sources/P4Lang/Declarations.swift b/Sources/P4Lang/Declarations.swift index 69fddc9..6b735dd 100644 --- a/Sources/P4Lang/Declarations.swift +++ b/Sources/P4Lang/Declarations.swift @@ -19,34 +19,34 @@ import Common public struct Declaration {} -public struct FunctionDeclaration: P4Type, P4Value { - public func type() -> any Common.P4Type { +public struct FunctionDeclaration: P4DataType, P4DataValue { + public func type() -> any Common.P4DataType { return self } - public func eq(rhs: any Common.P4Type) -> Bool { + public func eq(rhs: any Common.P4DataType) -> Bool { switch rhs { case let frhs as FunctionDeclaration: - return frhs.tipe.eq(rhs: self.tipe) && frhs.params == self.params + return frhs.tipe.eq(self.tipe) && frhs.params == self.params default: return false } } - public func eq(rhs: any Common.P4Value) -> Bool { + public func eq(rhs: any Common.P4DataValue) -> Bool { switch rhs { - case let frhs as FunctionDeclaration: return self.eq(rhs: frhs as P4Type) + case let frhs as FunctionDeclaration: return self.eq(rhs: frhs as P4DataType) default: return false } } - public func lt(rhs: any Common.P4Value) -> Bool { + public func lt(rhs: any Common.P4DataValue) -> Bool { switch rhs { case let frhs as FunctionDeclaration: return self.name < frhs.name default: return false } } - public func lte(rhs: any Common.P4Value) -> Bool { + public func lte(rhs: any Common.P4DataValue) -> Bool { switch rhs { case let frhs as FunctionDeclaration: return self.name <= frhs.name default: return false @@ -54,23 +54,24 @@ public struct FunctionDeclaration: P4Type, P4Value { } - public func gt(rhs: any Common.P4Value) -> Bool { + public func gt(rhs: any Common.P4DataValue) -> Bool { switch rhs { case let frhs as FunctionDeclaration: return self.name > frhs.name default: return false } } - public func gte(rhs: any Common.P4Value) -> Bool { + public func gte(rhs: any Common.P4DataValue) -> Bool { switch rhs { case let frhs as FunctionDeclaration: return self.name >= frhs.name default: return false } } - public func def() -> any Common.P4Value { + public func def() -> any Common.P4DataValue { return FunctionDeclaration( - named: Identifier(name: ""), ofType: P4Boolean(), withParameters: ParameterList([]), + named: Identifier(name: ""), ofType: P4Type(P4Boolean()), + withParameters: ParameterList([]), withBody: .none) } diff --git a/Sources/P4Lang/Expressions.swift b/Sources/P4Lang/Expressions.swift index 113358d..ec198db 100644 --- a/Sources/P4Lang/Expressions.swift +++ b/Sources/P4Lang/Expressions.swift @@ -25,15 +25,15 @@ public struct KeysetExpression { } public func compatible(type: P4Type) -> Result<()> { - if let key_type = self.key.type() as? P4Set { - if !key_type.set_type().eq(rhs: type) { + if let key_type = self.key.type().dataType() as? P4Set { + if !key_type.set_type().eq(type) { return .Error( Error( withMessage: "Key expression of type set of type \(key_type.set_type()) is not compatible with selector type \(type)" )) } - } else if !self.key.type().eq(rhs: type) { + } else if !self.key.type().eq(type) { return .Error( Error( withMessage: @@ -66,26 +66,27 @@ public struct SelectCaseExpression { public struct SelectExpression { public let selector: EvaluatableExpression - public let select_expressions: [SelectCaseExpression] + public let case_expressions: [SelectCaseExpression] public init( withSelector selector: EvaluatableExpression, withSelectCaseExpressions sces: [SelectCaseExpression] ) { self.selector = selector - self.select_expressions = sces + self.case_expressions = sces } public func append_checked_sce(sce: SelectCaseExpression) -> SelectExpression { - var new_cses = self.select_expressions + var new_cses = self.case_expressions new_cses.append(sce) return SelectExpression( withSelector: self.selector, withSelectCaseExpressions: new_cses) } } -public typealias NamedBinaryOperatorEvaluator = (String, P4Type, (P4Value, P4Value) -> P4Value) -public typealias BinaryOperatorEvaluator = (P4Value, P4Value) -> P4Value +public typealias NamedBinaryOperatorEvaluator = (String, P4Type, (P4Value, P4Value) -> P4DataValue) +public typealias BinaryOperatorEvaluator = (P4Value, P4Value) -> P4DataValue + public struct BinaryOperatorExpression { public let evaluator: NamedBinaryOperatorEvaluator public let left: EvaluatableExpression diff --git a/Sources/P4Lang/Parser.swift b/Sources/P4Lang/Parser.swift index e60478c..cd76ff1 100644 --- a/Sources/P4Lang/Parser.swift +++ b/Sources/P4Lang/Parser.swift @@ -41,53 +41,53 @@ public struct ParserAssignmentStatement { /// /// Note: A P4 Parser State is both a type and a value. /// This "bare" parser state represents the state more as a type than a value. -public class ParserState: P4Type, P4Value, Equatable, CustomStringConvertible { +public class ParserState: P4DataType, P4DataValue, Equatable, CustomStringConvertible { public static func == (lhs: ParserState, rhs: ParserState) -> Bool { // Two "bare" parser states are always equal. return true } - public func eq(rhs: any Common.P4Type) -> Bool { + public func eq(rhs: any Common.P4DataType) -> Bool { return switch rhs { case is ParserState: true default: false } } - public func type() -> any Common.P4Type { + public func type() -> any Common.P4DataType { return self } // Any operation between two "bare" parser states is always true. - public func eq(rhs: any Common.P4Value) -> Bool { + public func eq(rhs: any Common.P4DataValue) -> Bool { return switch rhs { case is ParserState: true default: false } } - public func lt(rhs: any Common.P4Value) -> Bool { + public func lt(rhs: any Common.P4DataValue) -> Bool { return switch rhs { case is ParserState: true default: false } } - public func lte(rhs: any Common.P4Value) -> Bool { + public func lte(rhs: any Common.P4DataValue) -> Bool { return switch rhs { case is ParserState: true default: false } } - public func gt(rhs: any Common.P4Value) -> Bool { + public func gt(rhs: any Common.P4DataValue) -> Bool { return switch rhs { case is ParserState: true default: false } } - public func gte(rhs: any Common.P4Value) -> Bool { + public func gte(rhs: any Common.P4DataValue) -> Bool { return switch rhs { case is ParserState: true default: false @@ -101,7 +101,7 @@ public class ParserState: P4Type, P4Value, Equatable, CustomStringConvertible { /// Construct a ParserState public init() {} - public func def() -> any P4Value { + public func def() -> any P4DataValue { return ParserState() } } @@ -116,46 +116,46 @@ public class InstantiatedParserState: ParserState { return lhs.state == rhs.state } - public override func eq(rhs: any Common.P4Type) -> Bool { + public override func eq(rhs: any Common.P4DataType) -> Bool { return switch rhs { case is ParserState: true default: false } } - public override func type() -> any Common.P4Type { + public override func type() -> any Common.P4DataType { return self } - public override func eq(rhs: any Common.P4Value) -> Bool { + public override func eq(rhs: any Common.P4DataValue) -> Bool { return switch rhs { case let other as InstantiatedParserState: self.state == other.state default: false } } - public override func lt(rhs: any Common.P4Value) -> Bool { + public override func lt(rhs: any Common.P4DataValue) -> Bool { return switch rhs { case let other as InstantiatedParserState: self.state < other.state default: false } } - public override func lte(rhs: any Common.P4Value) -> Bool { + public override func lte(rhs: any Common.P4DataValue) -> Bool { return switch rhs { case let other as InstantiatedParserState: self.state <= other.state default: false } } - public override func gt(rhs: any Common.P4Value) -> Bool { + public override func gt(rhs: any Common.P4DataValue) -> Bool { return switch rhs { case let other as InstantiatedParserState: self.state > other.state default: false } } - public override func gte(rhs: any Common.P4Value) -> Bool { + public override func gte(rhs: any Common.P4DataValue) -> Bool { return switch rhs { case let other as InstantiatedParserState: self.state >= other.state default: false @@ -185,7 +185,7 @@ public class InstantiatedParserState: ParserState { statements = Array() } - public override func def() -> any P4Value { + public override func def() -> any P4DataValue { return InstantiatedParserState(name: Identifier(name: "")) } } @@ -276,40 +276,40 @@ public struct ParserStates { /// A P4 Parser /// /// Note: A Parser is both a type _and_ a value. -public struct Parser: P4Type, P4Value { - public func type() -> any Common.P4Type { +public struct Parser: P4DataType, P4DataValue { + public func type() -> any Common.P4DataType { return self } - public func eq(rhs: any Common.P4Type) -> Bool { + public func eq(rhs: any Common.P4DataType) -> Bool { return switch rhs { case let parser_rhs as Parser: self.name == parser_rhs.name default: false } } - public func lt(rhs: any Common.P4Value) -> Bool { + public func lt(rhs: any Common.P4DataValue) -> Bool { return switch rhs { case let parser_rhs as Parser: self.name < parser_rhs.name default: false } } - public func lte(rhs: any Common.P4Value) -> Bool { + public func lte(rhs: any Common.P4DataValue) -> Bool { return switch rhs { case let parser_rhs as Parser: self.name <= parser_rhs.name default: false } } - public func gt(rhs: any Common.P4Value) -> Bool { + public func gt(rhs: any Common.P4DataValue) -> Bool { return switch rhs { case let parser_rhs as Parser: self.name > parser_rhs.name default: false } } - public func gte(rhs: any Common.P4Value) -> Bool { + public func gte(rhs: any Common.P4DataValue) -> Bool { return switch rhs { case let parser_rhs as Parser: self.name >= parser_rhs.name default: false @@ -342,7 +342,7 @@ public struct Parser: P4Type, P4Value { return .none } - public func eq(rhs: any P4Value) -> Bool { + public func eq(rhs: any P4DataValue) -> Bool { return switch rhs { case let other as Parser: self.name == other.name default: false @@ -353,7 +353,7 @@ public struct Parser: P4Type, P4Value { return "Parser \(self.name) with parameters: \(parameters) and states: \(self.states)" } - public func def() -> any P4Value { + public func def() -> any P4DataValue { return Parser(withName: Identifier(name: "")) } } diff --git a/Sources/P4Lang/Program.swift b/Sources/P4Lang/Program.swift index 9986757..6bc7810 100644 --- a/Sources/P4Lang/Program.swift +++ b/Sources/P4Lang/Program.swift @@ -22,16 +22,16 @@ public struct ExpressionStatement { } public struct Program { - public var types: [P4Type] = Array() - public var instances: [P4TypeAttributed] = Array() + public var types: [P4DataType] = Array() + public var instances: [P4Type] = Array() /// Type of closure for filtering results from ``Program/InstancesWithTypes(_:)`` - public typealias AttributedTypeFilter = (P4TypeAttributed) -> Bool + public typealias AttributedTypeFilter = (P4Type) -> Bool /// Type of closure for filtering results from ``Program/TypesWithTypes(_:)`` - public typealias TypeFilter = (P4Type) -> Bool + public typealias TypeFilter = (P4DataType) -> Bool /// Retrieve global instances in the compiled P4 program. - public func InstancesWithTypes() -> [P4TypeAttributed] { + public func InstancesWithTypes() -> [P4Type] { return self.instances } @@ -47,14 +47,14 @@ public struct Program { /// /// @Snippet(path: "use-program-instanceswithtypes", slice: "include") /// - public func InstancesWithTypes(_ filter: AttributedTypeFilter) -> [P4TypeAttributed] { + public func InstancesWithTypes(_ filter: AttributedTypeFilter) -> [P4Type] { return self.instances.filter { instance in filter(instance) } } /// Retrieve global types in the compiled P4 program. - public func TypesWithTypes() -> [P4Type] { + public func TypesWithTypes() -> [P4DataType] { return self.types } @@ -70,7 +70,7 @@ public struct Program { /// /// @Snippet(path: "use-program-typeswithtypes", slice: "include") /// - public func TypesWithTypes(_ filter: TypeFilter) -> [P4Type] { + public func TypesWithTypes(_ filter: TypeFilter) -> [P4DataType] { return self.types.filter { instance in filter(instance) } @@ -85,7 +85,7 @@ public struct Program { public func find_parser(withName name: Identifier) -> Result { for instance in self.instances { - guard let parser = instance.type as? Parser else { + guard let parser = instance.dataType() as? Parser else { continue } if parser.name == name { diff --git a/Sources/P4Lang/Types.swift b/Sources/P4Lang/Types.swift index fc85538..15ce50a 100644 --- a/Sources/P4Lang/Types.swift +++ b/Sources/P4Lang/Types.swift @@ -18,10 +18,10 @@ import Common public struct AttributedP4Type { - public let type: P4Type - public let attributes: P4TypeAttributed + public let type: P4DataType + public let attributes: P4Type - public init(_ type: P4Type, _ attributes: P4TypeAttributed) { + public init(_ type: P4DataType, _ attributes: P4Type) { self.type = type self.attributes = attributes } diff --git a/Sources/P4Runtime/Expressions.swift b/Sources/P4Runtime/Expressions.swift index f93595c..b09931c 100644 --- a/Sources/P4Runtime/Expressions.swift +++ b/Sources/P4Runtime/Expressions.swift @@ -19,22 +19,22 @@ import Common import P4Lang extension SelectCaseExpression: EvaluatableExpression { - public func evaluate(execution: Common.ProgramExecution) -> Common.Result { + public func evaluate(execution: Common.ProgramExecution) -> Common.Result { return execution.scopes.lookup(identifier: next_state_identifier) } - public func type() -> any Common.P4Type { - return ParserState() + public func type() -> P4Type { + return P4Type(ParserState()) } } extension SelectExpression: EvaluatableExpression { - public func evaluate(execution: Common.ProgramExecution) -> Common.Result { + public func evaluate(execution: Common.ProgramExecution) -> Common.Result { switch self.selector.evaluate(execution: execution) { case .Ok(let selector_value): - for sce in self.select_expressions { + for sce in self.case_expressions { if case .Ok(let kse) = sce.key.evaluate(execution: execution), - kse.eq(rhs: selector_value) + kse.eq(selector_value) { let result = sce.evaluate(execution: execution) return result @@ -45,14 +45,14 @@ extension SelectExpression: EvaluatableExpression { } } - public func type() -> any Common.P4Type { - return ParserState() + public func type() -> P4Type { + return P4Type(ParserState()) } } // Variables are evaluatable because they can be looked up by identifiers. extension TypedIdentifier: EvaluatableExpression { - public func type() -> any Common.P4Type { + public func type() -> P4Type { return self.type } @@ -64,7 +64,7 @@ extension TypedIdentifier: EvaluatableExpression { // Variables are evaluatable because they can be looked up by identifiers. extension TypedIdentifier: EvaluatableLValueExpression { public func set( - to: any Common.P4Value, inScopes scopes: Common.VarValueScopes, + to: P4Value, inScopes scopes: Common.VarValueScopes, duringExecution execution: ProgramExecution ) -> Common.Result<(Common.VarValueScopes, P4Value)> { if case .Error(let e) = scopes.lookup(identifier: self) { @@ -81,90 +81,90 @@ extension TypedIdentifier: EvaluatableLValueExpression { return .Error(Error(withMessage: "Cannot assign to identifier not in scope")) } - if !type.type.eq(rhs: to.type()) { + if !type.eq(to.type()) { return .Error( Error( withMessage: - "Cannot assign value with type \(to.type()) to identifier \(self) with type \(type.type)" + "Cannot assign value with type \(to.type()) to identifier \(self) with type \(type)" )) } return .Ok(()) } } -public func binary_equal_operator_evaluator(left: P4Value, right: P4Value) -> P4Value { - return Map(input: left.eq(rhs: right)) { input in +public func binary_equal_operator_evaluator(left: P4Value, right: P4Value) -> P4DataValue { + return Map(input: left.dataValue().eq(rhs: right.dataValue())) { input in P4BooleanValue(withValue: input) } } -public func binary_lt_operator_evaluator(left: P4Value, right: P4Value) -> P4Value { - return Map(input: left.lt(rhs: right)) { input in +public func binary_lt_operator_evaluator(left: P4Value, right: P4Value) -> P4DataValue { + return Map(input: left.dataValue().lt(rhs: right.dataValue())) { input in P4BooleanValue(withValue: input) } } -public func binary_lte_operator_evaluator(left: P4Value, right: P4Value) -> P4Value { - return Map(input: left.lte(rhs: right)) { input in +public func binary_lte_operator_evaluator(left: P4Value, right: P4Value) -> P4DataValue { + return Map(input: left.dataValue().lte(rhs: right.dataValue())) { input in P4BooleanValue(withValue: input) } } -public func binary_gt_operator_evaluator(left: P4Value, right: P4Value) -> P4Value { - return Map(input: left.gt(rhs: right)) { input in +public func binary_gt_operator_evaluator(left: P4Value, right: P4Value) -> P4DataValue { + return Map(input: left.dataValue().gt(rhs: right.dataValue())) { input in P4BooleanValue(withValue: input) } } -public func binary_gte_operator_evaluator(left: P4Value, right: P4Value) -> P4Value { - return Map(input: left.gte(rhs: right)) { input in +public func binary_gte_operator_evaluator(left: P4Value, right: P4Value) -> P4DataValue { + return Map(input: left.dataValue().gte(rhs: right.dataValue())) { input in P4BooleanValue(withValue: input) } } -public func binary_and_operator_evaluator(left: P4Value, right: P4Value) -> P4Value { - let bleft = left as! P4BooleanValue - let bright = right as! P4BooleanValue +public func binary_and_operator_evaluator(left: P4Value, right: P4Value) -> P4DataValue { + let bleft = left.dataValue() as! P4BooleanValue + let bright = right.dataValue() as! P4BooleanValue return Map(input: bleft.access() && bright.access()) { input in P4BooleanValue(withValue: input) } } -public func binary_or_operator_evaluator(left: P4Value, right: P4Value) -> P4Value { - let bleft = left as! P4BooleanValue - let bright = right as! P4BooleanValue +public func binary_or_operator_evaluator(left: P4Value, right: P4Value) -> P4DataValue { + let bleft = left.dataValue() as! P4BooleanValue + let bright = right.dataValue() as! P4BooleanValue return Map(input: bleft.access() || bright.access()) { input in P4BooleanValue(withValue: input) } } -public func binary_add_operator_evaluator(left: P4Value, right: P4Value) -> P4Value { - let ileft = left as! P4IntValue - let iright = right as! P4IntValue +public func binary_add_operator_evaluator(left: P4Value, right: P4Value) -> P4DataValue { + let ileft = left.dataValue() as! P4IntValue + let iright = right.dataValue() as! P4IntValue return Map(input: ileft.access() + iright.access()) { input in P4IntValue(withValue: input) } } -public func binary_subtract_operator_evaluator(left: P4Value, right: P4Value) -> P4Value { - let ileft = left as! P4IntValue - let iright = right as! P4IntValue +public func binary_subtract_operator_evaluator(left: P4Value, right: P4Value) -> P4DataValue { + let ileft = left.dataValue() as! P4IntValue + let iright = right.dataValue() as! P4IntValue return Map(input: ileft.access() - iright.access()) { input in P4IntValue(withValue: input) } } -public func binary_multiply_operator_evaluator(left: P4Value, right: P4Value) -> P4Value { - let ileft = left as! P4IntValue - let iright = right as! P4IntValue +public func binary_multiply_operator_evaluator(left: P4Value, right: P4Value) -> P4DataValue { + let ileft = left.dataValue() as! P4IntValue + let iright = right.dataValue() as! P4IntValue return Map(input: ileft.access() * iright.access()) { input in P4IntValue(withValue: input) } } -public func binary_divide_operator_evaluator(left: P4Value, right: P4Value) -> P4Value { - let ileft = left as! P4IntValue - let iright = right as! P4IntValue +public func binary_divide_operator_evaluator(left: P4Value, right: P4Value) -> P4DataValue { + let ileft = left.dataValue() as! P4IntValue + let iright = right.dataValue() as! P4IntValue return Map(input: ileft.access() / iright.access()) { input in P4IntValue(withValue: input) } @@ -177,7 +177,8 @@ public func binary_and_or_operator_checker( left: EvaluatableExpression, right: EvaluatableExpression ) -> Result<()> { // Check that both are Boolean-typed things! - if !(left.type().eq(rhs: P4Boolean()) && right.type().eq(rhs: P4Boolean())) { + if !(left.type().dataType().eq(rhs: P4Boolean()) && right.type().dataType().eq(rhs: P4Boolean())) + { return .Error(Error(withMessage: "And/Or on operands with non-bool type is not allowed")) } return .Ok(()) @@ -187,7 +188,7 @@ public func binary_int_math_operator_checker( left: EvaluatableExpression, right: EvaluatableExpression ) -> Result<()> { // Check that both are int-typed things! - if !(left.type().eq(rhs: P4Int()) && right.type().eq(rhs: P4Int())) { + if !(left.type().dataType().eq(rhs: P4Int()) && right.type().dataType().eq(rhs: P4Int())) { return .Error( Error(withMessage: "Mathematical operation on operands with non-int type is not allowed")) } @@ -195,7 +196,7 @@ public func binary_int_math_operator_checker( } extension BinaryOperatorExpression: EvaluatableExpression { - public func evaluate(execution: Common.ProgramExecution) -> Common.Result { + public func evaluate(execution: Common.ProgramExecution) -> Common.Result { let maybe_evaluated_left = self.left.evaluate(execution: execution) guard case Result.Ok(let evaluated_left) = maybe_evaluated_left else { return maybe_evaluated_left @@ -206,16 +207,16 @@ extension BinaryOperatorExpression: EvaluatableExpression { return maybe_evaluated_right } - return Result.Ok(self.evaluator.2(evaluated_left, evaluated_right)) + return Result.Ok(P4Value(self.evaluator.2(evaluated_left, evaluated_right))) } - public func type() -> any Common.P4Type { + public func type() -> P4Type { return self.evaluator.1 } } extension ArrayAccessExpression: EvaluatableExpression { - public func evaluate(execution: Common.ProgramExecution) -> Common.Result { + public func evaluate(execution: Common.ProgramExecution) -> Common.Result { let maybe_name = self.name.evaluate(execution: execution) guard case Result.Ok(let name) = maybe_name else { return maybe_name @@ -226,11 +227,11 @@ extension ArrayAccessExpression: EvaluatableExpression { return maybe_indexor } - guard let indexor_int = indexor as? P4IntValue else { + guard let indexor_int = indexor.dataValue() as? P4IntValue else { return Result.Error(Error(withMessage: "\(indexor) cannot index an array")) } - guard let array = name as? P4ArrayValue else { + guard let array = name.dataValue() as? P4ArrayValue else { return Result.Error(Error(withMessage: "\(name) does not name an array")) } let accessed = array.access(indexor_int.access()) @@ -238,29 +239,24 @@ extension ArrayAccessExpression: EvaluatableExpression { return .Ok(accessed) } - public func type() -> any Common.P4Type { + public func type() -> P4Type { return self.type.value_type() } } extension ArrayAccessExpression: EvaluatableLValueExpression { public func set( - to: any Common.P4Value, inScopes scopes: Common.VarValueScopes, + to: P4Value, inScopes scopes: Common.VarValueScopes, duringExecution execution: ProgramExecution ) -> Common.Result<(Common.VarValueScopes, P4Value)> { - // For purposes of documentation, assume the field access expression we are evaluating is - // (strct_id)[indexor] = new_value - // where strct_id expands to - // (identifier.field_id1.field_id2...).field_id = new_field_value - // First, evaluate strct_id and make sure that it names a struct. let maybe_value = self.name.evaluate(execution: execution) guard case .Ok(let value) = maybe_value else { return Result.Error( Error(withMessage: "\(self.name) cannot be evaluated: \(maybe_value.error()!)")) } - guard let array_value = value as? P4ArrayValue else { - return Result.Error(Error(withMessage: "\(self.name) does not identify a struct")) + guard let array_value = value.dataValue() as? P4ArrayValue else { + return Result.Error(Error(withMessage: "\(self.name) does not identify an array")) } // Now, get the indexor! @@ -269,27 +265,31 @@ extension ArrayAccessExpression: EvaluatableLValueExpression { return Result.Error( Error(withMessage: "\(self.indexor) cannot be evaluated: \(maybe_indexor_value.error()!)")) } - guard let indexor_int = indexor_value as? P4IntValue else { + guard let indexor_int = indexor_value.dataValue() as? P4IntValue else { return Result.Error(Error(withMessage: "\(self.indexor) cannot be used to index an array")) } // Now we have an array and an index! - // Update field_id of that structure and get the new structure value. - let set_result = array_value.set(index: indexor_int.access(), to: to) - guard case .Ok(let new_array_value) = set_result else { - return .Error(set_result.error()!) + let maybe_updated_array_data_value = array_value.set(index: indexor_int.access(), to: to) + guard case .Ok(let new_array_value) = maybe_updated_array_data_value else { + return .Error(maybe_updated_array_data_value.error()!) + } + + let maybe_updated_array_value = value.update(withNewValue: new_array_value) + guard case .Ok(let updated_array_value) = maybe_updated_array_value else { + return .Error(maybe_updated_array_value.error()!) } let array_lvalue = self.name as! EvaluatableLValueExpression - return array_lvalue.set(to: new_array_value, inScopes: scopes, duringExecution: execution) + return array_lvalue.set(to: updated_array_value, inScopes: scopes, duringExecution: execution) } public func check( to: any Common.EvaluatableExpression, inScopes scopes: Common.VarTypeScopes ) -> Common.Result<()> { - if !self.type.value_type().eq(rhs: to.type()) { + if !self.type.value_type().eq(to.type()) { return .Error( Error( withMessage: @@ -301,13 +301,14 @@ extension ArrayAccessExpression: EvaluatableLValueExpression { } extension FieldAccessExpression: EvaluatableExpression { - public func evaluate(execution: Common.ProgramExecution) -> Common.Result { + public func evaluate(execution: Common.ProgramExecution) -> Common.Result { + let maybe_struct = self.strct.evaluate(execution: execution) guard case Result.Ok(let strct) = maybe_struct else { return maybe_struct } - guard let struct_strct = strct as? P4StructValue else { + guard let struct_strct = strct.dataValue() as? P4StructValue else { return Result.Error(Error(withMessage: "\(strct) does not identify a struct")) } @@ -319,14 +320,14 @@ extension FieldAccessExpression: EvaluatableExpression { return .Ok(value) } - public func type() -> any Common.P4Type { + public func type() -> P4Type { return self.field.type } } extension FieldAccessExpression: EvaluatableLValueExpression { public func set( - to: any Common.P4Value, inScopes scopes: Common.VarValueScopes, + to: P4Value, inScopes scopes: Common.VarValueScopes, duringExecution execution: ProgramExecution ) -> Common.Result<(Common.VarValueScopes, P4Value)> { // For purposes of documentation, assume the field access expression we are evaluating is @@ -341,16 +342,21 @@ extension FieldAccessExpression: EvaluatableLValueExpression { Error(withMessage: "\(self.strct) cannot be evaluated: \(maybe_value.error()!)")) } - guard let struct_value = value as? P4StructValue else { + guard let struct_value = value.dataValue() as? P4StructValue else { return Result.Error(Error(withMessage: "\(self.strct) does not identify a struct")) } // Now we know that struct_id identifies a structure value. // Update field_id of that structure and get the new structure value. - let set_result = struct_value.set(field: self.field, to: to) - guard case .Ok(let new_struct_value) = set_result else { - return .Error(set_result.error()!) + let maybe_new_struct_data_value = struct_value.set(field: self.field, to: to) + guard case .Ok(let new_struct_data_value) = maybe_new_struct_data_value else { + return .Error(maybe_new_struct_data_value.error()!) + } + + let maybe_new_struct_value = value.update(withNewValue: new_struct_data_value) + guard case .Ok(let new_struct_value) = maybe_new_struct_value else { + return .Error(maybe_new_struct_value.error()!) } // That new structure value should be assignable to the lvalue that is strct_id. @@ -364,7 +370,7 @@ extension FieldAccessExpression: EvaluatableLValueExpression { to: any Common.EvaluatableExpression, inScopes scopes: Common.VarTypeScopes ) -> Common.Result<()> { - if !self.field.type.eq(rhs: to.type()) { + if !self.field.type.eq(to.type()) { return .Error( Error( withMessage: @@ -385,7 +391,7 @@ extension KeysetExpression: EvaluatableExpression { } extension FunctionCall: EvaluatableExpression { - public func evaluate(execution: Common.ProgramExecution) -> Common.Result { + public func evaluate(execution: Common.ProgramExecution) -> Common.Result { guard let body = self.callee.body else { return .Error(Error(withMessage: "No body for called function (\(self.callee.name))")) @@ -419,7 +425,13 @@ extension FunctionCall: EvaluatableExpression { } } - public func type() -> any Common.P4Type { + public func type() -> P4Type { return self.callee.tipe } } + +extension P4Value: EvaluatableExpression { + public func evaluate(execution: ProgramExecution) -> Result { + return .Ok(self) + } +} diff --git a/Sources/P4Runtime/Parser.swift b/Sources/P4Runtime/Parser.swift index 036ceec..3d5f4ce 100644 --- a/Sources/P4Runtime/Parser.swift +++ b/Sources/P4Runtime/Parser.swift @@ -58,8 +58,8 @@ extension ParserStateDirectTransition: EvaluatableParserState { let res = program.scopes.lookup(identifier: get_next_state()) if case .Ok(let value) = res { - if value.type().eq(rhs: self) { - return (value as! EvaluatableParserState, program.exit_scope()) + if value.type().dataType().eq(rhs: self) { + return (value.dataValue() as! EvaluatableParserState, program.exit_scope()) } } @@ -119,8 +119,14 @@ extension ParserStateSelectTransition: EvaluatableParserState { let res = self.selectExpression.evaluate(execution: program) if case .Ok(let value) = res { - if value.type().eq(rhs: self) { - return (value as! EvaluatableParserState, program.exit_scope()) + if value.type().dataType().eq(rhs: self) { + return (value.dataValue() as! EvaluatableParserState, program.exit_scope()) + } else { + return ( + self, + program.setError( + error: Error(withMessage: "Select transition transitioned to a none state")) + ) } } @@ -145,9 +151,11 @@ extension Parser: CallableExecution { var execution = execution.enter_scope() execution = execution.declare( - identifier: AsInstantiatedParserState(accept.state()).state, withValue: accept) + identifier: AsInstantiatedParserState(accept.state()).state, + withValue: P4Value(accept, P4Type.ReadOnly(accept.type()))) execution = execution.declare( - identifier: AsInstantiatedParserState(reject.state()).state, withValue: reject) + identifier: AsInstantiatedParserState(reject.state()).state, + withValue: P4Value(reject, P4Type.ReadOnly(reject.type()))) // Add initial values to the global scope if let initial = execution.initial_values() { @@ -158,7 +166,8 @@ extension Parser: CallableExecution { // First, add every state to the scope! for state in self.states.states { - execution = execution.declare(identifier: state.state, withValue: state) + execution = execution.declare( + identifier: state.state, withValue: P4Value(state)) } guard let _current_state = self.findStartState(), diff --git a/Sources/P4Runtime/Protocols.swift b/Sources/P4Runtime/Protocols.swift index eecb3c4..c8088fb 100644 --- a/Sources/P4Runtime/Protocols.swift +++ b/Sources/P4Runtime/Protocols.swift @@ -22,7 +22,7 @@ public protocol Execution { func execute(execution: ProgramExecution) -> ProgramExecution } -public protocol EvaluatableParserState: P4Value { +public protocol EvaluatableParserState: P4DataValue { func execute(program: ProgramExecution) -> (EvaluatableParserState, ProgramExecution) func done() -> Bool func state() -> ParserState diff --git a/Sources/P4Runtime/Statements.swift b/Sources/P4Runtime/Statements.swift index 3213d98..0d47ad9 100644 --- a/Sources/P4Runtime/Statements.swift +++ b/Sources/P4Runtime/Statements.swift @@ -62,14 +62,14 @@ extension ConditionalStatement: EvaluatableStatement { ) } - if !evaluated_condition.type().eq(rhs: P4Boolean()) { + if !evaluated_condition.type().dataType().eq(rhs: P4Boolean()) { return ( ControlFlow.Error, execution.setError(error: Error(withMessage: "Condition expression is not a Boolean")) ) } - if evaluated_condition.eq(rhs: P4BooleanValue.init(withValue: true)) { + if evaluated_condition.dataValue().eq(rhs: P4BooleanValue.init(withValue: true)) { let execution = execution.enter_scope() switch self.thenn.evaluate(execution: execution) { case (ControlFlow.Next, let result): return (ControlFlow.Next, result.exit_scope()) diff --git a/Tests/p4rseTests/ArrayTests.swift b/Tests/p4rseTests/ArrayTests.swift index fcd5148..6fa800a 100644 --- a/Tests/p4rseTests/ArrayTests.swift +++ b/Tests/p4rseTests/ArrayTests.swift @@ -40,13 +40,13 @@ import TreeSitterP4 }; """ var test_declarations = VarTypeScopes().enter() - test_declarations = test_declarations.declare(identifier: Identifier(name: "ta"), withValue: P4TypeAttributed.Attributeless(P4Array(withValueType: P4Int()))) + test_declarations = test_declarations.declare(identifier: Identifier(name: "ta"), withValue: P4Type(P4Array(withValueType: P4Type(P4Int())))) var test_values = VarValueScopes().enter() test_values = test_values.declare( identifier: Identifier(name: "ta"), - withValue: P4ArrayValue(withType: P4Int(), withValue: [ - P4IntValue(withValue: 1), P4IntValue(withValue: 2), P4IntValue(withValue: 3), - ])) + withValue: P4Value(P4ArrayValue(withType: P4Type(P4Int()), withValue: [ + P4Value(P4IntValue(withValue: 1)), P4Value(P4IntValue(withValue: 2)), P4Value(P4IntValue(withValue: 3)) + ]))) let program = try #UseOkResult( Program.Compile(simple_parser_declaration, withGlobalInstances: test_declarations)) let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program, withInitialValues: test_values)) @@ -68,7 +68,7 @@ import TreeSitterP4 }; """ var test_declarations = VarTypeScopes().enter() - test_declarations = test_declarations.declare(identifier: Identifier(name: "ta"), withValue: P4TypeAttributed.Attributeless(P4Int())) + test_declarations = test_declarations.declare(identifier: Identifier(name: "ta"), withValue: P4Type(P4Int())) #expect( #RequireErrorResult( Error( @@ -91,13 +91,14 @@ import TreeSitterP4 }; """ var test_declarations = VarTypeScopes().enter() - test_declarations = test_declarations.declare(identifier: Identifier(name: "ta"), withValue: P4TypeAttributed.Attributeless(P4Array(withValueType: P4Int()))) + test_declarations = test_declarations.declare(identifier: Identifier(name: "ta"), withValue: P4Type(P4Array(withValueType: P4Type(P4Int())))) var test_values = VarValueScopes().enter() + test_values = test_values.declare( identifier: Identifier(name: "ta"), - withValue: P4ArrayValue(withType: P4Int(), withValue: [ - P4IntValue(withValue: 1), P4IntValue(withValue: 2), P4IntValue(withValue: 3), - ])) + withValue: P4Value(P4ArrayValue(withType: P4Type(P4Int()), withValue: [ + P4Value(P4IntValue(withValue: 1)), P4Value(P4IntValue(withValue: 2)), P4Value(P4IntValue(withValue: 3)) + ]))) let program = try #UseOkResult( Program.Compile(simple_parser_declaration, withGlobalInstances: test_declarations)) let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program, withInitialValues: test_values)) @@ -118,13 +119,13 @@ import TreeSitterP4 }; """ var test_declarations = VarTypeScopes().enter() - test_declarations = test_declarations.declare(identifier: Identifier(name: "ta"), withValue: P4TypeAttributed.Attributeless(P4Array(withValueType: P4Int()))) + test_declarations = test_declarations.declare(identifier: Identifier(name: "ta"), withValue: P4Type(P4Array(withValueType: P4Type(P4Int())))) var test_values = VarValueScopes().enter() test_values = test_values.declare( identifier: Identifier(name: "ta"), - withValue: P4ArrayValue(withType: P4Int(), withValue: [ - P4IntValue(withValue: 1), P4IntValue(withValue: 2), P4IntValue(withValue: 3), - ])) + withValue: P4Value(P4ArrayValue(withType: P4Type(P4Int()), withValue: [ + P4Value(P4IntValue(withValue: 1)), P4Value(P4IntValue(withValue: 2)), P4Value(P4IntValue(withValue: 3)), + ]))) let program = try #UseOkResult( Program.Compile(simple_parser_declaration, withGlobalInstances: test_declarations)) let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program, withInitialValues: test_values)) @@ -145,13 +146,13 @@ import TreeSitterP4 }; """ var test_declarations = VarTypeScopes().enter() - test_declarations = test_declarations.declare(identifier: Identifier(name: "ta"), withValue: P4TypeAttributed.Attributeless(P4Array(withValueType: P4Int()))) + test_declarations = test_declarations.declare(identifier: Identifier(name: "ta"), withValue: P4Type(P4Array(withValueType: P4Type(P4Int())))) var test_values = VarValueScopes().enter() test_values = test_values.declare( identifier: Identifier(name: "ta"), - withValue: P4ArrayValue(withType: P4Int(), withValue: [ - P4IntValue(withValue: 1), P4IntValue(withValue: 2), P4IntValue(withValue: 3), - ])) + withValue: P4Value(P4ArrayValue(withType: P4Type(P4Int()), withValue: [ + P4Value(P4IntValue(withValue: 1)), P4Value(P4IntValue(withValue: 2)), P4Value(P4IntValue(withValue: 3)), + ]))) let program = try #UseOkResult( Program.Compile(simple_parser_declaration, withGlobalInstances: test_declarations)) let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program, withInitialValues: test_values)) @@ -173,16 +174,16 @@ import TreeSitterP4 }; """ var test_declarations = VarTypeScopes().enter() - test_declarations = test_declarations.declare(identifier: Identifier(name: "ta"), withValue: P4TypeAttributed.Attributeless(P4Array(withValueType: P4Array(withValueType: P4Int())))) + test_declarations = test_declarations.declare(identifier: Identifier(name: "ta"), withValue: P4Type(P4Array(withValueType: P4Type(P4Array(withValueType: P4Type(P4Int())))))) var test_values = VarValueScopes().enter() - let nested = P4ArrayValue( - withType: P4Int(), - withValue: [P4IntValue(withValue: 5), P4IntValue(withValue: 2), P4IntValue(withValue: 3)]) + let nested = P4Value(P4ArrayValue( + withType: P4Type(P4Int()), + withValue: [P4Value(P4IntValue(withValue: 5)), P4Value(P4IntValue(withValue: 2)), P4Value(P4IntValue(withValue: 3))])) test_values = test_values.declare( identifier: Identifier(name: "ta"), - withValue: P4ArrayValue(withType: P4Array(withValueType: P4Int()), withValue: [nested])) + withValue: P4Value(P4ArrayValue(withType: P4Type(P4Array(withValueType: P4Type(P4Int()))), withValue: [nested]))) let program = try #UseOkResult( Program.Compile(simple_parser_declaration, withGlobalInstances: test_declarations)) @@ -206,13 +207,13 @@ import TreeSitterP4 }; """ var test_declarations = VarTypeScopes().enter() - test_declarations = test_declarations.declare(identifier: Identifier(name: "ta"), withValue: P4TypeAttributed.Attributeless(P4Array(withValueType: P4Int()))) + test_declarations = test_declarations.declare(identifier: Identifier(name: "ta"), withValue: P4Type(P4Array(withValueType: P4Type(P4Int())))) var test_values = VarValueScopes().enter() test_values = test_values.declare( identifier: Identifier(name: "ta"), - withValue: P4ArrayValue(withType: P4Int(), withValue: [ - P4IntValue(withValue: 1), P4IntValue(withValue: 2), P4IntValue(withValue: 3), - ])) + withValue: P4Value(P4ArrayValue(withType: P4Type(P4Int()), withValue: [ + P4Value(P4IntValue(withValue: 1)), P4Value(P4IntValue(withValue: 2)), P4Value(P4IntValue(withValue: 3)), + ]))) let program = try #UseOkResult( Program.Compile(simple_parser_declaration, withGlobalInstances: test_declarations)) let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program, withInitialValues: test_values)) @@ -235,16 +236,16 @@ import TreeSitterP4 }; """ var test_declarations = VarTypeScopes().enter() - test_declarations = test_declarations.declare(identifier: Identifier(name: "ta"), withValue: P4TypeAttributed.Attributeless(P4Array(withValueType: P4Array(withValueType: P4Int())))) + test_declarations = test_declarations.declare(identifier: Identifier(name: "ta"), withValue: P4Type(P4Array(withValueType: P4Type(P4Array(withValueType: P4Type(P4Int())))))) var test_values = VarValueScopes().enter() - let nested = P4ArrayValue( - withType: P4Int(), - withValue: [P4IntValue(withValue: 1), P4IntValue(withValue: 2), P4IntValue(withValue: 3)]) + let nested = P4Value(P4ArrayValue( + withType: P4Type(P4Int()), + withValue: [P4Value(P4IntValue(withValue: 1)), P4Value(P4IntValue(withValue: 2)), P4Value(P4IntValue(withValue: 3))])) test_values = test_values.declare( identifier: Identifier(name: "ta"), - withValue: P4ArrayValue(withType: P4Array(withValueType: P4Int()), withValue: [nested])) + withValue: P4Value(P4ArrayValue(withType: P4Type(P4Array(withValueType: P4Type(P4Int()))), withValue: [nested]))) let program = try #UseOkResult( Program.Compile(simple_parser_declaration, withGlobalInstances: test_declarations)) diff --git a/Tests/p4rseTests/BinaryOperatorTests/Struct.swift b/Tests/p4rseTests/BinaryOperatorTests/Struct.swift index 061652c..6372776 100644 --- a/Tests/p4rseTests/BinaryOperatorTests/Struct.swift +++ b/Tests/p4rseTests/BinaryOperatorTests/Struct.swift @@ -42,8 +42,8 @@ import TreeSitterP4 """ let test_declarations = VarTypeScopes().enter() let fields = P4StructFields([ - P4StructFieldIdentifier(name: "yesno", withType: P4Boolean()), - P4StructFieldIdentifier(name: "count", withType: P4Int()), + P4StructFieldIdentifier(name: "yesno", withType: P4Type(P4Boolean())), + P4StructFieldIdentifier(name: "count", withType: P4Type(P4Int())), ]) var test_types = TypeTypeScopes().enter() let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields) @@ -75,8 +75,8 @@ import TreeSitterP4 """ let test_declarations = VarTypeScopes().enter() let fields = P4StructFields([ - P4StructFieldIdentifier(name: "yesno", withType: P4Boolean()), - P4StructFieldIdentifier(name: "count", withType: P4Int()), + P4StructFieldIdentifier(name: "yesno", withType: P4Type(P4Boolean())), + P4StructFieldIdentifier(name: "count", withType: P4Type(P4Int())), ]) var test_types = TypeTypeScopes().enter() let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields) @@ -109,8 +109,8 @@ import TreeSitterP4 """ let test_declarations = VarTypeScopes().enter() let fields = P4StructFields([ - P4StructFieldIdentifier(name: "yesno", withType: P4Boolean()), - P4StructFieldIdentifier(name: "count", withType: P4Int()), + P4StructFieldIdentifier(name: "yesno", withType: P4Type(P4Boolean())), + P4StructFieldIdentifier(name: "count", withType: P4Type(P4Int())), ]) var test_types = TypeTypeScopes().enter() let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields) @@ -146,8 +146,8 @@ import TreeSitterP4 """ let test_declarations = VarTypeScopes().enter() let fields = P4StructFields([ - P4StructFieldIdentifier(name: "yesno", withType: P4Boolean()), - P4StructFieldIdentifier(name: "count", withType: P4Int()), + P4StructFieldIdentifier(name: "yesno", withType: P4Type(P4Boolean())), + P4StructFieldIdentifier(name: "count", withType: P4Type(P4Int())), ]) var test_types = TypeTypeScopes().enter() let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields) @@ -183,8 +183,8 @@ import TreeSitterP4 """ let test_declarations = VarTypeScopes().enter() let fields = P4StructFields([ - P4StructFieldIdentifier(name: "yesno", withType: P4Boolean()), - P4StructFieldIdentifier(name: "count", withType: P4Int()), + P4StructFieldIdentifier(name: "yesno", withType: P4Type(P4Boolean())), + P4StructFieldIdentifier(name: "count", withType: P4Type(P4Int())), ]) var test_types = TypeTypeScopes().enter() let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields) diff --git a/Tests/p4rseTests/ControlCompilerTests.swift b/Tests/p4rseTests/ControlCompilerTests.swift index 4b36fce..2c12240 100644 --- a/Tests/p4rseTests/ControlCompilerTests.swift +++ b/Tests/p4rseTests/ControlCompilerTests.swift @@ -39,8 +39,8 @@ import P4Lang } }; """ - let x = { (tipe: P4TypeAttributed) -> Bool in - switch tipe.type { + let x = { (tipe: P4Type) -> Bool in + switch tipe.dataType() { case let c as Control: c.name == "simple" default: false } @@ -73,8 +73,8 @@ import P4Lang }; """ - let filter = { (tipe: P4TypeAttributed) -> Bool in - switch tipe.type { + let filter = { (tipe: P4Type) -> Bool in + switch tipe.dataType() { case let c as Control: c.name == "simple" || c.name == "complex" default: false } diff --git a/Tests/p4rseTests/ExpressionTests/SelectExpression.swift b/Tests/p4rseTests/ExpressionTests/SelectExpression.swift index 64c0e88..ea2c9ad 100644 --- a/Tests/p4rseTests/ExpressionTests/SelectExpression.swift +++ b/Tests/p4rseTests/ExpressionTests/SelectExpression.swift @@ -175,7 +175,7 @@ import TreeSitterP4 let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program)) let args = ArgumentList([ - Argument(P4BooleanValue(withValue: false), atIndex: 1), Argument(P4StringValue(withValue: "Testing"), atIndex: 2), Argument(P4IntValue(withValue: 5), atIndex: 3), + 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(AsInstantiatedParserState(state_result) == P4Lang.reject) @@ -196,7 +196,7 @@ import TreeSitterP4 let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program)) let args = ArgumentList([ - Argument(P4BooleanValue(withValue: false), atIndex: 1), Argument(P4StringValue(withValue: "Testing"), atIndex: 2), Argument(P4IntValue(withValue: 5), atIndex: 3), + 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(AsInstantiatedParserState(state_result) == P4Lang.accept) diff --git a/Tests/p4rseTests/ParserCompilerTests.swift b/Tests/p4rseTests/ParserCompilerTests.swift index f829f82..a413886 100644 --- a/Tests/p4rseTests/ParserCompilerTests.swift +++ b/Tests/p4rseTests/ParserCompilerTests.swift @@ -118,7 +118,7 @@ import P4Lang #expect(parameters.parameters.count == 1) #expect(parameters.parameters[0].name == Identifier(name: "pmtr")) - #expect(parameters.parameters[0].type.eq(rhs: P4Boolean())) + #expect(parameters.parameters[0].type.dataType().eq(rhs: P4Boolean())) } @Test func test_simple_compiler_parser_with_multiple_parameters() async throws { @@ -138,10 +138,10 @@ import P4Lang #expect(parameters.parameters.count == 2) #expect(parameters.parameters[0].name == Identifier(name: "pmtr")) - #expect(parameters.parameters[0].type.eq(rhs: P4Boolean())) + #expect(parameters.parameters[0].type.dataType().eq(rhs: P4Boolean())) #expect(parameters.parameters[1].name == Identifier(name: "smtr")) - #expect(parameters.parameters[1].type.eq(rhs: P4String())) + #expect(parameters.parameters[1].type.dataType().eq(rhs: P4String())) } @Test func test_simple_compiler_parser_with_multiple_parameters2() async throws { @@ -161,13 +161,13 @@ import P4Lang #expect(parameters.parameters.count == 3) #expect(parameters.parameters[0].name == Identifier(name: "pmtr")) - #expect(parameters.parameters[0].type.eq(rhs: P4Boolean())) + #expect(parameters.parameters[0].type.dataType().eq(rhs: P4Boolean())) #expect(parameters.parameters[1].name == Identifier(name: "smtr")) - #expect(parameters.parameters[1].type.eq(rhs: P4String())) + #expect(parameters.parameters[1].type.dataType().eq(rhs: P4String())) #expect(parameters.parameters[2].name == Identifier(name: "imtr")) - #expect(parameters.parameters[2].type.eq(rhs: P4Int())) + #expect(parameters.parameters[2].type.dataType().eq(rhs: P4Int())) } @Test func test_simple_compiler_parser_use_parameters() async throws { diff --git a/Tests/p4rseTests/RuntimeTests.swift b/Tests/p4rseTests/RuntimeTests.swift index 83ef97c..17016ff 100644 --- a/Tests/p4rseTests/RuntimeTests.swift +++ b/Tests/p4rseTests/RuntimeTests.swift @@ -96,7 +96,7 @@ import TreeSitterP4 let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program)) let args = ArgumentList([ - Argument(P4BooleanValue(withValue: true), atIndex: 1), Argument(P4StringValue(withValue: "Testing"), atIndex: 2), Argument(P4IntValue(withValue: 5), atIndex: 3), + 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. @@ -118,7 +118,7 @@ import TreeSitterP4 let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program)) let args = ArgumentList([ - Argument(P4BooleanValue(withValue: true), atIndex: 1), Argument(P4BooleanValue(withValue: false), atIndex: 2), Argument(P4IntValue(withValue: 5), atIndex: 3), + Argument(P4Value(P4BooleanValue(withValue: true)), atIndex: 1), Argument(P4Value(P4BooleanValue(withValue: false)), atIndex: 2), Argument(P4Value(P4IntValue(withValue: 5)), atIndex: 3), ]) #expect( @@ -142,7 +142,7 @@ import TreeSitterP4 let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program)) let args = ArgumentList([ - Argument(P4IntValue(withValue: 5), atIndex: 1), Argument(P4StringValue(withValue: "Testing"), atIndex: 2), Argument(P4IntValue(withValue: 5), atIndex: 3), + Argument(P4Value(P4IntValue(withValue: 5)), atIndex: 1), Argument(P4Value(P4StringValue(withValue: "Testing")), atIndex: 2), Argument(P4Value(P4IntValue(withValue: 5)), atIndex: 3), ]) #expect( @@ -164,7 +164,7 @@ import TreeSitterP4 """ let program = try #UseOkResult(Program.Compile(simple_parser_declaration)) let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program)) - let args = ArgumentList([Argument(P4BooleanValue(withValue: true), atIndex: 0)]) + let args = ArgumentList([Argument(P4Value(P4BooleanValue(withValue: true)), atIndex: 0)]) #expect( #RequireErrorResult<(ParserState, ProgramExecution)>( diff --git a/Tests/p4rseTests/ScopeTests.swift b/Tests/p4rseTests/ScopeTests.swift index 457a78f..48fc355 100644 --- a/Tests/p4rseTests/ScopeTests.swift +++ b/Tests/p4rseTests/ScopeTests.swift @@ -28,39 +28,39 @@ import TreeSitterP4 @Test func test_scope() async throws { let s = VarTypeScope() - let s2 = s.declare(identifier: Identifier(name: "first"), withValue: P4TypeAttributed.Attributeless(P4Int())) + let s2 = s.declare(identifier: Identifier(name: "first"), withValue: P4Type(P4Int())) let found_first = try! #require(s2.lookup(identifier: Identifier(name: "first"))) - #expect(found_first.type.eq(rhs: P4Int())) + #expect(found_first.dataType().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: P4TypeAttributed.Attributeless(P4Int())) + ss = ss.declare(identifier: Identifier(name: "first"), withValue: P4Type(P4Int())) ss = ss.enter() - ss = ss.declare(identifier: Identifier(name: "second"), withValue: P4TypeAttributed.Attributeless(P4Boolean())) + ss = ss.declare(identifier: Identifier(name: "second"), withValue: P4Type(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.type.eq(rhs: P4Int())) - #expect(found_second.type.eq(rhs: P4Boolean())) + #expect(found_first.dataType().eq(rhs: P4Int())) + #expect(found_second.dataType().eq(rhs: P4Boolean())) } @Test func test_scope_set() async throws { var ss = VarTypeScopes().enter() let id = Identifier(name: "first") - let id_type = P4TypeAttributed.Attributeless(P4Int()) + let id_type = P4Type(P4Int()) ss = ss.declare(identifier: id, withValue: id_type) ss = ss.enter() - ss = ss.declare(identifier: Identifier(name: "second"), withValue: P4TypeAttributed.Attributeless(P4Boolean())) + ss = ss.declare(identifier: Identifier(name: "second"), withValue: P4Type(P4Boolean())) // Change the value of `first`. - ss = ss.set(identifier: id, withValue: P4TypeAttributed.Attributeless(P4String())) + ss = ss.set(identifier: id, withValue: P4Type(P4String())) // Verify the change! let found = try! #UseOkResult(ss.lookup(identifier: id)) - #expect(found.type.eq(rhs: P4String())) + #expect(found.dataType().eq(rhs: P4String())) } diff --git a/Tests/p4rseTests/StructTests.swift b/Tests/p4rseTests/StructTests.swift index e97df55..1840d5e 100644 --- a/Tests/p4rseTests/StructTests.swift +++ b/Tests/p4rseTests/StructTests.swift @@ -41,19 +41,19 @@ import TreeSitterP4 """ var test_declarations = VarTypeScopes().enter() let fields = P4StructFields([ - P4StructFieldIdentifier(name: "yesno", withType: P4Boolean()), - P4StructFieldIdentifier(name: "count", withType: P4Int()), + P4StructFieldIdentifier(name: "yesno", withType: P4Type(P4Boolean())), + P4StructFieldIdentifier(name: "count", withType: P4Type(P4Int())), ]) let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields) - test_declarations = test_declarations.declare(identifier: Identifier(name: "ts"), withValue: P4TypeAttributed.Attributeless(struct_type)) + test_declarations = test_declarations.declare(identifier: Identifier(name: "ts"), withValue: P4Type(struct_type)) var test_values = VarValueScopes().enter() test_values = test_values.declare( identifier: Identifier(name: "ts"), - withValue: P4StructValue(withType: struct_type, andInitializers: [ - P4BooleanValue(withValue: true), - P4IntValue(withValue: 5), - ])) + withValue: P4Value(P4StructValue(withType: struct_type, andInitializers: [ + P4Value(P4BooleanValue(withValue: true)), + P4Value(P4IntValue(withValue: 5)), + ]))) let program = try #UseOkResult( Program.Compile(simple_parser_declaration, withGlobalInstances: test_declarations)) @@ -78,8 +78,8 @@ import TreeSitterP4 """ var test_types = TypeTypeScopes().enter() let fields = P4StructFields([ - P4StructFieldIdentifier(name: "yesno", withType: P4Boolean()), - P4StructFieldIdentifier(name: "count", withType: P4Int()), + P4StructFieldIdentifier(name: "yesno", withType: P4Type(P4Boolean())), + P4StructFieldIdentifier(name: "count", withType: P4Type(P4Int())), ]) let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields) test_types = test_types.declare(identifier: Identifier(name: "Testing"), withValue: struct_type) @@ -108,8 +108,8 @@ import TreeSitterP4 """ var test_types = TypeTypeScopes().enter() let fields = P4StructFields([ - P4StructFieldIdentifier(name: "yesno", withType: P4Boolean()), - P4StructFieldIdentifier(name: "count", withType: P4Int()), + P4StructFieldIdentifier(name: "yesno", withType: P4Type(P4Boolean())), + P4StructFieldIdentifier(name: "count", withType: P4Type(P4Int())), ]) let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields) test_types = test_types.declare(identifier: Identifier(name: "Testing"), withValue: struct_type) @@ -135,19 +135,19 @@ import TreeSitterP4 """ var test_declarations = VarTypeScopes().enter() let fields = P4StructFields([ - P4StructFieldIdentifier(name: "yesno", withType: P4Boolean()), - P4StructFieldIdentifier(name: "count", withType: P4Int()), + P4StructFieldIdentifier(name: "yesno", withType: P4Type(P4Boolean())), + P4StructFieldIdentifier(name: "count", withType: P4Type(P4Int())), ]) let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields) - test_declarations = test_declarations.declare(identifier: Identifier(name: "ts"), withValue: P4TypeAttributed.Attributeless(struct_type)) + test_declarations = test_declarations.declare(identifier: Identifier(name: "ts"), withValue: P4Type(struct_type)) var test_values = VarValueScopes().enter() test_values = test_values.declare( identifier: Identifier(name: "ts"), - withValue: P4StructValue(withType: struct_type, andInitializers: [ - P4BooleanValue(withValue: false), - P4IntValue(withValue: 5), - ])) + withValue: P4Value(P4StructValue(withType: struct_type, andInitializers: [ + P4Value(P4BooleanValue(withValue: false)), + P4Value(P4IntValue(withValue: 5)), + ]))) let program = try #UseOkResult( Program.Compile(simple_parser_declaration, withGlobalInstances: test_declarations)) @@ -170,19 +170,19 @@ import TreeSitterP4 """ var test_declarations = VarTypeScopes().enter() let fields = P4StructFields([ - P4StructFieldIdentifier(name: "yesno", withType: P4Boolean()), - P4StructFieldIdentifier(name: "count", withType: P4Int()), + P4StructFieldIdentifier(name: "yesno", withType: P4Type(P4Boolean())), + P4StructFieldIdentifier(name: "count", withType: P4Type(P4Int())), ]) let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields) - test_declarations = test_declarations.declare(identifier: Identifier(name: "ts"), withValue: P4TypeAttributed.Attributeless(struct_type)) + test_declarations = test_declarations.declare(identifier: Identifier(name: "ts"), withValue: P4Type(struct_type)) var test_values = VarValueScopes().enter() test_values = test_values.declare( identifier: Identifier(name: "ts"), - withValue: P4StructValue(withType: struct_type, andInitializers: [ - P4BooleanValue(withValue: true), - P4IntValue(withValue: 5), - ])) + withValue: P4Value(P4StructValue(withType: struct_type, andInitializers: [ + P4Value(P4BooleanValue(withValue: true)), + P4Value(P4IntValue(withValue: 5)), + ]))) let program = try #UseOkResult( Program.Compile(simple_parser_declaration, withGlobalInstances: test_declarations)) @@ -204,19 +204,19 @@ import TreeSitterP4 """ var test_declarations = VarTypeScopes().enter() let fields = P4StructFields([ - P4StructFieldIdentifier(name: "yesno", withType: P4Boolean()), - P4StructFieldIdentifier(name: "count", withType: P4Int()), + P4StructFieldIdentifier(name: "yesno", withType: P4Type(P4Boolean())), + P4StructFieldIdentifier(name: "count", withType: P4Type(P4Int())), ]) let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields) - test_declarations = test_declarations.declare(identifier: Identifier(name: "ts"), withValue: P4TypeAttributed.Attributeless(struct_type)) + test_declarations = test_declarations.declare(identifier: Identifier(name: "ts"), withValue: P4Type(struct_type)) var test_values = VarValueScopes().enter() test_values = test_values.declare( identifier: Identifier(name: "ts"), - withValue: P4StructValue(withType: struct_type, andInitializers: [ - P4BooleanValue(withValue: true), - P4IntValue(withValue: 8), - ])) + withValue: P4Value(P4StructValue(withType: struct_type, andInitializers: [ + P4Value(P4BooleanValue(withValue: true)), + P4Value(P4IntValue(withValue: 8)), + ]))) let program = try #UseOkResult( Program.Compile(simple_parser_declaration, withGlobalInstances: test_declarations)) @@ -240,30 +240,30 @@ import TreeSitterP4 var test_declarations = VarTypeScopes().enter() let ty_fields = P4StructFields([ - P4StructFieldIdentifier(name: "yesno", withType: P4Boolean()), - P4StructFieldIdentifier(name: "count", withType: P4Int()), + P4StructFieldIdentifier(name: "yesno", withType: P4Type(P4Boolean())), + P4StructFieldIdentifier(name: "count", withType: P4Type(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_fields = P4StructFields([P4StructFieldIdentifier(name: "ty", withType: P4Type(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: P4TypeAttributed.Attributeless(ts_struct_type)) + test_declarations = test_declarations.declare(identifier: Identifier(name: "ts"), withValue: P4Type(ts_struct_type)) var test_values = VarValueScopes().enter() test_values = test_values.declare( identifier: Identifier(name: "ts"), - withValue: P4StructValue( + withValue: P4Value(P4StructValue( withType: ts_struct_type, andInitializers: [ - P4StructValue( + P4Value(P4StructValue( withType: ty_struct_type, andInitializers: [ - P4BooleanValue(withValue: true), - P4IntValue(withValue: 5), - ]) - ])) + P4Value(P4BooleanValue(withValue: true)), + P4Value(P4IntValue(withValue: 5)), + ])) + ]))) let program = try #UseOkResult( Program.Compile(simple_parser_declaration, withGlobalInstances: test_declarations)) let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program, withInitialValues: test_values)) @@ -286,19 +286,19 @@ import TreeSitterP4 """ var test_declarations = VarTypeScopes().enter() let fields = P4StructFields([ - P4StructFieldIdentifier(name: "yesno", withType: P4Boolean()), - P4StructFieldIdentifier(name: "count", withType: P4Int()), + P4StructFieldIdentifier(name: "yesno", withType: P4Type(P4Boolean())), + P4StructFieldIdentifier(name: "count", withType: P4Type(P4Int())), ]) let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields) - test_declarations = test_declarations.declare(identifier: Identifier(name: "ts"), withValue: P4TypeAttributed.Attributeless(struct_type)) + test_declarations = test_declarations.declare(identifier: Identifier(name: "ts"), withValue: P4Type(struct_type)) var test_values = VarValueScopes().enter() test_values = test_values.declare( identifier: Identifier(name: "ts"), - withValue: P4StructValue(withType: struct_type, andInitializers: [ - P4BooleanValue(withValue: false), - P4IntValue(withValue: 5), - ])) + withValue: P4Value(P4StructValue(withType: struct_type, andInitializers: [ + P4Value(P4BooleanValue(withValue: false)), + P4Value(P4IntValue(withValue: 5)), + ]))) let program = try #UseOkResult( Program.Compile(simple_parser_declaration, withGlobalInstances: test_declarations)) @@ -318,11 +318,11 @@ import TreeSitterP4 """ var test_declarations = VarTypeScopes().enter() let fields = P4StructFields([ - P4StructFieldIdentifier(name: "yesno", withType: P4Boolean()), - P4StructFieldIdentifier(name: "count", withType: P4Int()), + P4StructFieldIdentifier(name: "yesno", withType: P4Type(P4Boolean())), + P4StructFieldIdentifier(name: "count", withType: P4Type(P4Int())), ]) let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields) - test_declarations = test_declarations.declare(identifier: Identifier(name: "ts"), withValue: P4TypeAttributed.Attributeless(struct_type)) + test_declarations = test_declarations.declare(identifier: Identifier(name: "ts"), withValue: P4Type(struct_type)) #expect( #RequireErrorResult( @@ -349,30 +349,30 @@ import TreeSitterP4 var test_declarations = VarTypeScopes().enter() let ty_fields = P4StructFields([ - P4StructFieldIdentifier(name: "yesno", withType: P4Boolean()), - P4StructFieldIdentifier(name: "count", withType: P4Int()), + P4StructFieldIdentifier(name: "yesno", withType: P4Type(P4Boolean())), + P4StructFieldIdentifier(name: "count", withType: P4Type(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_fields = P4StructFields([P4StructFieldIdentifier(name: "ty", withType: P4Type(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: P4TypeAttributed.Attributeless(ts_struct_type)) + test_declarations = test_declarations.declare(identifier: Identifier(name: "ts"), withValue: P4Type(ts_struct_type)) var test_values = VarValueScopes().enter() test_values = test_values.declare( identifier: Identifier(name: "ts"), - withValue: P4StructValue( + withValue: P4Value(P4StructValue( withType: ts_struct_type, andInitializers: [ - P4StructValue( + P4Value(P4StructValue( withType: ty_struct_type, andInitializers: [ - P4BooleanValue(withValue: true), - P4IntValue(withValue: 7), - ]) - ])) + P4Value(P4BooleanValue(withValue: true)), + P4Value(P4IntValue(withValue: 7)), + ])) + ]))) let program = try #UseOkResult( Program.Compile(simple_parser_declaration, withGlobalInstances: test_declarations)) let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program, withInitialValues: test_values)) @@ -397,30 +397,30 @@ import TreeSitterP4 var test_declarations = VarTypeScopes().enter() let ty_fields = P4StructFields([ - P4StructFieldIdentifier(name: "yesno", withType: P4Boolean()), - P4StructFieldIdentifier(name: "count", withType: P4Int()), + P4StructFieldIdentifier(name: "yesno", withType: P4Type(P4Boolean())), + P4StructFieldIdentifier(name: "count", withType: P4Type(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_fields = P4StructFields([P4StructFieldIdentifier(name: "ty", withType: P4Type(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: P4TypeAttributed.Attributeless(ts_struct_type)) + test_declarations = test_declarations.declare(identifier: Identifier(name: "ts"), withValue: P4Type(ts_struct_type)) var test_values = VarValueScopes().enter() test_values = test_values.declare( identifier: Identifier(name: "ts"), - withValue: P4StructValue( + withValue: P4Value(P4StructValue( withType: ts_struct_type, andInitializers: [ - P4StructValue( + P4Value(P4StructValue( withType: ty_struct_type, andInitializers: [ - P4BooleanValue(withValue: true), - P4IntValue(withValue: 7), - ]) - ])) + P4Value(P4BooleanValue(withValue: true)), + P4Value(P4IntValue(withValue: 7)), + ])) + ]))) let program = try #UseOkResult( Program.Compile(simple_parser_declaration, withGlobalInstances: test_declarations)) let runtime = try #UseOkResult(P4Runtime.ParserRuntime.create(program: program, withInitialValues: test_values)) @@ -444,15 +444,15 @@ import TreeSitterP4 var test_declarations = VarTypeScopes().enter() let ty_fields = P4StructFields([ - P4StructFieldIdentifier(name: "yesno", withType: P4Boolean()), - P4StructFieldIdentifier(name: "count", withType: P4Int()), + P4StructFieldIdentifier(name: "yesno", withType: P4Type(P4Boolean())), + P4StructFieldIdentifier(name: "count", withType: P4Type(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_fields = P4StructFields([P4StructFieldIdentifier(name: "ty", withType: P4Type(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: P4TypeAttributed.Attributeless(ts_struct_type)) + test_declarations = test_declarations.declare(identifier: Identifier(name: "ts"), withValue: P4Type(ts_struct_type)) #expect( #RequireErrorResult( diff --git a/Tests/p4rseTests/TypeTests.swift b/Tests/p4rseTests/TypeTests.swift index 5d18f90..1eab21f 100644 --- a/Tests/p4rseTests/TypeTests.swift +++ b/Tests/p4rseTests/TypeTests.swift @@ -26,8 +26,8 @@ import TreeSitterP4 @Test func test_simple_struct() async throws { let fields = P4StructFields([ - P4StructFieldIdentifier(name: "yesno", withType: P4Boolean()), - P4StructFieldIdentifier(name: "count", withType: P4Int()), + P4StructFieldIdentifier(name: "yesno", withType: P4Type(P4Boolean())), + P4StructFieldIdentifier(name: "count", withType: P4Type(P4Int())), ]) let struct_type = P4Struct(withName: Identifier(name: "Testing"), andFields: fields) diff --git a/Tests/p4rseTests/ValueTypeParserTests.swift b/Tests/p4rseTests/ValueTypeParserTests.swift index 9c8072e..231d83f 100644 --- a/Tests/p4rseTests/ValueTypeParserTests.swift +++ b/Tests/p4rseTests/ValueTypeParserTests.swift @@ -253,7 +253,7 @@ import TreeSitterP4 }; """ var test_types = VarTypeScopes().enter() - test_types = test_types.declare(identifier: Identifier(name: "ta"), withValue: P4TypeAttributed.Attributeless(P4Array(withValueType: P4Int()))) + test_types = test_types.declare(identifier: Identifier(name: "ta"), withValue: P4Type(P4Array(withValueType: P4Type(P4Int())))) #expect( #RequireErrorResult( Error(