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 <hawkinsw@obs.cr>
This commit is contained in:
@@ -16,13 +16,13 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
/// A scope that resolves variable identifiers to their types.
|
||||
public typealias VarTypeScope = Scope<P4TypeAttributed>
|
||||
public typealias VarTypeScope = Scope<P4Type>
|
||||
|
||||
/// Scopes that resolve variable identifiers to their types.
|
||||
public typealias VarTypeScopes = Scopes<P4TypeAttributed>
|
||||
public typealias VarTypeScopes = Scopes<P4Type>
|
||||
|
||||
/// A scope that resolves type identifiers to their types.
|
||||
public typealias TypeTypeScope = Scope<P4Type>
|
||||
public typealias TypeTypeScope = Scope<P4DataType>
|
||||
|
||||
/// Scopes that resolve type identifiers to their types.
|
||||
public typealias TypeTypeScopes = Scopes<P4Type>
|
||||
public typealias TypeTypeScopes = Scopes<P4DataType>
|
||||
|
||||
@@ -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..<stype.fields.count() {
|
||||
if stype.fields.fields[field_idx] == field {
|
||||
if !stype.fields.fields[field_idx].type.eq(rhs: to.type()) {
|
||||
if !stype.fields.fields[field_idx].type.eq(to.type()) {
|
||||
return .Error(
|
||||
Error(
|
||||
withMessage:
|
||||
@@ -355,25 +350,25 @@ public class P4StructValue: P4Value {
|
||||
}
|
||||
|
||||
/// A P4 boolean type
|
||||
public struct P4Boolean: P4Type {
|
||||
public struct P4Boolean: P4DataType {
|
||||
public init() {}
|
||||
public var description: String {
|
||||
return "Boolean"
|
||||
}
|
||||
public func eq(rhs: P4Type) -> 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<Direction>.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, [])
|
||||
}
|
||||
}
|
||||
@@ -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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
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<Direction>.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<P4Value> {
|
||||
// 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())
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<P4Value>
|
||||
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<P4Value> {
|
||||
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 {
|
||||
|
||||
Reference in New Issue
Block a user