diff --git a/Package.resolved b/Package.resolved
index 5c8c2bf..235c26b 100644
--- a/Package.resolved
+++ b/Package.resolved
@@ -1,5 +1,5 @@
{
- "originHash" : "ef9c8ff40b986db3a591fe3c50d79e4fe2a9e11749d84a72fbe97babc9ba3683",
+ "originHash" : "87d6d60d6a77921d74305adbe82f77e088a6e06d44cb3db30aa4d25c864181fd",
"pins" : [
{
"identity" : "swift-argument-parser",
@@ -15,8 +15,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-docc-plugin",
"state" : {
- "revision" : "3e4f133a77e644a5812911a0513aeb7288b07d06",
- "version" : "1.4.5"
+ "revision" : "647c708be89f834fa6a6d4945442793a77ddf5b6",
+ "version" : "1.5.0"
}
},
{
@@ -52,7 +52,7 @@
"location" : "https://github.com/tree-sitter/swift-tree-sitter",
"state" : {
"branch" : "main",
- "revision" : "769f4770fe8197e2f4ce810375e9b21398ae36d5"
+ "revision" : "f97df585296977d8fcaf644cbde567151d1367b8"
}
},
{
diff --git a/Package.swift b/Package.swift
index c319e07..1b5c79a 100644
--- a/Package.swift
+++ b/Package.swift
@@ -18,16 +18,8 @@ let package = Package(
targets: ["Common"]
),
.library(
- name: "P4Lang",
- targets: ["P4Lang"]
- ),
- .library(
- name: "P4Runtime",
- targets: ["P4Runtime"]
- ),
- .executable(
- name: "p4ce",
- targets: ["Cli"]
+ name: "P4CodeGen",
+ targets: ["P4CodeGen"]
),
],
dependencies: [
@@ -37,6 +29,7 @@ let package = Package(
.package(url: "https://github.com/swiftlang/swift-syntax", from: "602.0.0"),
.package(url: "https://github.com/apple/swift-argument-parser", from: "1.0.0"),
.package(url: "https://github.com/apple/swift-system", from: "1.6.1"),
+ //.package(url: "https://github.com/apple/swift-protobuf.git", from: "1.27.0"),
],
targets: [
.macro(
@@ -54,8 +47,6 @@ let package = Package(
.product(name: "TreeSitterP4", package: "tree-sitter-p4"),
.target(name: "TreeSitterExtensions"),
.target(name: "Common"),
- .target(name: "P4Lang"),
- .target(name: "P4Runtime"),
],
swiftSettings: [.enableExperimentalFeature("CodeItemMacros")],
),
@@ -71,32 +62,25 @@ let package = Package(
dependencies: [
"Macros",
.product(name: "SystemPackage", package: "swift-system"),
+ .product(name: "SwiftTreeSitter", package: "swift-tree-sitter"),
],
swiftSettings: [.enableExperimentalFeature("CodeItemMacros")],
),
.target(
- name: "P4Lang",
- dependencies: ["Common"]
- ),
- .target(
- name: "P4Runtime",
- dependencies: ["P4Lang", "Common"]
- ),
- .executableTarget(
- name: "Cli",
+ name: "P4CodeGen",
dependencies: [
- "Common", "P4Lang", "P4Compiler", "P4Runtime", "Macros",
- .product(name: "ArgumentParser", package: "swift-argument-parser"),
- ],
- swiftSettings: [.enableExperimentalFeature("CodeItemMacros")],
+ "P4Compiler", "Common",
+ //.product(name: "SwiftProtobuf", package: "swift-protobuf"),
+ ]
),
.testTarget(
name: "Tests",
dependencies: [
- "P4Compiler", "P4Runtime", "P4Lang", "Macros", "TreeSitterExtensions", "Common",
+ "P4Compiler", "P4CodeGen", "Macros", "TreeSitterExtensions", "Common",
.product(name: "SystemPackage", package: "swift-system"),
],
+ //swiftSettings: [.enableExperimentalFeature("CodeItemMacros"), .unsafeFlags(["-Xfrontend", "-dump-macro-expansions"])],
swiftSettings: [.enableExperimentalFeature("CodeItemMacros")],
),
],
diff --git a/Snippets/use-program-instanceswithtypes.swift b/Snippets/use-program-instanceswithtypes.swift
index 02b6ba6..fb46fad 100644
--- a/Snippets/use-program-instanceswithtypes.swift
+++ b/Snippets/use-program-instanceswithtypes.swift
@@ -22,7 +22,6 @@ import SwiftTreeSitter
import Testing
import TreeSitter
import TreeSitterP4
-import P4Lang
import P4Compiler
let p4_program_with_control_decl = """
@@ -37,7 +36,7 @@ let p4_program_with_control_decl = """
};
"""
-
+/*
// snippet.include
let flter = { (tipe: P4QualifiedType) -> Bool in
switch tipe.baseType(){
@@ -48,3 +47,4 @@ let flter = { (tipe: P4QualifiedType) -> Bool in
if case .Ok(let program) = SpecialCompilers.ProgramCompiler.Compile(p4_program_with_control_decl) {
print(program.InstancesWithTypes(flter))
}
+*/
\ No newline at end of file
diff --git a/Snippets/use-program-typeswithtypes.swift b/Snippets/use-program-typeswithtypes.swift
index 713c65b..31124cc 100644
--- a/Snippets/use-program-typeswithtypes.swift
+++ b/Snippets/use-program-typeswithtypes.swift
@@ -22,7 +22,6 @@ import SwiftTreeSitter
import Testing
import TreeSitter
import TreeSitterP4
-import P4Lang
import P4Compiler
let p4_program_with_struct_decl = """
@@ -31,6 +30,7 @@ let p4_program_with_struct_decl = """
};
"""
+/*
// snippet.include
let flter = { (tipe: P4Type) -> Bool in
switch tipe {
@@ -42,3 +42,4 @@ if case .Ok(let program) = SpecialCompilers.ProgramCompiler.Compile(p4_program_w
print(program.TypesWithTypes(flter))
}
+*/
\ No newline at end of file
diff --git a/Sources/Cli/main.swift b/Sources/Cli/main.swift
index d745283..4f01b7b 100644
--- a/Sources/Cli/main.swift
+++ b/Sources/Cli/main.swift
@@ -140,6 +140,7 @@ extension Cli {
return
}
+/*
let maybe_codegen = P4Runtime.CodeGenerator().codeGen(program)
guard case .Ok(let codegen) = maybe_codegen else {
let formatter = FormatterAnsi()
@@ -148,6 +149,7 @@ extension Cli {
}
print("\(codegen.getGeneratedCode())")
+ */
}
}
}
diff --git a/Sources/Common/Call.swift b/Sources/Common/Call.swift
deleted file mode 100644
index 4eeb016..0000000
--- a/Sources/Common/Call.swift
+++ /dev/null
@@ -1,134 +0,0 @@
-// 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 struct Parameter: CustomStringConvertible, Equatable {
- public static func == (lhs: Parameter, rhs: Parameter) -> Bool {
- return lhs.name == rhs.name && lhs.type.eq(rhs.type)
- }
-
- public var name: Identifier
- public var type: P4QualifiedType
-
- public init(
- identifier: Identifier, withType type: P4QualifiedType
- ) {
- self.name = identifier
- self.type = type
- }
-
- public var description: String {
- 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()
-
- // If the parameter is (in)out, then the argument must be an lvalue.
- if let param_direction = self.type.direction(),
- param_direction == Direction.In || param_direction == Direction.InOut
- {
- if !(argument.argument is P4LValueExpression) {
- return false
- }
- }
- return arg_type.baseType().eq(rhs: self.type.baseType())
- }
-
-}
-
-public struct ParameterList: CustomStringConvertible, Equatable {
- public static func == (lhs: ParameterList, rhs: ParameterList) -> Bool {
- if lhs.parameters.count != rhs.parameters.count {
- return false
- }
-
- return 0
- == zip(lhs.parameters, rhs.parameters).count { (lparam, rparam) in
- return lparam != rparam
- }
- }
-
- public var parameters: [Parameter]
-
- public init() {
- self.parameters = Array()
- }
-
- public init(_ parameters: [Parameter]) {
- self.parameters = parameters
- }
-
- public func addParameter(_ parameter: Parameter) -> ParameterList {
- return ParameterList(self.parameters + [parameter])
- }
-
- public var description: String {
- let parameters = self.parameters.map { parameter in
- parameter.description
- }.joined(separator: ";")
- return "Parameter list: \(parameters)"
- }
-}
-
-public struct ArgumentList {
- public let arguments: [Argument]
-
- public init(_ arguments: [Argument] = []) {
- self.arguments = arguments
- }
-
- public func compatible(_ parameters: ParameterList) -> Result<()> {
- if self.arguments.count != parameters.parameters.count {
- return .Error(
- Error(
- withMessage:
- "\(self.arguments.count) arguments found but \(parameters.parameters.count) required"))
- }
-
- for (arg, param) in zip(self.arguments, parameters.parameters) {
- let arg_index = arg.index
- let arg_type = arg.argument.type()
- if !param.compatible(arg) {
- return .Error(
- Error(
- withMessage:
- "Argument \(arg_index)'s type (\(arg_type)) is incompatible with the parameter type (\(param.type))"
- ))
- }
- }
- return .Ok(())
- }
-
- public func addArgument(_ argument: Argument) -> ArgumentList {
- return ArgumentList(self.arguments + [argument])
- }
-
- public func count() -> Int {
- return self.arguments.count
- }
-}
-
-public struct Argument {
- public let index: Int
- public let argument: P4Expression
-
- public init(_ argument: P4Expression, atIndex index: Int) {
- self.argument = argument
- self.index = index
- }
-}
diff --git a/Sources/Common/Compiler.swift b/Sources/Common/Compiler.swift
deleted file mode 100644
index a6bf391..0000000
--- a/Sources/Common/Compiler.swift
+++ /dev/null
@@ -1,203 +0,0 @@
-// 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 .
-
-/// A scope that resolves variable identifiers to their types.
-public typealias VarTypeScope = Scope
-
-/// Scopes that resolve variable identifiers to their types.
-public typealias VarTypeScopes = Scopes
-
-/// A scope that resolves type identifiers to their types.
-public typealias TypeTypeScope = Scope
-
-/// Scopes that resolve type identifiers to their types.
-public typealias TypeTypeScopes = Scopes
-
-/// Context for compilation
-///
-/// It contains (at least) three important pieces of information:
-/// 1. Instances: A ``VarTypeScopes`` that contains information about instantiated objects
-/// (and their types) in scope
-/// 1. Types: A ``TypeTypeScopes`` that contains information about declared types in scope.
-/// 1. Expected Type: In certain situations, to typecheck an element of a P4 program requires
-/// knowledge of an expected type. For instance, when compiling a return statement, the
-/// compiler must know the return type of the function to type check.
-public struct CompilerContext {
- public let instances: StaticVarValueScopes
- public let types: TypeTypeScopes
- public let externs: TypeTypeScopes
- public let ffis: [P4FFI]
- public let expected_type: P4QualifiedType?
- public let extern_context: Bool
- public let lexical_context_name: Identifier?
- public let lexical_context_statements: [P4Statement]?
-
- public init() {
- instances = StaticVarValueScopes().enter()
- types = TypeTypeScopes().enter()
- externs = TypeTypeScopes().enter()
- expected_type = .none
- extern_context = false
- ffis = Array()
- lexical_context_name = .none
- lexical_context_statements = .none
- }
-
- public init(withInstances _instances: StaticVarValueScopes, withTypes _types: TypeTypeScopes) {
- instances = _instances
- types = _types
- externs = TypeTypeScopes().enter()
- expected_type = .none
- extern_context = false
- ffis = Array()
- lexical_context_name = .none
- lexical_context_statements = .none
- }
-
- public init(
- withInstances _instances: StaticVarValueScopes, withTypes _types: TypeTypeScopes,
- withExpectation expectation: P4QualifiedType?, withExtern extern: Bool,
- withExterns externs: TypeTypeScopes, withFFIs foreigns: [P4FFI],
- withLexicalContextName lexical_context_name: Identifier?,
- withLexicalContextStatements lexical_context_statements: [P4Statement]?
- ) {
- instances = _instances
- types = _types
- expected_type = expectation
- extern_context = extern
- self.externs = externs
- ffis = foreigns
- self.lexical_context_name = lexical_context_name
- self.lexical_context_statements = lexical_context_statements
- }
-
- /// Update a compiler context
- ///
- /// Create a new compiler context based on the current but new instances.
- ///
- /// - Parameter instances: a ``VarTypeScopes`` with the updated instances for the newly created compiler context.
- /// - Returns: A new compiler context based on the current but new instances.
- public func update(newInstances instances: StaticVarValueScopes) -> CompilerContext {
- return CompilerContext(
- withInstances: instances, withTypes: self.types, withExpectation: self.expected_type,
- withExtern: self.extern_context, withExterns: self.externs, withFFIs: self.ffis,
- withLexicalContextName: self.lexical_context_name,
- withLexicalContextStatements: self.lexical_context_statements)
- }
-
- /// Update a compiler context
- ///
- /// Create a new compiler context based on the current but new types.
- ///
- /// - Parameter types: a ``TypeTypeScopes`` with the updated types for the newly created compiler context.
- /// - Returns: A new compiler context based on the current but new types.
- public func update(newTypes types: TypeTypeScopes) -> CompilerContext {
- return CompilerContext(
- withInstances: self.instances, withTypes: types, withExpectation: self.expected_type,
- withExtern: self.extern_context, withExterns: self.externs, withFFIs: self.ffis,
- withLexicalContextName: self.lexical_context_name,
- withLexicalContextStatements: self.lexical_context_statements)
- }
-
- /// Update a compiler context
- ///
- /// Create a new compiler context based on the current but new expected type.
- ///
- /// - Parameter expectation: a ``P4Type?`` to (re)set the type the compiler is expecting.
- /// - Returns: A new compiler context based on the current but new expected type.
- public func update(newExpectation expectation: P4QualifiedType?) -> CompilerContext {
- return CompilerContext(
- withInstances: self.instances, withTypes: self.types, withExpectation: expectation,
- withExtern: self.extern_context, withExterns: self.externs, withFFIs: self.ffis,
- withLexicalContextName: self.lexical_context_name,
- withLexicalContextStatements: self.lexical_context_statements)
- }
-
- /// Update a compiler context
- ///
- /// Create a new compiler context based on the current but new extern context value.
- ///
- /// - Parameter extern: a ``Bool`` to (re)set whether the compiler is compiling in an extern context.
- /// - Returns: A new compiler context based on the current but new extern context value.
- public func update(newExtern extern: Bool) -> CompilerContext {
- return CompilerContext(
- withInstances: self.instances, withTypes: self.types, withExpectation: self.expected_type,
- withExtern: extern, withExterns: self.externs, withFFIs: self.ffis,
- withLexicalContextName: self.lexical_context_name,
- withLexicalContextStatements: self.lexical_context_statements)
- }
-
- /// Update a compiler context
- ///
- /// Create a new compiler context based on the current but new externs.
- ///
- /// - Parameter externs: a ``TypeTypeScopes`` to (re)set the list of extern-al declarations.
- /// - Returns: A new compiler context based on the current but new list of external-al declarations.
- public func update(newExterns externs: TypeTypeScopes) -> CompilerContext {
- return CompilerContext(
- withInstances: self.instances, withTypes: self.types, withExpectation: self.expected_type,
- withExtern: self.extern_context, withExterns: externs, withFFIs: self.ffis,
- withLexicalContextName: self.lexical_context_name,
- withLexicalContextStatements: self.lexical_context_statements)
- }
-
- /// Update a compiler context
- ///
- /// Create a new compiler context based on the current but new FFIs.
- ///
- /// - Parameter foreigns: an array of ``P4FFI`` to (re)set the list of foreign functions.
- /// - Returns: A new compiler context based on the current but with a new list of foreign functions.
- public func update(newFFIs foreigns: [P4FFI]) -> CompilerContext {
- return CompilerContext(
- withInstances: self.instances, withTypes: self.types, withExpectation: self.expected_type,
- withExtern: self.extern_context, withExterns: externs, withFFIs: foreigns,
- withLexicalContextName: self.lexical_context_name,
- withLexicalContextStatements: self.lexical_context_statements)
- }
-
- /// Update a compiler context
- ///
- /// Create a new compiler context based on the current but with a new lexical context name.
- ///
- /// - Parameter new_lexical_context_name: an optional new lexical context name; passing `.none` resets.
- /// - Returns: A new compiler context based on the current but with a new lexical context name.
- public func update(newLexicalContextName new_lexical_context_name: Identifier?) -> CompilerContext
- {
- return CompilerContext(
- withInstances: self.instances, withTypes: self.types, withExpectation: self.expected_type,
- withExtern: self.extern_context, withExterns: externs, withFFIs: self.ffis,
- withLexicalContextName: new_lexical_context_name,
- withLexicalContextStatements: self.lexical_context_statements)
- }
-
- /// Update a compiler context
- ///
- /// Create a new compiler context based on the current but with a new set of lexical context statements.
- ///
- /// - Parameter new_lexical_context_statements: an optional new set of lexical context statements; passing `.none` resets.
- /// - Returns: A new compiler context based on the current but with a new set of lexical context statements.
- public func update(
- newLexicalContextStatements new_lexical_context_statements: [P4Statement]?
- ) -> CompilerContext {
- return CompilerContext(
- withInstances: self.instances, withTypes: self.types, withExpectation: self.expected_type,
- withExtern: self.extern_context, withExterns: externs, withFFIs: self.ffis,
- withLexicalContextName: self.lexical_context_name,
- withLexicalContextStatements: new_lexical_context_statements)
- }
-
-}
diff --git a/Sources/Common/Execution.swift b/Sources/Common/Execution.swift
deleted file mode 100644
index a0bd827..0000000
--- a/Sources/Common/Execution.swift
+++ /dev/null
@@ -1,285 +0,0 @@
-// 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 typealias ExecuteStatementResultHandlerT = (ControlFlow, ProgramExecution) -> (
- ControlFlow, ProgramExecution
-)
-
-public typealias ExecuteStatementT = (EvaluatableStatement, ProgramExecution) -> (
- ControlFlow, ProgramExecution
-)
-
-func CanonicalExecuteStatements(
- _ statements: [EvaluatableStatement], inExecution execution: ProgramExecution,
- _ executor: ExecuteStatementT
-) -> (ControlFlow, ProgramExecution) {
- var execution = execution
- for s in statements {
- // Execute the statement with the user-provided statement executor.
- switch executor(s, execution) {
- // And decide what to do next!
- case (ControlFlow.Next, let handled_next_execution): execution = handled_next_execution
- case (ControlFlow.Return(let value), let handled_next_execution):
- return (ControlFlow.Return(value), handled_next_execution)
- case (let handled_control_flow, let handled_next_execution):
- return (handled_control_flow, handled_next_execution)
- }
- }
- return (ControlFlow.Next, execution)
-}
-
-public struct ClassicEvaluator: ProgramExecutionEvaluator {
- public func ExecuteStatements(
- _ statements: [EvaluatableStatement], inExecution execution: ProgramExecution,
- _ handler: ExecuteStatementResultHandlerT?
- ) -> (ControlFlow, ProgramExecution) {
-
- return CanonicalExecuteStatements(statements, inExecution: execution) { statement, execution in
- let (cf, value) = statement.evaluate(execution: execution)
- // Apply the user-specified handler before continuing.
- guard let handler = handler else {
- return (cf, value)
- }
- return handler(cf, value)
- }
- }
-
- public func EvaluateExpression(
- _ expression: EvaluatableExpression, inExecution execution: ProgramExecution,
- ) -> (Result, ProgramExecution) {
- return expression.evaluate(execution: execution)
- }
-}
-
-public struct InterloperEvaluator: ProgramExecutionEvaluator {
- var statement_interloper: StatementInterloper?
- var expression_interloper: ExpressionInterloper?
-
- public init() {}
-
- public func getStatementInterloper() -> StatementInterloper? {
- return self.statement_interloper
- }
-
- public func setStatementInterloper(
- _ interloper: @escaping StatementInterloper
- ) -> InterloperEvaluator {
- var pe = self
- pe.statement_interloper = interloper
- return pe
- }
-
- public func getExpressionInterloper() -> ExpressionInterloper? {
- return self.expression_interloper
- }
-
- public func setExpressionInterloper(
- _ interloper: @escaping ExpressionInterloper
- ) -> InterloperEvaluator {
- var pe = self
- pe.expression_interloper = interloper
- return pe
- }
-
- public func ExecuteStatements(
- _ statements: [EvaluatableStatement], inExecution execution: ProgramExecution,
- _ handler: ExecuteStatementResultHandlerT?
- ) -> (ControlFlow, ProgramExecution) {
-
- var debugger: StatementInterloper? = .none
- var hasDebugInterloper = false
- if let found_deb = self.getStatementInterloper() {
- debugger = found_deb
- hasDebugInterloper = true
- }
-
- return CanonicalExecuteStatements(statements, inExecution: execution) { statement, execution in
- let (cf, value) = statement.evaluate(execution: execution)
-
- let (handled_cf, handled_value) =
- if let handler = handler {
- handler(cf, value)
- } else {
- (cf, value)
- }
- if hasDebugInterloper {
- debugger!(statement, handled_cf, handled_value)
- }
- return (handled_cf, handled_value)
- /*
- let (handled_cf, handled_value) =
- if let handler = handler {
- handler(cf, value)
- } else {
- (cf, value)
- }
-
- if hasDebugInterloper {
- debugger!(statement, handled_cf, handled_value)
- }
- */
- }
- }
-
- public func EvaluateExpression(
- _ expression: EvaluatableExpression, inExecution execution: ProgramExecution,
- ) -> (Result, ProgramExecution) {
-
- var debugger: ExpressionInterloper? = .none
- var hasDebugInterloper = false
- if let found_deb = self.getExpressionInterloper() {
- debugger = found_deb
- hasDebugInterloper = true
- }
-
- let (result, execution) = expression.evaluate(execution: execution)
-
- if hasDebugInterloper {
- debugger!(expression, result, execution)
- }
-
- return (result, execution)
-
- }
-}
-
-public typealias StatementInterloper = (EvaluatableStatement, ControlFlow, ProgramExecution) -> Void
-public typealias ExpressionInterloper = (EvaluatableExpression, Result, ProgramExecution)
- -> Void
-
-open class ProgramExecution: CustomStringConvertible {
- public var scopes: VarValueScopes = VarValueScopes()
- var globalValues: VarValueScopes?
- var error: (any Errorable)?
- var debug: DebugLevel = DebugLevel.Error
- public let evaluator: ProgramExecutionEvaluator
-
- init(copy: ProgramExecution) {
- self.scopes = copy.scopes
- self.globalValues = copy.globalValues
- self.error = copy.error
- self.debug = copy.debug
- self.evaluator = copy.evaluator
- }
-
- public init() {
- globalValues = .none
- evaluator = ClassicEvaluator()
- }
-
- public init(_ evaluator: ProgramExecutionEvaluator) {
- globalValues = .none
- self.evaluator = evaluator
- }
-
- open var description: String {
- return "Runtime:\nScopes: \(scopes)"
- }
-
- public func hasError() -> Bool {
- return self.error != nil
- }
-
- public func getError() -> (any Errorable)? {
- return self.error
- }
-
- public func setError(error: any Errorable) -> ProgramExecution {
- let npe = ProgramExecution(copy: self)
- npe.error = error
- return npe
- }
-
- public func getDebugLevel() -> DebugLevel {
- return self.debug
- }
-
- public func setDebugLevel(_ dl: DebugLevel) -> ProgramExecution {
- let pe = ProgramExecution(copy: self)
- pe.debug = dl
- return pe
- }
-
- open func isDone() -> Bool {
- return false
- }
-
- open func setDone() -> ProgramExecution {
- // For a bare ProgramExecution, setDone is a noop.
- return self
- }
-
- public func enter_scope() -> ProgramExecution {
- let new_pe = ProgramExecution(copy: self)
- new_pe.scopes = new_pe.scopes.enter()
-
- return new_pe
- }
-
- public func exit_scope() -> ProgramExecution {
- let new_pe = ProgramExecution(copy: self)
- new_pe.scopes = new_pe.scopes.exit()
-
- return new_pe
- }
-
- public func replaceScopes(_ new_scopes: VarValueScopes) -> ProgramExecution {
- let new_pe = ProgramExecution(copy: self)
- new_pe.scopes = new_scopes
- return new_pe
- }
-
- public func declare(identifier: Identifier, withValue value: P4Value) -> ProgramExecution {
- let new_pe = ProgramExecution(copy: self)
- let new_scopes = new_pe.scopes.declare(identifier: identifier, withValue: value)
-
- new_pe.scopes = new_scopes
- return new_pe
- }
-
- public func getGlobalValues() -> VarValueScopes {
- return self.globalValues ?? VarValueScopes()
- }
-
- public func setGlobalValues(_ global_values: VarValueScopes) -> ProgramExecution {
- let new_pe = ProgramExecution(copy: self)
- new_pe.globalValues = global_values
- return new_pe
- }
-
-}
-
-/// A scope that resolves variable identifiers to their values.
-public typealias VarValueScope = Scope
-
-/// Scopes that resolves variable identifiers to their values.
-public typealias VarValueScopes = Scopes
-
-/// A scope that resolves variable identifiers to their values.
-public typealias StaticVarValueScope = Scope<(P4QualifiedType, P4Value?)>
-
-/// Scopes that resolves variable identifiers to their values.
-public typealias StaticVarValueScopes = Scopes<(P4QualifiedType, P4Value?)>
-
-/// Indicate the control flow result of a particular statement.
-public enum ControlFlow {
- case Next
- case Continue
- case Break
- case Return(P4Value?)
- case Error
-}
diff --git a/Sources/Common/FFI.swift b/Sources/Common/FFI.swift
deleted file mode 100644
index 02c0f11..0000000
--- a/Sources/Common/FFI.swift
+++ /dev/null
@@ -1,22 +0,0 @@
-// 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 protocol P4FFI {
- func execute(execution: ProgramExecution) -> (ControlFlow, ProgramExecution)
- func type() -> P4QualifiedType
- func parameters() -> ParameterList
-}
diff --git a/Sources/Common/Protocols.swift b/Sources/Common/Protocols.swift
index dec209e..99209f6 100644
--- a/Sources/Common/Protocols.swift
+++ b/Sources/Common/Protocols.swift
@@ -58,67 +58,13 @@ public protocol Formattable {
}
public protocol P4Statement {
- /// Evaluate a statement for a given execution
- /// - Parameters
- /// - execution: The execution context in which to evaluate the parser statement
- /// - Returns: A tuple of
- /// 1. Whether this statement affects control flow.
- /// 2. An updated execution after evaluating the parser statement
- func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution)
-
- func effect(context: CompilerContext) -> CompilerContext
}
public protocol P4Expression {
- func effect(context: CompilerContext) -> CompilerContext
- func type() -> P4QualifiedType
- /// Evaluate an expression for a given execution
- /// - Parameters
- /// - execution: The execution context in which to evaluate the expression
- /// - Returns: The value of expression
- func evaluate(execution: ProgramExecution) -> (Result, ProgramExecution)
}
extension P4Expression {
- func effect(context: CompilerContext) -> CompilerContext {
- return context
- }
}
-public protocol P4LValueExpression {
- func effect(context: CompilerContext) -> CompilerContext
- func type() -> P4QualifiedType
- func check(to: P4Expression, inScopes scopes: StaticVarValueScopes) -> Result<()>
- func set(
- to: P4Value, inScopes scopes: VarValueScopes, duringExecution execution: ProgramExecution
- ) -> Result<(VarValueScopes, P4Value)>
-
-}
-
-/// TODO: Only generate these after going through the codegen!
-public typealias EvaluatableStatement = P4Statement
-public typealias EvaluatableLValueExpression = P4LValueExpression
-public typealias EvaluatableExpression = P4Expression
-
-public protocol ProgramExecutionEvaluator {
- func ExecuteStatements(
- _ statements: [EvaluatableStatement], inExecution execution: ProgramExecution,
- _ handler: ExecuteStatementResultHandlerT?
- ) -> (ControlFlow, ProgramExecution)
-
- func ExecuteStatements(
- _ statements: [EvaluatableStatement], inExecution execution: ProgramExecution
- ) -> (ControlFlow, ProgramExecution)
-
- func EvaluateExpression(
- _ expression: EvaluatableExpression, inExecution execution: ProgramExecution,
- ) -> (Result, ProgramExecution)
-}
-
-extension ProgramExecutionEvaluator {
- public func ExecuteStatements(
- _ statements: [EvaluatableStatement], inExecution execution: ProgramExecution
- ) -> (ControlFlow, ProgramExecution) {
- return ExecuteStatements(statements, inExecution: execution, .none)
- }
+extension P4Expression {
}
diff --git a/Sources/Macros/Macros.swift b/Sources/Macros/Macros.swift
index 0382fb6..b8a4ef3 100644
--- a/Sources/Macros/Macros.swift
+++ b/Sources/Macros/Macros.swift
@@ -448,8 +448,8 @@ public enum DeriveCompilableStatement: MemberMacro {
let implementation = DeclSyntax(
"""
public static func CompileStatement(
- node: Node, withContext context: CompilerContext
- ) -> Result {
+ node: Node, withContext context: ASTCompilerContext
+ ) -> Result {
return switch Compile(node: node, withContext: context) {
case .Ok(let res): .Ok(res)
case .Error(let e): .Error(e)
diff --git a/Sources/P4CodeGen/Serializer.swift b/Sources/P4CodeGen/Serializer.swift
new file mode 100644
index 0000000..ec82e7c
--- /dev/null
+++ b/Sources/P4CodeGen/Serializer.swift
@@ -0,0 +1,95 @@
+// 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 .
+
+import Common
+import P4Compiler
+
+public struct TextSerializer {
+ public init() {}
+}
+
+public struct TextSerializerContext {
+ public let serialized: String
+
+ public init(_ serialized: String = "") {
+ self.serialized = serialized
+ }
+
+ public func append(_ a: String) -> TextSerializerContext {
+ return TextSerializerContext(self.serialized + a)
+ }
+}
+
+extension TextSerializer: ASTVisitor {
+ public func visit(
+ node: P4Compiler.AST.BinaryOperatorExpression, driver: P4Compiler.ASTVisitorDriver,
+ context: TextSerializerContext
+ ) -> Common.Result {
+ return .Ok(context.append("Binary Operator Expression"))
+
+ }
+
+ public func visit(
+ node: P4Compiler.AST.Literal, driver: P4Compiler.ASTVisitorDriver,
+ context: TextSerializerContext
+ ) -> Common.Result {
+ return .Ok(context.append("Literal Expression"))
+ }
+
+ public func visit(
+ node: P4Compiler.AST.Identifier, driver: P4Compiler.ASTVisitorDriver,
+ context: TextSerializerContext
+ ) -> Common.Result {
+ return .Ok(context.append("Identifier Expression"))
+ }
+
+ public func visit(
+ node: P4Compiler.AST.Parser, driver: P4Compiler.ASTVisitorDriver, context: TextSerializerContext
+ ) -> Common.Result {
+ var context = context.append("Identifier Expression")
+ for s in node.states.states {
+ switch driver.visit(state: s, visitor: self, context: context) {
+ case .Ok(let c): context = c
+ case .Error(let e): return .Error(e)
+ }
+ }
+
+ return .Ok(context)
+ }
+
+ public func visit(
+ node: P4Compiler.AST.ParserStateDirectTransition, driver: P4Compiler.ASTVisitorDriver,
+ context: TextSerializerContext
+ ) -> Common.Result {
+ return .Ok(context.append("State: Direct Transition"))
+ }
+
+ public func visit(
+ node: P4Compiler.AST.ParserStateNoTransition, driver: P4Compiler.ASTVisitorDriver,
+ context: TextSerializerContext
+ ) -> Common.Result {
+ return .Ok(context.append("State: No Transition"))
+ }
+
+ public func visit(
+ node: P4Compiler.AST.ParserStateSelectTransition, driver: P4Compiler.ASTVisitorDriver,
+ context: TextSerializerContext
+ ) -> Common.Result {
+ return .Ok(context.append("State: Direct Transition"))
+ }
+
+}
diff --git a/Sources/P4Compiler/AST.swift b/Sources/P4Compiler/AST.swift
new file mode 100644
index 0000000..8b3f94f
--- /dev/null
+++ b/Sources/P4Compiler/AST.swift
@@ -0,0 +1,665 @@
+// 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 .
+
+import Common
+
+extension P4Value: AST.AnExpression {}
+
+public struct AST {
+
+ public protocol AnExpression {}
+ public protocol AnStatement {}
+ public protocol AnState {}
+
+ public struct Statement {}
+ struct Expression {}
+
+ public struct VariableDeclarationStatement: AnStatement {
+ public var initializer: AnExpression?
+ public var identifier: AST.Identifier
+ public var tipe: AST.Tipe
+
+ public init(
+ identifier: Identifier, withType tipe: AST.Tipe, withInitializer initializer: AnExpression?
+ ) {
+ self.identifier = identifier
+ self.initializer = initializer
+ self.tipe = tipe
+ }
+ }
+
+ public struct ConditionalStatement: AnStatement {
+ public var condition: AnExpression
+ public var thenn: AnStatement
+ public var elss: AnStatement?
+
+ public init(condition: AnExpression, withThen thenn: AnStatement) {
+ self.condition = condition
+ self.thenn = thenn
+ self.elss = .none
+ }
+
+ public init(
+ condition: AnExpression, withThen thenn: AnStatement,
+ andElse elss: AnStatement
+ ) {
+ self.condition = condition
+ self.thenn = thenn
+ self.elss = elss
+ }
+ }
+
+ public struct BlockStatement: AnStatement {
+ public var statements: [AnStatement]
+
+ public init(_ statements: [AnStatement]) {
+ self.statements = statements
+ }
+
+ }
+
+ public struct ReturnStatement: AnStatement {
+ public let value: AnExpression
+
+ public init(_ value: AnExpression) {
+ self.value = value
+ }
+ }
+
+ public struct ApplyStatement: AnStatement {
+ public let body: AST.BlockStatement?
+
+ public init() { self.body = .none }
+ public init(_ body: AST.BlockStatement) {
+ self.body = body
+ }
+ }
+
+ public struct Action: CustomStringConvertible {
+ public var description: String {
+ return "Action: "
+ + "\(self.name) with parameters \(self.params) and body \(String(describing: self.body))"
+ }
+
+ public var body: AST.BlockStatement?
+ public var params: AST.ParameterList
+ public var name: AST.Identifier
+
+ public init(
+ named name: AST.Identifier = AST.Identifier(Common.Identifier(name: "")),
+ withParameters parameters: ParameterList = ParameterList([]),
+ withBody body: AST.BlockStatement? = .none
+ ) {
+ self.name = name
+ self.params = parameters
+ self.body = body
+ }
+
+ }
+
+ public struct Actions: CustomStringConvertible {
+ public let actions: [AST.Action]
+ public init(withActions actions: [AST.Action]) {
+ self.actions = actions
+ }
+
+ public var description: String {
+ return "Actions: "
+ + actions.map { action in
+ return "\(action)"
+ }.joined(separator: ";")
+ }
+ }
+
+ public enum TableKeyMatchType {
+ case Exact
+ }
+
+ public struct TableKeyEntry: CustomStringConvertible {
+ public let key: AST.KeysetExpression
+ public let match_type: AST.TableKeyMatchType
+
+ public init(_ key: AST.KeysetExpression, _ match: AST.TableKeyMatchType) {
+ self.key = key
+ self.match_type = match
+ }
+
+ public var description: String {
+ return "Table Key Entry: " + "\(self.key): \(self.match_type)"
+ }
+ }
+
+ public struct TableKeys: CustomStringConvertible {
+ public let keys: [AST.TableKeyEntry]
+
+ public init(withEntries entries: [AST.TableKeyEntry]) {
+ self.keys = entries
+ }
+ public init() {
+ self.keys = []
+ }
+
+ public var description: String {
+ return "Table Keys: "
+ + self.keys.map { key in
+ return "\(key)"
+ }.joined(separator: ";")
+ }
+ }
+
+ public struct TableActionsProperty: CustomStringConvertible {
+ public let actions: [AST.Identifier]
+ public init(_ actions: [AST.Identifier] = []) {
+ self.actions = actions
+ }
+
+ public var description: String {
+ return "Table Actions: "
+ + self.actions.map { action in
+ return "\(action)"
+ }.joined(separator: ";")
+ }
+ }
+
+ public struct TablePropertyList: CustomStringConvertible {
+ public let actions: AST.TableActionsProperty
+ public let keys: AST.TableKeys
+ public init(withActions actions: AST.TableActionsProperty, withKeys keys: AST.TableKeys) {
+ self.actions = actions
+ self.keys = keys
+ }
+
+ public var description: String {
+ return "Table Property List: \(self.actions) \(self.keys)"
+ }
+ }
+
+ public struct Table: CustomStringConvertible {
+ public let properties: AST.TablePropertyList
+ let name: AST.Identifier
+ public let entries: [(P4Value, AST.Identifier)]
+
+ public init(
+ withName name: AST.Identifier, withPropertyList property_list: AST.TablePropertyList,
+ withEntries entries: [(P4Value, AST.Identifier)] = []
+ ) {
+ self.name = name
+ self.properties = property_list
+ self.entries = entries
+ }
+
+ public var description: String {
+ return "Table named: \(self.name) \(self.properties)"
+ }
+
+ /// When the control is evaluated, the value of the x in the table is
+ /// compared to the entries and the match is assocated with an action
+ /// that is invoked when the match occurs!
+
+ public func update(addEntry entry: (P4Value, AST.Identifier)) -> Table {
+ return Table(
+ withName: self.name, withPropertyList: self.properties, withEntries: self.entries + [entry])
+ }
+ }
+
+ public protocol AnDeclaration: AnStatement {}
+
+ public struct Declaration {}
+
+ public struct Control: CustomStringConvertible, AnDeclaration {
+ public var description: String {
+ return "Control named \(self._name) \(self.parameters) \(self.actions) \(self.table)"
+ }
+
+ public let actions: AST.Actions
+ public let table: AST.Table
+ let _parameters: AST.ParameterList
+ let _name: AST.Identifier
+ let apply: AST.ApplyStatement
+
+ public var parameters: AST.ParameterList {
+ _parameters
+ }
+
+ public var name: AST.Identifier {
+ _name
+ }
+
+ public init(
+ named: AST.Identifier, withParameters parameters: AST.ParameterList,
+ withTable table: AST.Table,
+ withActions actions: AST.Actions, withApply apply: AST.ApplyStatement
+ ) {
+ self._name = named
+ self._parameters = parameters
+ self.actions = actions
+ self.table = table
+ self.apply = apply
+ }
+
+ public func updateTable(addEntry entry: (P4Value, AST.Identifier)) -> Control {
+ let table = self.table.update(addEntry: entry)
+
+ return Control(
+ named: self.name, withParameters: self.parameters, withTable: table,
+ withActions: self.actions, withApply: self.apply)
+ }
+
+ public func def() -> P4DataValue? {
+ return .none
+ }
+
+ }
+
+ public struct ExternDeclaration: AnDeclaration {
+ public let declaration: AST.AnDeclaration
+
+ public init(_ declaration: AST.AnDeclaration) {
+ self.declaration = declaration
+ }
+ }
+
+ public struct FunctionDeclaration: AnDeclaration {
+ public var description: String {
+ return "Function named \(self.name) that returns \(self.tipe) with parameters \(self.params)"
+ }
+
+ public var body: AST.BlockStatement?
+ public var params: AST.ParameterList
+ public var name: AST.Identifier
+ public var tipe: AST.Tipe
+
+ public init(
+ named name: AST.Identifier, ofType type: AST.Tipe,
+ withParameters parameters: AST.ParameterList,
+ withBody body: AST.BlockStatement?
+ ) {
+ self.name = name
+ self.tipe = type
+ self.params = parameters
+ self.body = body
+ }
+ }
+
+ public struct StructDeclaration: AnDeclaration {
+ public let fields: [AST.VariableDeclarationStatement]
+ public let identifier: AST.Identifier
+ public init(_ id: AST.Identifier, _ fields: [AST.VariableDeclarationStatement]) {
+ self.identifier = id
+ self.fields = fields
+ }
+ }
+
+ public struct Instantiation: AnStatement {
+ public let name: AST.Identifier
+ public var tipe: AST.Identifier
+ public let arguments: AST.ArgumentList
+
+ public init(named name: AST.Identifier, withType tipe: AST.Identifier, withArguments arguments: AST.ArgumentList) {
+ self.name = name
+ self.arguments = arguments
+ self.tipe = tipe
+ }
+ }
+
+ public struct ExpressionStatement: AnStatement {
+ public let expression: AnExpression
+
+ public init(_ expr: AnExpression) {
+ self.expression = expr
+ }
+ }
+
+ public struct Identifier: AnExpression {
+ public let id: Common.Identifier
+ public init(_ id: Common.Identifier) {
+ self.id = id
+ }
+ }
+
+ public struct Literal: AnExpression {
+ public let literal: P4Value
+ public init(_ literal: P4Value) {
+ self.literal = literal
+ }
+ }
+
+ public enum KeysetExpression: AnExpression {
+ case Default
+ case Value(AnExpression)
+ }
+
+ public struct SelectCaseExpression: AnExpression {
+ public let key: AST.KeysetExpression
+ public let next_state_identifier: AST.Identifier
+
+ public init(withKey key: AST.KeysetExpression, withNextState next_state_id: AST.Identifier) {
+ self.key = key
+ self.next_state_identifier = next_state_id
+ }
+ }
+
+ public struct SelectExpression: AnExpression {
+ public let selector: AnExpression
+ public let case_expressions: [AST.SelectCaseExpression]
+
+ public init(
+ withSelector selector: AnExpression,
+ withSelectCaseExpressions sces: [AST.SelectCaseExpression]
+ ) {
+ self.selector = selector
+ self.case_expressions = sces
+ }
+
+ public func append_checked_sce(sce: AST.SelectCaseExpression) -> AST.SelectExpression {
+ var new_cses = self.case_expressions
+ new_cses.append(sce)
+ return SelectExpression(
+ withSelector: self.selector, withSelectCaseExpressions: new_cses)
+ }
+ }
+
+ public enum BinaryOperatorExpressionType {
+ case Add
+ case Subtract
+ case Multiply
+ case Divide
+ case Lt
+ case Lte
+ case Gt
+ case Gte
+ case Eq
+ case And
+ case Or
+ }
+
+ public struct BinaryOperatorExpression: AnExpression {
+ public let left: AnExpression
+ public let right: AnExpression
+ public let type: BinaryOperatorExpressionType
+
+ public init(
+ withType tipe: BinaryOperatorExpressionType,
+ withLhs lhs: AnExpression,
+ withRhs rhs: AnExpression
+ ) {
+ self.type = tipe
+ self.left = lhs
+ self.right = rhs
+ }
+ }
+
+ public struct ArrayAccessExpression: AnExpression {
+ public let indexor: AnExpression
+ public let name: AnExpression
+
+ public init(
+ withName name: AnExpression,
+ withIndexor indexor: AnExpression
+ ) {
+ self.name = name
+ self.indexor = indexor
+ }
+ }
+
+ public struct FieldAccessExpression: AnExpression {
+ public let field: Identifier
+ public let strct: AnExpression
+
+ public init(withStruct strct: AnExpression, withField field: Identifier) {
+ self.strct = strct
+ self.field = field
+ }
+ }
+
+ public struct FunctionCall: AnExpression {
+ public let callee: Identifier
+ public let arguments: ArgumentList
+
+ public init(_ callee: Identifier, withArguments arguments: ArgumentList) {
+ self.callee = callee
+ self.arguments = arguments
+ }
+ }
+
+ public struct LocalElements {}
+
+ public struct LocalElement {}
+
+ public struct ParserAssignmentStatement: AnStatement {
+ public let lvalue: AnExpression
+ public let value: AnExpression
+
+ public init(
+ withLValue lvalue: AnExpression, withValue value: AnExpression
+ ) {
+ self.lvalue = lvalue
+ self.value = value
+ }
+ }
+
+ /// A P4 Parser State
+ public class ParserState {
+ let name: Identifier
+ public let statements: [AnStatement]
+
+ public var description: String {
+ return "Parser State named \(self.name)"
+ }
+
+ public func getName() -> Identifier {
+ return self.name
+ }
+
+ public func getStatements() -> [AnStatement] {
+ return self.statements
+ }
+
+ /// Construct a ParserState
+ public init(_ name: Identifier, _ statements: [AnStatement] = Array()) {
+ self.name = name
+ self.statements = statements
+ }
+ }
+
+ /// TransitionStatement
+ ///
+ /// Only defined to define Compilable extension.
+ public struct TransitionStatement {}
+
+ public class ParserStateDirectTransition: ParserState, AnState {
+ public let next_state_identifier: Identifier?
+
+ public init(
+ name: Identifier, withNextStateIdentifier next_state_id: Identifier,
+ withStatements stmts: [AnStatement] = Array(),
+ ) {
+ self.next_state_identifier = next_state_id
+ super.init(name, stmts)
+ }
+ }
+
+ public class ParserStateNoTransition: ParserState, AnState {
+ /// Construct a ParserState
+ public init(
+ name: Identifier, withStatements stmts: [AnStatement] = Array(),
+ ) {
+ super.init(name, stmts)
+ }
+ }
+
+ public class ParserStateSelectTransition: ParserState, AnState {
+
+ public let te: SelectExpression
+
+ public init(
+ name: Identifier, withTransitionExpression te: SelectExpression,
+ withStatements stmts: [AnStatement] = Array()
+ ) {
+ self.te = te
+ super.init(name, stmts)
+ }
+ }
+
+ public struct ParserStates {
+ public var states: [AnState] = Array()
+
+ public func count() -> Int {
+ return states.count
+ }
+
+ public init(_ states: [AnState] = Array()) {
+ self.states = states
+ }
+
+ public func append(state: AnState) -> ParserStates {
+ var new_states = self.states
+ new_states.append(state)
+ return ParserStates(new_states)
+ }
+ }
+
+ /// A P4 Parser
+ ///
+ /// Note: A Parser is a type
+ public struct Parser: AnDeclaration {
+ public var states: ParserStates
+
+ public var name: Identifier
+ public var parameters: ParameterList
+
+ public init(withName name: Identifier) {
+ self.states = ParserStates()
+ self.parameters = ParameterList()
+ self.name = name
+ }
+
+ public init(withName name: Identifier, withParameters parameters: ParameterList) {
+ self.states = ParserStates()
+ self.parameters = parameters
+ self.name = name
+ }
+
+ public var description: String {
+ return "Parser \(self.name) with parameters: \(parameters) and states: \(self.states)"
+ }
+ }
+
+ public struct Types {}
+
+ public struct Tipe {
+ public let tipe: P4QualifiedType
+ public init(_ tipe: P4QualifiedType) {
+ self.tipe = tipe
+ }
+ }
+
+ public struct Parameter: CustomStringConvertible {
+ public var name: AST.Identifier
+ public var type: AST.Tipe
+
+ public init(
+ identifier: Identifier, withType type: AST.Tipe
+ ) {
+ self.name = identifier
+ self.type = type
+ }
+
+ public var description: String {
+ return "Parameter: \(self.name) with type \(self.type)"
+ }
+
+ }
+
+ public struct ParameterList: CustomStringConvertible {
+ public var parameters: [AST.Parameter]
+
+ public init() {
+ self.parameters = Array()
+ }
+
+ public init(_ parameters: [AST.Parameter]) {
+ self.parameters = parameters
+ }
+
+ public func addParameter(_ parameter: AST.Parameter) -> AST.ParameterList {
+ return AST.ParameterList(self.parameters + [parameter])
+ }
+
+ public var description: String {
+ let parameters = self.parameters.map { parameter in
+ parameter.description
+ }.joined(separator: ";")
+ return "Parameter list: \(parameters)"
+ }
+ }
+
+ public struct ArgumentList {
+ public let arguments: [AST.Argument]
+
+ public init(_ arguments: [AST.Argument] = []) {
+ self.arguments = arguments
+ }
+
+ public func addArgument(_ argument: AST.Argument) -> AST.ArgumentList {
+ return ArgumentList(self.arguments + [argument])
+ }
+ }
+
+ public struct Argument {
+ public let index: Int
+ public let argument: AST.AnExpression
+
+ public init(_ argument: AST.AnExpression, atIndex index: Int) {
+ self.argument = argument
+ self.index = index
+ }
+ }
+
+ public struct Program {
+ public var statements: [AnStatement]
+ public init(_ stmts: [AnStatement] = Array()) {
+ self.statements = stmts
+ }
+ }
+}
+
+public struct ASTCompilerContext {
+ public let lexical_context_name: AST.Identifier?
+ public let lexical_context_statements: [AST.AnStatement]?
+ public let extern_context: Bool
+
+ public init(_ name: AST.Identifier? = .none, _ stmts: [AST.AnStatement]? = .none, _ extern: Bool = false) {
+ self.lexical_context_name = name
+ self.lexical_context_statements = stmts
+ self.extern_context = extern
+ }
+
+ public func update(withContextName cn: AST.Identifier?) -> ASTCompilerContext {
+ return ASTCompilerContext(cn, self.lexical_context_statements, self.extern_context)
+ }
+
+ public func update(withContextStatements stmts: [AST.AnStatement]?) -> ASTCompilerContext {
+ return ASTCompilerContext(self.lexical_context_name, stmts, self.extern_context)
+ }
+
+ public func update(withExtern extern: Bool) -> ASTCompilerContext {
+ return ASTCompilerContext(self.lexical_context_name, self.lexical_context_statements, extern)
+ }
+}
+
+
diff --git a/Sources/P4Compiler/Common.swift b/Sources/P4Compiler/Common.swift
index 0c2d2cb..b7df1f5 100644
--- a/Sources/P4Compiler/Common.swift
+++ b/Sources/P4Compiler/Common.swift
@@ -16,369 +16,10 @@
// along with this program. If not, see .
import Common
-import P4Lang
-import P4Runtime
import SwiftTreeSitter
import TreeSitterExtensions
import TreeSitterP4
-func parameter_list_compiler(
- node: SwiftTreeSitter.Node, withContext context: CompilerContext
-) -> Common.Result {
-
- var walker = Walker(node: node)
- var current_node: Node? = .none
-
- if node.text == ")" {
- // There are no parameters!
- return Result.Ok(ParameterList([]))
- }
-
- #RequireNodeType(
- node: node, type: "parameter_list", nice_type_name: "Parameter List")
-
- var parameters: ParameterList = ParameterList([])
-
- #MustOr(
- result: current_node, thing: walker.getNext(),
- or: Result.Error(
- ErrorWithLocation(
- sourceLocation: node.toSourceLocation(), withError: "Missing parameter list component")))
-
- if current_node?.nodeType == "parameter_list" {
- switch parameter_list_compiler(node: current_node!, withContext: context) {
- case .Ok(let ps):
- parameters = ps
- case .Error(let e): return Result.Error(e)
- }
- walker.next()
- }
-
- #MustOr(
- result: current_node, thing: walker.getNext(),
- or: Result.Error(
- ErrorWithLocation(
- sourceLocation: node.toSourceLocation(), withError: "Missing parameter list component")))
-
- // If this is a ')', we are done.
- if current_node?.text == ")" {
- return Result.Ok(parameters)
- }
-
- // If this is a comma, we skip it!
- if current_node?.text == "," {
- walker.next()
- }
-
- #MustOr(
- result: current_node, thing: walker.getNext(),
- or: Result.Error(
- ErrorWithLocation(
- sourceLocation: node.toSourceLocation(), withError: "Missing parameter list component")))
-
- // Otherwise, there should be one parameter left!
- switch Parameter.Compile(node: current_node!, withContext: context) {
- case .Ok(let parsed_parameter):
- return Result.Ok(parameters.addParameter(parsed_parameter))
- case .Error(let e): return Result.Error(e)
- }
-}
-
-extension ParameterList: Compilable {
- public typealias C = ParameterList
- public static func Compile(
- node: SwiftTreeSitter.Node, withContext context: CompilerContext
- ) -> Common.Result {
-
- let parameter_node = node
- #RequireNodeType(
- node: parameter_node, type: "parameters", nice_type_name: "Parameters")
-
- var walker = Walker(node: parameter_node)
-
- var current_node: Node? = .none
-
- #MustOr(
- result: current_node, thing: walker.getNext(),
- or: Result.Error(
- ErrorWithLocation(
- sourceLocation: node.toSourceLocation(),
- withError: "Missing '(' in parameter list component")))
-
- walker.next()
- #MustOr(
- result: current_node, thing: walker.getNext(),
- or: Result.Error(
- ErrorWithLocation(
- sourceLocation: node.toSourceLocation(), withError: "Missing parameter list component")))
-
- return parameter_list_compiler(node: current_node!, withContext: context)
- }
-}
-
-extension Direction: Compilable {
- public typealias C = Direction
- public static func Compile(
- node: Node, withContext context: CompilerContext
- ) -> Result {
- let direction_node = node
- #RequireNodeType(
- node: direction_node, type: "direction", nice_type_name: "direction")
- let directions = [
- "in": Direction.In,
- "out": Direction.Out,
- "inout": Direction.InOut,
- ]
-
- guard let parsed_direction = directions[direction_node.text!] else {
- return .Error(
- ErrorWithLocation(
- sourceLocation: direction_node.toSourceLocation(),
- withError: "\(direction_node.text!) is not a valid direction"))
- }
-
- return .Ok(parsed_direction)
- }
-}
-
-extension Parameter: Compilable {
- public typealias C = Parameter
- public static func Compile(
- node: Node, withContext context: CompilerContext
- ) -> Result {
-
- #RequireNodeType(
- node: node, type: "parameter", nice_type_name: "parameter")
-
- var walker = Walker(node: node)
- var current_node: Node? = .none
-
- #MustOr(
- result: current_node, thing: walker.getNext(),
- or: Result.Error(
- ErrorWithLocation(
- sourceLocation: node.toSourceLocation(),
- withError: "Missing parameter declaration component")))
-
- // Annotation?
- if current_node!.nodeType == "annotations" {
- return .Error(
- ErrorWithLocation(
- sourceLocation: current_node!.toSourceLocation(),
- withError: "Annotations in parameter declarations are not yet handled"))
- // Will increment indexes here.
- }
-
- #MustOr(
- result: current_node, thing: walker.getNext(),
- or: Result.Error(
- ErrorWithLocation(
- sourceLocation: node.toSourceLocation(),
- withError: "Missing parameter declaration component")))
-
- var direction: Direction? = .none
- // Direction?
- if current_node!.nodeType == "direction" {
-
- let maybe_parsed_direction = Direction.Compile(node: current_node!, withContext: context)
- guard case .Ok(let parsed_direction) = maybe_parsed_direction else {
- return .Error(maybe_parsed_direction.error()!)
- }
- direction = parsed_direction
-
- walker.next()
- }
-
- #MustOr(
- result: current_node, thing: walker.getNext(),
- or: Result.Error(
- ErrorWithLocation(
- sourceLocation: node.toSourceLocation(),
- withError: "Missing parameter declaration component")))
-
- if current_node!.nodeType != "typeRef" {
- return Result.Error(
- ErrorWithLocation(
- sourceLocation: node.toSourceLocation(),
- withError: "Did not find type name for parameter declaration"))
- }
-
- guard
- case .Ok(let parameter_type) = Types.CompileType(type: current_node!, withContext: context)
- else {
- return Result.Error(
- Error(withMessage: "Could not parse a P4 type from \(current_node!.text!)"))
- }
-
- walker.next()
- #MustOr(
- result: current_node, thing: walker.getNext(),
- or: Result.Error(
- ErrorWithLocation(
- sourceLocation: node.toSourceLocation(),
- withError: "Missing parameter declaration component")))
-
- if current_node!.nodeType != "identifier" {
- return Result.Error(
- ErrorWithLocation(
- sourceLocation: node.toSourceLocation(),
- withError: "Did not find identifier for parameter statement"))
- }
-
- guard
- case .Ok(let parameter_name) = Identifier.Compile(node: current_node!, withContext: context)
- else {
- return Result.Error(
- Error(withMessage: "Could not parse a parameter name from \(current_node!.text!)"))
- }
-
- return Result.Ok(
- Parameter(
- identifier: parameter_name,
- withType: direction != nil
- ? parameter_type.update(addAttribute: P4TypeQualifier.Direction(direction!))
- : parameter_type),
- )
- }
-}
-
-func argument_list_compiler(
- node: SwiftTreeSitter.Node, withContext context: CompilerContext
-) -> Common.Result {
-
- var walker = Walker(node: node)
- var current_node: Node? = .none
-
- if node.text == ")" {
- // There are no arguments!
- return Result.Ok(ArgumentList([]))
- }
-
- #RequireNodeType(
- node: node, type: "argument_list", nice_type_name: "argument List")
-
- var arguments: ArgumentList = ArgumentList([])
-
- #MustOr(
- result: current_node, thing: walker.getNext(),
- or: Result.Error(
- ErrorWithLocation(
- sourceLocation: node.toSourceLocation(), withError: "Missing argument list component")))
-
- if current_node?.nodeType == "argument_list" {
- switch argument_list_compiler(node: current_node!, withContext: context) {
- case .Ok(let ps):
- arguments = ps
- case .Error(let e): return Result.Error(e)
- }
-
- walker.next()
- }
-
- // We may have moved nodes, check/reset current_node.
- #MustOr(
- result: current_node, thing: walker.getNext(),
- or: Result.Error(
- ErrorWithLocation(
- sourceLocation: node.toSourceLocation(), withError: "Missing argument list component")))
-
- // If this is a ')', we are done.
- if current_node?.text == ")" {
- return Result.Ok(arguments)
- }
-
- // If this is a comma, we skip it!
- if current_node?.text == "," {
- walker.next()
- }
-
- #MustOr(
- result: current_node, thing: walker.getNext(),
- or: Result.Error(
- ErrorWithLocation(
- sourceLocation: node.toSourceLocation(), withError: "Missing argument list component")))
-
- // Otherwise, there should be one argument left!
- switch Argument.Compile(node: current_node!, withContext: context) {
- case .Ok(let ce):
- return Result.Ok(
- arguments.addArgument(Argument(ce, atIndex: arguments.count() + 1)))
- case .Error(let e): return Result.Error(e)
- }
-}
-
-extension ArgumentList: Compilable {
- public typealias C = ArgumentList
- public static func Compile(
- node: SwiftTreeSitter.Node, withContext context: CompilerContext
- ) -> Common.Result {
-
- let argument_node = node
- #RequireNodeType(
- node: argument_node, type: "arguments", nice_type_name: "arguments")
-
- var walker = Walker(node: argument_node)
- var current_node: Node? = .none
-
- #MustOr(
- result: current_node, thing: walker.getNext(),
- or: Result.Error(
- ErrorWithLocation(
- sourceLocation: node.toSourceLocation(),
- withError: "Missing '(' in argument list component")))
-
- walker.next()
-
- #MustOr(
- result: current_node, thing: walker.getNext(),
- or: Result.Error(
- ErrorWithLocation(
- sourceLocation: node.toSourceLocation(), withError: "Missing argument list component")))
-
- return argument_list_compiler(node: current_node!, withContext: context)
- }
-}
-
-extension Argument: Compilable {
- public typealias C = P4Expression
- public static func Compile(
- node: SwiftTreeSitter.Node, withContext context: CompilerContext
- ) -> Common.Result {
- let argument_node = node
- #RequireNodeType(
- node: argument_node, type: "argument", nice_type_name: "argument")
-
- let expression_node = node.child(at: 0)!
-
- return switch Expression.Compile(node: expression_node, withContext: context) {
- case .Ok(let compiled_expression): .Ok(compiled_expression)
- case .Error(let e): .Error(e)
- }
- }
-}
-
-func ContainsInvalidStatements(
- statement: P4Statement, invalids: [P4Statement.Type]
-) -> Bool {
- for es in invalids {
- if type(of: statement) == es {
- return true
- }
- }
- return false
-}
-
-func ContainsInvalidStatements(block: BlockStatement, invalids: [P4Statement.Type]) -> Bool {
- return block.statements.contains { statement in
- for es in invalids {
- if type(of: statement) == es {
- return true
- }
- }
- return false
- }
-}
-
extension Node {
public func toSourceLocation() -> SourceLocation {
return SourceLocation(self.range.location, self.range.length)
diff --git a/Sources/P4Compiler/Compiler.swift b/Sources/P4Compiler/Compiler.swift
index 6ce95d1..45b30cd 100644
--- a/Sources/P4Compiler/Compiler.swift
+++ b/Sources/P4Compiler/Compiler.swift
@@ -16,7 +16,6 @@
// along with this program. If not, see .
import Common
-import P4Runtime
import SwiftTreeSitter
import TreeSitterExtensions
import TreeSitterP4
diff --git a/Sources/P4Compiler/Declarations.swift b/Sources/P4Compiler/Declarations.swift
index 919c724..a81ee7c 100644
--- a/Sources/P4Compiler/Declarations.swift
+++ b/Sources/P4Compiler/Declarations.swift
@@ -16,28 +16,15 @@
// along with this program. If not, see .
import Common
-import P4Lang
-import P4Runtime
import SwiftTreeSitter
import TreeSitterExtensions
import TreeSitterP4
-extension Declaration: CompilableStatement {
- public static func CompileStatement(
- node: Node, withContext context: CompilerContext
- ) -> Result {
- return switch Compile(node: node, withContext: context) {
- case .Ok(let res): .Ok(res)
- case .Error(let e): .Error(e)
- }
- }
-}
-
-extension Declaration: Compilable {
- public typealias C = Declaration
+extension AST.Declaration: Compilable {
+ public typealias C = AST.AnDeclaration
public static func Compile(
- node: Node, withContext context: CompilerContext
- ) -> Result {
+ node: Node, withContext context: ASTCompilerContext
+ ) -> Result {
// Be kind to our user -- if we are at a declaration node, dive into it!
let declaration_node =
@@ -47,13 +34,13 @@ extension Declaration: Compilable {
node
}
- let declaration_compilers: [String: any Compilable.Type] = [
- "function_declaration": FunctionDeclaration.self,
- "control_declaration": Control.self,
- "type_declaration": P4Struct.self,
- "parserDeclaration": Parser.self,
+ let declaration_compilers: [String: any Compilable.Type] = [
+ "function_declaration": AST.FunctionDeclaration.self,
+ "control_declaration": AST.Control.self,
+ //"type_declaration": AST.P4Struct.self,
+ "parserDeclaration": AST.Parser.self,
/// ASSUME: Type declarations are struct declarations.
- "extern_declaration": ExternDeclaration.self,
+ "extern_declaration": AST.ExternDeclaration.self,
]
guard let declaration_compiler = declaration_compilers[declaration_node.nodeType!] else {
@@ -70,13 +57,16 @@ extension Declaration: Compilable {
}
}
-extension FunctionDeclaration: Compilable {
- public typealias C = Declaration
+@deriveCompilableStatement
+extension AST.Declaration: CompilableStatement {}
+
+extension AST.FunctionDeclaration: Compilable {
+ public typealias C = AST.AnDeclaration
public static func Compile(
- node: SwiftTreeSitter.Node, withContext context: CompilerContext
- ) -> Common.Result {
+ node: SwiftTreeSitter.Node, withContext context: ASTCompilerContext
+ ) -> Common.Result {
let function_declaration_node = node
- #RequireNodeType(
+ #RequireNodeType(
node: function_declaration_node, type: "function_declaration",
nice_type_name: "Function Declaration")
@@ -85,12 +75,12 @@ extension FunctionDeclaration: Compilable {
#MustOr(
result: current_node, thing: walker.getNext(),
- or: Result.Error(
+ or: Result.Error(
ErrorWithLocation(
sourceLocation: function_declaration_node.toSourceLocation(),
withError: "Missing function declaration component")))
- let maybe_function_type = Types.CompileType(type: current_node!, withContext: context)
+ let maybe_function_type = AST.Types.CompileType(type: current_node!, withContext: context)
guard case .Ok(let function_type) = maybe_function_type else {
return .Error(maybe_function_type.error()!)
}
@@ -98,12 +88,12 @@ extension FunctionDeclaration: Compilable {
walker.next()
#MustOr(
result: current_node, thing: walker.getNext(),
- or: Result.Error(
+ or: Result.Error(
ErrorWithLocation(
sourceLocation: function_declaration_node.toSourceLocation(),
withError: "Missing function declaration component")))
- let maybe_function_name = Identifier.Compile(node: current_node!, withContext: context)
+ let maybe_function_name = AST.Identifier.CompileExpression(node: current_node!, withContext: context)
guard case .Ok(let function_name) = maybe_function_name else {
return .Error(maybe_function_name.error()!)
}
@@ -111,32 +101,23 @@ extension FunctionDeclaration: Compilable {
walker.next()
#MustOr(
result: current_node, thing: walker.getNext(),
- or: Result.Error(
+ or: Result.Error(
ErrorWithLocation(
sourceLocation: function_declaration_node.toSourceLocation(),
withError: "Missing function declaration component")))
- let maybe_function_parameters = ParameterList.Compile(node: current_node!, withContext: context)
+ let maybe_function_parameters = AST.ParameterList.Compile(
+ node: current_node!, withContext: context)
guard case .Ok(let function_parameters) = maybe_function_parameters
else {
return .Error(maybe_function_parameters.error()!)
}
- var function_body: BlockStatement? = .none
+ var function_body: AST.BlockStatement? = .none
walker.next()
if let body = walker.getNext() {
- // Add the parameters into scope.
- var function_scope = context.instances.enter()
- for parameter in function_parameters.parameters {
- function_scope = function_scope.declare(
- identifier: parameter.name, withValue: (parameter.type, .none))
- }
-
- let maybe_function_body = BlockStatement.Compile(
- node: body,
- withContext: context.update(newInstances: function_scope).update(
- newExpectation: function_type))
+ let maybe_function_body = AST.BlockStatement.Compile(node: body, withContext: context)
guard case .Ok(let parsed_function_body) = maybe_function_body else {
return .Error(maybe_function_body.error()!)
@@ -154,13 +135,10 @@ extension FunctionDeclaration: Compilable {
}
}
- let function_declaration = Declaration(
- TypedIdentifier(
- id: function_name,
- withType: P4QualifiedType(
- FunctionDeclaration(
- named: function_name, ofType: function_type, withParameters: function_parameters,
- withBody: function_body))))
+ let function_declaration = AST.FunctionDeclaration(
+ named: function_name as! AST.Identifier, ofType: function_type,
+ withParameters: function_parameters,
+ withBody: function_body)
// Do not use the updated context returned by parsing the body
// and do not use the function_scope, either.
@@ -172,16 +150,16 @@ extension FunctionDeclaration: Compilable {
}
}
-extension P4Struct: Compilable {
- public typealias C = Declaration
+extension AST.StructDeclaration: Compilable {
+ public typealias C = AST.StructDeclaration
static public func Compile(
- node: Node, withContext context: CompilerContext
- ) -> Result {
+ node: Node, withContext context: ASTCompilerContext
+ ) -> Result {
let struct_declaration_node = node.child(at: 0)!
var walker = Walker(node: struct_declaration_node)
var currentNode: Node? = .none
- #RequireNodeType>(
+ #RequireNodeType>(
node: struct_declaration_node, type: "struct_declaration",
nice_type_name: "struct declaration")
@@ -189,13 +167,13 @@ extension P4Struct: Compilable {
walker.next()
#MustOr(
result: currentNode, thing: walker.getNext(),
- or: Result.Error(
+ or: Result.Error(
ErrorWithLocation(
sourceLocation: struct_declaration_node.toSourceLocation(),
withError: "Missing function declaration component")))
// The name of the struct type.
- let maybe_struct_identifier = Identifier.Compile(
+ let maybe_struct_identifier = AST.Identifier.CompileExpression(
node: currentNode!, withContext: context)
guard case Result.Ok(let struct_identifier) = maybe_struct_identifier else {
return Result.Error(maybe_struct_identifier.error()!)
@@ -206,34 +184,27 @@ extension P4Struct: Compilable {
walker.next()
#MustOr(
result: currentNode, thing: walker.getNext(),
- or: Result.Error(
+ or: Result.Error(
ErrorWithLocation(
sourceLocation: struct_declaration_node.toSourceLocation(),
withError: "Missing function declaration component")))
// If there are no fields, it will be a "}"
if currentNode!.nodeType == "}" {
- let struc = Declaration(
- TypedIdentifier(
- id: struct_identifier,
- withType: P4QualifiedType(
- P4Struct(withName: struct_identifier, andFields: P4StructFields([])))))
+ let struc = AST.StructDeclaration(struct_identifier as! AST.Identifier, [])
return Result.Ok(struc)
}
var parse_errs: (any Errorable)? = .none
- var parsed_fields: [P4StructFieldIdentifier] = Array()
+ var parsed_fields: [AST.VariableDeclarationStatement] = Array()
if currentNode!.nodeType == "struct_declaration_fields" {
currentNode!.enumerateNamedChildren { declaration_field in
- switch VariableDeclarationStatement.Compile(
+ switch AST.VariableDeclarationStatement.Compile(
node: declaration_field, withContext: context)
{
case .Ok(let variable_declaration):
- parsed_fields.append(
- P4StructFieldIdentifier(
- id: variable_declaration.identifier, withType: variable_declaration.initializer.type()
- ))
+ parsed_fields.append(variable_declaration)
case .Error(let e):
parse_errs =
if let e = parse_errs {
@@ -249,33 +220,25 @@ extension P4Struct: Compilable {
return .Error(ErrorWithLabel("Error(s) parsing select cases", parse_errs))
}
- let declared_struct = Declaration(
- TypedIdentifier(
- id: struct_identifier,
- withType: P4QualifiedType(
- P4Struct(
- withName: struct_identifier, andFields: P4StructFields(parsed_fields)))))
+ let declared_struct = AST.StructDeclaration(struct_identifier as! AST.Identifier, parsed_fields)
return .Ok(declared_struct)
}
}
-extension P4Lang.Parser: Compilable {
- public typealias C = Declaration
-
+extension AST.Parser: Compilable {
+ public typealias C = AST.AnDeclaration
public static func Compile(
- node: Node, withContext context: CompilerContext
- ) -> Result {
+ node: Node, withContext context: ASTCompilerContext
+ ) -> Result {
let parser_node = node
- #RequireNodeType>(
+ #RequireNodeType>(
node: parser_node, type: "parserDeclaration", nice_type_name: "parser declaration")
- var current_context = context
-
var walker = Walker(node: parser_node)
var current_node: Node? = .none
#MustOr(
result: current_node, thing: walker.getNext(),
- or: Result.Error(
+ or: Result.Error(
ErrorWithLocation(
sourceLocation: parser_node.toSourceLocation(),
withError: "Missing elements of parser declaration")))
@@ -288,10 +251,10 @@ extension P4Lang.Parser: Compilable {
}
let type_node = current_node
- var parser_name: Common.Identifier? = .none
+ var parser_name: AST.Identifier? = .none
/// TODO: Handle parser parameter lists.
- var parameter_list = ParameterList()
+ var parameter_list = AST.ParameterList()
do {
var type_node_walker = Walker(node: type_node!)
@@ -299,7 +262,7 @@ extension P4Lang.Parser: Compilable {
#MustOr(
result: type_node_child, thing: type_node_walker.getNext(),
- or: Result.Error(
+ or: Result.Error(
ErrorWithLocation(
sourceLocation: parser_node.toSourceLocation(),
withError: "Missing elements of parser type in parser declaration")))
@@ -315,13 +278,13 @@ extension P4Lang.Parser: Compilable {
type_node_walker.next()
#MustOr(
result: type_node_child, thing: type_node_walker.getNext(),
- or: Result.Error(
+ or: Result.Error(
ErrorWithLocation(
sourceLocation: type_node_child!.toSourceLocation(),
withError: "Missing name in parser type declaration")))
- switch Identifier.Compile(node: type_node_child!, withContext: current_context) {
- case .Ok(let id): parser_name = id
+ switch AST.Identifier.CompileExpression(node: type_node_child!, withContext: context) {
+ case .Ok(let id): parser_name = (id as! AST.Identifier)
case .Error(let e):
return .Error(e)
}
@@ -329,12 +292,12 @@ extension P4Lang.Parser: Compilable {
type_node_walker.next()
#MustOr(
result: type_node_child, thing: type_node_walker.getNext(),
- or: Result.Error(
+ or: Result.Error(
ErrorWithLocation(
sourceLocation: type_node_child!.toSourceLocation(),
withError: "Missing parser parameters")))
- switch ParameterList.Compile(node: type_node_child!, withContext: current_context) {
+ switch AST.ParameterList.Compile(node: type_node_child!, withContext: context) {
case .Ok(let parsed_parameter_list):
parameter_list = parsed_parameter_list
case .Error(let e):
@@ -342,17 +305,10 @@ extension P4Lang.Parser: Compilable {
}
}
- // Now, let's put the parameters into scope.
- for parameter in parameter_list.parameters {
- current_context = current_context.update(
- newInstances: current_context.instances.declare(
- identifier: parameter.name, withValue: (parameter.type, .none)))
- }
-
walker.next()
#MustOr(
result: current_node, thing: walker.getNext(),
- or: Result.Error(
+ or: Result.Error(
ErrorWithLocation(
sourceLocation: parser_node.toSourceLocation(),
withError: "Missing parser declaration component")))
@@ -360,7 +316,7 @@ extension P4Lang.Parser: Compilable {
walker.next()
#MustOr(
result: current_node, thing: walker.getNext(),
- or: Result.Error(
+ or: Result.Error(
ErrorWithLocation(
sourceLocation: parser_node.toSourceLocation(),
withError: "Missing elements of parser declaration")))
@@ -375,7 +331,7 @@ extension P4Lang.Parser: Compilable {
#MustOr(
result: current_node, thing: walker.getNext(),
- or: Result.Error(
+ or: Result.Error(
ErrorWithLocation(
sourceLocation: parser_node.toSourceLocation(),
withError: "Missing body of parser declaration")))
@@ -387,45 +343,37 @@ extension P4Lang.Parser: Compilable {
/// TODO: Handle extern parsers.
switch SpecialCompilers.CompileParserBody(
withName: parser_name!, withParameters: parameter_list, node: current_node!,
- withContext: current_context)
+ withContext: context)
{
- case Result.Ok(let parser):
- let parser_declaration = Declaration(
- TypedIdentifier(id: parser.name, withType: P4QualifiedType(parser)))
- // Create a new context with the name of the parser that was just compiled in scope.
- return .Ok(
- parser_declaration,
- )
+ case Result.Ok(let parser): return .Ok(parser)
case Result.Error(let error): return .Error(error)
}
}
}
-extension Control: Compilable {
- public typealias C = Declaration
+extension AST.Control: Compilable {
+ public typealias C = AST.AnDeclaration
public static func Compile(
- node: SwiftTreeSitter.Node, withContext context: CompilerContext
- ) -> Common.Result {
+ node: SwiftTreeSitter.Node, withContext context: ASTCompilerContext
+ ) -> Common.Result {
- #RequireNodeType>(
+ #RequireNodeType>(
node: node, type: "control_declaration", nice_type_name: "control declaration")
var walker = Walker(node: node)
var current_node: Node? = .none
- var local_context = context
-
walker.next()
#MustOr(
result: current_node, thing: walker.getNext(),
- or: Result.Error(
+ or: Result.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(),
withError: "Missing control declaration component")))
guard
- case .Ok(let control_name) = Identifier.Compile(
- node: current_node!, withContext: local_context)
+ case .Ok(let control_name) = AST.Identifier.CompileExpression(
+ node: current_node!, withContext: context)
else {
return Result.Error(
Error(withMessage: "Could not parse a parameter name from \(current_node!.text!)"))
@@ -434,60 +382,48 @@ extension Control: Compilable {
walker.next()
#MustOr(
result: current_node, thing: walker.getNext(),
- or: Result.Error(
+ or: Result.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(),
withError: "Missing control declaration component")))
- let maybe_control_parameters = ParameterList.Compile(
- node: current_node!, withContext: local_context)
+ let maybe_control_parameters = AST.ParameterList.Compile(
+ node: current_node!, withContext: context)
guard case .Ok(let control_parameters) = maybe_control_parameters
else {
return .Error(maybe_control_parameters.error()!)
}
- // Before continuing, make sure to put the parameters into context.
- var control_scope = local_context.instances.enter()
- for parameter in control_parameters.parameters {
- control_scope = control_scope.declare(
- identifier: parameter.name, withValue: (parameter.type, .none))
- }
- local_context = local_context.update(newInstances: control_scope)
-
walker.next()
// Skip the '{'
walker.next()
#MustOr(
result: current_node, thing: walker.getNext(),
- or: Result.Error(
+ or: Result.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(),
withError: "Missing control declaration component")))
- var actions: [Action] = Array()
- var tables: [Table] = Array()
- var apply: ApplyStatement? = .none
+ var actions: [AST.Action] = Array()
+ var tables: [AST.Table] = Array()
+ var apply: AST.ApplyStatement? = .none
// Because the final child
// is the '}'.
// \/\/
let body_parse_results = walker.overUntil(n: node.childCount - 1) { current_node in
if current_node.nodeType == "action_declaration" {
- let maybe_action_declaration = Action.Compile(
- node: current_node, withContext: local_context)
+ let maybe_action_declaration = AST.Action.Compile(
+ node: current_node, withContext: context)
guard
case .Ok(let action_declaration) = maybe_action_declaration
else {
return .Error(maybe_action_declaration.error()!)
}
actions.append(action_declaration)
- // Now, add the declaration into the context.
- local_context = local_context.update(
- newTypes: local_context.types.declare(
- identifier: action_declaration.name, withValue: action_declaration))
} else if current_node.nodeType == "table_declaration" {
- let maybe_table_declaration = Table.Compile(
- node: current_node, withContext: local_context)
+ let maybe_table_declaration = AST.Table.Compile(
+ node: current_node, withContext: context)
guard
case .Ok(let table_declaration) = maybe_table_declaration
else {
@@ -496,8 +432,8 @@ extension Control: Compilable {
tables.append(table_declaration)
} else if current_node.nodeType == "apply_statement" {
// When we see an apply, that is it for the actions and the tables.
- let maybe_apply_statement = ApplyStatement.Compile(
- node: current_node, withContext: local_context)
+ let maybe_apply_statement = AST.ApplyStatement.Compile(
+ node: current_node, withContext: context)
guard
case .Ok(let apply_statement) = maybe_apply_statement
else {
@@ -540,27 +476,17 @@ extension Control: Compilable {
))
}
- let control = Control(
- named: control_name, withParameters: control_parameters, withTable: tables[0],
- withActions: Actions(withActions: actions), withApply: apply)
-
- let declared_control =
- Declaration(
- TypedIdentifier(
- id: control_name,
- withType: P4QualifiedType(control)))
-
- // 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).
- return .Ok(declared_control)
+ return .Ok(AST.Control(
+ named: control_name as! AST.Identifier, withParameters: control_parameters, withTable: tables[0],
+ withActions: AST.Actions(withActions: actions), withApply: apply))
}
}
-extension Action: Compilable {
- public typealias C = Action
+extension AST.Action: Compilable {
+ public typealias C = AST.Action
public static func Compile(
- node: SwiftTreeSitter.Node, withContext context: CompilerContext
- ) -> Result {
+ node: SwiftTreeSitter.Node, withContext context: ASTCompilerContext
+ ) -> Result {
#RequireNodeType(
node: node, type: "action_declaration", nice_type_name: "Action Declaration")
@@ -572,14 +498,14 @@ extension Action: Compilable {
#MustOr(
result: current_node, thing: walker.getNext(),
- or: Result.Error(
+ or: Result.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(), withError: "Missing action declaration component"
))
)
guard
- case .Ok(let action_name) = Identifier.Compile(
+ case .Ok(let action_name) = AST.Identifier.CompileExpression(
node: current_node!, withContext: context)
else {
return Result.Error(
@@ -589,13 +515,13 @@ extension Action: Compilable {
walker.next()
#MustOr(
result: current_node, thing: walker.getNext(),
- or: Result.Error(
+ or: Result.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(), withError: "Missing action declaration component"
))
)
- let maybe_action_parameters = ParameterList.Compile(
+ let maybe_action_parameters = AST.ParameterList.Compile(
node: current_node!, withContext: context)
guard case .Ok(let action_parameters) = maybe_action_parameters
else {
@@ -604,9 +530,9 @@ extension Action: Compilable {
// Check whether the parameters are in the proper order.
let remaining_parameters = action_parameters.parameters.drop(while: {
- $0.type.direction() != .none
+ $0.type.tipe.direction() != .none
})
- if remaining_parameters.contains(where: { $0.type.direction() != .none }) {
+ if remaining_parameters.contains(where: { $0.type.tipe.direction() != .none }) {
return .Error(
ErrorWithLocation(
sourceLocation: current_node!.toSourceLocation(),
@@ -616,21 +542,14 @@ extension Action: Compilable {
walker.next()
#MustOr(
result: current_node, thing: walker.getNext(),
- or: Result.Error(
+ or: Result.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(), withError: "Missing action declaration component"
))
)
- // Add the parameters into scope.
- var function_scope = context.instances.enter()
- for parameter in action_parameters.parameters {
- function_scope = function_scope.declare(
- identifier: parameter.name, withValue: (parameter.type, .none))
- }
-
- let maybe_action_body = BlockStatement.Compile(
- node: current_node!, withContext: context.update(newInstances: function_scope))
+ let maybe_action_body = AST.BlockStatement.Compile(
+ node: current_node!, withContext: context)
guard case .Ok(let action_body) = maybe_action_body else {
return .Error(maybe_action_body.error()!)
}
@@ -638,19 +557,19 @@ extension Action: Compilable {
/// TODO: Actions cannot contain switches!
return .Ok(
- Action(
- named: action_name, withParameters: action_parameters,
+ AST.Action(
+ named: action_name as! AST.Identifier, withParameters: action_parameters,
withBody: action_body))
}
}
-extension TableKeyEntry: Compilable {
- public typealias C = TableKeyEntry
+extension AST.TableKeyEntry: Compilable {
+ public typealias C = AST.TableKeyEntry
public static func Compile(
- node: SwiftTreeSitter.Node, withContext context: CompilerContext
- ) -> Result {
+ node: SwiftTreeSitter.Node, withContext context: ASTCompilerContext
+ ) -> Result {
- #RequireNodeType(
+ #RequireNodeType(
node: node, type: "table_key_entry", nice_type_name: "Table Key Entry")
var walker = Walker(node: node)
@@ -659,12 +578,12 @@ extension TableKeyEntry: Compilable {
#MustOr(
result: current_node, thing: walker.getNext(),
- or: Result.Error(
+ or: Result.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(),
withError: "Missing table key entry declaration component")))
- let maybe_keyset_expression = KeysetExpression.compile(
+ let maybe_keyset_expression = AST.KeysetExpression.CompileExpression(
node: current_node!, withContext: context)
guard case .Ok(let keyset_expression) = maybe_keyset_expression else {
return Result.Error(maybe_keyset_expression.error()!)
@@ -675,31 +594,31 @@ extension TableKeyEntry: Compilable {
walker.next()
#MustOr(
result: current_node, thing: walker.getNext(),
- or: Result.Error(
+ or: Result.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(),
withError: "Missing table key entry declaration component")))
- let maybe_match_type = TableKeyMatchType.Compile(
+ let maybe_match_type = AST.TableKeyMatchType.Compile(
node: current_node!, withContext: context)
guard case .Ok(let match_type) = maybe_match_type else {
return .Error(maybe_match_type.error()!)
}
- return .Ok(TableKeyEntry(keyset_expression as! KeysetExpression, match_type))
+ return .Ok(AST.TableKeyEntry(keyset_expression as! AST.KeysetExpression, match_type))
}
}
-extension TableKeyMatchType: Compilable {
- public typealias C = TableKeyMatchType
+extension AST.TableKeyMatchType: Compilable {
+ public typealias C = AST.TableKeyMatchType
public static func Compile(
- node: SwiftTreeSitter.Node, withContext context: CompilerContext
- ) -> Result {
- #RequireNodeType(
+ node: SwiftTreeSitter.Node, withContext context: ASTCompilerContext
+ ) -> Result {
+ #RequireNodeType(
node: node, type: "table_key_match_type", nice_type_name: "Table Key Match Type")
if node.text! == "exact" {
- return .Ok(TableKeyMatchType.Exact)
+ return .Ok(AST.TableKeyMatchType.Exact)
}
return .Error(
ErrorWithLocation(
@@ -708,12 +627,12 @@ extension TableKeyMatchType: Compilable {
}
}
-extension TableKeys: Compilable {
- public typealias C = TableKeys
+extension AST.TableKeys: Compilable {
+ public typealias C = AST.TableKeys
public static func Compile(
- node: SwiftTreeSitter.Node, withContext context: CompilerContext
- ) -> Result {
- #RequireNodeType(
+ node: SwiftTreeSitter.Node, withContext context: ASTCompilerContext
+ ) -> Result {
+ #RequireNodeType(
node: node, type: "table_keys", nice_type_name: "Table Keys")
var walker = Walker(node: node)
@@ -728,14 +647,14 @@ extension TableKeys: Compilable {
#MustOr(
result: current_node, thing: walker.getNext(),
- or: Result.Error(
+ or: Result.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(),
withError: "Missing table keys declaration component in control declaration"))
)
let (keys, errors) = walker.try_map(n: node.childCount - 1, onlyNamed: true) { current_node in
- return switch TableKeyEntry.Compile(node: current_node, withContext: context) {
+ return switch AST.TableKeyEntry.Compile(node: current_node, withContext: context) {
case .Ok(let keyset_expression): .Ok(keyset_expression)
case .Error(let e): .Error(e)
}
@@ -751,16 +670,16 @@ extension TableKeys: Compilable {
}.joined(separator: ";"))))
}
- return .Ok(TableKeys(withEntries: keys))
+ return .Ok(AST.TableKeys(withEntries: keys))
}
}
-extension TableActionsProperty: Compilable {
- public typealias C = TableActionsProperty
+extension AST.TableActionsProperty: Compilable {
+ public typealias C = AST.TableActionsProperty
public static func Compile(
- node: SwiftTreeSitter.Node, withContext context: CompilerContext
- ) -> Result {
- #RequireNodeType(
+ node: SwiftTreeSitter.Node, withContext context: ASTCompilerContext
+ ) -> Result {
+ #RequireNodeType(
node: node, type: "table_actions", nice_type_name: "Table Actions")
var walker = Walker(node: node)
@@ -775,7 +694,7 @@ extension TableActionsProperty: Compilable {
#MustOr(
result: current_node, thing: walker.getNext(),
- or: Result.Error(
+ or: Result.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(),
withError: "Missing table actions declaration component in control declaration"))
@@ -783,19 +702,9 @@ extension TableActionsProperty: Compilable {
let (actions, errors) = walker.try_map(n: node.childCount - 1, onlyNamed: true) {
current_node in
- switch Identifier.Compile(node: current_node, withContext: context) {
+ switch AST.Identifier.CompileExpression(node: current_node, withContext: context) {
case .Ok(let listed_action):
- switch context.types.lookup(identifier: listed_action) {
- case .Ok(let maybe_action):
- if maybe_action.eq(rhs: Action()) {
- return .Ok(TypedIdentifier(id: listed_action, withType: P4QualifiedType(maybe_action)))
- }
- return .Error(
- ErrorWithLocation(
- sourceLocation: node.toSourceLocation(),
- withError: "\(listed_action) does not name an action"))
- case .Error(let e): return .Error(e)
- }
+ return .Ok(listed_action as! AST.Identifier)
case .Error(let e): return .Error(e)
}
}
@@ -810,31 +719,31 @@ extension TableActionsProperty: Compilable {
}.joined(separator: ";"))))
}
- return .Ok(TableActionsProperty(actions))
+ return .Ok(AST.TableActionsProperty(actions))
}
}
-extension TablePropertyList: Compilable {
- public typealias C = TablePropertyList
+extension AST.TablePropertyList: Compilable {
+ public typealias C = AST.TablePropertyList
public static func Compile(
- node: SwiftTreeSitter.Node, withContext context: CompilerContext
- ) -> Result {
+ node: SwiftTreeSitter.Node, withContext context: ASTCompilerContext
+ ) -> Result {
- #RequireNodeType(
+ #RequireNodeType(
node: node, type: "table_property_list", nice_type_name: "Table Property List")
- var keys: [TableKeys] = Array()
- var actions: [TableActionsProperty] = Array()
+ var keys: [AST.TableKeys] = Array()
+ var actions: [AST.TableActionsProperty] = Array()
var errors: [any Errorable] = Array()
node.enumerateNamedChildren { child in
if child.nodeType == "table_keys" {
- switch TableKeys.Compile(node: child, withContext: context) {
+ switch AST.TableKeys.Compile(node: child, withContext: context) {
case .Ok(let table_key):
keys.append(table_key)
case .Error(let e): errors.append(e)
}
} else if child.nodeType == "table_actions" {
- switch TableActionsProperty.Compile(node: child, withContext: context) {
+ switch AST.TableActionsProperty.Compile(node: child, withContext: context) {
case .Ok(let table_action_property):
actions.append(table_action_property)
case .Error(let e): errors.append(e)
@@ -875,22 +784,22 @@ extension TablePropertyList: Compilable {
withError: "More than one actions in table property list"))
}
if actions.isEmpty {
- actions.append(TableActionsProperty())
+ actions.append(AST.TableActionsProperty())
}
- return .Ok(TablePropertyList(withActions: actions[0], withKeys: keys[0]))
+ return .Ok(AST.TablePropertyList(withActions: actions[0], withKeys: keys[0]))
}
}
-extension Table: Compilable {
- public typealias C = Table
+extension AST.Table: Compilable {
+ public typealias C = AST.Table
public static func Compile(
- node: SwiftTreeSitter.Node, withContext context: CompilerContext
- ) -> Result {
+ node: SwiftTreeSitter.Node, withContext context: ASTCompilerContext
+ ) -> Result {
let table_declaration_node = node
- #RequireNodeType(
+ #RequireNodeType(
node: table_declaration_node, type: "table_declaration", nice_type_name: "Table Declaration")
var walker = Walker(node: table_declaration_node)
@@ -900,13 +809,13 @@ extension Table: Compilable {
walker.next() // Skip the XXX?
#MustOr(
result: current_node, thing: walker.getNext(),
- or: Result.Error(
+ or: Result.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(), withError: "Missing table declaration component")
))
guard
- case .Ok(let table_name) = Identifier.Compile(
+ case .Ok(let table_name) = AST.Identifier.CompileExpression(
node: current_node!, withContext: context)
else {
return Result.Error(
@@ -918,62 +827,386 @@ extension Table: Compilable {
walker.next()
#MustOr(
result: current_node, thing: walker.getNext(),
- or: Result.Error(
+ or: Result.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(), withError: "Missing table declaration component")
))
- let maybe_table_property_list = TablePropertyList.Compile(
+ let maybe_table_property_list = AST.TablePropertyList.Compile(
node: current_node!, withContext: context)
guard case .Ok(let table_property_list) = maybe_table_property_list else {
return Result.Error(maybe_table_property_list.error()!)
}
- return .Ok(Table(withName: table_name, withPropertyList: table_property_list))
+ return .Ok(
+ AST.Table(withName: table_name as! AST.Identifier, withPropertyList: table_property_list))
}
}
-extension ExternDeclaration: Compilable {
- public typealias C = Declaration
+extension AST.ExternDeclaration: Compilable {
+ public typealias C = AST.AnDeclaration
public static func Compile(
- node: SwiftTreeSitter.Node, withContext context: CompilerContext
- ) -> Result {
+ node: SwiftTreeSitter.Node, withContext context: ASTCompilerContext
+ ) -> Result {
let extern_declaration_node = node
- #RequireNodeType(
+ #RequireNodeType(
node: extern_declaration_node, type: "extern_declaration",
nice_type_name: "Extern Declaration")
let declaration_node = extern_declaration_node.child(at: 1)!
- #RequireNodeType(
+ #RequireNodeType(
node: declaration_node, type: "declaration", nice_type_name: "Declaration")
let declarationed_node = declaration_node.child(at: 0)!
- let maybe_declared = Declaration.Compile(
- node: declarationed_node, withContext: context.update(newExtern: true))
+ let maybe_declared = AST.Declaration.Compile(
+ node: declarationed_node, withContext: context.update(withExtern: true))
guard case .Ok(let declared) = maybe_declared else {
return .Error(maybe_declared.error()!)
}
-
- // Before we are okay with this declaration, it must already be registered as an extern
- // with the matching "stuff".
-
- let found_ffi = context.ffis.first { ffi in
- ffi.type().baseType().eq(rhs: declared.identifier.type.baseType())
- }
-
- guard let found_ffi = found_ffi else {
- return .Error(
- ErrorWithLocation(
- sourceLocation: declarationed_node.toSourceLocation(),
- withError:
- "Could not find a foreign function that matches the extern declaration (\(declared))"))
- }
-
- let extern_declaration = Declaration(extern: declared, ffi: found_ffi)
+ let extern_declaration = AST.ExternDeclaration(declared)
return .Ok(
extern_declaration,
)
}
}
+
+func parameter_list_compiler(
+ node: SwiftTreeSitter.Node, withContext context: ASTCompilerContext
+) -> Common.Result {
+
+ var walker = Walker(node: node)
+ var current_node: Node? = .none
+
+ if node.text == ")" {
+ // There are no parameters!
+ return Result.Ok(AST.ParameterList([]))
+ }
+
+ #RequireNodeType(
+ node: node, type: "parameter_list", nice_type_name: "Parameter List")
+
+ var parameters: AST.ParameterList = AST.ParameterList([])
+
+ #MustOr(
+ result: current_node, thing: walker.getNext(),
+ or: Result.Error(
+ ErrorWithLocation(
+ sourceLocation: node.toSourceLocation(), withError: "Missing parameter list component")))
+
+ if current_node?.nodeType == "parameter_list" {
+ switch parameter_list_compiler(node: current_node!, withContext: context) {
+ case .Ok(let ps):
+ parameters = ps
+ case .Error(let e): return Result.Error(e)
+ }
+ walker.next()
+ }
+
+ #MustOr(
+ result: current_node, thing: walker.getNext(),
+ or: Result.Error(
+ ErrorWithLocation(
+ sourceLocation: node.toSourceLocation(), withError: "Missing parameter list component")))
+
+ // If this is a ')', we are done.
+ if current_node?.text == ")" {
+ return Result.Ok(parameters)
+ }
+
+ // If this is a comma, we skip it!
+ if current_node?.text == "," {
+ walker.next()
+ }
+
+ #MustOr(
+ result: current_node, thing: walker.getNext(),
+ or: Result.Error(
+ ErrorWithLocation(
+ sourceLocation: node.toSourceLocation(), withError: "Missing parameter list component")))
+
+ // Otherwise, there should be one parameter left!
+ switch AST.Parameter.Compile(node: current_node!, withContext: context) {
+ case .Ok(let parsed_parameter):
+ return Result.Ok(parameters.addParameter(parsed_parameter))
+ case .Error(let e): return Result.Error(e)
+ }
+}
+
+extension AST.ParameterList: Compilable {
+ public typealias C = AST.ParameterList
+ public static func Compile(
+ node: SwiftTreeSitter.Node, withContext context: ASTCompilerContext
+ ) -> Result {
+
+ let parameter_node = node
+ #RequireNodeType(
+ node: parameter_node, type: "parameters", nice_type_name: "Parameters")
+
+ var walker = Walker(node: parameter_node)
+
+ var current_node: Node? = .none
+
+ #MustOr(
+ result: current_node, thing: walker.getNext(),
+ or: Result.Error(
+ ErrorWithLocation(
+ sourceLocation: node.toSourceLocation(),
+ withError: "Missing '(' in parameter list component")))
+
+ walker.next()
+ #MustOr(
+ result: current_node, thing: walker.getNext(),
+ or: Result.Error(
+ ErrorWithLocation(
+ sourceLocation: node.toSourceLocation(), withError: "Missing parameter list component")))
+
+ return parameter_list_compiler(node: current_node!, withContext: context)
+ }
+}
+
+extension Direction: Compilable {
+ public typealias C = Direction
+ public static func Compile(
+ node: Node, withContext context: ASTCompilerContext
+ ) -> Result {
+ let direction_node = node
+ #RequireNodeType(
+ node: direction_node, type: "direction", nice_type_name: "direction")
+ let directions = [
+ "in": Direction.In,
+ "out": Direction.Out,
+ "inout": Direction.InOut,
+ ]
+
+ guard let parsed_direction = directions[direction_node.text!] else {
+ return .Error(
+ ErrorWithLocation(
+ sourceLocation: direction_node.toSourceLocation(),
+ withError: "\(direction_node.text!) is not a valid direction"))
+ }
+
+ return .Ok(parsed_direction)
+ }
+}
+
+extension AST.Parameter: Compilable {
+ public typealias C = AST.Parameter
+ public static func Compile(
+ node: Node, withContext context: ASTCompilerContext
+ ) -> Result {
+
+ #RequireNodeType(
+ node: node, type: "parameter", nice_type_name: "parameter")
+
+ var walker = Walker(node: node)
+ var current_node: Node? = .none
+
+ #MustOr(
+ result: current_node, thing: walker.getNext(),
+ or: Result.Error(
+ ErrorWithLocation(
+ sourceLocation: node.toSourceLocation(),
+ withError: "Missing parameter declaration component")))
+
+ // Annotation?
+ if current_node!.nodeType == "annotations" {
+ return .Error(
+ ErrorWithLocation(
+ sourceLocation: current_node!.toSourceLocation(),
+ withError: "Annotations in parameter declarations are not yet handled"))
+ // Will increment indexes here.
+ }
+
+ #MustOr(
+ result: current_node, thing: walker.getNext(),
+ or: Result.Error(
+ ErrorWithLocation(
+ sourceLocation: node.toSourceLocation(),
+ withError: "Missing parameter declaration component")))
+
+ var direction: Direction? = .none
+ // Direction?
+ if current_node!.nodeType == "direction" {
+
+ let maybe_parsed_direction = Direction.Compile(node: current_node!, withContext: context)
+ guard case .Ok(let parsed_direction) = maybe_parsed_direction else {
+ return .Error(maybe_parsed_direction.error()!)
+ }
+ direction = parsed_direction
+
+ walker.next()
+ }
+
+ #MustOr(
+ result: current_node, thing: walker.getNext(),
+ or: Result.Error(
+ ErrorWithLocation(
+ sourceLocation: node.toSourceLocation(),
+ withError: "Missing parameter declaration component")))
+
+ if current_node!.nodeType != "typeRef" {
+ return Result.Error(
+ ErrorWithLocation(
+ sourceLocation: node.toSourceLocation(),
+ withError: "Did not find type name for parameter declaration"))
+ }
+
+ guard
+ case .Ok(let parameter_type) = AST.Types.CompileType(
+ type: current_node!, withContext: context)
+ else {
+ return Result.Error(
+ Error(withMessage: "Could not parse a P4 type from \(current_node!.text!)"))
+ }
+
+ walker.next()
+ #MustOr(
+ result: current_node, thing: walker.getNext(),
+ or: Result.Error(
+ ErrorWithLocation(
+ sourceLocation: node.toSourceLocation(),
+ withError: "Missing parameter declaration component")))
+
+ if current_node!.nodeType != "identifier" {
+ return Result.Error(
+ ErrorWithLocation(
+ sourceLocation: node.toSourceLocation(),
+ withError: "Did not find identifier for parameter statement"))
+ }
+
+ guard
+ case .Ok(let parameter_name) = AST.Identifier.CompileExpression(
+ node: current_node!, withContext: context)
+ else {
+ return Result.Error(
+ Error(withMessage: "Could not parse a parameter name from \(current_node!.text!)"))
+ }
+
+ let qualified_parameter_type =
+ direction != nil
+ ? parameter_type.tipe.update(addAttribute: P4TypeQualifier.Direction(direction!))
+ : parameter_type.tipe
+
+ return Result.Ok(
+ AST.Parameter(
+ identifier: parameter_name as! AST.Identifier,
+ withType: AST.Tipe(qualified_parameter_type)))
+ }
+}
+
+func argument_list_compiler(
+ node: SwiftTreeSitter.Node, withContext context: ASTCompilerContext
+) -> Common.Result {
+
+ var walker = Walker(node: node)
+ var current_node: Node? = .none
+
+ if node.text == ")" {
+ // There are no arguments!
+ return Result.Ok(AST.ArgumentList([]))
+ }
+
+ #RequireNodeType(
+ node: node, type: "argument_list", nice_type_name: "argument List")
+
+ var arguments: AST.ArgumentList = AST.ArgumentList([])
+
+ #MustOr(
+ result: current_node, thing: walker.getNext(),
+ or: Result.Error(
+ ErrorWithLocation(
+ sourceLocation: node.toSourceLocation(), withError: "Missing argument list component")))
+
+ if current_node?.nodeType == "argument_list" {
+ switch argument_list_compiler(node: current_node!, withContext: context) {
+ case .Ok(let ps):
+ arguments = ps
+ case .Error(let e): return Result.Error(e)
+ }
+
+ walker.next()
+ }
+
+ // We may have moved nodes, check/reset current_node.
+ #MustOr(
+ result: current_node, thing: walker.getNext(),
+ or: Result.Error(
+ ErrorWithLocation(
+ sourceLocation: node.toSourceLocation(), withError: "Missing argument list component")))
+
+ // If this is a ')', we are done.
+ if current_node?.text == ")" {
+ return Result.Ok(arguments)
+ }
+
+ // If this is a comma, we skip it!
+ if current_node?.text == "," {
+ walker.next()
+ }
+
+ #MustOr(
+ result: current_node, thing: walker.getNext(),
+ or: Result.Error(
+ ErrorWithLocation(
+ sourceLocation: node.toSourceLocation(), withError: "Missing argument list component")))
+
+ // Otherwise, there should be one argument left!
+ switch AST.Argument.Compile(node: current_node!, withContext: context) {
+ case .Ok(let ce):
+ return Result.Ok(
+ arguments.addArgument(AST.Argument(ce, atIndex: arguments.arguments.count + 1)))
+ case .Error(let e): return Result.Error(e)
+ }
+}
+
+extension AST.ArgumentList: Compilable {
+ public typealias C = AST.ArgumentList
+ public static func Compile(
+ node: SwiftTreeSitter.Node, withContext context: ASTCompilerContext
+ ) -> Common.Result {
+
+ let argument_node = node
+ #RequireNodeType(
+ node: argument_node, type: "arguments", nice_type_name: "arguments")
+
+ var walker = Walker(node: argument_node)
+ var current_node: Node? = .none
+
+ #MustOr(
+ result: current_node, thing: walker.getNext(),
+ or: Result.Error(
+ ErrorWithLocation(
+ sourceLocation: node.toSourceLocation(),
+ withError: "Missing '(' in argument list component")))
+
+ walker.next()
+
+ #MustOr(
+ result: current_node, thing: walker.getNext(),
+ or: Result.Error(
+ ErrorWithLocation(
+ sourceLocation: node.toSourceLocation(), withError: "Missing argument list component")))
+
+ return argument_list_compiler(node: current_node!, withContext: context)
+ }
+}
+
+extension AST.Argument: Compilable {
+ public typealias C = AST.AnExpression
+ public static func Compile(
+ node: SwiftTreeSitter.Node, withContext context: ASTCompilerContext
+ ) -> Common.Result {
+ let argument_node = node
+ #RequireNodeType(
+ node: argument_node, type: "argument", nice_type_name: "argument")
+
+ let expression_node = node.child(at: 0)!
+
+ return switch AST.Expression.Compile(node: expression_node, withContext: context) {
+ case .Ok(let compiled_expression): .Ok(compiled_expression)
+ case .Error(let e): .Error(e)
+ }
+ }
+}
diff --git a/Sources/P4Compiler/Expression.swift b/Sources/P4Compiler/Expression.swift
index e55f90f..903008a 100644
--- a/Sources/P4Compiler/Expression.swift
+++ b/Sources/P4Compiler/Expression.swift
@@ -16,66 +16,34 @@
// along with this program. If not, see .
import Common
-import P4Lang
-import P4Runtime
import SwiftTreeSitter
import TreeSitterP4
-extension TypedIdentifier: CompilableExpression {
- public static func compile(
- node: SwiftTreeSitter.Node, withContext context: CompilerContext
- ) -> Result {
+extension AST.Identifier: CompilableExpression {
+ public static func CompileExpression(
+ node: SwiftTreeSitter.Node, withContext context: ASTCompilerContext
+ ) -> Result {
- let node = node.child(at: 0)!
- #SkipUnlessNodeType(
- node: node, type: "identifier")
-
- guard
- case Result.Ok(let type) = context.instances.lookup(
- identifier: Common.Identifier(name: node.text!))
- else {
- return .Error(
- ErrorWithLocation(
- sourceLocation: node.toSourceLocation(), withError: "Cannot find \(node.text!) in scope"))
- }
+ #RequireNodeType(
+ node: node, type: "identifier", nice_type_name: "Identifier")
/// TODO: If there is a value here, then we can make this a compile-time constant!
- return .Ok(TypedIdentifier(name: node.text!, withType: type.0))
- }
-}
-
-extension TypedIdentifier: CompilableLValueExpression {
- public static func compile_as_lvalue(
- node: SwiftTreeSitter.Node, withContext context: CompilerContext
- ) -> Result {
-
- let expression = node.child(at: 0)!
- #SkipUnlessNodeType(
- node: expression, type: "identifier")
-
- let maybe_parsed_expression = TypedIdentifier.compile(node: node, withContext: context)
- guard case .Ok(let maybe_typed_identifier) = maybe_parsed_expression else {
- return .Error(maybe_parsed_expression.error()!)
- }
-
- let typed_identifier_expression = maybe_typed_identifier as! TypedIdentifier
-
- return Result.Ok(typed_identifier_expression)
+ return .Ok(AST.Identifier(Common.Identifier(name: node.text!)))
}
}
extension P4BooleanValue: CompilableExpression {
- public static func compile(
- node: SwiftTreeSitter.Node, withContext context: CompilerContext
- ) -> Result {
+ public static func CompileExpression(
+ node: SwiftTreeSitter.Node, withContext context: ASTCompilerContext
+ ) -> Result {
let node = node.child(at: 0)!
- #SkipUnlessNodeType(
- node: node, type: "booleanLiteralExpression")
+ #RequireNodeType(
+ node: node, type: "booleanLiteralExpression", nice_type_name: "Boolean Literal Expression")
if node.text == "false" {
- return .Ok(P4Value(P4BooleanValue(withValue: false)))
+ return .Ok(AST.Literal(P4Value(P4BooleanValue(withValue: false))))
} else if node.text == "true" {
- return .Ok(P4Value(P4BooleanValue(withValue: true)))
+ return .Ok(AST.Literal(P4Value(P4BooleanValue(withValue: true))))
}
return .Error(
@@ -86,13 +54,14 @@ extension P4BooleanValue: CompilableExpression {
}
extension P4IntValue: CompilableExpression {
- public static func compile(
- node: SwiftTreeSitter.Node, withContext context: CompilerContext
- ) -> Result {
+ public static func CompileExpression(
+ node: SwiftTreeSitter.Node, withContext context: ASTCompilerContext
+ ) -> Result {
let node = node.child(at: 0)!
- #SkipUnlessNodesTypes(
- node: node, types: ["integer", "integer_elaborated"])
+ #RequireNodesType(
+ nodes: node, type: ["integer", "integer_elaborated"],
+ nice_type_names: ["Integer", "Elaborated Integer"])
var bit_width: BitWidth = BitWidth.Infinite
let value_source: String
@@ -124,7 +93,7 @@ extension P4IntValue: CompilableExpression {
}
if let parsed_int = Int(value_source) {
- return .Ok(P4Value(P4IntValue(withValue: parsed_int, andWidth: bit_width)))
+ return .Ok(AST.Literal(P4Value(P4IntValue(withValue: parsed_int, andWidth: bit_width))))
} else {
return .Error(
ErrorWithLocation(
@@ -135,131 +104,83 @@ extension P4IntValue: CompilableExpression {
}
extension P4StringValue: CompilableExpression {
- public static func compile(
- node: SwiftTreeSitter.Node, withContext scopes: CompilerContext
- ) -> Result {
+ public static func CompileExpression(
+ node: SwiftTreeSitter.Node, withContext scopes: ASTCompilerContext
+ ) -> Result {
let node = node.child(at: 0)!
- #SkipUnlessNodeType(
- node: node, type: "string_literal")
- return .Ok(P4Value(P4StringValue(withValue: node.text!)))
+ #RequireNodeType(
+ node: node, type: "string_literal", nice_type_name: "String Literal")
+ return .Ok(AST.Literal(P4Value(P4StringValue(withValue: node.text!))))
}
}
-extension KeysetExpression: CompilableExpression {
- public static func compile(
- node: SwiftTreeSitter.Node, withContext context: CompilerContext
- ) -> Result {
+extension AST.Expression: Compilable {
+ public static func Compile(
+ node: Node, withContext context: ASTCompilerContext
+ ) -> Result {
+ #RequireNodeType(
+ node: node, type: "expression", nice_type_name: "expression")
+
+ let expression_node = node.child(at: 0)!
+ #RequireNodesType(
+ nodes: expression_node, type: ["grouped_expression", "simple_expression"],
+ nice_type_names: ["grouped expression", "simple expression"])
+
+ // If this is a grouped expression, recurse!
+ if expression_node.nodeType == "grouped_expression" {
+ return AST.Expression.Compile(node: expression_node.child(at: 1)!, withContext: context)
+ }
+
+ let expression_parsers: [CompilableExpression.Type] = [
+ P4BooleanValue.self, P4StringValue.self, P4IntValue.self, AST.Identifier.self,
+ AST.BinaryOperatorExpression.self, AST.ArrayAccessExpression.self, AST.FieldAccessExpression.self,
+ AST.FunctionCall.self,
+ ]
+
+ for candidate_expression_parser in expression_parsers {
+ switch candidate_expression_parser.CompileExpression(
+ node: expression_node, withContext: context)
+ {
+ case .Ok(let parsed): return .Ok(parsed)
+ case .Error(let e): return .Error(e)
+ }
+ }
+
+ return Result.Error(Error(withMessage: "\(node.range): Could not parse into expression"))
+ }
+}
+
+extension AST.KeysetExpression: CompilableExpression {
+ public static func CompileExpression(
+ node: SwiftTreeSitter.Node, withContext context: ASTCompilerContext
+ ) -> Result {
let keyset_expression_node = node.child(at: 0)!
- #RequireNodesType(
+ #RequireNodesType(
nodes: keyset_expression_node, type: ["expression", "default_keyset"],
nice_type_names: ["expression", "default keyset"])
// If there is a default keyset, that's easy!
if keyset_expression_node.nodeType == "default_keyset" {
- return .Ok(KeysetExpression(P4Value(P4SetDefaultValue(withType: context.expected_type!))))
+ return .Ok(AST.KeysetExpression.Default)
}
// Compile the expression:
- let maybe_compiled_set_expression = Expression.Compile(
+ let maybe_compiled_set_expression = AST.Expression.Compile(
node: keyset_expression_node, withContext: context)
guard case .Ok(let compiled_expression) = maybe_compiled_set_expression else {
return .Error(maybe_compiled_set_expression.error()!)
}
- return .Ok(KeysetExpression(compiled_expression))
+ return .Ok(AST.KeysetExpression.Value(compiled_expression))
}
}
-struct Expression {
- public static func Compile(
- node: Node, withContext context: CompilerContext
- ) -> Result {
- #RequireNodeType(
- node: node, type: "expression", nice_type_name: "expression")
-
- let expression_node = node.child(at: 0)!
- #RequireNodesType(
- nodes: expression_node, type: ["grouped_expression", "simple_expression"],
- nice_type_names: ["grouped expression", "simple expression"])
-
- // If this is a grouped expression, recurse!
- if expression_node.nodeType == "grouped_expression" {
- return Expression.Compile(node: expression_node.child(at: 1)!, withContext: context)
- }
-
- let expression_parsers: [CompilableExpression.Type] = [
- P4BooleanValue.self, P4StringValue.self, P4IntValue.self, TypedIdentifier.self,
- BinaryOperatorExpression.self, ArrayAccessExpression.self, FieldAccessExpression.self,
- FunctionCall.self,
- ]
-
- for candidate_expression_parser in expression_parsers {
- switch candidate_expression_parser.compile(
- node: expression_node, withContext: context)
- {
- case .Ok(.some(let parsed)): return .Ok(parsed)
- case .Error(let e): return .Error(e)
- default: continue
- }
- }
-
- return Result.Error(Error(withMessage: "\(node.range): Could not parse into expression"))
- }
-}
-
-struct LValue {
- public static func Compile(
- node: Node, withContext context: CompilerContext
- ) -> Result {
- #RequireNodeType(
- node: node, type: "expression", nice_type_name: "expression")
-
- let expression_node = node.child(at: 0)!
- #RequireNodesType(
- nodes: expression_node, type: ["grouped_expression", "simple_expression"],
- nice_type_names: ["grouped expression", "simple expression"])
-
- // If this is a grouped expression, recurse!
- if expression_node.nodeType == "grouped_expression" {
- return LValue.Compile(node: expression_node.child(at: 1)!, withContext: context)
- }
-
- let lvalue_parsers: [CompilableLValueExpression.Type] = [
- TypedIdentifier.self, FieldAccessExpression.self, ArrayAccessExpression.self,
- ]
-
- for candidate_lvalue_parser in lvalue_parsers {
- switch candidate_lvalue_parser.compile_as_lvalue(
- node: expression_node, withContext: context)
- {
- case .Ok(.some(let parsed)): return .Ok(parsed)
- case .Error(let e): return .Error(e)
- default: continue
- }
- }
-
- return Result.Error(Error(withMessage: "\(node.range): Could not parse into expression"))
- }
-}
-
-struct Identifier {
- public static func Compile(
- node: Node, withContext context: CompilerContext
- ) -> Result {
- return if let node_text_value = node.text {
- .Ok(Common.Identifier(name: node_text_value))
- } else {
- .Error(Error(withMessage: "Could not parse an identifier from \(node)"))
- }
- }
-}
-
-extension SelectExpression: CompilableExpression {
- public static func compile(
- node: Node, withContext context: CompilerContext
- ) -> Result {
- #RequireNodeType(
+extension AST.SelectExpression: CompilableExpression {
+ public static func CompileExpression(
+ node: Node, withContext context: ASTCompilerContext
+ ) -> Result {
+ #RequireNodeType(
node: node, type: "selectExpression", nice_type_name: "parser select expression")
guard let selector_node = node.child(at: 2),
@@ -279,7 +200,7 @@ extension SelectExpression: CompilableExpression {
withError: "Could not find select expression body"))
}
- let maybe_selector = Expression.Compile(node: selector_node, withContext: context)
+ let maybe_selector = AST.Expression.Compile(node: selector_node, withContext: context)
guard case .Ok(let selector) = maybe_selector else {
return .Error(
ErrorWithLocation(
@@ -289,14 +210,14 @@ extension SelectExpression: CompilableExpression {
))
}
- var sces: [SelectCaseExpression] = Array()
+ var sces: [AST.SelectCaseExpression] = Array()
var sces_errors: (any Errorable)? = .none
select_body_node.enumerateNamedChildren { current_node in
- let maybe_parsed_cse = SelectCaseExpression.compile(
- node: current_node, withContext: context.update(newExpectation: selector.type()))
+ let maybe_parsed_cse = AST.SelectCaseExpression.CompileExpression(
+ node: current_node, withContext: context)
switch maybe_parsed_cse {
- case .Ok(let parsed_cse): sces.append(parsed_cse as! SelectCaseExpression)
+ case .Ok(let parsed_cse): sces.append(parsed_cse as! AST.SelectCaseExpression)
case .Error(let e):
sces_errors =
if let sces_errors = sces_errors {
@@ -312,18 +233,18 @@ extension SelectExpression: CompilableExpression {
}
return .Ok(
- SelectExpression(withSelector: selector, withSelectCaseExpressions: sces),
+ AST.SelectExpression(withSelector: selector, withSelectCaseExpressions: sces),
)
}
}
-extension SelectCaseExpression: CompilableExpression {
- public static func compile(
- node: Node, withContext context: CompilerContext
- ) -> Result {
- if node.nodeType != "selectCase" {
- return Result.Error(Error(withMessage: "Expected select case not found"))
- }
+extension AST.SelectCaseExpression: CompilableExpression {
+ public static func CompileExpression(
+ node: Node, withContext context: ASTCompilerContext
+ ) -> Result {
+
+ #RequireNodeType(
+ node: node, type: "selectCase", nice_type_name: "Select Case")
guard let keysetexpression_node = node.child(at: 0),
keysetexpression_node.nodeType == "keysetExpression"
@@ -337,94 +258,56 @@ extension SelectCaseExpression: CompilableExpression {
return Result.Error(Error(withMessage: "Missing target state in select case"))
}
- let maybe_parsed_keysetexpression = KeysetExpression.compile(
+ let maybe_parsed_keysetexpression = AST.KeysetExpression.CompileExpression(
node: keysetexpression_node, withContext: context)
guard case Result.Ok(let maybe_keysetexpression) = maybe_parsed_keysetexpression else {
return Result.Error(maybe_parsed_keysetexpression.error()!)
}
- guard let maybe_keysetexpression = maybe_keysetexpression else {
- return Result.Error(
- ErrorWithLocation(
- sourceLocation: keysetexpression_node.toSourceLocation(),
- withError: "Missing expected keyset expression"))
- }
+ let keysetexpression = maybe_keysetexpression as! AST.KeysetExpression
- let keysetexpression = maybe_keysetexpression as! KeysetExpression
-
- if case .Error(let e) = keysetexpression.compatible(type: context.expected_type!) {
- return .Error(
- ErrorWithLocation(
- sourceLocation: keysetexpression_node.toSourceLocation(), withError: e.msg()))
- }
-
- let maybe_parsed_targetstate = Identifier.Compile(
+ let maybe_parsed_targetstate = AST.Identifier.CompileExpression(
node: targetstate_node, withContext: context)
guard case .Ok(let targetstate) = maybe_parsed_targetstate else {
return Result.Error(maybe_parsed_targetstate.error()!)
}
return .Ok(
- SelectCaseExpression(
- withKey: keysetexpression, withNextState: targetstate)
+ AST.SelectCaseExpression(
+ withKey: keysetexpression, withNextState: targetstate as! AST.Identifier)
)
}
}
-// swift-format-ignore
-public typealias BinaryOperatorChecker = (P4Expression, P4Expression) -> Result<()>
-
-public func binary_and_or_operator_checker(
- left: P4Expression, right: P4Expression
-) -> Result<()> {
- // Check that both are Boolean-typed things!
- if !(left.type().baseType().eq(rhs: P4Boolean()) && right.type().baseType().eq(rhs: P4Boolean()))
- {
- return .Error(Error(withMessage: "And/Or on operands with non-bool type is not allowed"))
- }
- return .Ok(())
-}
-
-public func binary_int_math_operator_checker(
- left: P4Expression, right: P4Expression
-) -> Result<()> {
- // Check that both are int-typed things!
- if !(left.type().baseType().eq(rhs: P4Int()) && right.type().baseType().eq(rhs: P4Int())) {
- return .Error(
- Error(withMessage: "Mathematical operation on operands with non-int type is not allowed"))
- }
- return .Ok(())
-}
-
-extension BinaryOperatorExpression: CompilableExpression {
- public static func compile(
- node: SwiftTreeSitter.Node, withContext context: CompilerContext
- ) -> Result<(P4Expression)?> {
+extension AST.BinaryOperatorExpression: CompilableExpression {
+ public static func CompileExpression(
+ node: SwiftTreeSitter.Node, withContext context: ASTCompilerContext
+ ) -> Result {
let expression = node.child(at: 0)!
- #SkipUnlessNodeType(
- node: expression, type: "binaryOperatorExpression")
-
+ #RequireNodeType(
+ node: expression, type: "binaryOperatorExpression",
+ nice_type_name: "Binary Operator Expression")
let binary_operator_expression_node = expression.child(at: 0)!
var walker = Walker(node: binary_operator_expression_node)
var current_node: Node? = .none
#MustOr(
result: current_node, thing: walker.getNext(),
- or: Result.Error(
+ or: Result.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(), withError: "Malformed binary operator expression"
)))
/// TODO: This macro cannot handle new lines in the arrays
// swift-format-ignore
- #RequireNodesType(
+ #RequireNodesType(
nodes: binary_operator_expression_node,
type: ["binaryEqualOperatorExpression", "binaryLessThanOperatorExpression", "binaryLessThanEqualOperatorExpression", "binaryGreaterThanOperatorExpression", "binaryGreaterThanEqualOperatorExpression", "binaryAndOperatorExpression", "binaryOrOperatorExpression", "binaryAddOperatorExpression", "binarySubtractOperatorExpression", "binaryMultiplyOperatorExpression", "binaryDivideOperatorExpression"],
nice_type_names: [ "binary equal operator", "binary less than operator", "binary less than or equal to operator", "binary greater than operator", "binary greater than or equal to operator", "binary and operator", "binary or operator", "binary add operator", "binary subtract operator", "binary multiply operator", "binary divide operator"])
#MustOr(
result: current_node, thing: walker.getNext(),
- or: Result.Error(
+ or: Result.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(),
withError: "Missing LHS for binary operator expression")))
@@ -434,7 +317,7 @@ extension BinaryOperatorExpression: CompilableExpression {
walker.next()
#MustOr(
result: current_node, thing: walker.getNext(),
- or: Result.Error(
+ or: Result.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(),
withError: "Missing binary operator for binary operator expression")))
@@ -442,105 +325,92 @@ extension BinaryOperatorExpression: CompilableExpression {
walker.next()
#MustOr(
result: current_node, thing: walker.getNext(),
- or: Result.Error(
+ or: Result.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(),
withError: "Missing RHS for binary operator expression")))
let right_hand_side_raw = current_node!
- let maybe_left_hand_side = Expression.Compile(node: left_hand_side_raw, withContext: context)
+ let maybe_left_hand_side = AST.Expression.Compile(
+ node: left_hand_side_raw, withContext: context)
guard case Result.Ok(let left_hand_side) = maybe_left_hand_side else {
return Result.Error(maybe_left_hand_side.error()!)
}
- let maybe_right_hand_side = Expression.Compile(node: right_hand_side_raw, withContext: context)
+ let maybe_right_hand_side = AST.Expression.Compile(
+ node: right_hand_side_raw, withContext: context)
guard case Result.Ok(let right_hand_side) = maybe_right_hand_side else {
return Result.Error(maybe_right_hand_side.error()!)
}
- let evaluators:
- [String: (String, P4QualifiedType, BinaryOperatorChecker?, BinaryOperatorEvaluator)] = [
- "binaryEqualOperatorExpression": (
- "Binary Equal", P4QualifiedType(P4Boolean()), Optional.none,
- binary_equal_operator_evaluator
- ),
- "binaryLessThanOperatorExpression": (
- "Binary Less Than", P4QualifiedType(P4Boolean()), Optional.none,
- binary_lt_operator_evaluator
- ),
- "binaryLessThanEqualOperatorExpression": (
- "Binary Less Than Or Equal", P4QualifiedType(P4Boolean()),
- Optional.none,
- binary_lte_operator_evaluator
- ),
- "binaryGreaterThanOperatorExpression": (
- "Binary Greater Than", P4QualifiedType(P4Boolean()), Optional.none,
- binary_gt_operator_evaluator
- ),
- "binaryGreaterThanEqualOperatorExpression": (
- "Binary Greater Than Or Equal", P4QualifiedType(P4Boolean()),
- Optional.none,
- binary_gte_operator_evaluator
- ),
- "binaryAndOperatorExpression": (
- "Binary Or", P4QualifiedType(P4Boolean()), binary_and_or_operator_checker,
- binary_and_operator_evaluator
- ),
- "binaryOrOperatorExpression": (
- "Binary And", P4QualifiedType(P4Boolean()), binary_and_or_operator_checker,
- binary_or_operator_evaluator
- ),
- "binaryAddOperatorExpression": (
- "Binary Add", P4QualifiedType(P4Int()), binary_int_math_operator_checker,
- binary_add_operator_evaluator
- ),
- "binarySubtractOperatorExpression": (
- "Binary Subtract", P4QualifiedType(P4Int()), binary_int_math_operator_checker,
- binary_subtract_operator_evaluator
- ),
- "binaryMultiplyOperatorExpression": (
- "Binary Multiply", P4QualifiedType(P4Int()), binary_int_math_operator_checker,
- binary_multiply_operator_evaluator
- ),
- "binaryDivideOperatorExpression": (
- "Binary Divide", P4QualifiedType(P4Int()), binary_int_math_operator_checker,
- binary_divide_operator_evaluator
- ),
- ]
-
- if !left_hand_side.type().eq(right_hand_side.type()) {
- return Result.Error(
- Error(withMessage: "Types of values used with binary expression are not the same"))
- }
+ let evaluators: [String: (String, P4QualifiedType, AST.BinaryOperatorExpressionType)] = [
+ "binaryEqualOperatorExpression": (
+ "Binary Equal", P4QualifiedType(P4Boolean()),
+ AST.BinaryOperatorExpressionType.Eq
+ ),
+ "binaryLessThanOperatorExpression": (
+ "Binary Less Than", P4QualifiedType(P4Boolean()),
+ AST.BinaryOperatorExpressionType.Lt
+ ),
+ "binaryLessThanEqualOperatorExpression": (
+ "Binary Less Than Or Equal", P4QualifiedType(P4Boolean()),
+ AST.BinaryOperatorExpressionType.Lte
+ ),
+ "binaryGreaterThanOperatorExpression": (
+ "Binary Greater Than", P4QualifiedType(P4Boolean()),
+ AST.BinaryOperatorExpressionType.Gt
+ ),
+ "binaryGreaterThanEqualOperatorExpression": (
+ "Binary Greater Than Or Equal", P4QualifiedType(P4Boolean()),
+ AST.BinaryOperatorExpressionType.Gte
+ ),
+ "binaryAndOperatorExpression": (
+ "Binary Or", P4QualifiedType(P4Boolean()),
+ AST.BinaryOperatorExpressionType.And
+ ),
+ "binaryOrOperatorExpression": (
+ "Binary And", P4QualifiedType(P4Boolean()),
+ AST.BinaryOperatorExpressionType.Or
+ ),
+ "binaryAddOperatorExpression": (
+ "Binary Add", P4QualifiedType(P4Int()),
+ AST.BinaryOperatorExpressionType.Add
+ ),
+ "binarySubtractOperatorExpression": (
+ "Binary Subtract", P4QualifiedType(P4Int()),
+ AST.BinaryOperatorExpressionType.Subtract
+ ),
+ "binaryMultiplyOperatorExpression": (
+ "Binary Multiply", P4QualifiedType(P4Int()),
+ AST.BinaryOperatorExpressionType.Multiply
+ ),
+ "binaryDivideOperatorExpression": (
+ "Binary Divide", P4QualifiedType(P4Int()),
+ AST.BinaryOperatorExpressionType.Divide
+ ),
+ ]
guard let selected_evaluator = evaluators[binary_operator_expression_node.nodeType!] else {
return Result.Error(
Error(withMessage: "No evaluator for \(binary_operator_expression_node.nodeType!)"))
}
- if let checker = selected_evaluator.2,
- case .Error(let e) = checker(left_hand_side, right_hand_side)
- {
- return Result.Error(e)
- }
-
return .Ok(
- BinaryOperatorExpression(
- withEvaluator: (selected_evaluator.0, selected_evaluator.1, selected_evaluator.3),
+ AST.BinaryOperatorExpression(
+ withType: selected_evaluator.2,
withLhs: left_hand_side, withRhs: right_hand_side))
}
}
-extension ArrayAccessExpression: CompilableExpression {
- public static func compile(
- node: SwiftTreeSitter.Node, withContext context: CompilerContext
- ) -> Result {
+extension AST.ArrayAccessExpression: CompilableExpression {
+ public static func CompileExpression(
+ node: SwiftTreeSitter.Node, withContext context: ASTCompilerContext
+ ) -> Result {
let expression = node.child(at: 0)!
- #SkipUnlessNodeType(
- node: expression, type: "arrayAccessExpression")
-
+ #RequireNodeType(
+ node: expression, type: "arrayAccessExpression", nice_type_name: "Array Access Expression")
let array_access_expression_node = expression
var walker = Walker(node: array_access_expression_node)
@@ -548,11 +418,11 @@ extension ArrayAccessExpression: CompilableExpression {
#MustOr(
result: current_node, thing: walker.getNext(),
- or: Result.Error(
+ or: Result.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(), withError: "Malformed array access expression")))
- #RequireNodeType(
+ #RequireNodeType(
node: current_node!, type: "expression",
nice_type_name: "array identifier expression")
let array_access_identifier_node = current_node!
@@ -560,7 +430,7 @@ extension ArrayAccessExpression: CompilableExpression {
walker.next()
#MustOr(
result: current_node, thing: walker.getNext(),
- or: Result.Error(
+ or: Result.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(),
withError: "Missing [ for array access expression")))
@@ -569,52 +439,43 @@ extension ArrayAccessExpression: CompilableExpression {
#MustOr(
result: current_node, thing: walker.getNext(),
- or: Result.Error(
+ or: Result.Error(
ErrorWithLocation(
sourceLocation: node.toSourceLocation(),
withError: "Missing indexor expression for array access expression")))
- #RequireNodeType(
+ #RequireNodeType(
node: current_node!, type: "expression",
nice_type_name: "array indexor expression")
let array_access_indexor_node = current_node!
- let maybe_array_identifier = Expression.Compile(
+ let maybe_array_identifier = AST.Expression.Compile(
node: array_access_identifier_node, withContext: context)
guard case Result.Ok(let array_identifier) = maybe_array_identifier else {
return Result.Error(maybe_array_identifier.error()!)
}
- let maybe_array_type = array_identifier.type()
- guard let array_type = maybe_array_type.baseType() as? P4Array else {
- return Result.Error(
- ErrorWithLocation(
- sourceLocation: array_access_identifier_node.toSourceLocation(),
- withError: "\(array_identifier) does not name an array type")
- )
- }
-
- let maybe_array_indexor = Expression.Compile(
+ let maybe_array_indexor = AST.Expression.Compile(
node: array_access_indexor_node, withContext: context)
guard case Result.Ok(let array_indexor) = maybe_array_indexor else {
return Result.Error(maybe_array_indexor.error()!)
}
return .Ok(
- ArrayAccessExpression(
- withName: array_identifier, withType: array_type, withIndexor: array_indexor))
+ AST.ArrayAccessExpression(
+ withName: array_identifier, withIndexor: array_indexor))
}
}
-extension FieldAccessExpression: CompilableExpression {
- public static func compile(
- node: SwiftTreeSitter.Node, withContext context: CompilerContext
- ) -> Result {
+extension AST.FieldAccessExpression: CompilableExpression {
+ public static func CompileExpression(
+ node: SwiftTreeSitter.Node, withContext context: ASTCompilerContext
+ ) -> Result {
let expression = node.child(at: 0)!
- #SkipUnlessNodeType(
- node: expression, type: "fieldAccessExpression")
+ #RequireNodeType(
+ node: expression, type: "fieldAccessExpression", nice_type_name: "Array Access Expression")
let field_access_expression_node = expression
@@ -623,11 +484,11 @@ extension FieldAccessExpression: CompilableExpression {
#MustOr(
result: current_node, thing: walker.getNext(),
- or: Result