compiler, runtime: Make Default Values Optional
For types, make it optional to return a default value. While default values for some types are meaningful, they are not meaningful for all types (e.g., Action, Control, Parser, Parser state, etc.). Signed-off-by: Will Hawkins <hawkinsw@obs.cr>
This commit is contained in:
@@ -162,7 +162,7 @@ public struct P4Struct: P4Type {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func def() -> any P4DataValue {
|
public func def() -> P4DataValue? {
|
||||||
return P4StructValue(withType: self)
|
return P4StructValue(withType: self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -203,7 +203,7 @@ public class P4StructValue: P4DataValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Now that we know that the field names match, do the values match?
|
// Now that we know that the field names match, do the values match?
|
||||||
if !op(left_field_value.dataValue(), right_field_value.dataValue()) {
|
if !op(left_field_value?.dataValue(), right_field_value?.dataValue()) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -297,19 +297,21 @@ public class P4StructValue: P4DataValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public let stype: P4Struct
|
public let stype: P4Struct
|
||||||
public let values: [P4Value]
|
public let values: [P4Value?]
|
||||||
|
|
||||||
public convenience init(withType type: P4Struct) {
|
public convenience init(withType type: P4Struct) {
|
||||||
self.init(withType: type, andInitializers: [])
|
self.init(withType: type, andInitializers: [])
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(withType type: P4Struct, andInitializers initializers: [P4Value?]) {
|
public init(withType type: P4Struct, andInitializers initializers: [P4Value?]) {
|
||||||
let values = zip(0..<type.fields.count(), type.fields.fields).map { (index, field) in
|
let values: [P4Value?] = zip(0..<type.fields.count(), type.fields.fields).map { (index, field) in
|
||||||
// If there is an initializer for the field, then use it.
|
// If there is an initializer for the field, then use it.
|
||||||
if index < initializers.count, let initializer = initializers[index] {
|
if index < initializers.count, let initializer = initializers[index] {
|
||||||
initializer
|
initializer
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, set a default!
|
// Otherwise, try to set a default!
|
||||||
|
// Note: If the field type does not have a default, then the value
|
||||||
|
// will be a none. Pretty cool!
|
||||||
field.type.def()
|
field.type.def()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -361,7 +363,7 @@ public struct P4Boolean: P4Type {
|
|||||||
default: false
|
default: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public func def() -> any P4DataValue {
|
public func def() -> P4DataValue? {
|
||||||
return P4BooleanValue(withValue: false)
|
return P4BooleanValue(withValue: false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -434,7 +436,7 @@ public struct P4Int: P4Type {
|
|||||||
default: false
|
default: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public func def() -> any P4DataValue {
|
public func def() -> P4DataValue? {
|
||||||
return P4IntValue(withValue: 0)
|
return P4IntValue(withValue: 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -506,7 +508,7 @@ public struct P4String: P4Type {
|
|||||||
default: false
|
default: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public func def() -> any P4DataValue {
|
public func def() -> P4DataValue? {
|
||||||
return P4StringValue(withValue: "")
|
return P4StringValue(withValue: "")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -587,7 +589,7 @@ public struct P4Array: P4Type {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func def() -> P4DataValue {
|
public func def() -> P4DataValue? {
|
||||||
return P4ArrayValue(withType: self.vtype, withValue: [])
|
return P4ArrayValue(withType: self.vtype, withValue: [])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -686,8 +688,11 @@ public struct P4Set: P4Type {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func def() -> P4DataValue {
|
public func def() -> P4DataValue? {
|
||||||
return P4SetValue(withValue: P4Value(self.stype.baseType().def(), self.stype))
|
if let base_type_default = self.stype.baseType().def() {
|
||||||
|
return P4SetValue(withValue: P4Value(base_type_default, self.stype))
|
||||||
|
}
|
||||||
|
return .none
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -784,7 +789,7 @@ public struct P4HitMiss: P4Type {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func def() -> any P4DataValue {
|
public func def() -> P4DataValue? {
|
||||||
return P4TableHitMissValue.Miss
|
return P4TableHitMissValue.Miss
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -141,8 +141,11 @@ public struct P4QualifiedType: CustomStringConvertible {
|
|||||||
return self.base_type
|
return self.base_type
|
||||||
}
|
}
|
||||||
|
|
||||||
public func def() -> P4Value {
|
public func def() -> P4Value? {
|
||||||
return P4Value(self.base_type.def(), self)
|
if let default_value = self.base_type.def() {
|
||||||
|
return P4Value(default_value, self)
|
||||||
|
}
|
||||||
|
return .none
|
||||||
}
|
}
|
||||||
|
|
||||||
public func eq(_ rhs: P4QualifiedType) -> Bool {
|
public func eq(_ rhs: P4QualifiedType) -> Bool {
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ public protocol EvaluatableStatement {
|
|||||||
|
|
||||||
public protocol P4Type: CustomStringConvertible {
|
public protocol P4Type: CustomStringConvertible {
|
||||||
func eq(rhs: any P4Type) -> Bool
|
func eq(rhs: any P4Type) -> Bool
|
||||||
func def() -> P4DataValue
|
func def() -> P4DataValue?
|
||||||
}
|
}
|
||||||
|
|
||||||
public protocol P4DataValue: CustomStringConvertible {
|
public protocol P4DataValue: CustomStringConvertible {
|
||||||
|
|||||||
@@ -194,17 +194,18 @@ extension VariableDeclarationStatement: CompilableStatement {
|
|||||||
Error(withMessage: "Could not parse a P4 type from \(typeref.text!)"))
|
Error(withMessage: "Could not parse a P4 type from \(typeref.text!)"))
|
||||||
}
|
}
|
||||||
|
|
||||||
var initializer: EvaluatableExpression = declaration_p4_type.def()
|
var initializer: EvaluatableExpression? = .none
|
||||||
|
|
||||||
// If there is an initializer, it must be an expression.
|
// If there is an initializer, it must be an expression.
|
||||||
if let rvalue = maybe_rvalue {
|
if let initializer_expression = maybe_rvalue {
|
||||||
guard rvalue.nodeType == "expression" else {
|
guard initializer_expression.nodeType == "expression" else {
|
||||||
return Result.Error(
|
return Result.Error(
|
||||||
ErrorOnNode(
|
ErrorOnNode(
|
||||||
node: node,
|
node: node,
|
||||||
withError: "initial value for declaration statement is not an expression"))
|
withError: "initial value for declaration statement is not an expression"))
|
||||||
}
|
}
|
||||||
|
|
||||||
let maybe_parsed_rvalue = Expression.Compile(node: rvalue, withContext: context)
|
let maybe_parsed_rvalue = Expression.Compile(node: initializer_expression, withContext: context)
|
||||||
guard
|
guard
|
||||||
case .Ok(let parsed_rvalue) = maybe_parsed_rvalue
|
case .Ok(let parsed_rvalue) = maybe_parsed_rvalue
|
||||||
else {
|
else {
|
||||||
@@ -217,10 +218,22 @@ extension VariableDeclarationStatement: CompilableStatement {
|
|||||||
return Result.Error(
|
return Result.Error(
|
||||||
Error(
|
Error(
|
||||||
withMessage:
|
withMessage:
|
||||||
"Cannot initialize \(parsed_variablename) (with type \(declaration_p4_type)) from rvalue with type \(parsed_rvalue.type())"
|
"Cannot initialize \(parsed_variablename) (with type \(declaration_p4_type)) from expression with type \(parsed_rvalue.type())"
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If there is no initializer, then it must be defaultable.
|
||||||
|
|
||||||
|
if initializer == nil {
|
||||||
|
initializer = declaration_p4_type.def()
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let initializer = initializer else {
|
||||||
|
return Result.Error(
|
||||||
|
ErrorOnNode(node: node, withError: "No initializer for declaration"))
|
||||||
|
}
|
||||||
|
|
||||||
return Result.Ok(
|
return Result.Ok(
|
||||||
(
|
(
|
||||||
VariableDeclarationStatement(
|
VariableDeclarationStatement(
|
||||||
|
|||||||
@@ -64,8 +64,8 @@ public struct Action: CustomStringConvertible, P4Type, P4DataValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func def() -> any Common.P4DataValue {
|
public func def() -> P4DataValue? {
|
||||||
return Action()
|
return .none
|
||||||
}
|
}
|
||||||
|
|
||||||
public var description: String {
|
public var description: String {
|
||||||
@@ -284,15 +284,8 @@ public struct Control: P4Type, P4DataValue, Equatable, CustomStringConvertible {
|
|||||||
withActions: self.actions, withApply: self.apply)
|
withActions: self.actions, withApply: self.apply)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func def() -> any P4DataValue {
|
public func def() -> P4DataValue? {
|
||||||
return Control(
|
return .none
|
||||||
named: Identifier(name: ""),
|
|
||||||
withParameters: ParameterList(),
|
|
||||||
withTable: Table(
|
|
||||||
withName: Identifier(name: "empty"),
|
|
||||||
withPropertyList: TablePropertyList(
|
|
||||||
withActions: TableActionsProperty(), withKeys: TableKeys())),
|
|
||||||
withActions: Actions(withActions: []), withApply: ApplyStatement())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public struct Declaration: P4Type {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func def() -> any Common.P4DataValue {
|
public func def() -> P4DataValue? {
|
||||||
/// TODO: Is a default of the extern'd type the right way to go?
|
/// TODO: Is a default of the extern'd type the right way to go?
|
||||||
return self.identifier.type.baseType().def()
|
return self.identifier.type.baseType().def()
|
||||||
}
|
}
|
||||||
@@ -107,11 +107,8 @@ public struct FunctionDeclaration: P4Type, P4DataValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func def() -> any Common.P4DataValue {
|
public func def() -> P4DataValue? {
|
||||||
return FunctionDeclaration(
|
return .none
|
||||||
named: Identifier(name: ""), ofType: P4QualifiedType(P4Boolean()),
|
|
||||||
withParameters: ParameterList([]),
|
|
||||||
withBody: .none)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public var description: String {
|
public var description: String {
|
||||||
|
|||||||
@@ -101,8 +101,8 @@ public class ParserState: P4Type, P4DataValue, Equatable, CustomStringConvertibl
|
|||||||
/// Construct a ParserState
|
/// Construct a ParserState
|
||||||
public init() {}
|
public init() {}
|
||||||
|
|
||||||
public func def() -> any P4DataValue {
|
public func def() -> P4DataValue? {
|
||||||
return ParserState()
|
return .none
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,8 +353,8 @@ public struct Parser: P4Type, P4DataValue {
|
|||||||
return "Parser \(self.name) with parameters: \(parameters) and states: \(self.states)"
|
return "Parser \(self.name) with parameters: \(parameters) and states: \(self.states)"
|
||||||
}
|
}
|
||||||
|
|
||||||
public func def() -> any P4DataValue {
|
public func def() -> P4DataValue? {
|
||||||
return Parser(withName: Identifier(name: ""))
|
return .none
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ import TreeSitterP4
|
|||||||
#RequireErrorResult(
|
#RequireErrorResult(
|
||||||
Error(
|
Error(
|
||||||
withMessage:
|
withMessage:
|
||||||
"{86, 27}: Failed to parse a statement element: Cannot initialize where_to (with type Boolean) from rvalue with type String"
|
"{86, 27}: Failed to parse a statement element: Cannot initialize where_to (with type Boolean) from expression with type String"
|
||||||
),
|
),
|
||||||
Program.Compile(simple_parser_declaration)))
|
Program.Compile(simple_parser_declaration)))
|
||||||
}
|
}
|
||||||
@@ -123,7 +123,7 @@ import TreeSitterP4
|
|||||||
#RequireErrorResult(
|
#RequireErrorResult(
|
||||||
Error(
|
Error(
|
||||||
withMessage:
|
withMessage:
|
||||||
"{77, 29}: Failed to parse a statement element: Cannot initialize where_from (with type String) from rvalue with type Boolean"
|
"{77, 29}: Failed to parse a statement element: Cannot initialize where_from (with type String) from expression with type Boolean"
|
||||||
),
|
),
|
||||||
Program.Compile(simple_parser_declaration)))
|
Program.Compile(simple_parser_declaration)))
|
||||||
}
|
}
|
||||||
@@ -258,7 +258,7 @@ import TreeSitterP4
|
|||||||
#RequireErrorResult(
|
#RequireErrorResult(
|
||||||
Error(
|
Error(
|
||||||
withMessage:
|
withMessage:
|
||||||
"{49, 22}: Failed to parse a statement element: Cannot initialize where_to (with type Boolean) from rvalue with type Int"
|
"{49, 22}: Failed to parse a statement element: Cannot initialize where_to (with type Boolean) from expression with type Int"
|
||||||
),
|
),
|
||||||
Program.Compile(simple_parser_declaration, withGlobalInstances: test_types)))
|
Program.Compile(simple_parser_declaration, withGlobalInstances: test_types)))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user