@@ -26,4 +26,3 @@ public typealias TypeTypeScope = Scope<P4Type>
|
|||||||
|
|
||||||
/// Scopes that resolve type identifiers to their types.
|
/// Scopes that resolve type identifiers to their types.
|
||||||
public typealias TypeTypeScopes = Scopes<P4Type>
|
public typealias TypeTypeScopes = Scopes<P4Type>
|
||||||
|
|
||||||
|
|||||||
@@ -120,8 +120,9 @@ public struct P4StructFields: Sequence, CustomStringConvertible, Equatable {
|
|||||||
|
|
||||||
public func describe_with_values(values: [P4Value?]) -> String {
|
public func describe_with_values(values: [P4Value?]) -> String {
|
||||||
assert(values.count == self.count())
|
assert(values.count == self.count())
|
||||||
return zip(self.fields, values).map() { (field, value) in
|
return zip(self.fields, values).map { (field, value) in
|
||||||
let actual_value = if let v = value {
|
let actual_value =
|
||||||
|
if let v = value {
|
||||||
v.description
|
v.description
|
||||||
} else {
|
} else {
|
||||||
"Unset"
|
"Unset"
|
||||||
@@ -211,7 +212,11 @@ public class P4StructValue: P4Value {
|
|||||||
for field_idx in 0..<stype.fields.count() {
|
for field_idx in 0..<stype.fields.count() {
|
||||||
if stype.fields.fields[field_idx] == field {
|
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(rhs: to.type()) {
|
||||||
return .Error(Error(withMessage: "Cannot assign value with type \(to.type()) to field with type \(stype.fields.fields[field_idx].type))"))
|
return .Error(
|
||||||
|
Error(
|
||||||
|
withMessage:
|
||||||
|
"Cannot assign value with type \(to.type()) to field with type \(stype.fields.fields[field_idx].type))"
|
||||||
|
))
|
||||||
}
|
}
|
||||||
updated_values[field_idx] = to
|
updated_values[field_idx] = to
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -42,13 +42,15 @@ public protocol P4Value: EvaluatableExpression, CustomStringConvertible {
|
|||||||
func eq(rhs: P4Value) -> Bool
|
func eq(rhs: P4Value) -> Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
public extension P4Value {
|
extension P4Value {
|
||||||
func evaluate(execution: ProgramExecution) -> Result<P4Value> {
|
public func evaluate(execution: ProgramExecution) -> Result<P4Value> {
|
||||||
return Result.Ok(self)
|
return Result.Ok(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public protocol EvaluatableLValueExpression: EvaluatableExpression {
|
public protocol EvaluatableLValueExpression: EvaluatableExpression {
|
||||||
func set(to: P4Value, inScopes scopes: VarValueScopes, duringExecution execution: ProgramExecution) -> Result<(VarValueScopes, P4Value)>
|
func set(
|
||||||
|
to: P4Value, inScopes scopes: VarValueScopes, duringExecution execution: ProgramExecution
|
||||||
|
) -> Result<(VarValueScopes, P4Value)>
|
||||||
func check(to: EvaluatableExpression, inScopes scopes: VarTypeScopes) -> Result<()>
|
func check(to: EvaluatableExpression, inScopes scopes: VarTypeScopes) -> Result<()>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import SwiftTreeSitter
|
|||||||
import TreeSitterExtensions
|
import TreeSitterExtensions
|
||||||
import TreeSitterP4
|
import TreeSitterP4
|
||||||
|
|
||||||
|
|
||||||
public struct Parser {
|
public struct Parser {
|
||||||
public struct LocalElements {
|
public struct LocalElements {
|
||||||
static func Compile(
|
static func Compile(
|
||||||
@@ -165,7 +164,9 @@ public struct Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !parse_errs.isEmpty {
|
if !parse_errs.isEmpty {
|
||||||
return Result.Error(Error(withMessage: parse_errs.map() { err in
|
return Result.Error(
|
||||||
|
Error(
|
||||||
|
withMessage: parse_errs.map { err in
|
||||||
return String(err.msg)
|
return String(err.msg)
|
||||||
}.joined(separator: ";")))
|
}.joined(separator: ";")))
|
||||||
}
|
}
|
||||||
@@ -246,7 +247,9 @@ public struct Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !parse_errs.isEmpty {
|
if !parse_errs.isEmpty {
|
||||||
return Result.Error(Error(withMessage: parse_errs.map() { err in
|
return Result.Error(
|
||||||
|
Error(
|
||||||
|
withMessage: parse_errs.map { err in
|
||||||
return String(err.msg)
|
return String(err.msg)
|
||||||
}.joined(separator: ";")))
|
}.joined(separator: ";")))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,12 +27,15 @@ public struct Program {
|
|||||||
return Program.Compile(source, withGlobalInstances: .none, withGlobalTypes: .none)
|
return Program.Compile(source, withGlobalInstances: .none, withGlobalTypes: .none)
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func Compile(_ source: String, withGlobalInstances globalInstances: VarTypeScopes) -> Result<P4Lang.Program> {
|
public static func Compile(
|
||||||
|
_ source: String, withGlobalInstances globalInstances: VarTypeScopes
|
||||||
|
) -> Result<P4Lang.Program> {
|
||||||
return Program.Compile(source, withGlobalInstances: globalInstances, withGlobalTypes: .none)
|
return Program.Compile(source, withGlobalInstances: globalInstances, withGlobalTypes: .none)
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func Compile(
|
public static func Compile(
|
||||||
_ source: String, withGlobalInstances globalInstances: VarTypeScopes?, withGlobalTypes globalTypes: TypeTypeScopes?
|
_ source: String, withGlobalInstances globalInstances: VarTypeScopes?,
|
||||||
|
withGlobalTypes globalTypes: TypeTypeScopes?
|
||||||
) -> Result<P4Lang.Program> {
|
) -> Result<P4Lang.Program> {
|
||||||
|
|
||||||
let maybe_parser = ConfigureP4Parser()
|
let maybe_parser = ConfigureP4Parser()
|
||||||
|
|||||||
@@ -33,5 +33,7 @@ public protocol CompilableValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public protocol CompilableType {
|
public protocol CompilableType {
|
||||||
static func CompileType(type: SwiftTreeSitter.Node, withContext: CompilerContext) -> Result<P4Type?>
|
static func CompileType(
|
||||||
|
type: SwiftTreeSitter.Node, withContext: CompilerContext
|
||||||
|
) -> Result<P4Type?>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -191,7 +191,8 @@ extension VariableDeclarationStatement: CompilableStatement {
|
|||||||
Error(withMessage: "Could not parse variable name"))
|
Error(withMessage: "Could not parse variable name"))
|
||||||
}
|
}
|
||||||
|
|
||||||
guard case .Ok(let declaration_p4_type) = Types.CompileType(type: typeref, withContext: context) else {
|
guard case .Ok(let declaration_p4_type) = Types.CompileType(type: typeref, withContext: context)
|
||||||
|
else {
|
||||||
return Result.Error(
|
return Result.Error(
|
||||||
Error(withMessage: "Could not parse a P4 type from \(typeref.text!)"))
|
Error(withMessage: "Could not parse a P4 type from \(typeref.text!)"))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,31 +23,40 @@ import TreeSitterExtensions
|
|||||||
import TreeSitterP4
|
import TreeSitterP4
|
||||||
|
|
||||||
extension P4Boolean: CompilableType {
|
extension P4Boolean: CompilableType {
|
||||||
public static func CompileType(type: SwiftTreeSitter.Node, withContext: CompilerContext) -> Common.Result<(any Common.P4Type)?> {
|
public static func CompileType(
|
||||||
|
type: SwiftTreeSitter.Node, withContext: CompilerContext
|
||||||
|
) -> Common.Result<(any Common.P4Type)?> {
|
||||||
return type.text == "bool" ? .Ok(P4Boolean()) : .Ok(.none)
|
return type.text == "bool" ? .Ok(P4Boolean()) : .Ok(.none)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension P4Int: CompilableType {
|
extension P4Int: CompilableType {
|
||||||
public static func CompileType(type: SwiftTreeSitter.Node, withContext: CompilerContext) -> Common.Result<(any Common.P4Type)?> {
|
public static func CompileType(
|
||||||
|
type: SwiftTreeSitter.Node, withContext: CompilerContext
|
||||||
|
) -> Common.Result<(any Common.P4Type)?> {
|
||||||
return type.text == "int" ? .Ok(P4Int()) : .Ok(.none)
|
return type.text == "int" ? .Ok(P4Int()) : .Ok(.none)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension P4String: CompilableType {
|
extension P4String: CompilableType {
|
||||||
public static func CompileType(type: SwiftTreeSitter.Node, withContext: CompilerContext) -> Common.Result<(any Common.P4Type)?> {
|
public static func CompileType(
|
||||||
|
type: SwiftTreeSitter.Node, withContext: CompilerContext
|
||||||
|
) -> Common.Result<(any Common.P4Type)?> {
|
||||||
return type.text == "string" ? .Ok(P4String()) : .Ok(.none)
|
return type.text == "string" ? .Ok(P4String()) : .Ok(.none)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension P4Struct: CompilableType {
|
extension P4Struct: CompilableType {
|
||||||
public static func CompileType(type: SwiftTreeSitter.Node, withContext context: CompilerContext) -> Common.Result<(any Common.P4Type)?> {
|
public static func CompileType(
|
||||||
|
type: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
|
) -> Common.Result<(any Common.P4Type)?> {
|
||||||
let maybe_parsed_type_id = Identifier.Compile(node: type, withContext: context)
|
let maybe_parsed_type_id = Identifier.Compile(node: type, withContext: context)
|
||||||
guard case .Ok(let parsed_type_id) = maybe_parsed_type_id else {
|
guard case .Ok(let parsed_type_id) = maybe_parsed_type_id else {
|
||||||
return .Error(maybe_parsed_type_id.error()!)
|
return .Error(maybe_parsed_type_id.error()!)
|
||||||
}
|
}
|
||||||
if case .Ok(let found_type) = context.types.lookup(identifier: parsed_type_id),
|
if case .Ok(let found_type) = context.types.lookup(identifier: parsed_type_id),
|
||||||
let found_struct_type = found_type as? P4Struct {
|
let found_struct_type = found_type as? P4Struct
|
||||||
|
{
|
||||||
return .Ok(found_struct_type)
|
return .Ok(found_struct_type)
|
||||||
}
|
}
|
||||||
return .Ok(.none)
|
return .Ok(.none)
|
||||||
@@ -55,8 +64,12 @@ extension P4Struct: CompilableType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public struct Types {
|
public struct Types {
|
||||||
static func CompileType(type: SwiftTreeSitter.Node, withContext context: CompilerContext) -> Result<P4Type> {
|
static func CompileType(
|
||||||
let type_parsers: [CompilableType.Type] = [P4Boolean.self, P4Int.self, P4String.self, P4Struct.self]
|
type: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
|
) -> Result<P4Type> {
|
||||||
|
let type_parsers: [CompilableType.Type] = [
|
||||||
|
P4Boolean.self, P4Int.self, P4String.self, P4Struct.self,
|
||||||
|
]
|
||||||
for type_parser in type_parsers {
|
for type_parser in type_parsers {
|
||||||
switch type_parser.CompileType(type: type, withContext: context) {
|
switch type_parser.CompileType(type: type, withContext: context) {
|
||||||
case .Ok(.some(let type)): return .Ok(type)
|
case .Ok(.some(let type)): return .Ok(type)
|
||||||
|
|||||||
@@ -29,7 +29,9 @@ public struct ParserAssignmentStatement {
|
|||||||
public let lvalue: EvaluatableLValueExpression
|
public let lvalue: EvaluatableLValueExpression
|
||||||
public let value: EvaluatableExpression
|
public let value: EvaluatableExpression
|
||||||
|
|
||||||
public init(withLValue lvalue: EvaluatableLValueExpression, withValue value: EvaluatableExpression) {
|
public init(
|
||||||
|
withLValue lvalue: EvaluatableLValueExpression, withValue value: EvaluatableExpression
|
||||||
|
) {
|
||||||
self.lvalue = lvalue
|
self.lvalue = lvalue
|
||||||
self.value = value
|
self.value = value
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,8 @@ extension TypedIdentifier: EvaluatableExpression {
|
|||||||
// Variables are evaluatable because they can be looked up by identifiers.
|
// Variables are evaluatable because they can be looked up by identifiers.
|
||||||
extension TypedIdentifier: EvaluatableLValueExpression {
|
extension TypedIdentifier: EvaluatableLValueExpression {
|
||||||
public func set(
|
public func set(
|
||||||
to: any Common.P4Value, inScopes scopes: Common.VarValueScopes, duringExecution execution: ProgramExecution
|
to: any Common.P4Value, inScopes scopes: Common.VarValueScopes,
|
||||||
|
duringExecution execution: ProgramExecution
|
||||||
) -> Common.Result<(Common.VarValueScopes, P4Value)> {
|
) -> Common.Result<(Common.VarValueScopes, P4Value)> {
|
||||||
if case .Error(let e) = scopes.lookup(identifier: self) {
|
if case .Error(let e) = scopes.lookup(identifier: self) {
|
||||||
return .Error(e)
|
return .Error(e)
|
||||||
@@ -75,13 +76,18 @@ extension TypedIdentifier: EvaluatableLValueExpression {
|
|||||||
return .Ok((scopes.set(identifier: self, withValue: to), to))
|
return .Ok((scopes.set(identifier: self, withValue: to), to))
|
||||||
}
|
}
|
||||||
|
|
||||||
public func check(to: any Common.EvaluatableExpression, inScopes scopes: Common.VarTypeScopes) -> Result<()> {
|
public func check(
|
||||||
|
to: any Common.EvaluatableExpression, inScopes scopes: Common.VarTypeScopes
|
||||||
|
) -> Result<()> {
|
||||||
guard case .Ok(let type) = scopes.lookup(identifier: self) else {
|
guard case .Ok(let type) = scopes.lookup(identifier: self) else {
|
||||||
return .Error(Error(withMessage: "Cannot assign to identifier not in scope"))
|
return .Error(Error(withMessage: "Cannot assign to identifier not in scope"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if !type.eq(rhs: to.type()) {
|
if !type.eq(rhs: to.type()) {
|
||||||
return .Error(Error(withMessage: "Cannot assign value with type \(to.type()) to identifier \(self) with type \(type)"))
|
return .Error(
|
||||||
|
Error(
|
||||||
|
withMessage:
|
||||||
|
"Cannot assign value with type \(to.type()) to identifier \(self) with type \(type)"))
|
||||||
}
|
}
|
||||||
return .Ok(())
|
return .Ok(())
|
||||||
}
|
}
|
||||||
@@ -145,7 +151,8 @@ extension ArrayAccessExpression: EvaluatableExpression {
|
|||||||
|
|
||||||
extension ArrayAccessExpression: EvaluatableLValueExpression {
|
extension ArrayAccessExpression: EvaluatableLValueExpression {
|
||||||
public func set(
|
public func set(
|
||||||
to: any Common.P4Value, inScopes scopes: Common.VarValueScopes, duringExecution execution: ProgramExecution
|
to: any Common.P4Value, inScopes scopes: Common.VarValueScopes,
|
||||||
|
duringExecution execution: ProgramExecution
|
||||||
) -> Common.Result<(Common.VarValueScopes, P4Value)> {
|
) -> Common.Result<(Common.VarValueScopes, P4Value)> {
|
||||||
// For purposes of documentation, assume the field access expression we are evaluating is
|
// For purposes of documentation, assume the field access expression we are evaluating is
|
||||||
// (strct_id)[indexor] = new_value
|
// (strct_id)[indexor] = new_value
|
||||||
@@ -155,7 +162,8 @@ extension ArrayAccessExpression: EvaluatableLValueExpression {
|
|||||||
// First, evaluate strct_id and make sure that it names a struct.
|
// First, evaluate strct_id and make sure that it names a struct.
|
||||||
let maybe_value = self.name.evaluate(execution: execution)
|
let maybe_value = self.name.evaluate(execution: execution)
|
||||||
guard case .Ok(let value) = maybe_value else {
|
guard case .Ok(let value) = maybe_value else {
|
||||||
return Result.Error(Error(withMessage: "\(self.name) cannot be evaluated: \(maybe_value.error()!)"))
|
return Result.Error(
|
||||||
|
Error(withMessage: "\(self.name) cannot be evaluated: \(maybe_value.error()!)"))
|
||||||
}
|
}
|
||||||
guard let array_value = value as? P4ArrayValue else {
|
guard let array_value = value as? P4ArrayValue else {
|
||||||
return Result.Error(Error(withMessage: "\(self.name) does not identify a struct"))
|
return Result.Error(Error(withMessage: "\(self.name) does not identify a struct"))
|
||||||
@@ -164,7 +172,8 @@ extension ArrayAccessExpression: EvaluatableLValueExpression {
|
|||||||
// Now, get the indexor!
|
// Now, get the indexor!
|
||||||
let maybe_indexor_value = self.indexor.evaluate(execution: execution)
|
let maybe_indexor_value = self.indexor.evaluate(execution: execution)
|
||||||
guard case .Ok(let indexor_value) = maybe_indexor_value else {
|
guard case .Ok(let indexor_value) = maybe_indexor_value else {
|
||||||
return Result.Error(Error(withMessage: "\(self.indexor) cannot be evaluated: \(maybe_indexor_value.error()!)"))
|
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 as? P4IntValue else {
|
||||||
return Result.Error(Error(withMessage: "\(self.indexor) cannot be used to index an array"))
|
return Result.Error(Error(withMessage: "\(self.indexor) cannot be used to index an array"))
|
||||||
@@ -187,7 +196,11 @@ extension ArrayAccessExpression: EvaluatableLValueExpression {
|
|||||||
) -> Common.Result<()> {
|
) -> Common.Result<()> {
|
||||||
|
|
||||||
if !self.type.value_type().eq(rhs: to.type()) {
|
if !self.type.value_type().eq(rhs: to.type()) {
|
||||||
return .Error(Error(withMessage: "Cannot assign value of type \(to.type()) to array with values of type \(self.name.type())"))
|
return .Error(
|
||||||
|
Error(
|
||||||
|
withMessage:
|
||||||
|
"Cannot assign value of type \(to.type()) to array with values of type \(self.name.type())"
|
||||||
|
))
|
||||||
}
|
}
|
||||||
return .Ok(())
|
return .Ok(())
|
||||||
}
|
}
|
||||||
@@ -219,7 +232,8 @@ extension FieldAccessExpression: EvaluatableExpression {
|
|||||||
|
|
||||||
extension FieldAccessExpression: EvaluatableLValueExpression {
|
extension FieldAccessExpression: EvaluatableLValueExpression {
|
||||||
public func set(
|
public func set(
|
||||||
to: any Common.P4Value, inScopes scopes: Common.VarValueScopes, duringExecution execution: ProgramExecution
|
to: any Common.P4Value, inScopes scopes: Common.VarValueScopes,
|
||||||
|
duringExecution execution: ProgramExecution
|
||||||
) -> Common.Result<(Common.VarValueScopes, P4Value)> {
|
) -> Common.Result<(Common.VarValueScopes, P4Value)> {
|
||||||
// For purposes of documentation, assume the field access expression we are evaluating is
|
// For purposes of documentation, assume the field access expression we are evaluating is
|
||||||
// (strct_id).field_id = new_field_value
|
// (strct_id).field_id = new_field_value
|
||||||
@@ -229,7 +243,8 @@ extension FieldAccessExpression: EvaluatableLValueExpression {
|
|||||||
// First, evaluate strct_id and make sure that it names a struct.
|
// First, evaluate strct_id and make sure that it names a struct.
|
||||||
let maybe_value = self.strct.evaluate(execution: execution)
|
let maybe_value = self.strct.evaluate(execution: execution)
|
||||||
guard case .Ok(let value) = maybe_value else {
|
guard case .Ok(let value) = maybe_value else {
|
||||||
return Result.Error(Error(withMessage: "\(self.strct) cannot be evaluated: \(maybe_value.error()!)"))
|
return Result.Error(
|
||||||
|
Error(withMessage: "\(self.strct) cannot be evaluated: \(maybe_value.error()!)"))
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let struct_value = value as? P4StructValue else {
|
guard let struct_value = value as? P4StructValue else {
|
||||||
@@ -255,8 +270,11 @@ extension FieldAccessExpression: EvaluatableLValueExpression {
|
|||||||
to: any Common.EvaluatableExpression, inScopes scopes: Common.VarTypeScopes
|
to: any Common.EvaluatableExpression, inScopes scopes: Common.VarTypeScopes
|
||||||
) -> Common.Result<()> {
|
) -> Common.Result<()> {
|
||||||
|
|
||||||
if !self.field.type.eq(rhs:to.type()) {
|
if !self.field.type.eq(rhs: to.type()) {
|
||||||
return .Error(Error(withMessage: "Cannot assign value of type \(to.type()) to field with type \(self.field.type)"))
|
return .Error(
|
||||||
|
Error(
|
||||||
|
withMessage:
|
||||||
|
"Cannot assign value of type \(to.type()) to field with type \(self.field.type)"))
|
||||||
}
|
}
|
||||||
return .Ok(())
|
return .Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user