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:
Will Hawkins
2026-04-13 23:53:31 -04:00
parent 35b2537754
commit 94086c8e17
34 changed files with 690 additions and 552 deletions
+4 -11
View File
@@ -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 {
+9 -9
View File
@@ -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(),
+13 -12
View File
@@ -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)
}
+9 -8
View File
@@ -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
+26 -26
View File
@@ -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: ""))
}
}
+9 -9
View File
@@ -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<Parser> {
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 {
+3 -3
View File
@@ -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
}