compiler, runtime: Begin Runtime Refactor
Ultimately, the goal is to completely separate the compilation from the runtime to make it possible to have the interpreter/evaluator be "just another" entity that can perform meaningful work when given a parsed GP4 program. Signed-off-by: Will Hawkins <hawkinsw@obs.cr>
This commit is contained in:
@@ -42,7 +42,7 @@ public struct Parameter: CustomStringConvertible, Equatable {
|
|||||||
if let param_direction = self.type.direction(),
|
if let param_direction = self.type.direction(),
|
||||||
param_direction == Direction.In || param_direction == Direction.InOut
|
param_direction == Direction.In || param_direction == Direction.InOut
|
||||||
{
|
{
|
||||||
if !(argument.argument is EvaluatableLValueExpression) {
|
if !(argument.argument is P4LValueExpression) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -125,9 +125,9 @@ public struct ArgumentList {
|
|||||||
|
|
||||||
public struct Argument {
|
public struct Argument {
|
||||||
public let index: Int
|
public let index: Int
|
||||||
public let argument: EvaluatableExpression
|
public let argument: P4Expression
|
||||||
|
|
||||||
public init(_ argument: EvaluatableExpression, atIndex index: Int) {
|
public init(_ argument: P4Expression, atIndex index: Int) {
|
||||||
self.argument = argument
|
self.argument = argument
|
||||||
self.index = index
|
self.index = index
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,3 +26,124 @@ public typealias TypeTypeScope = Scope<P4Type>
|
|||||||
|
|
||||||
/// Scopes that resolve type identifiers to their types.
|
/// Scopes that resolve type identifiers to their types.
|
||||||
public typealias TypeTypeScopes = Scopes<P4Type>
|
public typealias TypeTypeScopes = Scopes<P4Type>
|
||||||
|
|
||||||
|
/// 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 init() {
|
||||||
|
instances = StaticVarValueScopes().enter()
|
||||||
|
types = TypeTypeScopes().enter()
|
||||||
|
externs = TypeTypeScopes().enter()
|
||||||
|
expected_type = .none
|
||||||
|
extern_context = false
|
||||||
|
ffis = Array()
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(withInstances _instances: StaticVarValueScopes, withTypes _types: TypeTypeScopes) {
|
||||||
|
instances = _instances
|
||||||
|
types = _types
|
||||||
|
externs = TypeTypeScopes().enter()
|
||||||
|
expected_type = .none
|
||||||
|
extern_context = false
|
||||||
|
ffis = Array()
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(
|
||||||
|
withInstances _instances: StaticVarValueScopes, withTypes _types: TypeTypeScopes,
|
||||||
|
withExpectation expectation: P4QualifiedType?, withExtern extern: Bool,
|
||||||
|
withExterns externs: TypeTypeScopes, withFFIs foreigns: [P4FFI]
|
||||||
|
) {
|
||||||
|
instances = _instances
|
||||||
|
types = _types
|
||||||
|
expected_type = expectation
|
||||||
|
extern_context = extern
|
||||||
|
self.externs = externs
|
||||||
|
ffis = foreigns
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -109,6 +109,18 @@ public struct InterloperEvaluator: ProgramExecutionEvaluator {
|
|||||||
|
|
||||||
return CanonicalExecuteStatements(statements, inExecution: execution) { statement, execution in
|
return CanonicalExecuteStatements(statements, inExecution: execution) { statement, execution in
|
||||||
let (cf, value) = statement.evaluate(execution: execution)
|
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) =
|
let (handled_cf, handled_value) =
|
||||||
if let handler = handler {
|
if let handler = handler {
|
||||||
handler(cf, value)
|
handler(cf, value)
|
||||||
@@ -119,7 +131,7 @@ public struct InterloperEvaluator: ProgramExecutionEvaluator {
|
|||||||
if hasDebugInterloper {
|
if hasDebugInterloper {
|
||||||
debugger!(statement, handled_cf, handled_value)
|
debugger!(statement, handled_cf, handled_value)
|
||||||
}
|
}
|
||||||
return (handled_cf, handled_value)
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,28 +15,16 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
public protocol EvaluatableExpression {
|
|
||||||
/// 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<P4Value>, ProgramExecution)
|
|
||||||
func type() -> P4QualifiedType
|
|
||||||
}
|
|
||||||
|
|
||||||
public protocol EvaluatableStatement {
|
|
||||||
/// 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)
|
|
||||||
}
|
|
||||||
|
|
||||||
public protocol P4Type: CustomStringConvertible {
|
public protocol P4Type: CustomStringConvertible {
|
||||||
func eq(rhs: any P4Type) -> Bool
|
func eq(rhs: any P4Type) -> Bool
|
||||||
func def() -> P4DataValue?
|
func def() -> P4DataValue?
|
||||||
|
func instantiable() -> Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
extension P4Type {
|
||||||
|
public func instantiable() -> Bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public protocol P4DataValue: CustomStringConvertible {
|
public protocol P4DataValue: CustomStringConvertible {
|
||||||
@@ -48,28 +36,6 @@ public protocol P4DataValue: CustomStringConvertible {
|
|||||||
func gte(rhs: P4DataValue) -> Bool
|
func gte(rhs: P4DataValue) -> Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
public protocol EvaluatableLValueExpression: EvaluatableExpression {
|
|
||||||
func set(
|
|
||||||
to: P4Value, inScopes scopes: VarValueScopes, duringExecution execution: ProgramExecution
|
|
||||||
) -> Result<(VarValueScopes, P4Value)>
|
|
||||||
func check(to: EvaluatableExpression, inScopes scopes: StaticVarValueScopes) -> Result<()>
|
|
||||||
}
|
|
||||||
|
|
||||||
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<P4Value>, ProgramExecution)
|
|
||||||
}
|
|
||||||
|
|
||||||
public protocol Errorable: CustomStringConvertible {
|
public protocol Errorable: CustomStringConvertible {
|
||||||
func format(_ formatter: Formattable) -> String
|
func format(_ formatter: Formattable) -> String
|
||||||
func format(_ formatter: Formattable, _ sc: SourceCode) -> String
|
func format(_ formatter: Formattable, _ sc: SourceCode) -> String
|
||||||
@@ -91,6 +57,64 @@ public protocol Formattable {
|
|||||||
func formatWithStyle(_ value: String, _ style: Style) -> String
|
func formatWithStyle(_ value: String, _ style: Style) -> String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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<P4Value>, 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<P4Value>, ProgramExecution)
|
||||||
|
}
|
||||||
|
|
||||||
extension ProgramExecutionEvaluator {
|
extension ProgramExecutionEvaluator {
|
||||||
public func ExecuteStatements(
|
public func ExecuteStatements(
|
||||||
_ statements: [EvaluatableStatement], inExecution execution: ProgramExecution
|
_ statements: [EvaluatableStatement], inExecution execution: ProgramExecution
|
||||||
|
|||||||
@@ -106,3 +106,6 @@ public func Fold<T, A>(input: [T], initial: A, block: (T, A) -> A) -> A {
|
|||||||
|
|
||||||
@freestanding(codeItem) public macro MustOr<E, N>(result: E, thing: E?, or: N) =
|
@freestanding(codeItem) public macro MustOr<E, N>(result: E, thing: E?, or: N) =
|
||||||
#externalMacro(module: "Macros", type: "MustOr")
|
#externalMacro(module: "Macros", type: "MustOr")
|
||||||
|
|
||||||
|
@attached(peer) public macro DeriveCompilableStatement() =
|
||||||
|
#externalMacro(module: "Macros", type: "DeriveCompilableStatement")
|
||||||
|
|||||||
@@ -439,11 +439,36 @@ public struct CliTestDeclarationMacro: PeerMacro, Sendable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct DeriveCompilableStatement: PeerMacro, Sendable {
|
||||||
|
public static func expansion(
|
||||||
|
of node: AttributeSyntax,
|
||||||
|
providingPeersOf declaration: some DeclSyntaxProtocol,
|
||||||
|
in context: some MacroExpansionContext
|
||||||
|
) throws -> [DeclSyntax] {
|
||||||
|
|
||||||
|
let type_name = declaration.cast(ExtensionDeclSyntax.self).extendedType
|
||||||
|
let implementation = DeclSyntax(
|
||||||
|
"""
|
||||||
|
extension VariableDeclarationStatement: CompilableStatement {
|
||||||
|
public static func CompileStatement(
|
||||||
|
node: Node, withContext context: CompilerContext
|
||||||
|
) -> Result<P4Statement> {
|
||||||
|
return switch Compile(node: node, withContext: context) {
|
||||||
|
case .Ok(let res): .Ok(res)
|
||||||
|
case .Error(let e): .Error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
return [implementation]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@main
|
@main
|
||||||
struct P4Macros: CompilerPlugin {
|
struct P4Macros: CompilerPlugin {
|
||||||
var providingMacros: [Macro.Type] = [
|
var providingMacros: [Macro.Type] = [
|
||||||
RequireResult.self, RequireErrorResult.self, UseOkResult.self, UseErrorResult.self,
|
RequireResult.self, RequireErrorResult.self, UseOkResult.self, UseErrorResult.self,
|
||||||
RequireNodeType.self, SkipUnlessNodeType.self, SkipUnlessNodesTypes.self, RequireNodesType.self,
|
RequireNodeType.self, SkipUnlessNodeType.self, SkipUnlessNodesTypes.self, RequireNodesType.self,
|
||||||
MustOr.self, CliTestDeclarationMacro.self,
|
MustOr.self, CliTestDeclarationMacro.self, DeriveCompilableStatement.self,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,30 +24,30 @@ import TreeSitterP4
|
|||||||
|
|
||||||
func parameter_list_compiler(
|
func parameter_list_compiler(
|
||||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Common.Result<(ParameterList, CompilerContext)> {
|
) -> Common.Result<ParameterList> {
|
||||||
|
|
||||||
var walker = Walker(node: node)
|
var walker = Walker(node: node)
|
||||||
var current_node: Node? = .none
|
var current_node: Node? = .none
|
||||||
|
|
||||||
if node.text == ")" {
|
if node.text == ")" {
|
||||||
// There are no parameters!
|
// There are no parameters!
|
||||||
return Result.Ok((ParameterList([]), context))
|
return Result.Ok(ParameterList([]))
|
||||||
}
|
}
|
||||||
|
|
||||||
#RequireNodeType<Node, (ParameterList, CompilerContext)>(
|
#RequireNodeType<Node, ParameterList>(
|
||||||
node: node, type: "parameter_list", nice_type_name: "Parameter List")
|
node: node, type: "parameter_list", nice_type_name: "Parameter List")
|
||||||
|
|
||||||
var parameters: ParameterList = ParameterList([])
|
var parameters: ParameterList = ParameterList([])
|
||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(ParameterList, CompilerContext)>.Error(
|
or: Result<ParameterList>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(), withError: "Missing parameter list component")))
|
sourceLocation: node.toSourceLocation(), withError: "Missing parameter list component")))
|
||||||
|
|
||||||
if current_node?.nodeType == "parameter_list" {
|
if current_node?.nodeType == "parameter_list" {
|
||||||
switch parameter_list_compiler(node: current_node!, withContext: context) {
|
switch parameter_list_compiler(node: current_node!, withContext: context) {
|
||||||
case .Ok(let (ps, _)):
|
case .Ok(let ps):
|
||||||
parameters = ps
|
parameters = ps
|
||||||
case .Error(let e): return Result.Error(e)
|
case .Error(let e): return Result.Error(e)
|
||||||
}
|
}
|
||||||
@@ -56,13 +56,13 @@ func parameter_list_compiler(
|
|||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(ParameterList, CompilerContext)>.Error(
|
or: Result<ParameterList>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(), withError: "Missing parameter list component")))
|
sourceLocation: node.toSourceLocation(), withError: "Missing parameter list component")))
|
||||||
|
|
||||||
// If this is a ')', we are done.
|
// If this is a ')', we are done.
|
||||||
if current_node?.text == ")" {
|
if current_node?.text == ")" {
|
||||||
return Result.Ok((parameters, context))
|
return Result.Ok(parameters)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is a comma, we skip it!
|
// If this is a comma, we skip it!
|
||||||
@@ -72,26 +72,26 @@ func parameter_list_compiler(
|
|||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(ParameterList, CompilerContext)>.Error(
|
or: Result<ParameterList>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(), withError: "Missing parameter list component")))
|
sourceLocation: node.toSourceLocation(), withError: "Missing parameter list component")))
|
||||||
|
|
||||||
// Otherwise, there should be one parameter left!
|
// Otherwise, there should be one parameter left!
|
||||||
switch Parameter.Compile(node: current_node!, withContext: context) {
|
switch Parameter.Compile(node: current_node!, withContext: context) {
|
||||||
case .Ok(let (parsed_parameter, updated_context)):
|
case .Ok(let parsed_parameter):
|
||||||
return Result.Ok((parameters.addParameter(parsed_parameter), updated_context))
|
return Result.Ok(parameters.addParameter(parsed_parameter))
|
||||||
case .Error(let e): return Result.Error(e)
|
case .Error(let e): return Result.Error(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ParameterList: Compilable {
|
extension ParameterList: Compilable {
|
||||||
public typealias T = ParameterList
|
public typealias C = ParameterList
|
||||||
public static func Compile(
|
public static func Compile(
|
||||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Common.Result<(ParameterList, CompilerContext)> {
|
) -> Common.Result<ParameterList> {
|
||||||
|
|
||||||
let parameter_node = node
|
let parameter_node = node
|
||||||
#RequireNodeType<Node, (ParameterList, CompilerContext)>(
|
#RequireNodeType<Node, ParameterList>(
|
||||||
node: parameter_node, type: "parameters", nice_type_name: "Parameters")
|
node: parameter_node, type: "parameters", nice_type_name: "Parameters")
|
||||||
|
|
||||||
var walker = Walker(node: parameter_node)
|
var walker = Walker(node: parameter_node)
|
||||||
@@ -100,7 +100,7 @@ extension ParameterList: Compilable {
|
|||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(ParameterList, CompilerContext)>.Error(
|
or: Result<ParameterList>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(),
|
sourceLocation: node.toSourceLocation(),
|
||||||
withError: "Missing '(' in parameter list component")))
|
withError: "Missing '(' in parameter list component")))
|
||||||
@@ -108,7 +108,7 @@ extension ParameterList: Compilable {
|
|||||||
walker.next()
|
walker.next()
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(ParameterList, CompilerContext)>.Error(
|
or: Result<ParameterList>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(), withError: "Missing parameter list component")))
|
sourceLocation: node.toSourceLocation(), withError: "Missing parameter list component")))
|
||||||
|
|
||||||
@@ -117,12 +117,12 @@ extension ParameterList: Compilable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension Direction: Compilable {
|
extension Direction: Compilable {
|
||||||
public typealias T = Direction
|
public typealias C = Direction
|
||||||
public static func Compile(
|
public static func Compile(
|
||||||
node: Node, withContext context: CompilerContext
|
node: Node, withContext context: CompilerContext
|
||||||
) -> Result<(Direction, CompilerContext)> {
|
) -> Result<Direction> {
|
||||||
let direction_node = node
|
let direction_node = node
|
||||||
#RequireNodeType<Node, (Direction, CompilerContext)>(
|
#RequireNodeType<Node, Direction>(
|
||||||
node: direction_node, type: "direction", nice_type_name: "direction")
|
node: direction_node, type: "direction", nice_type_name: "direction")
|
||||||
let directions = [
|
let directions = [
|
||||||
"in": Direction.In,
|
"in": Direction.In,
|
||||||
@@ -137,17 +137,17 @@ extension Direction: Compilable {
|
|||||||
withError: "\(direction_node.text!) is not a valid direction"))
|
withError: "\(direction_node.text!) is not a valid direction"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return .Ok((parsed_direction, context))
|
return .Ok(parsed_direction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Parameter: Compilable {
|
extension Parameter: Compilable {
|
||||||
public typealias T = Parameter
|
public typealias C = Parameter
|
||||||
public static func Compile(
|
public static func Compile(
|
||||||
node: Node, withContext context: CompilerContext
|
node: Node, withContext context: CompilerContext
|
||||||
) -> Result<(Parameter, CompilerContext)> {
|
) -> Result<Parameter> {
|
||||||
|
|
||||||
#RequireNodeType<Node, (EvaluatableStatement, CompilerContext)>(
|
#RequireNodeType<Node, P4Statement>(
|
||||||
node: node, type: "parameter", nice_type_name: "parameter")
|
node: node, type: "parameter", nice_type_name: "parameter")
|
||||||
|
|
||||||
var walker = Walker(node: node)
|
var walker = Walker(node: node)
|
||||||
@@ -155,7 +155,7 @@ extension Parameter: Compilable {
|
|||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(Parameter, CompilerContext)>.Error(
|
or: Result<Parameter>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(),
|
sourceLocation: node.toSourceLocation(),
|
||||||
withError: "Missing parameter declaration component")))
|
withError: "Missing parameter declaration component")))
|
||||||
@@ -171,7 +171,7 @@ extension Parameter: Compilable {
|
|||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(Parameter, CompilerContext)>.Error(
|
or: Result<Parameter>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(),
|
sourceLocation: node.toSourceLocation(),
|
||||||
withError: "Missing parameter declaration component")))
|
withError: "Missing parameter declaration component")))
|
||||||
@@ -181,7 +181,7 @@ extension Parameter: Compilable {
|
|||||||
if current_node!.nodeType == "direction" {
|
if current_node!.nodeType == "direction" {
|
||||||
|
|
||||||
let maybe_parsed_direction = Direction.Compile(node: current_node!, withContext: context)
|
let maybe_parsed_direction = Direction.Compile(node: current_node!, withContext: context)
|
||||||
guard case .Ok((let parsed_direction, _)) = maybe_parsed_direction else {
|
guard case .Ok(let parsed_direction) = maybe_parsed_direction else {
|
||||||
return .Error(maybe_parsed_direction.error()!)
|
return .Error(maybe_parsed_direction.error()!)
|
||||||
}
|
}
|
||||||
direction = parsed_direction
|
direction = parsed_direction
|
||||||
@@ -191,7 +191,7 @@ extension Parameter: Compilable {
|
|||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(Parameter, CompilerContext)>.Error(
|
or: Result<Parameter>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(),
|
sourceLocation: node.toSourceLocation(),
|
||||||
withError: "Missing parameter declaration component")))
|
withError: "Missing parameter declaration component")))
|
||||||
@@ -213,7 +213,7 @@ extension Parameter: Compilable {
|
|||||||
walker.next()
|
walker.next()
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(Parameter, CompilerContext)>.Error(
|
or: Result<Parameter>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(),
|
sourceLocation: node.toSourceLocation(),
|
||||||
withError: "Missing parameter declaration component")))
|
withError: "Missing parameter declaration component")))
|
||||||
@@ -233,43 +233,41 @@ extension Parameter: Compilable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Result.Ok(
|
return Result.Ok(
|
||||||
(
|
|
||||||
Parameter(
|
Parameter(
|
||||||
identifier: parameter_name,
|
identifier: parameter_name,
|
||||||
withType: direction != nil
|
withType: direction != nil
|
||||||
? parameter_type.update(addAttribute: P4TypeQualifier.Direction(direction!))
|
? parameter_type.update(addAttribute: P4TypeQualifier.Direction(direction!))
|
||||||
: parameter_type),
|
: parameter_type),
|
||||||
context
|
)
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func argument_list_compiler(
|
func argument_list_compiler(
|
||||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Common.Result<(ArgumentList, CompilerContext)> {
|
) -> Common.Result<ArgumentList> {
|
||||||
|
|
||||||
var walker = Walker(node: node)
|
var walker = Walker(node: node)
|
||||||
var current_node: Node? = .none
|
var current_node: Node? = .none
|
||||||
|
|
||||||
if node.text == ")" {
|
if node.text == ")" {
|
||||||
// There are no arguments!
|
// There are no arguments!
|
||||||
return Result.Ok((ArgumentList([]), context))
|
return Result.Ok(ArgumentList([]))
|
||||||
}
|
}
|
||||||
|
|
||||||
#RequireNodeType<Node, (ArgumentList, CompilerContext)>(
|
#RequireNodeType<Node, ArgumentList>(
|
||||||
node: node, type: "argument_list", nice_type_name: "argument List")
|
node: node, type: "argument_list", nice_type_name: "argument List")
|
||||||
|
|
||||||
var arguments: ArgumentList = ArgumentList([])
|
var arguments: ArgumentList = ArgumentList([])
|
||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(ArgumentList, CompilerContext)>.Error(
|
or: Result<ArgumentList>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(), withError: "Missing argument list component")))
|
sourceLocation: node.toSourceLocation(), withError: "Missing argument list component")))
|
||||||
|
|
||||||
if current_node?.nodeType == "argument_list" {
|
if current_node?.nodeType == "argument_list" {
|
||||||
switch argument_list_compiler(node: current_node!, withContext: context) {
|
switch argument_list_compiler(node: current_node!, withContext: context) {
|
||||||
case .Ok(let (ps, _)):
|
case .Ok(let ps):
|
||||||
arguments = ps
|
arguments = ps
|
||||||
case .Error(let e): return Result.Error(e)
|
case .Error(let e): return Result.Error(e)
|
||||||
}
|
}
|
||||||
@@ -280,13 +278,13 @@ func argument_list_compiler(
|
|||||||
// We may have moved nodes, check/reset current_node.
|
// We may have moved nodes, check/reset current_node.
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(ArgumentList, CompilerContext)>.Error(
|
or: Result<ArgumentList>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(), withError: "Missing argument list component")))
|
sourceLocation: node.toSourceLocation(), withError: "Missing argument list component")))
|
||||||
|
|
||||||
// If this is a ')', we are done.
|
// If this is a ')', we are done.
|
||||||
if current_node?.text == ")" {
|
if current_node?.text == ")" {
|
||||||
return Result.Ok((arguments, context))
|
return Result.Ok(arguments)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is a comma, we skip it!
|
// If this is a comma, we skip it!
|
||||||
@@ -296,27 +294,27 @@ func argument_list_compiler(
|
|||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(ArgumentList, CompilerContext)>.Error(
|
or: Result<ArgumentList>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(), withError: "Missing argument list component")))
|
sourceLocation: node.toSourceLocation(), withError: "Missing argument list component")))
|
||||||
|
|
||||||
// Otherwise, there should be one argument left!
|
// Otherwise, there should be one argument left!
|
||||||
switch Argument.Compile(node: current_node!, withContext: context) {
|
switch Argument.Compile(node: current_node!, withContext: context) {
|
||||||
case .Ok(let (ce, updated_context)):
|
case .Ok(let ce):
|
||||||
return Result.Ok(
|
return Result.Ok(
|
||||||
(arguments.addArgument(Argument(ce, atIndex: arguments.count() + 1)), updated_context))
|
arguments.addArgument(Argument(ce, atIndex: arguments.count() + 1)))
|
||||||
case .Error(let e): return Result.Error(e)
|
case .Error(let e): return Result.Error(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ArgumentList: Compilable {
|
extension ArgumentList: Compilable {
|
||||||
public typealias T = ArgumentList
|
public typealias C = ArgumentList
|
||||||
public static func Compile(
|
public static func Compile(
|
||||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Common.Result<(ArgumentList, CompilerContext)> {
|
) -> Common.Result<ArgumentList> {
|
||||||
|
|
||||||
let argument_node = node
|
let argument_node = node
|
||||||
#RequireNodeType<Node, (ArgumentList, CompilerContext)>(
|
#RequireNodeType<Node, ArgumentList>(
|
||||||
node: argument_node, type: "arguments", nice_type_name: "arguments")
|
node: argument_node, type: "arguments", nice_type_name: "arguments")
|
||||||
|
|
||||||
var walker = Walker(node: argument_node)
|
var walker = Walker(node: argument_node)
|
||||||
@@ -324,7 +322,7 @@ extension ArgumentList: Compilable {
|
|||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(ArgumentList, CompilerContext)>.Error(
|
or: Result<ArgumentList>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(),
|
sourceLocation: node.toSourceLocation(),
|
||||||
withError: "Missing '(' in argument list component")))
|
withError: "Missing '(' in argument list component")))
|
||||||
@@ -333,7 +331,7 @@ extension ArgumentList: Compilable {
|
|||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(ArgumentList, CompilerContext)>.Error(
|
or: Result<ArgumentList>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(), withError: "Missing argument list component")))
|
sourceLocation: node.toSourceLocation(), withError: "Missing argument list component")))
|
||||||
|
|
||||||
@@ -342,25 +340,25 @@ extension ArgumentList: Compilable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension Argument: Compilable {
|
extension Argument: Compilable {
|
||||||
public typealias T = EvaluatableExpression
|
public typealias C = P4Expression
|
||||||
public static func Compile(
|
public static func Compile(
|
||||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Common.Result<(EvaluatableExpression, CompilerContext)> {
|
) -> Common.Result<P4Expression> {
|
||||||
let argument_node = node
|
let argument_node = node
|
||||||
#RequireNodeType<Node, (EvaluatableExpression, CompilerContext)>(
|
#RequireNodeType<Node, P4Expression>(
|
||||||
node: argument_node, type: "argument", nice_type_name: "argument")
|
node: argument_node, type: "argument", nice_type_name: "argument")
|
||||||
|
|
||||||
let expression_node = node.child(at: 0)!
|
let expression_node = node.child(at: 0)!
|
||||||
|
|
||||||
return switch Expression.Compile(node: expression_node, withContext: context) {
|
return switch Expression.Compile(node: expression_node, withContext: context) {
|
||||||
case .Ok(let compiled_expression): .Ok((compiled_expression, context))
|
case .Ok(let compiled_expression): .Ok(compiled_expression)
|
||||||
case .Error(let e): .Error(e)
|
case .Error(let e): .Error(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ContainsInvalidStatements(
|
func ContainsInvalidStatements(
|
||||||
statement: EvaluatableStatement, invalids: [EvaluatableStatement.Type]
|
statement: P4Statement, invalids: [P4Statement.Type]
|
||||||
) -> Bool {
|
) -> Bool {
|
||||||
for es in invalids {
|
for es in invalids {
|
||||||
if type(of: statement) == es {
|
if type(of: statement) == es {
|
||||||
@@ -370,8 +368,7 @@ func ContainsInvalidStatements(
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func ContainsInvalidStatements(block: BlockStatement, invalids: [EvaluatableStatement.Type]) -> Bool
|
func ContainsInvalidStatements(block: BlockStatement, invalids: [P4Statement.Type]) -> Bool {
|
||||||
{
|
|
||||||
return block.statements.contains { statement in
|
return block.statements.contains { statement in
|
||||||
for es in invalids {
|
for es in invalids {
|
||||||
if type(of: statement) == es {
|
if type(of: statement) == es {
|
||||||
|
|||||||
@@ -34,124 +34,3 @@ public func ConfigureP4Parser() -> Result<SwiftTreeSitter.Parser> {
|
|||||||
|
|
||||||
return .Ok(p)
|
return .Ok(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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 {
|
|
||||||
let instances: StaticVarValueScopes
|
|
||||||
let types: TypeTypeScopes
|
|
||||||
let externs: TypeTypeScopes
|
|
||||||
let ffis: [P4FFI]
|
|
||||||
let expected_type: P4QualifiedType?
|
|
||||||
let extern_context: Bool
|
|
||||||
|
|
||||||
public init() {
|
|
||||||
instances = StaticVarValueScopes().enter()
|
|
||||||
types = TypeTypeScopes().enter()
|
|
||||||
externs = TypeTypeScopes().enter()
|
|
||||||
expected_type = .none
|
|
||||||
extern_context = false
|
|
||||||
ffis = Array()
|
|
||||||
}
|
|
||||||
|
|
||||||
public init(withInstances _instances: StaticVarValueScopes, withTypes _types: TypeTypeScopes) {
|
|
||||||
instances = _instances
|
|
||||||
types = _types
|
|
||||||
externs = TypeTypeScopes().enter()
|
|
||||||
expected_type = .none
|
|
||||||
extern_context = false
|
|
||||||
ffis = Array()
|
|
||||||
}
|
|
||||||
|
|
||||||
public init(
|
|
||||||
withInstances _instances: StaticVarValueScopes, withTypes _types: TypeTypeScopes,
|
|
||||||
withExpectation expectation: P4QualifiedType?, withExtern extern: Bool,
|
|
||||||
withExterns externs: TypeTypeScopes, withFFIs foreigns: [P4FFI]
|
|
||||||
) {
|
|
||||||
instances = _instances
|
|
||||||
types = _types
|
|
||||||
expected_type = expectation
|
|
||||||
extern_context = extern
|
|
||||||
self.externs = externs
|
|
||||||
ffis = foreigns
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -22,33 +22,61 @@ import SwiftTreeSitter
|
|||||||
import TreeSitterExtensions
|
import TreeSitterExtensions
|
||||||
import TreeSitterP4
|
import TreeSitterP4
|
||||||
|
|
||||||
extension Declaration: CompilableDeclaration {
|
extension Declaration: CompilableStatement {
|
||||||
|
public static func CompileStatement(
|
||||||
|
node: Node, withContext context: CompilerContext
|
||||||
|
) -> Result<P4Statement> {
|
||||||
|
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
|
||||||
public static func Compile(
|
public static func Compile(
|
||||||
node: Node, withContext context: CompilerContext
|
node: Node, withContext context: CompilerContext
|
||||||
) -> Result<(Declaration, CompilerContext)?> {
|
) -> Result<Declaration> {
|
||||||
|
|
||||||
let declaration_compilers: [String: CompilableDeclaration.Type] = [
|
// Be kind to our user -- if we are at a declaration node, dive into it!
|
||||||
|
let declaration_node =
|
||||||
|
if node.nodeType == "declaration" {
|
||||||
|
node.child(at: 0)!
|
||||||
|
} else {
|
||||||
|
node
|
||||||
|
}
|
||||||
|
|
||||||
|
let declaration_compilers: [String: any Compilable<Declaration>.Type] = [
|
||||||
"function_declaration": FunctionDeclaration.self,
|
"function_declaration": FunctionDeclaration.self,
|
||||||
"control_declaration": Control.self,
|
"control_declaration": Control.self,
|
||||||
"type_declaration": P4Struct.self,
|
"type_declaration": P4Struct.self,
|
||||||
|
"parserDeclaration": Parser.self,
|
||||||
/// ASSUME: Type declarations are struct declarations.
|
/// ASSUME: Type declarations are struct declarations.
|
||||||
"extern_declaration": ExternDeclaration.self,
|
"extern_declaration": ExternDeclaration.self,
|
||||||
]
|
]
|
||||||
|
|
||||||
guard let declaration_compiler = declaration_compilers[node.nodeType!] else {
|
guard let declaration_compiler = declaration_compilers[declaration_node.nodeType!] else {
|
||||||
return .Ok(.none)
|
return .Error(
|
||||||
|
ErrorWithLocation(
|
||||||
|
sourceLocation: node.toSourceLocation(),
|
||||||
|
withError: "Could not find parser for declaration \(declaration_node.nodeType!)"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return declaration_compiler.Compile(node: node, withContext: context)
|
return declaration_compiler.Compile(node: declaration_node, withContext: context).map {
|
||||||
|
result in
|
||||||
|
.Ok(result)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension FunctionDeclaration: CompilableDeclaration {
|
extension FunctionDeclaration: Compilable {
|
||||||
|
public typealias C = Declaration
|
||||||
public static func Compile(
|
public static func Compile(
|
||||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Common.Result<(Declaration, CompilerContext)?> {
|
) -> Common.Result<Declaration> {
|
||||||
let function_declaration_node = node
|
let function_declaration_node = node
|
||||||
#RequireNodeType<Node, (ParameterList, CompilerContext)>(
|
#RequireNodeType<Node, ParameterList>(
|
||||||
node: function_declaration_node, type: "function_declaration",
|
node: function_declaration_node, type: "function_declaration",
|
||||||
nice_type_name: "Function Declaration")
|
nice_type_name: "Function Declaration")
|
||||||
|
|
||||||
@@ -59,7 +87,7 @@ extension FunctionDeclaration: CompilableDeclaration {
|
|||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
or: Result<Declaration>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: function_declaration_node.toSourceLocation(),
|
sourceLocation: function_declaration_node.toSourceLocation(),
|
||||||
withError: "Missing function declaration component")))
|
withError: "Missing function declaration component")))
|
||||||
@@ -72,7 +100,7 @@ extension FunctionDeclaration: CompilableDeclaration {
|
|||||||
walker.next()
|
walker.next()
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
or: Result<Declaration>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: function_declaration_node.toSourceLocation(),
|
sourceLocation: function_declaration_node.toSourceLocation(),
|
||||||
withError: "Missing function declaration component")))
|
withError: "Missing function declaration component")))
|
||||||
@@ -85,17 +113,16 @@ extension FunctionDeclaration: CompilableDeclaration {
|
|||||||
walker.next()
|
walker.next()
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
or: Result<Declaration>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: function_declaration_node.toSourceLocation(),
|
sourceLocation: function_declaration_node.toSourceLocation(),
|
||||||
withError: "Missing function declaration component")))
|
withError: "Missing function declaration component")))
|
||||||
|
|
||||||
let maybe_function_parameters = ParameterList.Compile(node: current_node!, withContext: context)
|
let maybe_function_parameters = ParameterList.Compile(node: current_node!, withContext: context)
|
||||||
guard case .Ok((let function_parameters, let updated_context)) = maybe_function_parameters
|
guard case .Ok(let function_parameters) = maybe_function_parameters
|
||||||
else {
|
else {
|
||||||
return .Error(maybe_function_parameters.error()!)
|
return .Error(maybe_function_parameters.error()!)
|
||||||
}
|
}
|
||||||
context = updated_context
|
|
||||||
|
|
||||||
var function_body: BlockStatement? = .none
|
var function_body: BlockStatement? = .none
|
||||||
|
|
||||||
@@ -113,10 +140,10 @@ extension FunctionDeclaration: CompilableDeclaration {
|
|||||||
withContext: context.update(newInstances: function_scope).update(
|
withContext: context.update(newInstances: function_scope).update(
|
||||||
newExpectation: function_type))
|
newExpectation: function_type))
|
||||||
|
|
||||||
guard case .Ok((let parsed_function_body, _)) = maybe_function_body else {
|
guard case .Ok(let parsed_function_body) = maybe_function_body else {
|
||||||
return .Error(maybe_function_body.error()!)
|
return .Error(maybe_function_body.error()!)
|
||||||
}
|
}
|
||||||
function_body = (parsed_function_body as! BlockStatement)
|
function_body = parsed_function_body
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// If we are in an extern context, no body is okay!
|
// If we are in an extern context, no body is okay!
|
||||||
@@ -142,33 +169,29 @@ extension FunctionDeclaration: CompilableDeclaration {
|
|||||||
// And, do not update the context if we are compiling in an
|
// And, do not update the context if we are compiling in an
|
||||||
// extern context -- the wrapping extern declaration will take care of that.
|
// extern context -- the wrapping extern declaration will take care of that.
|
||||||
return .Ok(
|
return .Ok(
|
||||||
(
|
|
||||||
function_declaration,
|
function_declaration,
|
||||||
context.extern_context
|
|
||||||
? context
|
|
||||||
: context.update(
|
|
||||||
newTypes: context.types.declare(
|
|
||||||
identifier: function_name, withValue: function_declaration.identifier.type.baseType())
|
|
||||||
)
|
)
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension P4Struct: CompilableDeclaration {
|
extension P4Struct: Compilable {
|
||||||
|
public typealias C = Declaration
|
||||||
static public func Compile(
|
static public func Compile(
|
||||||
node: Node, withContext context: CompilerContext
|
node: Node, withContext context: CompilerContext
|
||||||
) -> Result<(Declaration, CompilerContext)?> {
|
) -> Result<Declaration> {
|
||||||
let struct_declaration_node = node.child(at: 0)!
|
let struct_declaration_node = node.child(at: 0)!
|
||||||
var walker = Walker(node: struct_declaration_node)
|
var walker = Walker(node: struct_declaration_node)
|
||||||
var currentNode: Node? = .none
|
var currentNode: Node? = .none
|
||||||
|
|
||||||
#SkipUnlessNodeType(node: struct_declaration_node, type: "struct_declaration")
|
#RequireNodeType<Node, Result<Declaration>>(
|
||||||
|
node: struct_declaration_node, type: "struct_declaration",
|
||||||
|
nice_type_name: "struct declaration")
|
||||||
|
|
||||||
// Skip the keyword struct
|
// Skip the keyword struct
|
||||||
walker.next()
|
walker.next()
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: currentNode, thing: walker.getNext(),
|
result: currentNode, thing: walker.getNext(),
|
||||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
or: Result<Declaration>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: struct_declaration_node.toSourceLocation(),
|
sourceLocation: struct_declaration_node.toSourceLocation(),
|
||||||
withError: "Missing function declaration component")))
|
withError: "Missing function declaration component")))
|
||||||
@@ -185,7 +208,7 @@ extension P4Struct: CompilableDeclaration {
|
|||||||
walker.next()
|
walker.next()
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: currentNode, thing: walker.getNext(),
|
result: currentNode, thing: walker.getNext(),
|
||||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
or: Result<Declaration>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: struct_declaration_node.toSourceLocation(),
|
sourceLocation: struct_declaration_node.toSourceLocation(),
|
||||||
withError: "Missing function declaration component")))
|
withError: "Missing function declaration component")))
|
||||||
@@ -197,15 +220,7 @@ extension P4Struct: CompilableDeclaration {
|
|||||||
id: struct_identifier,
|
id: struct_identifier,
|
||||||
withType: P4QualifiedType(
|
withType: P4QualifiedType(
|
||||||
P4Struct(withName: struct_identifier, andFields: P4StructFields([])))))
|
P4Struct(withName: struct_identifier, andFields: P4StructFields([])))))
|
||||||
return Result.Ok(
|
return Result.Ok(struc)
|
||||||
(
|
|
||||||
struc,
|
|
||||||
context.extern_context
|
|
||||||
? context
|
|
||||||
: context.update(
|
|
||||||
newTypes: context.types.declare(
|
|
||||||
identifier: struct_identifier, withValue: struc.identifier.type.baseType()))
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var parse_errs: (any Errorable)? = .none
|
var parse_errs: (any Errorable)? = .none
|
||||||
@@ -217,13 +232,12 @@ extension P4Struct: CompilableDeclaration {
|
|||||||
switch VariableDeclarationStatement.Compile(
|
switch VariableDeclarationStatement.Compile(
|
||||||
node: declaration_field, withContext: current_context)
|
node: declaration_field, withContext: current_context)
|
||||||
{
|
{
|
||||||
case .Ok((let declaration, let updated_context)):
|
case .Ok(let declaration):
|
||||||
let variable_declaration = declaration as! VariableDeclarationStatement
|
let variable_declaration = declaration as! VariableDeclarationStatement
|
||||||
parsed_fields.append(
|
parsed_fields.append(
|
||||||
P4StructFieldIdentifier(
|
P4StructFieldIdentifier(
|
||||||
id: variable_declaration.identifier, withType: variable_declaration.initializer.type()
|
id: variable_declaration.identifier, withType: variable_declaration.initializer.type()
|
||||||
))
|
))
|
||||||
current_context = updated_context
|
|
||||||
case .Error(let e):
|
case .Error(let e):
|
||||||
parse_errs =
|
parse_errs =
|
||||||
if let e = parse_errs {
|
if let e = parse_errs {
|
||||||
@@ -245,24 +259,19 @@ extension P4Struct: CompilableDeclaration {
|
|||||||
withType: P4QualifiedType(
|
withType: P4QualifiedType(
|
||||||
P4Struct(
|
P4Struct(
|
||||||
withName: struct_identifier, andFields: P4StructFields(parsed_fields)))))
|
withName: struct_identifier, andFields: P4StructFields(parsed_fields)))))
|
||||||
return .Ok(
|
return .Ok(declared_struct)
|
||||||
(
|
|
||||||
declared_struct,
|
|
||||||
current_context.extern_context
|
|
||||||
? current_context
|
|
||||||
: current_context.update(
|
|
||||||
newTypes: current_context.types.declare(
|
|
||||||
identifier: struct_identifier, withValue: declared_struct.identifier.type.baseType()))
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension P4Lang.Parser: CompilableDeclaration {
|
extension P4Lang.Parser: Compilable {
|
||||||
|
public typealias C = Declaration
|
||||||
|
|
||||||
public static func Compile(
|
public static func Compile(
|
||||||
node: Node, withContext context: CompilerContext
|
node: Node, withContext context: CompilerContext
|
||||||
) -> Result<(Declaration, CompilerContext)?> {
|
) -> Result<Declaration> {
|
||||||
let parser_node = node
|
let parser_node = node
|
||||||
#SkipUnlessNodeType<Node>(node: parser_node, type: "parserDeclaration")
|
#RequireNodeType<Node, Result<Declaration>>(
|
||||||
|
node: parser_node, type: "parserDeclaration", nice_type_name: "parser declaration")
|
||||||
var current_context = context
|
var current_context = context
|
||||||
|
|
||||||
var walker = Walker(node: parser_node)
|
var walker = Walker(node: parser_node)
|
||||||
@@ -270,7 +279,7 @@ extension P4Lang.Parser: CompilableDeclaration {
|
|||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
or: Result<Declaration>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: parser_node.toSourceLocation(),
|
sourceLocation: parser_node.toSourceLocation(),
|
||||||
withError: "Missing elements of parser declaration")))
|
withError: "Missing elements of parser declaration")))
|
||||||
@@ -294,7 +303,7 @@ extension P4Lang.Parser: CompilableDeclaration {
|
|||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: type_node_child, thing: type_node_walker.getNext(),
|
result: type_node_child, thing: type_node_walker.getNext(),
|
||||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
or: Result<Declaration>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: parser_node.toSourceLocation(),
|
sourceLocation: parser_node.toSourceLocation(),
|
||||||
withError: "Missing elements of parser type in parser declaration")))
|
withError: "Missing elements of parser type in parser declaration")))
|
||||||
@@ -310,7 +319,7 @@ extension P4Lang.Parser: CompilableDeclaration {
|
|||||||
type_node_walker.next()
|
type_node_walker.next()
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: type_node_child, thing: type_node_walker.getNext(),
|
result: type_node_child, thing: type_node_walker.getNext(),
|
||||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
or: Result<Declaration>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: type_node_child!.toSourceLocation(),
|
sourceLocation: type_node_child!.toSourceLocation(),
|
||||||
withError: "Missing name in parser type declaration")))
|
withError: "Missing name in parser type declaration")))
|
||||||
@@ -324,15 +333,14 @@ extension P4Lang.Parser: CompilableDeclaration {
|
|||||||
type_node_walker.next()
|
type_node_walker.next()
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: type_node_child, thing: type_node_walker.getNext(),
|
result: type_node_child, thing: type_node_walker.getNext(),
|
||||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
or: Result<Declaration>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: type_node_child!.toSourceLocation(),
|
sourceLocation: type_node_child!.toSourceLocation(),
|
||||||
withError: "Missing parser parameters")))
|
withError: "Missing parser parameters")))
|
||||||
|
|
||||||
switch ParameterList.Compile(node: type_node_child!, withContext: current_context) {
|
switch ParameterList.Compile(node: type_node_child!, withContext: current_context) {
|
||||||
case .Ok(let (parsed_parameter_list, updated_context)):
|
case .Ok(let parsed_parameter_list):
|
||||||
parameter_list = parsed_parameter_list
|
parameter_list = parsed_parameter_list
|
||||||
current_context = updated_context
|
|
||||||
case .Error(let e):
|
case .Error(let e):
|
||||||
return .Error(e)
|
return .Error(e)
|
||||||
}
|
}
|
||||||
@@ -348,7 +356,7 @@ extension P4Lang.Parser: CompilableDeclaration {
|
|||||||
walker.next()
|
walker.next()
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
or: Result<Declaration>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: parser_node.toSourceLocation(),
|
sourceLocation: parser_node.toSourceLocation(),
|
||||||
withError: "Missing parser declaration component")))
|
withError: "Missing parser declaration component")))
|
||||||
@@ -356,7 +364,7 @@ extension P4Lang.Parser: CompilableDeclaration {
|
|||||||
walker.next()
|
walker.next()
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
or: Result<Declaration>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: parser_node.toSourceLocation(),
|
sourceLocation: parser_node.toSourceLocation(),
|
||||||
withError: "Missing elements of parser declaration")))
|
withError: "Missing elements of parser declaration")))
|
||||||
@@ -371,7 +379,7 @@ extension P4Lang.Parser: CompilableDeclaration {
|
|||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
or: Result<Declaration>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: parser_node.toSourceLocation(),
|
sourceLocation: parser_node.toSourceLocation(),
|
||||||
withError: "Missing body of parser declaration")))
|
withError: "Missing body of parser declaration")))
|
||||||
@@ -381,7 +389,7 @@ extension P4Lang.Parser: CompilableDeclaration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TODO: Handle extern parsers.
|
/// TODO: Handle extern parsers.
|
||||||
switch SpecialCompilers.Compile(
|
switch SpecialCompilers.CompileParserBody(
|
||||||
withName: parser_name!, withParameters: parameter_list, node: current_node!,
|
withName: parser_name!, withParameters: parameter_list, node: current_node!,
|
||||||
withContext: current_context)
|
withContext: current_context)
|
||||||
{
|
{
|
||||||
@@ -390,24 +398,21 @@ extension P4Lang.Parser: CompilableDeclaration {
|
|||||||
TypedIdentifier(id: parser.name, withType: P4QualifiedType(parser)))
|
TypedIdentifier(id: parser.name, withType: P4QualifiedType(parser)))
|
||||||
// Create a new context with the name of the parser that was just compiled in scope.
|
// Create a new context with the name of the parser that was just compiled in scope.
|
||||||
return .Ok(
|
return .Ok(
|
||||||
(
|
|
||||||
parser_declaration,
|
parser_declaration,
|
||||||
context.extern_context
|
)
|
||||||
? context
|
|
||||||
: updated_context.update(
|
|
||||||
newTypes: updated_context.types.declare(identifier: parser.name, withValue: parser))
|
|
||||||
))
|
|
||||||
case Result.Error(let error): return .Error(error)
|
case Result.Error(let error): return .Error(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Control: CompilableDeclaration {
|
extension Control: Compilable {
|
||||||
|
public typealias C = Declaration
|
||||||
public static func Compile(
|
public static func Compile(
|
||||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Common.Result<(Declaration, CompilerContext)?> {
|
) -> Common.Result<Declaration> {
|
||||||
|
|
||||||
#SkipUnlessNodeType<Node>(node: node, type: "control_declaration")
|
#RequireNodeType<Node, Result<Declaration>>(
|
||||||
|
node: node, type: "control_declaration", nice_type_name: "control declaration")
|
||||||
|
|
||||||
var walker = Walker(node: node)
|
var walker = Walker(node: node)
|
||||||
var current_node: Node? = .none
|
var current_node: Node? = .none
|
||||||
@@ -417,7 +422,7 @@ extension Control: CompilableDeclaration {
|
|||||||
walker.next()
|
walker.next()
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
or: Result<Declaration>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(),
|
sourceLocation: node.toSourceLocation(),
|
||||||
withError: "Missing control declaration component")))
|
withError: "Missing control declaration component")))
|
||||||
@@ -433,18 +438,17 @@ extension Control: CompilableDeclaration {
|
|||||||
walker.next()
|
walker.next()
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
or: Result<Declaration>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(),
|
sourceLocation: node.toSourceLocation(),
|
||||||
withError: "Missing control declaration component")))
|
withError: "Missing control declaration component")))
|
||||||
|
|
||||||
let maybe_control_parameters = ParameterList.Compile(
|
let maybe_control_parameters = ParameterList.Compile(
|
||||||
node: current_node!, withContext: local_context)
|
node: current_node!, withContext: local_context)
|
||||||
guard case .Ok((let control_parameters, let updated_context)) = maybe_control_parameters
|
guard case .Ok(let control_parameters) = maybe_control_parameters
|
||||||
else {
|
else {
|
||||||
return .Error(maybe_control_parameters.error()!)
|
return .Error(maybe_control_parameters.error()!)
|
||||||
}
|
}
|
||||||
local_context = updated_context
|
|
||||||
|
|
||||||
// Before continuing, make sure to put the parameters into context.
|
// Before continuing, make sure to put the parameters into context.
|
||||||
var control_scope = local_context.instances.enter()
|
var control_scope = local_context.instances.enter()
|
||||||
@@ -459,7 +463,7 @@ extension Control: CompilableDeclaration {
|
|||||||
walker.next()
|
walker.next()
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
or: Result<Declaration>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(),
|
sourceLocation: node.toSourceLocation(),
|
||||||
withError: "Missing control declaration component")))
|
withError: "Missing control declaration component")))
|
||||||
@@ -476,12 +480,11 @@ extension Control: CompilableDeclaration {
|
|||||||
let maybe_action_declaration = Action.Compile(
|
let maybe_action_declaration = Action.Compile(
|
||||||
node: current_node, withContext: local_context)
|
node: current_node, withContext: local_context)
|
||||||
guard
|
guard
|
||||||
case .Ok((let action_declaration, let updated_context)) = maybe_action_declaration
|
case .Ok(let action_declaration) = maybe_action_declaration
|
||||||
else {
|
else {
|
||||||
return .Error(maybe_action_declaration.error()!)
|
return .Error(maybe_action_declaration.error()!)
|
||||||
}
|
}
|
||||||
actions.append(action_declaration)
|
actions.append(action_declaration)
|
||||||
local_context = updated_context
|
|
||||||
// Now, add the declaration into the context.
|
// Now, add the declaration into the context.
|
||||||
local_context = local_context.update(
|
local_context = local_context.update(
|
||||||
newTypes: local_context.types.declare(
|
newTypes: local_context.types.declare(
|
||||||
@@ -490,22 +493,20 @@ extension Control: CompilableDeclaration {
|
|||||||
let maybe_table_declaration = Table.Compile(
|
let maybe_table_declaration = Table.Compile(
|
||||||
node: current_node, withContext: local_context)
|
node: current_node, withContext: local_context)
|
||||||
guard
|
guard
|
||||||
case .Ok((let table_declaration, let updated_context)) = maybe_table_declaration
|
case .Ok(let table_declaration) = maybe_table_declaration
|
||||||
else {
|
else {
|
||||||
return .Error(maybe_table_declaration.error()!)
|
return .Error(maybe_table_declaration.error()!)
|
||||||
}
|
}
|
||||||
tables.append(table_declaration)
|
tables.append(table_declaration)
|
||||||
local_context = updated_context
|
|
||||||
} else if current_node.nodeType == "apply_statement" {
|
} else if current_node.nodeType == "apply_statement" {
|
||||||
// When we see an apply, that is it for the actions and the tables.
|
// When we see an apply, that is it for the actions and the tables.
|
||||||
let maybe_apply_statement = ApplyStatement.Compile(
|
let maybe_apply_statement = ApplyStatement.Compile(
|
||||||
node: current_node, withContext: local_context)
|
node: current_node, withContext: local_context)
|
||||||
guard
|
guard
|
||||||
case .Ok((let apply_statement, let updated_context)) = maybe_apply_statement
|
case .Ok(let apply_statement) = maybe_apply_statement
|
||||||
else {
|
else {
|
||||||
return .Error(maybe_apply_statement.error()!)
|
return .Error(maybe_apply_statement.error()!)
|
||||||
}
|
}
|
||||||
local_context = updated_context
|
|
||||||
apply = (apply_statement as! ApplyStatement)
|
apply = (apply_statement as! ApplyStatement)
|
||||||
|
|
||||||
// The apply is the last thing in a control declaration.
|
// The apply is the last thing in a control declaration.
|
||||||
@@ -555,24 +556,16 @@ extension Control: CompilableDeclaration {
|
|||||||
|
|
||||||
// Don't forget to add the newly declared Control to the instance that we were given
|
// 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).
|
// (and not the one that we entered to do the parsing of this Control).
|
||||||
return .Ok(
|
return .Ok(declared_control)
|
||||||
(
|
|
||||||
declared_control,
|
|
||||||
context.extern_context
|
|
||||||
? context
|
|
||||||
: context.update(
|
|
||||||
newTypes: context.types.declare(
|
|
||||||
identifier: control_name, withValue: control))
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Action: Compilable {
|
extension Action: Compilable {
|
||||||
public typealias T = Action
|
public typealias C = Action
|
||||||
public static func Compile(
|
public static func Compile(
|
||||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Common.Result<(Action, CompilerContext)> {
|
) -> Result<Action> {
|
||||||
#RequireNodeType<Node, (P4Type, CompilerContext)>(
|
#RequireNodeType<Node, P4Type>(
|
||||||
node: node, type: "action_declaration", nice_type_name: "Action Declaration")
|
node: node, type: "action_declaration", nice_type_name: "Action Declaration")
|
||||||
|
|
||||||
var walker = Walker(node: node)
|
var walker = Walker(node: node)
|
||||||
@@ -584,7 +577,7 @@ extension Action: Compilable {
|
|||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(Action, CompilerContext)>.Error(
|
or: Result<Action>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(), withError: "Missing action declaration component"
|
sourceLocation: node.toSourceLocation(), withError: "Missing action declaration component"
|
||||||
))
|
))
|
||||||
@@ -601,7 +594,7 @@ extension Action: Compilable {
|
|||||||
walker.next()
|
walker.next()
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(Action, CompilerContext)>.Error(
|
or: Result<Action>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(), withError: "Missing action declaration component"
|
sourceLocation: node.toSourceLocation(), withError: "Missing action declaration component"
|
||||||
))
|
))
|
||||||
@@ -609,11 +602,10 @@ extension Action: Compilable {
|
|||||||
|
|
||||||
let maybe_action_parameters = ParameterList.Compile(
|
let maybe_action_parameters = ParameterList.Compile(
|
||||||
node: current_node!, withContext: current_context)
|
node: current_node!, withContext: current_context)
|
||||||
guard case .Ok((let action_parameters, let updated_context)) = maybe_action_parameters
|
guard case .Ok(let action_parameters) = maybe_action_parameters
|
||||||
else {
|
else {
|
||||||
return .Error(maybe_action_parameters.error()!)
|
return .Error(maybe_action_parameters.error()!)
|
||||||
}
|
}
|
||||||
current_context = updated_context
|
|
||||||
|
|
||||||
// Check whether the parameters are in the proper order.
|
// Check whether the parameters are in the proper order.
|
||||||
let remaining_parameters = action_parameters.parameters.drop(while: {
|
let remaining_parameters = action_parameters.parameters.drop(while: {
|
||||||
@@ -629,7 +621,7 @@ extension Action: Compilable {
|
|||||||
walker.next()
|
walker.next()
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(Action, CompilerContext)>.Error(
|
or: Result<Action>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(), withError: "Missing action declaration component"
|
sourceLocation: node.toSourceLocation(), withError: "Missing action declaration component"
|
||||||
))
|
))
|
||||||
@@ -644,29 +636,26 @@ extension Action: Compilable {
|
|||||||
|
|
||||||
let maybe_action_body = BlockStatement.Compile(
|
let maybe_action_body = BlockStatement.Compile(
|
||||||
node: current_node!, withContext: context.update(newInstances: function_scope))
|
node: current_node!, withContext: context.update(newInstances: function_scope))
|
||||||
guard case .Ok((let action_body, _)) = maybe_action_body else {
|
guard case .Ok(let action_body) = maybe_action_body else {
|
||||||
return .Error(maybe_action_body.error()!)
|
return .Error(maybe_action_body.error()!)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO: Actions cannot contain switches!
|
/// TODO: Actions cannot contain switches!
|
||||||
|
|
||||||
return .Ok(
|
return .Ok(
|
||||||
(
|
|
||||||
Action(
|
Action(
|
||||||
named: action_name, withParameters: action_parameters,
|
named: action_name, withParameters: action_parameters,
|
||||||
withBody: (action_body as! BlockStatement)),
|
withBody: (action_body as! BlockStatement)))
|
||||||
current_context
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension TableKeyEntry: Compilable {
|
extension TableKeyEntry: Compilable {
|
||||||
public typealias T = TableKeyEntry
|
public typealias C = TableKeyEntry
|
||||||
public static func Compile(
|
public static func Compile(
|
||||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Common.Result<(TableKeyEntry, CompilerContext)> {
|
) -> Result<TableKeyEntry> {
|
||||||
|
|
||||||
#RequireNodeType<Node, (P4Type, CompilerContext)>(
|
#RequireNodeType<Node, TableKeyEntry>(
|
||||||
node: node, type: "table_key_entry", nice_type_name: "Table Key Entry")
|
node: node, type: "table_key_entry", nice_type_name: "Table Key Entry")
|
||||||
|
|
||||||
var walker = Walker(node: node)
|
var walker = Walker(node: node)
|
||||||
@@ -677,7 +666,7 @@ extension TableKeyEntry: Compilable {
|
|||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(TableKeyEntry, CompilerContext)>.Error(
|
or: Result<TableKeyEntry>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(),
|
sourceLocation: node.toSourceLocation(),
|
||||||
withError: "Missing table key entry declaration component")))
|
withError: "Missing table key entry declaration component")))
|
||||||
@@ -693,31 +682,31 @@ extension TableKeyEntry: Compilable {
|
|||||||
walker.next()
|
walker.next()
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(TableKeyEntry, CompilerContext)>.Error(
|
or: Result<TableKeyEntry>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(),
|
sourceLocation: node.toSourceLocation(),
|
||||||
withError: "Missing table key entry declaration component")))
|
withError: "Missing table key entry declaration component")))
|
||||||
|
|
||||||
let maybe_match_type = TableKeyMatchType.Compile(
|
let maybe_match_type = TableKeyMatchType.Compile(
|
||||||
node: current_node!, withContext: current_context)
|
node: current_node!, withContext: current_context)
|
||||||
guard case .Ok((let match_type, _)) = maybe_match_type else {
|
guard case .Ok(let match_type) = maybe_match_type else {
|
||||||
return .Error(maybe_match_type.error()!)
|
return .Error(maybe_match_type.error()!)
|
||||||
}
|
}
|
||||||
|
|
||||||
return .Ok((TableKeyEntry(keyset_expression as! KeysetExpression, match_type), current_context))
|
return .Ok(TableKeyEntry(keyset_expression as! KeysetExpression, match_type))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension TableKeyMatchType: Compilable {
|
extension TableKeyMatchType: Compilable {
|
||||||
public typealias T = TableKeyMatchType
|
public typealias C = TableKeyMatchType
|
||||||
public static func Compile(
|
public static func Compile(
|
||||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Common.Result<(TableKeyMatchType, CompilerContext)> {
|
) -> Result<TableKeyMatchType> {
|
||||||
#RequireNodeType<Node, (TableKeyMatchType, CompilerContext)>(
|
#RequireNodeType<Node, TableKeyMatchType>(
|
||||||
node: node, type: "table_key_match_type", nice_type_name: "Table Key Match Type")
|
node: node, type: "table_key_match_type", nice_type_name: "Table Key Match Type")
|
||||||
|
|
||||||
if node.text! == "exact" {
|
if node.text! == "exact" {
|
||||||
return .Ok((TableKeyMatchType.Exact, context))
|
return .Ok(TableKeyMatchType.Exact)
|
||||||
}
|
}
|
||||||
return .Error(
|
return .Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
@@ -727,11 +716,11 @@ extension TableKeyMatchType: Compilable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension TableKeys: Compilable {
|
extension TableKeys: Compilable {
|
||||||
public typealias T = TableKeys
|
public typealias C = TableKeys
|
||||||
public static func Compile(
|
public static func Compile(
|
||||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Common.Result<(TableKeys, CompilerContext)> {
|
) -> Result<TableKeys> {
|
||||||
#RequireNodeType<Node, (TableKeyMatchType, CompilerContext)>(
|
#RequireNodeType<Node, TableKeyMatchType>(
|
||||||
node: node, type: "table_keys", nice_type_name: "Table Keys")
|
node: node, type: "table_keys", nice_type_name: "Table Keys")
|
||||||
|
|
||||||
var walker = Walker(node: node)
|
var walker = Walker(node: node)
|
||||||
@@ -746,7 +735,7 @@ extension TableKeys: Compilable {
|
|||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(TableKeys, CompilerContext)>.Error(
|
or: Result<TableKeys>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(),
|
sourceLocation: node.toSourceLocation(),
|
||||||
withError: "Missing table keys declaration component in control declaration"))
|
withError: "Missing table keys declaration component in control declaration"))
|
||||||
@@ -754,7 +743,7 @@ extension TableKeys: Compilable {
|
|||||||
|
|
||||||
let (keys, errors) = walker.try_map(n: node.childCount - 1, onlyNamed: true) { current_node in
|
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 TableKeyEntry.Compile(node: current_node, withContext: context) {
|
||||||
case .Ok((let keyset_expression, _)): .Ok(keyset_expression)
|
case .Ok(let keyset_expression): .Ok(keyset_expression)
|
||||||
case .Error(let e): .Error(e)
|
case .Error(let e): .Error(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -769,16 +758,16 @@ extension TableKeys: Compilable {
|
|||||||
}.joined(separator: ";"))))
|
}.joined(separator: ";"))))
|
||||||
}
|
}
|
||||||
|
|
||||||
return .Ok((TableKeys(withEntries: keys), context))
|
return .Ok(TableKeys(withEntries: keys))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension TableActionsProperty: Compilable {
|
extension TableActionsProperty: Compilable {
|
||||||
public typealias T = TableActionsProperty
|
public typealias C = TableActionsProperty
|
||||||
public static func Compile(
|
public static func Compile(
|
||||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Common.Result<(TableActionsProperty, CompilerContext)> {
|
) -> Result<TableActionsProperty> {
|
||||||
#RequireNodeType<Node, (TableActionsProperty, CompilerContext)>(
|
#RequireNodeType<Node, TableActionsProperty>(
|
||||||
node: node, type: "table_actions", nice_type_name: "Table Actions")
|
node: node, type: "table_actions", nice_type_name: "Table Actions")
|
||||||
|
|
||||||
var walker = Walker(node: node)
|
var walker = Walker(node: node)
|
||||||
@@ -793,7 +782,7 @@ extension TableActionsProperty: Compilable {
|
|||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(TableActionsProperty, CompilerContext)>.Error(
|
or: Result<TableActionsProperty>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(),
|
sourceLocation: node.toSourceLocation(),
|
||||||
withError: "Missing table actions declaration component in control declaration"))
|
withError: "Missing table actions declaration component in control declaration"))
|
||||||
@@ -828,16 +817,16 @@ extension TableActionsProperty: Compilable {
|
|||||||
}.joined(separator: ";"))))
|
}.joined(separator: ";"))))
|
||||||
}
|
}
|
||||||
|
|
||||||
return .Ok((TableActionsProperty(actions), context))
|
return .Ok(TableActionsProperty(actions))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
extension TablePropertyList: Compilable {
|
extension TablePropertyList: Compilable {
|
||||||
public typealias T = TablePropertyList
|
public typealias C = TablePropertyList
|
||||||
public static func Compile(
|
public static func Compile(
|
||||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Common.Result<(TablePropertyList, CompilerContext)> {
|
) -> Result<TablePropertyList> {
|
||||||
|
|
||||||
#RequireNodeType<Node, (P4Type, CompilerContext)>(
|
#RequireNodeType<Node, TablePropertyList>(
|
||||||
node: node, type: "table_property_list", nice_type_name: "Table Property List")
|
node: node, type: "table_property_list", nice_type_name: "Table Property List")
|
||||||
|
|
||||||
var current_context = context
|
var current_context = context
|
||||||
@@ -849,15 +838,13 @@ extension TablePropertyList: Compilable {
|
|||||||
node.enumerateNamedChildren { child in
|
node.enumerateNamedChildren { child in
|
||||||
if child.nodeType == "table_keys" {
|
if child.nodeType == "table_keys" {
|
||||||
switch TableKeys.Compile(node: child, withContext: current_context) {
|
switch TableKeys.Compile(node: child, withContext: current_context) {
|
||||||
case .Ok((let table_key, let updated_context)):
|
case .Ok(let table_key):
|
||||||
current_context = updated_context
|
|
||||||
keys.append(table_key)
|
keys.append(table_key)
|
||||||
case .Error(let e): errors.append(e)
|
case .Error(let e): errors.append(e)
|
||||||
}
|
}
|
||||||
} else if child.nodeType == "table_actions" {
|
} else if child.nodeType == "table_actions" {
|
||||||
switch TableActionsProperty.Compile(node: child, withContext: current_context) {
|
switch TableActionsProperty.Compile(node: child, withContext: current_context) {
|
||||||
case .Ok((let table_action_property, let updated_context)):
|
case .Ok(let table_action_property):
|
||||||
current_context = updated_context
|
|
||||||
actions.append(table_action_property)
|
actions.append(table_action_property)
|
||||||
case .Error(let e): errors.append(e)
|
case .Error(let e): errors.append(e)
|
||||||
}
|
}
|
||||||
@@ -900,19 +887,19 @@ extension TablePropertyList: Compilable {
|
|||||||
actions.append(TableActionsProperty())
|
actions.append(TableActionsProperty())
|
||||||
}
|
}
|
||||||
|
|
||||||
return .Ok((TablePropertyList(withActions: actions[0], withKeys: keys[0]), current_context))
|
return .Ok(TablePropertyList(withActions: actions[0], withKeys: keys[0]))
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Table: Compilable {
|
extension Table: Compilable {
|
||||||
public typealias T = Table
|
public typealias C = Table
|
||||||
public static func Compile(
|
public static func Compile(
|
||||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Common.Result<(Table, CompilerContext)> {
|
) -> Result<Table> {
|
||||||
|
|
||||||
let table_declaration_node = node
|
let table_declaration_node = node
|
||||||
#RequireNodeType<Node, (P4Type, CompilerContext)>(
|
#RequireNodeType<Node, Table>(
|
||||||
node: table_declaration_node, type: "table_declaration", nice_type_name: "Table Declaration")
|
node: table_declaration_node, type: "table_declaration", nice_type_name: "Table Declaration")
|
||||||
|
|
||||||
var walker = Walker(node: table_declaration_node)
|
var walker = Walker(node: table_declaration_node)
|
||||||
@@ -924,7 +911,7 @@ extension Table: Compilable {
|
|||||||
walker.next() // Skip the XXX?
|
walker.next() // Skip the XXX?
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(Table, CompilerContext)>.Error(
|
or: Result<Table>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(), withError: "Missing table declaration component")
|
sourceLocation: node.toSourceLocation(), withError: "Missing table declaration component")
|
||||||
))
|
))
|
||||||
@@ -942,46 +929,43 @@ extension Table: Compilable {
|
|||||||
walker.next()
|
walker.next()
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(Table, CompilerContext)>.Error(
|
or: Result<Table>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(), withError: "Missing table declaration component")
|
sourceLocation: node.toSourceLocation(), withError: "Missing table declaration component")
|
||||||
))
|
))
|
||||||
|
|
||||||
let maybe_table_property_list = TablePropertyList.Compile(
|
let maybe_table_property_list = TablePropertyList.Compile(
|
||||||
node: current_node!, withContext: current_context)
|
node: current_node!, withContext: current_context)
|
||||||
guard case .Ok((let table_property_list, _)) = maybe_table_property_list else {
|
guard case .Ok(let table_property_list) = maybe_table_property_list else {
|
||||||
return Result.Error(maybe_table_property_list.error()!)
|
return Result.Error(maybe_table_property_list.error()!)
|
||||||
}
|
}
|
||||||
|
|
||||||
return .Ok(
|
return .Ok(Table(withName: table_name, withPropertyList: table_property_list))
|
||||||
(Table(withName: table_name, withPropertyList: table_property_list), current_context))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ExternDeclaration: CompilableDeclaration {
|
extension ExternDeclaration: Compilable {
|
||||||
|
public typealias C = Declaration
|
||||||
public static func Compile(
|
public static func Compile(
|
||||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Common.Result<(Declaration, CompilerContext)?> {
|
) -> Result<Declaration> {
|
||||||
let extern_declaration_node = node
|
let extern_declaration_node = node
|
||||||
#RequireNodeType<Node, (Declaration, CompilerContext)>(
|
#RequireNodeType<Node, Declaration>(
|
||||||
node: extern_declaration_node, type: "extern_declaration",
|
node: extern_declaration_node, type: "extern_declaration",
|
||||||
nice_type_name: "Extern Declaration")
|
nice_type_name: "Extern Declaration")
|
||||||
|
|
||||||
let declaration_node = extern_declaration_node.child(at: 1)!
|
let declaration_node = extern_declaration_node.child(at: 1)!
|
||||||
#RequireNodeType<Node, (Declaration, CompilerContext)>(
|
#RequireNodeType<Node, Declaration>(
|
||||||
node: declaration_node, type: "declaration", nice_type_name: "Declaration")
|
node: declaration_node, type: "declaration", nice_type_name: "Declaration")
|
||||||
let declarationed_node = declaration_node.child(at: 0)!
|
let declarationed_node = declaration_node.child(at: 0)!
|
||||||
|
|
||||||
let maybe_declared = Declaration.Compile(
|
let maybe_declared = Declaration.Compile(
|
||||||
node: declarationed_node, withContext: context.update(newExtern: true))
|
node: declarationed_node, withContext: context.update(newExtern: true))
|
||||||
|
|
||||||
guard case .Ok(let maybe_declared) = maybe_declared else {
|
guard case .Ok(let declared) = maybe_declared else {
|
||||||
return .Error(maybe_declared.error()!)
|
return .Error(maybe_declared.error()!)
|
||||||
}
|
}
|
||||||
|
|
||||||
guard case .some((let declared, _)) = maybe_declared else {
|
|
||||||
return .Ok(.none)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Before we are okay with this declaration, it must already be registered as an extern
|
// Before we are okay with this declaration, it must already be registered as an extern
|
||||||
// with the matching "stuff".
|
// with the matching "stuff".
|
||||||
|
|
||||||
@@ -1000,11 +984,7 @@ extension ExternDeclaration: CompilableDeclaration {
|
|||||||
let extern_declaration = Declaration(extern: declared, ffi: found_ffi)
|
let extern_declaration = Declaration(extern: declared, ffi: found_ffi)
|
||||||
|
|
||||||
return .Ok(
|
return .Ok(
|
||||||
(
|
|
||||||
extern_declaration,
|
extern_declaration,
|
||||||
context.update(
|
)
|
||||||
newExterns: context.externs.declare(
|
|
||||||
identifier: declared.identifier, withValue: extern_declaration))
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,22 +21,10 @@ import P4Runtime
|
|||||||
import SwiftTreeSitter
|
import SwiftTreeSitter
|
||||||
import TreeSitterP4
|
import TreeSitterP4
|
||||||
|
|
||||||
protocol CompilableExpression {
|
|
||||||
static func compile(
|
|
||||||
node: Node, withContext context: CompilerContext
|
|
||||||
) -> Result<EvaluatableExpression?>
|
|
||||||
}
|
|
||||||
|
|
||||||
protocol CompilableLValueExpression {
|
|
||||||
static func compile_as_lvalue(
|
|
||||||
node: Node, withContext context: CompilerContext
|
|
||||||
) -> Result<EvaluatableLValueExpression?>
|
|
||||||
}
|
|
||||||
|
|
||||||
extension TypedIdentifier: CompilableExpression {
|
extension TypedIdentifier: CompilableExpression {
|
||||||
static func compile(
|
public static func compile(
|
||||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Result<EvaluatableExpression?> {
|
) -> Result<P4Expression?> {
|
||||||
|
|
||||||
let node = node.child(at: 0)!
|
let node = node.child(at: 0)!
|
||||||
#SkipUnlessNodeType<SwiftTreeSitter.Node>(
|
#SkipUnlessNodeType<SwiftTreeSitter.Node>(
|
||||||
@@ -57,9 +45,9 @@ extension TypedIdentifier: CompilableExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension TypedIdentifier: CompilableLValueExpression {
|
extension TypedIdentifier: CompilableLValueExpression {
|
||||||
static func compile_as_lvalue(
|
public static func compile_as_lvalue(
|
||||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Result<EvaluatableLValueExpression?> {
|
) -> Result<P4LValueExpression?> {
|
||||||
|
|
||||||
let expression = node.child(at: 0)!
|
let expression = node.child(at: 0)!
|
||||||
#SkipUnlessNodeType<SwiftTreeSitter.Node>(
|
#SkipUnlessNodeType<SwiftTreeSitter.Node>(
|
||||||
@@ -77,9 +65,9 @@ extension TypedIdentifier: CompilableLValueExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension P4BooleanValue: CompilableExpression {
|
extension P4BooleanValue: CompilableExpression {
|
||||||
static func compile(
|
public static func compile(
|
||||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Result<EvaluatableExpression?> {
|
) -> Result<P4Expression?> {
|
||||||
let node = node.child(at: 0)!
|
let node = node.child(at: 0)!
|
||||||
#SkipUnlessNodeType<SwiftTreeSitter.Node>(
|
#SkipUnlessNodeType<SwiftTreeSitter.Node>(
|
||||||
node: node, type: "booleanLiteralExpression")
|
node: node, type: "booleanLiteralExpression")
|
||||||
@@ -98,9 +86,9 @@ extension P4BooleanValue: CompilableExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension P4IntValue: CompilableExpression {
|
extension P4IntValue: CompilableExpression {
|
||||||
static func compile(
|
public static func compile(
|
||||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Result<EvaluatableExpression?> {
|
) -> Result<P4Expression?> {
|
||||||
let node = node.child(at: 0)!
|
let node = node.child(at: 0)!
|
||||||
|
|
||||||
#SkipUnlessNodesTypes<SwiftTreeSitter.Node>(
|
#SkipUnlessNodesTypes<SwiftTreeSitter.Node>(
|
||||||
@@ -147,9 +135,9 @@ extension P4IntValue: CompilableExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension P4StringValue: CompilableExpression {
|
extension P4StringValue: CompilableExpression {
|
||||||
static func compile(
|
public static func compile(
|
||||||
node: SwiftTreeSitter.Node, withContext scopes: CompilerContext
|
node: SwiftTreeSitter.Node, withContext scopes: CompilerContext
|
||||||
) -> Result<EvaluatableExpression?> {
|
) -> Result<P4Expression?> {
|
||||||
let node = node.child(at: 0)!
|
let node = node.child(at: 0)!
|
||||||
#SkipUnlessNodeType<SwiftTreeSitter.Node>(
|
#SkipUnlessNodeType<SwiftTreeSitter.Node>(
|
||||||
node: node, type: "string_literal")
|
node: node, type: "string_literal")
|
||||||
@@ -158,12 +146,12 @@ extension P4StringValue: CompilableExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension KeysetExpression: CompilableExpression {
|
extension KeysetExpression: CompilableExpression {
|
||||||
static func compile(
|
public static func compile(
|
||||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Common.Result<(any Common.EvaluatableExpression)?> {
|
) -> Result<P4Expression?> {
|
||||||
let keyset_expression_node = node.child(at: 0)!
|
let keyset_expression_node = node.child(at: 0)!
|
||||||
|
|
||||||
#RequireNodesType<Node, EvaluatableExpression>(
|
#RequireNodesType<Node, P4Expression>(
|
||||||
nodes: keyset_expression_node, type: ["expression", "default_keyset"],
|
nodes: keyset_expression_node, type: ["expression", "default_keyset"],
|
||||||
nice_type_names: ["expression", "default keyset"])
|
nice_type_names: ["expression", "default keyset"])
|
||||||
|
|
||||||
@@ -186,12 +174,12 @@ extension KeysetExpression: CompilableExpression {
|
|||||||
struct Expression {
|
struct Expression {
|
||||||
public static func Compile(
|
public static func Compile(
|
||||||
node: Node, withContext context: CompilerContext
|
node: Node, withContext context: CompilerContext
|
||||||
) -> Result<EvaluatableExpression> {
|
) -> Result<P4Expression> {
|
||||||
#RequireNodeType<Node, EvaluatableExpression>(
|
#RequireNodeType<Node, P4Expression>(
|
||||||
node: node, type: "expression", nice_type_name: "expression")
|
node: node, type: "expression", nice_type_name: "expression")
|
||||||
|
|
||||||
let expression_node = node.child(at: 0)!
|
let expression_node = node.child(at: 0)!
|
||||||
#RequireNodesType<Node, EvaluatableExpression>(
|
#RequireNodesType<Node, P4Expression>(
|
||||||
nodes: expression_node, type: ["grouped_expression", "simple_expression"],
|
nodes: expression_node, type: ["grouped_expression", "simple_expression"],
|
||||||
nice_type_names: ["grouped expression", "simple expression"])
|
nice_type_names: ["grouped expression", "simple expression"])
|
||||||
|
|
||||||
@@ -223,12 +211,12 @@ struct Expression {
|
|||||||
struct LValue {
|
struct LValue {
|
||||||
public static func Compile(
|
public static func Compile(
|
||||||
node: Node, withContext context: CompilerContext
|
node: Node, withContext context: CompilerContext
|
||||||
) -> Result<EvaluatableLValueExpression> {
|
) -> Result<P4LValueExpression> {
|
||||||
#RequireNodeType<Node, EvaluatableExpression>(
|
#RequireNodeType<Node, P4Expression>(
|
||||||
node: node, type: "expression", nice_type_name: "expression")
|
node: node, type: "expression", nice_type_name: "expression")
|
||||||
|
|
||||||
let expression_node = node.child(at: 0)!
|
let expression_node = node.child(at: 0)!
|
||||||
#RequireNodesType<Node, EvaluatableExpression>(
|
#RequireNodesType<Node, P4Expression>(
|
||||||
nodes: expression_node, type: ["grouped_expression", "simple_expression"],
|
nodes: expression_node, type: ["grouped_expression", "simple_expression"],
|
||||||
nice_type_names: ["grouped expression", "simple expression"])
|
nice_type_names: ["grouped expression", "simple expression"])
|
||||||
|
|
||||||
@@ -268,9 +256,9 @@ struct Identifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension SelectExpression: CompilableExpression {
|
extension SelectExpression: CompilableExpression {
|
||||||
static func compile(
|
public static func compile(
|
||||||
node: Node, withContext context: CompilerContext
|
node: Node, withContext context: CompilerContext
|
||||||
) -> Result<EvaluatableExpression?> {
|
) -> Result<P4Expression?> {
|
||||||
#RequireNodeType<Node, (SelectExpression, CompilerContext)>(
|
#RequireNodeType<Node, (SelectExpression, CompilerContext)>(
|
||||||
node: node, type: "selectExpression", nice_type_name: "parser select expression")
|
node: node, type: "selectExpression", nice_type_name: "parser select expression")
|
||||||
|
|
||||||
@@ -330,9 +318,9 @@ extension SelectExpression: CompilableExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension SelectCaseExpression: CompilableExpression {
|
extension SelectCaseExpression: CompilableExpression {
|
||||||
static func compile(
|
public static func compile(
|
||||||
node: Node, withContext context: CompilerContext
|
node: Node, withContext context: CompilerContext
|
||||||
) -> Result<EvaluatableExpression?> {
|
) -> Result<P4Expression?> {
|
||||||
if node.nodeType != "selectCase" {
|
if node.nodeType != "selectCase" {
|
||||||
return Result.Error(Error(withMessage: "Expected select case not found"))
|
return Result.Error(Error(withMessage: "Expected select case not found"))
|
||||||
}
|
}
|
||||||
@@ -383,10 +371,35 @@ extension SelectCaseExpression: CompilableExpression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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 {
|
extension BinaryOperatorExpression: CompilableExpression {
|
||||||
static func compile(
|
public static func compile(
|
||||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Result<(EvaluatableExpression)?> {
|
) -> Result<(P4Expression)?> {
|
||||||
let expression = node.child(at: 0)!
|
let expression = node.child(at: 0)!
|
||||||
|
|
||||||
#SkipUnlessNodeType<Node>(
|
#SkipUnlessNodeType<Node>(
|
||||||
@@ -398,20 +411,20 @@ extension BinaryOperatorExpression: CompilableExpression {
|
|||||||
var current_node: Node? = .none
|
var current_node: Node? = .none
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<EvaluatableExpression?>.Error(
|
or: Result<P4Expression?>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(), withError: "Malformed binary operator expression"
|
sourceLocation: node.toSourceLocation(), withError: "Malformed binary operator expression"
|
||||||
)))
|
)))
|
||||||
|
|
||||||
/// TODO: This macro cannot handle new lines in the arrays
|
/// TODO: This macro cannot handle new lines in the arrays
|
||||||
// swift-format-ignore
|
// swift-format-ignore
|
||||||
#RequireNodesType<Node, EvaluatableExpression?>(
|
#RequireNodesType<Node, P4Expression?>(
|
||||||
nodes: binary_operator_expression_node,
|
nodes: binary_operator_expression_node,
|
||||||
type: ["binaryEqualOperatorExpression", "binaryLessThanOperatorExpression", "binaryLessThanEqualOperatorExpression", "binaryGreaterThanOperatorExpression", "binaryGreaterThanEqualOperatorExpression", "binaryAndOperatorExpression", "binaryOrOperatorExpression", "binaryAddOperatorExpression", "binarySubtractOperatorExpression", "binaryMultiplyOperatorExpression", "binaryDivideOperatorExpression"],
|
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"])
|
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(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<EvaluatableExpression?>.Error(
|
or: Result<P4Expression?>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(),
|
sourceLocation: node.toSourceLocation(),
|
||||||
withError: "Missing LHS for binary operator expression")))
|
withError: "Missing LHS for binary operator expression")))
|
||||||
@@ -421,7 +434,7 @@ extension BinaryOperatorExpression: CompilableExpression {
|
|||||||
walker.next()
|
walker.next()
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<EvaluatableExpression?>.Error(
|
or: Result<P4Expression?>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(),
|
sourceLocation: node.toSourceLocation(),
|
||||||
withError: "Missing binary operator for binary operator expression")))
|
withError: "Missing binary operator for binary operator expression")))
|
||||||
@@ -429,7 +442,7 @@ extension BinaryOperatorExpression: CompilableExpression {
|
|||||||
walker.next()
|
walker.next()
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<EvaluatableExpression?>.Error(
|
or: Result<P4Expression?>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(),
|
sourceLocation: node.toSourceLocation(),
|
||||||
withError: "Missing RHS for binary operator expression")))
|
withError: "Missing RHS for binary operator expression")))
|
||||||
@@ -520,9 +533,9 @@ extension BinaryOperatorExpression: CompilableExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension ArrayAccessExpression: CompilableExpression {
|
extension ArrayAccessExpression: CompilableExpression {
|
||||||
static func compile(
|
public static func compile(
|
||||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Common.Result<EvaluatableExpression?> {
|
) -> Result<P4Expression?> {
|
||||||
let expression = node.child(at: 0)!
|
let expression = node.child(at: 0)!
|
||||||
|
|
||||||
#SkipUnlessNodeType<Node>(
|
#SkipUnlessNodeType<Node>(
|
||||||
@@ -535,11 +548,11 @@ extension ArrayAccessExpression: CompilableExpression {
|
|||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<EvaluatableExpression?>.Error(
|
or: Result<P4Expression?>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(), withError: "Malformed array access expression")))
|
sourceLocation: node.toSourceLocation(), withError: "Malformed array access expression")))
|
||||||
|
|
||||||
#RequireNodeType<Node, EvaluatableExpression?>(
|
#RequireNodeType<Node, P4Expression?>(
|
||||||
node: current_node!, type: "expression",
|
node: current_node!, type: "expression",
|
||||||
nice_type_name: "array identifier expression")
|
nice_type_name: "array identifier expression")
|
||||||
let array_access_identifier_node = current_node!
|
let array_access_identifier_node = current_node!
|
||||||
@@ -547,7 +560,7 @@ extension ArrayAccessExpression: CompilableExpression {
|
|||||||
walker.next()
|
walker.next()
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<EvaluatableExpression?>.Error(
|
or: Result<P4Expression?>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(),
|
sourceLocation: node.toSourceLocation(),
|
||||||
withError: "Missing [ for array access expression")))
|
withError: "Missing [ for array access expression")))
|
||||||
@@ -556,12 +569,12 @@ extension ArrayAccessExpression: CompilableExpression {
|
|||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<EvaluatableExpression?>.Error(
|
or: Result<P4Expression?>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(),
|
sourceLocation: node.toSourceLocation(),
|
||||||
withError: "Missing indexor expression for array access expression")))
|
withError: "Missing indexor expression for array access expression")))
|
||||||
|
|
||||||
#RequireNodeType<Node, EvaluatableExpression?>(
|
#RequireNodeType<Node, P4Expression?>(
|
||||||
node: current_node!, type: "expression",
|
node: current_node!, type: "expression",
|
||||||
nice_type_name: "array indexor expression")
|
nice_type_name: "array indexor expression")
|
||||||
|
|
||||||
@@ -595,9 +608,9 @@ extension ArrayAccessExpression: CompilableExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension FieldAccessExpression: CompilableExpression {
|
extension FieldAccessExpression: CompilableExpression {
|
||||||
static func compile(
|
public static func compile(
|
||||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Common.Result<(any Common.EvaluatableExpression)?> {
|
) -> Result<P4Expression?> {
|
||||||
let expression = node.child(at: 0)!
|
let expression = node.child(at: 0)!
|
||||||
|
|
||||||
#SkipUnlessNodeType<Node>(
|
#SkipUnlessNodeType<Node>(
|
||||||
@@ -610,11 +623,11 @@ extension FieldAccessExpression: CompilableExpression {
|
|||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<EvaluatableExpression?>.Error(
|
or: Result<P4Expression?>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(), withError: "Malformed field access expression")))
|
sourceLocation: node.toSourceLocation(), withError: "Malformed field access expression")))
|
||||||
|
|
||||||
#RequireNodeType<Node, EvaluatableExpression?>(
|
#RequireNodeType<Node, P4Expression?>(
|
||||||
node: current_node!, type: "expression",
|
node: current_node!, type: "expression",
|
||||||
nice_type_name: "struct identifier expression")
|
nice_type_name: "struct identifier expression")
|
||||||
let struct_identifier_node = current_node!
|
let struct_identifier_node = current_node!
|
||||||
@@ -622,7 +635,7 @@ extension FieldAccessExpression: CompilableExpression {
|
|||||||
walker.next()
|
walker.next()
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<EvaluatableExpression?>.Error(
|
or: Result<P4Expression?>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(),
|
sourceLocation: node.toSourceLocation(),
|
||||||
withError: "Missing . for field access expression")))
|
withError: "Missing . for field access expression")))
|
||||||
@@ -630,12 +643,12 @@ extension FieldAccessExpression: CompilableExpression {
|
|||||||
walker.next()
|
walker.next()
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<EvaluatableExpression?>.Error(
|
or: Result<P4Expression?>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(),
|
sourceLocation: node.toSourceLocation(),
|
||||||
withError: "Missing field name for field access expression")))
|
withError: "Missing field name for field access expression")))
|
||||||
|
|
||||||
#RequireNodeType<Node, EvaluatableExpression?>(
|
#RequireNodeType<Node, P4Expression?>(
|
||||||
node: current_node!, type: "identifier",
|
node: current_node!, type: "identifier",
|
||||||
nice_type_name: "field name")
|
nice_type_name: "field name")
|
||||||
|
|
||||||
@@ -677,9 +690,9 @@ extension FieldAccessExpression: CompilableExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension FieldAccessExpression: CompilableLValueExpression {
|
extension FieldAccessExpression: CompilableLValueExpression {
|
||||||
static func compile_as_lvalue(
|
public static func compile_as_lvalue(
|
||||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Result<EvaluatableLValueExpression?> {
|
) -> Result<P4LValueExpression?> {
|
||||||
let expression = node.child(at: 0)!
|
let expression = node.child(at: 0)!
|
||||||
#SkipUnlessNodeType<Node>(
|
#SkipUnlessNodeType<Node>(
|
||||||
node: expression, type: "fieldAccessExpression")
|
node: expression, type: "fieldAccessExpression")
|
||||||
@@ -696,9 +709,9 @@ extension FieldAccessExpression: CompilableLValueExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension ArrayAccessExpression: CompilableLValueExpression {
|
extension ArrayAccessExpression: CompilableLValueExpression {
|
||||||
static func compile_as_lvalue(
|
public static func compile_as_lvalue(
|
||||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Result<EvaluatableLValueExpression?> {
|
) -> Result<P4LValueExpression?> {
|
||||||
let expression = node.child(at: 0)!
|
let expression = node.child(at: 0)!
|
||||||
#SkipUnlessNodeType<Node>(
|
#SkipUnlessNodeType<Node>(
|
||||||
node: expression, type: "arrayAccessExpression")
|
node: expression, type: "arrayAccessExpression")
|
||||||
@@ -715,9 +728,9 @@ extension ArrayAccessExpression: CompilableLValueExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension FunctionCall: CompilableExpression {
|
extension FunctionCall: CompilableExpression {
|
||||||
static func compile(
|
public static func compile(
|
||||||
node: Node, withContext context: CompilerContext
|
node: Node, withContext context: CompilerContext
|
||||||
) -> Result<EvaluatableExpression?> {
|
) -> Result<P4Expression?> {
|
||||||
|
|
||||||
let expression = node.child(at: 0)!
|
let expression = node.child(at: 0)!
|
||||||
#SkipUnlessNodeType<Node>(
|
#SkipUnlessNodeType<Node>(
|
||||||
@@ -728,7 +741,7 @@ extension FunctionCall: CompilableExpression {
|
|||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<EvaluatableExpression?>.Error(
|
or: Result<P4Expression?>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(), withError: "Missing function call component")))
|
sourceLocation: node.toSourceLocation(), withError: "Missing function call component")))
|
||||||
|
|
||||||
@@ -780,13 +793,13 @@ extension FunctionCall: CompilableExpression {
|
|||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<EvaluatableExpression?>.Error(
|
or: Result<P4Expression?>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(), withError: "Missing function call component")))
|
sourceLocation: node.toSourceLocation(), withError: "Missing function call component")))
|
||||||
|
|
||||||
let maybe_argument_list = ArgumentList.Compile(node: current_node!, withContext: context)
|
let maybe_argument_list = ArgumentList.Compile(node: current_node!, withContext: context)
|
||||||
|
|
||||||
guard case .Ok((let arguments, _)) = maybe_argument_list else {
|
guard case .Ok(let arguments) = maybe_argument_list else {
|
||||||
return .Error(maybe_argument_list.error()!)
|
return .Error(maybe_argument_list.error()!)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,10 +23,10 @@ import TreeSitterExtensions
|
|||||||
import TreeSitterP4
|
import TreeSitterP4
|
||||||
|
|
||||||
extension Statement: Compilable {
|
extension Statement: Compilable {
|
||||||
public typealias T = EvaluatableStatement
|
public typealias C = P4Statement
|
||||||
public static func Compile(
|
public static func Compile(
|
||||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Common.Result<(EvaluatableStatement, CompilerContext)> {
|
) -> Result<P4Statement> {
|
||||||
|
|
||||||
if node.nodeType != "parserStatement" && node.nodeType != "statement" {
|
if node.nodeType != "parserStatement" && node.nodeType != "statement" {
|
||||||
return Result.Error(
|
return Result.Error(
|
||||||
@@ -51,9 +51,9 @@ extension Statement: Compilable {
|
|||||||
withError:
|
withError:
|
||||||
"Unparseable statement type (\(statement.nodeType ?? "Unknown Statement Type"))"))
|
"Unparseable statement type (\(statement.nodeType ?? "Unknown Statement Type"))"))
|
||||||
}
|
}
|
||||||
switch parser.Compile(node: statement, withContext: context) {
|
switch parser.CompileStatement(node: statement, withContext: context) {
|
||||||
case Result.Ok(let (parsed, updated_context)):
|
case Result.Ok(let parsed):
|
||||||
return .Ok((parsed, updated_context))
|
return .Ok(parsed)
|
||||||
case Result.Error(let e):
|
case Result.Error(let e):
|
||||||
return .Error(
|
return .Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
@@ -62,11 +62,12 @@ extension Statement: Compilable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension LocalElements: Compilable {
|
extension LocalElements: Compilable {
|
||||||
public typealias T = EvaluatableStatement
|
public typealias C = P4Statement
|
||||||
public static func Compile(
|
public static func Compile(
|
||||||
node: Node, withContext context: CompilerContext
|
node: Node, withContext context: CompilerContext
|
||||||
) -> Result<(EvaluatableStatement, CompilerContext)> {
|
) -> Result<P4Statement> {
|
||||||
let localElementsParsers: [String: CompilableStatement.Type] = [
|
let localElementsParsers: [String: CompilableStatement.Type] = [
|
||||||
"variableDeclaration": VariableDeclarationStatement.self
|
"variableDeclaration": VariableDeclarationStatement.self
|
||||||
]
|
]
|
||||||
@@ -78,9 +79,9 @@ extension LocalElements: Compilable {
|
|||||||
withError: "Unparseable statement type (\(node.nodeType ?? "Unknown Statement Type"))"))
|
withError: "Unparseable statement type (\(node.nodeType ?? "Unknown Statement Type"))"))
|
||||||
}
|
}
|
||||||
|
|
||||||
switch parser.Compile(node: node, withContext: context) {
|
switch parser.CompileStatement(node: node, withContext: context) {
|
||||||
case Result.Ok(let (parsed, parsed_updated_scopes)):
|
case Result.Ok(let parsed):
|
||||||
return Result.Ok((parsed, parsed_updated_scopes))
|
return Result.Ok(parsed)
|
||||||
case Result.Error(let e):
|
case Result.Error(let e):
|
||||||
return Result.Error(Error(withMessage: "Failed to parse local element: \(e)"))
|
return Result.Error(Error(withMessage: "Failed to parse local element: \(e)"))
|
||||||
}
|
}
|
||||||
@@ -88,10 +89,10 @@ extension LocalElements: Compilable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension ParserState: Compilable {
|
extension ParserState: Compilable {
|
||||||
public typealias T = ParserState
|
public typealias C = ParserState
|
||||||
public static func Compile(
|
public static func Compile(
|
||||||
node: Node, withContext context: CompilerContext
|
node: Node, withContext context: CompilerContext
|
||||||
) -> Result<(ParserState, CompilerContext)> {
|
) -> Result<ParserState> {
|
||||||
var walker = Walker(node: node)
|
var walker = Walker(node: node)
|
||||||
|
|
||||||
var current_node: Node? = .none
|
var current_node: Node? = .none
|
||||||
@@ -107,7 +108,7 @@ extension ParserState: Compilable {
|
|||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(ParserState, CompilerContext)>.Error(
|
or: Result<ParserState>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(),
|
sourceLocation: node.toSourceLocation(),
|
||||||
withError: "Missing elements in parser state declaration")))
|
withError: "Missing elements in parser state declaration")))
|
||||||
@@ -125,7 +126,7 @@ extension ParserState: Compilable {
|
|||||||
walker.next()
|
walker.next()
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(ParserState, CompilerContext)>.Error(
|
or: Result<ParserState>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(),
|
sourceLocation: node.toSourceLocation(),
|
||||||
withError: "Missing elements in parser state declaration")))
|
withError: "Missing elements in parser state declaration")))
|
||||||
@@ -141,22 +142,20 @@ extension ParserState: Compilable {
|
|||||||
walker.next()
|
walker.next()
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(ParserState, CompilerContext)>.Error(
|
or: Result<ParserState>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(), withError: "Missing body of state declaration")
|
sourceLocation: node.toSourceLocation(), withError: "Missing body of state declaration")
|
||||||
))
|
))
|
||||||
|
|
||||||
var errors: (any Errorable)? = .none
|
var errors: (any Errorable)? = .none
|
||||||
var current_context = context
|
var parsed_s: [P4Statement] = Array()
|
||||||
var parsed_s: [EvaluatableStatement] = Array()
|
|
||||||
|
|
||||||
if current_node!.nodeType == "parserStatements" {
|
if current_node!.nodeType == "parserStatements" {
|
||||||
switch SpecialCompilers.Statements.Compile(
|
switch SpecialCompilers.Statements.Compile(
|
||||||
node: current_node!, withContext: current_context)
|
node: current_node!, withContext: context)
|
||||||
{
|
{
|
||||||
case .Ok(let (state_statements, updated_context)):
|
case .Ok(let state_statements):
|
||||||
parsed_s = state_statements
|
parsed_s = state_statements
|
||||||
current_context = updated_context
|
|
||||||
case .Error(let error):
|
case .Error(let error):
|
||||||
errors =
|
errors =
|
||||||
if let errors = errors {
|
if let errors = errors {
|
||||||
@@ -174,13 +173,13 @@ extension ParserState: Compilable {
|
|||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(ParserState, CompilerContext)>.Error(
|
or: Result<ParserState>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(),
|
sourceLocation: node.toSourceLocation(),
|
||||||
withError: "Missing transition statement of state declaration")))
|
withError: "Missing transition statement of state declaration")))
|
||||||
|
|
||||||
return SpecialCompilers.TransitionStatement.Compile(
|
return SpecialCompilers.TransitionStatement.Compile(
|
||||||
node: current_node!, forState: state_identifier, withStatements: parsed_s,
|
node: current_node!, forState: state_identifier, withStatements: parsed_s,
|
||||||
withContext: current_context)
|
withContext: SpecialCompilers.Statements.effect(statements: parsed_s, context: context))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,12 +22,6 @@ import SwiftTreeSitter
|
|||||||
import TreeSitterExtensions
|
import TreeSitterExtensions
|
||||||
import TreeSitterP4
|
import TreeSitterP4
|
||||||
|
|
||||||
public protocol CompilableStatement {
|
|
||||||
static func Compile(
|
|
||||||
node: Node, withContext context: CompilerContext
|
|
||||||
) -> Result<(EvaluatableStatement, CompilerContext)>
|
|
||||||
}
|
|
||||||
|
|
||||||
public protocol CompilableValue {
|
public protocol CompilableValue {
|
||||||
static func CompileValue(withValue value: String) -> Result<P4DataValue>
|
static func CompileValue(withValue value: String) -> Result<P4DataValue>
|
||||||
}
|
}
|
||||||
@@ -38,19 +32,27 @@ public protocol CompilableType {
|
|||||||
) -> Result<P4Type?>
|
) -> Result<P4Type?>
|
||||||
}
|
}
|
||||||
|
|
||||||
public protocol CompilableDeclaration {
|
public protocol CompilableExpression {
|
||||||
/// Info
|
static func compile(
|
||||||
///
|
|
||||||
/// Extensions should update the context with the newly declared item _unless_
|
|
||||||
/// they are in an extern context (``CompilerContext.extern_context``).
|
|
||||||
static func Compile(
|
|
||||||
node: Node, withContext context: CompilerContext
|
node: Node, withContext context: CompilerContext
|
||||||
) -> Result<(Declaration, CompilerContext)?>
|
) -> Result<P4Expression?>
|
||||||
}
|
}
|
||||||
|
|
||||||
public protocol Compilable<T> {
|
public protocol CompilableLValueExpression {
|
||||||
associatedtype T
|
static func compile_as_lvalue(
|
||||||
|
node: Node, withContext context: CompilerContext
|
||||||
|
) -> Result<P4LValueExpression?>
|
||||||
|
}
|
||||||
|
|
||||||
|
public protocol Compilable<C> {
|
||||||
|
associatedtype C
|
||||||
static func Compile(
|
static func Compile(
|
||||||
node: Node, withContext context: CompilerContext
|
node: Node, withContext context: CompilerContext
|
||||||
) -> Result<(T, CompilerContext)>
|
) -> Result<C>
|
||||||
|
}
|
||||||
|
|
||||||
|
public protocol CompilableStatement {
|
||||||
|
static func CompileStatement(
|
||||||
|
node: Node, withContext context: CompilerContext
|
||||||
|
) -> Result<P4Statement>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,14 +22,20 @@ import SwiftTreeSitter
|
|||||||
import TreeSitterExtensions
|
import TreeSitterExtensions
|
||||||
import TreeSitterP4
|
import TreeSitterP4
|
||||||
|
|
||||||
|
protocol AnyCompilable {
|
||||||
|
static func Compile(
|
||||||
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
|
) -> Common.Result<(Any, CompilerContext)>
|
||||||
|
}
|
||||||
|
|
||||||
public struct SpecialCompilers {
|
public struct SpecialCompilers {
|
||||||
public struct TransitionStatement {
|
public struct TransitionStatement {
|
||||||
static func Compile(
|
static func Compile(
|
||||||
node: Node, forState state_identifier: Common.Identifier,
|
node: Node, forState state_identifier: Common.Identifier,
|
||||||
withStatements stmts: [EvaluatableStatement], withContext context: CompilerContext
|
withStatements stmts: [P4Statement], withContext context: CompilerContext
|
||||||
) -> Result<(ParserState, CompilerContext)> {
|
) -> Result<ParserState> {
|
||||||
|
|
||||||
#RequireNodeType<Node, (EvaluatableStatement, CompilerContext)>(
|
#RequireNodeType<Node, P4Statement>(
|
||||||
node: node, type: "parserTransitionStatement", nice_type_name: "parser transition statement"
|
node: node, type: "parserTransitionStatement", nice_type_name: "parser transition statement"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -58,19 +64,18 @@ public struct SpecialCompilers {
|
|||||||
switch next_state {
|
switch next_state {
|
||||||
case (_, .some(let instance)):
|
case (_, .some(let instance)):
|
||||||
return .Ok(
|
return .Ok(
|
||||||
(
|
|
||||||
ParserStateDirectTransition(
|
ParserStateDirectTransition(
|
||||||
name: state_identifier,
|
name: state_identifier,
|
||||||
withNextState: instance.dataValue() as! InstantiatedParserState,
|
withNextState: instance.dataValue() as! InstantiatedParserState,
|
||||||
withStatements: stmts), context
|
withStatements: stmts,
|
||||||
))
|
)
|
||||||
|
)
|
||||||
case (_, .none):
|
case (_, .none):
|
||||||
return .Ok(
|
return .Ok(
|
||||||
(
|
|
||||||
ParserStateDirectTransition(
|
ParserStateDirectTransition(
|
||||||
name: state_identifier,
|
name: state_identifier,
|
||||||
withNextStateIdentifier: next_state_id, withStatements: stmts), context
|
withNextStateIdentifier: next_state_id, withStatements: stmts)
|
||||||
))
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
@@ -95,12 +100,11 @@ public struct SpecialCompilers {
|
|||||||
{
|
{
|
||||||
case .Ok(let tse):
|
case .Ok(let tse):
|
||||||
.Ok(
|
.Ok(
|
||||||
(
|
|
||||||
ParserStateSelectTransition(
|
ParserStateSelectTransition(
|
||||||
name: state_identifier, withTransitionExpression: tse as! SelectExpression,
|
name: state_identifier, withTransitionExpression: tse as! SelectExpression,
|
||||||
withStatements: stmts,
|
withStatements: stmts,
|
||||||
), context
|
)
|
||||||
))
|
)
|
||||||
case .Error(let e): .Error(e)
|
case .Error(let e): .Error(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -109,7 +113,7 @@ public struct SpecialCompilers {
|
|||||||
public struct Statements {
|
public struct Statements {
|
||||||
static func Compile(
|
static func Compile(
|
||||||
node: Node, withContext context: CompilerContext
|
node: Node, withContext context: CompilerContext
|
||||||
) -> Result<([EvaluatableStatement], CompilerContext)> {
|
) -> Result<[P4Statement]> {
|
||||||
if node.nodeType != "statements" && node.nodeType != "parserStatements" {
|
if node.nodeType != "statements" && node.nodeType != "parserStatements" {
|
||||||
return Result.Error(
|
return Result.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
@@ -118,15 +122,15 @@ public struct SpecialCompilers {
|
|||||||
|
|
||||||
var errors: (any Errorable)? = .none
|
var errors: (any Errorable)? = .none
|
||||||
var current_context = context
|
var current_context = context
|
||||||
var parsed_s: [EvaluatableStatement] = Array()
|
var parsed_s: [P4Statement] = Array()
|
||||||
|
|
||||||
node.enumerateNamedChildren { node in
|
node.enumerateNamedChildren { node in
|
||||||
switch Statement.Compile(
|
switch Statement.Compile(
|
||||||
node: node, withContext: current_context)
|
node: node, withContext: current_context)
|
||||||
{
|
{
|
||||||
case .Ok((let parsed_statement, let updated_context)):
|
case .Ok(let parsed_statement):
|
||||||
current_context = updated_context
|
|
||||||
parsed_s.append(parsed_statement)
|
parsed_s.append(parsed_statement)
|
||||||
|
current_context = parsed_statement.effect(context: current_context)
|
||||||
case .Error(let e):
|
case .Error(let e):
|
||||||
errors =
|
errors =
|
||||||
if let errors = errors {
|
if let errors = errors {
|
||||||
@@ -141,11 +145,20 @@ public struct SpecialCompilers {
|
|||||||
return .Error(errors)
|
return .Error(errors)
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result.Ok((parsed_s, current_context))
|
return Result.Ok(parsed_s)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static func Compile(
|
static func effect(statements: [P4Statement], context: CompilerContext) -> CompilerContext {
|
||||||
|
var current = context
|
||||||
|
for s in statements {
|
||||||
|
current = s.effect(context: current)
|
||||||
|
}
|
||||||
|
return current
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static func CompileParserBody(
|
||||||
withName name: Common.Identifier, withParameters parameters: ParameterList, node: Node,
|
withName name: Common.Identifier, withParameters parameters: ParameterList, node: Node,
|
||||||
withContext context: CompilerContext
|
withContext context: CompilerContext
|
||||||
) -> Result<(P4Lang.Parser, CompilerContext)> {
|
) -> Result<(P4Lang.Parser, CompilerContext)> {
|
||||||
@@ -167,9 +180,10 @@ public struct SpecialCompilers {
|
|||||||
node: parser_state,
|
node: parser_state,
|
||||||
withContext: context.update(newInstances: current_context.instances.enter()))
|
withContext: context.update(newInstances: current_context.instances.enter()))
|
||||||
{
|
{
|
||||||
case Result.Ok(let (state, updated_context)):
|
case Result.Ok(let state):
|
||||||
|
let statement = state as P4Statement
|
||||||
|
current_context = statement.effect(context: current_context)
|
||||||
parser.states = parser.states.append(state: state)
|
parser.states = parser.states.append(state: state)
|
||||||
current_context = updated_context
|
|
||||||
case Result.Error(let e): error = e
|
case Result.Error(let e): error = e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -245,43 +259,35 @@ public struct SpecialCompilers {
|
|||||||
|
|
||||||
// Try to parse all top-level declarations.
|
// Try to parse all top-level declarations.
|
||||||
result?.rootNode?.enumerateNamedChildren { (declaration_node: Node) in
|
result?.rootNode?.enumerateNamedChildren { (declaration_node: Node) in
|
||||||
let specific_declaration_node = declaration_node.child(at: 0)!
|
let declaration_parsers: [String: CompilableStatement.Type] = [
|
||||||
|
"declaration": Declaration.self,
|
||||||
let declaration_parsers: [CompilableDeclaration.Type] = [
|
"instantiation": Instantiation.self,
|
||||||
Declaration.self, P4Lang.Parser.self,
|
|
||||||
]
|
]
|
||||||
var found_parser = false
|
|
||||||
|
|
||||||
for parser in declaration_parsers {
|
if let parser = declaration_parsers[declaration_node.nodeType!] {
|
||||||
switch parser.Compile(node: specific_declaration_node, withContext: compilation_context) {
|
let r = parser.CompileStatement(node: declaration_node, withContext: compilation_context)
|
||||||
case .Ok(.none): {}()
|
switch r {
|
||||||
case .Ok(.some((_, let updated_context))):
|
case .Ok(let compiled):
|
||||||
found_parser = true
|
compilation_context = compiled.effect(context: compilation_context)
|
||||||
compilation_context = updated_context
|
|
||||||
break
|
|
||||||
case .Error(let e):
|
case .Error(let e):
|
||||||
found_parser = true
|
|
||||||
errors =
|
errors =
|
||||||
if let errors = errors {
|
if let errors = errors {
|
||||||
errors.append(error: e)
|
errors.append(error: e)
|
||||||
} else {
|
} else {
|
||||||
e
|
e
|
||||||
}
|
}
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If none of the declaration parsers chose to parse, that's an error, too!
|
}
|
||||||
if !found_parser {
|
} else {
|
||||||
let no_parser_error = ErrorWithLocation(
|
let e = ErrorWithLocation(
|
||||||
sourceLocation: specific_declaration_node.toSourceLocation(),
|
sourceLocation: declaration_node.toSourceLocation(),
|
||||||
withError: "Could not find parser for declaration node"
|
withError:
|
||||||
)
|
"\(declaration_node.nodeType!) cannot be at a P4 program top level")
|
||||||
errors =
|
errors =
|
||||||
if let errors = errors {
|
if let errors = errors {
|
||||||
errors.append(error: no_parser_error)
|
errors.append(error: e)
|
||||||
} else {
|
} else {
|
||||||
no_parser_error
|
e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -313,4 +319,5 @@ public struct SpecialCompilers {
|
|||||||
return Result.Ok(program)
|
return Result.Ok(program)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,11 +22,12 @@ import SwiftTreeSitter
|
|||||||
import TreeSitterExtensions
|
import TreeSitterExtensions
|
||||||
import TreeSitterP4
|
import TreeSitterP4
|
||||||
|
|
||||||
extension BlockStatement: CompilableStatement {
|
extension BlockStatement: Compilable {
|
||||||
|
public typealias C = BlockStatement
|
||||||
public static func Compile(
|
public static func Compile(
|
||||||
node: Node, withContext context: CompilerContext
|
node: Node, withContext context: CompilerContext
|
||||||
) -> Result<(EvaluatableStatement, CompilerContext)> {
|
) -> Result<BlockStatement> {
|
||||||
#RequireNodeType<Node, (EvaluatableStatement, CompilerContext)>(
|
#RequireNodeType<Node, (P4Statement)>(
|
||||||
node: node, type: "blockStatement", nice_type_name: "block statement")
|
node: node, type: "blockStatement", nice_type_name: "block statement")
|
||||||
|
|
||||||
var walker = Walker(node: node)
|
var walker = Walker(node: node)
|
||||||
@@ -34,7 +35,7 @@ extension BlockStatement: CompilableStatement {
|
|||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(EvaluatableStatement, CompilerContext)>.Error(
|
or: Result<BlockStatement>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(), withError: "Malformed block statement")))
|
sourceLocation: node.toSourceLocation(), withError: "Malformed block statement")))
|
||||||
|
|
||||||
@@ -45,23 +46,21 @@ extension BlockStatement: CompilableStatement {
|
|||||||
withError: "Missing { on block statement"))
|
withError: "Missing { on block statement"))
|
||||||
}
|
}
|
||||||
|
|
||||||
var statements: [EvaluatableStatement] = Array()
|
var statements: [P4Statement] = Array()
|
||||||
var parse_err: (any Errorable)? = .none
|
var parse_err: (any Errorable)? = .none
|
||||||
var current_context = context
|
|
||||||
|
|
||||||
walker.next()
|
walker.next()
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(EvaluatableStatement, CompilerContext)>.Error(
|
or: Result<BlockStatement>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(), withError: "Malformed block statement")))
|
sourceLocation: node.toSourceLocation(), withError: "Malformed block statement")))
|
||||||
|
|
||||||
if current_node!.nodeType == "statements" {
|
if current_node!.nodeType == "statements" {
|
||||||
switch SpecialCompilers.Statements.Compile(
|
switch SpecialCompilers.Statements.Compile(
|
||||||
node: current_node!, withContext: current_context)
|
node: current_node!, withContext: context)
|
||||||
{
|
{
|
||||||
case .Ok(let (parsed_statements, updated_context)):
|
case .Ok(let parsed_statements):
|
||||||
current_context = updated_context
|
|
||||||
statements = parsed_statements
|
statements = parsed_statements
|
||||||
case .Error(let error):
|
case .Error(let error):
|
||||||
parse_err = error
|
parse_err = error
|
||||||
@@ -76,7 +75,7 @@ extension BlockStatement: CompilableStatement {
|
|||||||
|
|
||||||
#MustOr(
|
#MustOr(
|
||||||
result: current_node, thing: walker.getNext(),
|
result: current_node, thing: walker.getNext(),
|
||||||
or: Result<(EvaluatableStatement, CompilerContext)>.Error(
|
or: Result<BlockStatement>.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
sourceLocation: node.toSourceLocation(), withError: "Malformed block statement")))
|
sourceLocation: node.toSourceLocation(), withError: "Malformed block statement")))
|
||||||
|
|
||||||
@@ -87,16 +86,28 @@ extension BlockStatement: CompilableStatement {
|
|||||||
withError: "Missing } on block statement"))
|
withError: "Missing } on block statement"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return .Ok((BlockStatement(statements), current_context))
|
return .Ok(BlockStatement(statements))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ConditionalStatement: CompilableStatement {
|
extension BlockStatement: CompilableStatement {
|
||||||
|
public static func CompileStatement(
|
||||||
|
node: Node, withContext context: CompilerContext
|
||||||
|
) -> Result<P4Statement> {
|
||||||
|
return switch Compile(node: node, withContext: context) {
|
||||||
|
case .Ok(let res): .Ok(res)
|
||||||
|
case .Error(let e): .Error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ConditionalStatement: Compilable {
|
||||||
|
public typealias C = ConditionalStatement
|
||||||
public static func Compile(
|
public static func Compile(
|
||||||
node: Node, withContext context: CompilerContext
|
node: Node, withContext context: CompilerContext
|
||||||
) -> Result<(EvaluatableStatement, CompilerContext)> {
|
) -> Result<ConditionalStatement> {
|
||||||
|
|
||||||
#RequireNodeType<Node, (EvaluatableStatement, CompilerContext)>(
|
#RequireNodeType<Node, (P4Statement)>(
|
||||||
node: node, type: "conditionalStatement", nice_type_name: "conditional statement")
|
node: node, type: "conditionalStatement", nice_type_name: "conditional statement")
|
||||||
|
|
||||||
let maybe_condition_expression = node.child(at: 2)
|
let maybe_condition_expression = node.child(at: 2)
|
||||||
@@ -128,7 +139,7 @@ extension ConditionalStatement: CompilableStatement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
guard
|
guard
|
||||||
case .Ok((let thenns, _)) = Statement.Compile(
|
case .Ok(let thenns) = Statement.Compile(
|
||||||
node: thens, withContext: context)
|
node: thens, withContext: context)
|
||||||
else {
|
else {
|
||||||
return Result.Error(
|
return Result.Error(
|
||||||
@@ -137,7 +148,7 @@ extension ConditionalStatement: CompilableStatement {
|
|||||||
"Could not parse the then block in a conditional statement"))
|
"Could not parse the then block in a conditional statement"))
|
||||||
}
|
}
|
||||||
|
|
||||||
let optional_elss: Result<(any EvaluatableStatement, CompilerContext)>? =
|
let optional_elss: Result<any P4Statement>? =
|
||||||
if let elss = node.child(at: 6) {
|
if let elss = node.child(at: 6) {
|
||||||
.some(
|
.some(
|
||||||
Statement.Compile(
|
Statement.Compile(
|
||||||
@@ -148,7 +159,7 @@ extension ConditionalStatement: CompilableStatement {
|
|||||||
|
|
||||||
if let parsed_elss = optional_elss {
|
if let parsed_elss = optional_elss {
|
||||||
guard
|
guard
|
||||||
case .Ok((let elss, _)) = parsed_elss
|
case .Ok(let elss) = parsed_elss
|
||||||
else {
|
else {
|
||||||
return Result.Error(
|
return Result.Error(
|
||||||
Error(
|
Error(
|
||||||
@@ -156,18 +167,30 @@ extension ConditionalStatement: CompilableStatement {
|
|||||||
"Could not parse the else block in a conditional statement"))
|
"Could not parse the else block in a conditional statement"))
|
||||||
}
|
}
|
||||||
return .Ok(
|
return .Ok(
|
||||||
(ConditionalStatement(condition: condition, withThen: thenns, andElse: elss), context))
|
ConditionalStatement(condition: condition, withThen: thenns, andElse: elss))
|
||||||
}
|
}
|
||||||
return .Ok((ConditionalStatement(condition: condition, withThen: thenns), context))
|
return .Ok(ConditionalStatement(condition: condition, withThen: thenns))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension VariableDeclarationStatement: CompilableStatement {
|
extension ConditionalStatement: CompilableStatement {
|
||||||
|
public static func CompileStatement(
|
||||||
|
node: Node, withContext context: CompilerContext
|
||||||
|
) -> Result<P4Statement> {
|
||||||
|
return switch Compile(node: node, withContext: context) {
|
||||||
|
case .Ok(let res): .Ok(res)
|
||||||
|
case .Error(let e): .Error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension VariableDeclarationStatement: Compilable {
|
||||||
|
public typealias C = VariableDeclarationStatement
|
||||||
public static func Compile(
|
public static func Compile(
|
||||||
node: Node, withContext context: CompilerContext
|
node: Node, withContext context: CompilerContext
|
||||||
) -> Result<(EvaluatableStatement, CompilerContext)> {
|
) -> Result<VariableDeclarationStatement> {
|
||||||
|
|
||||||
#RequireNodeType<Node, (EvaluatableStatement, CompilerContext)>(
|
#RequireNodeType<Node, (P4Statement)>(
|
||||||
node: node, type: "variableDeclaration", nice_type_name: "variable declaration statement")
|
node: node, type: "variableDeclaration", nice_type_name: "variable declaration statement")
|
||||||
|
|
||||||
let maybe_typeref = node.child(at: 0)
|
let maybe_typeref = node.child(at: 0)
|
||||||
@@ -206,7 +229,7 @@ extension VariableDeclarationStatement: CompilableStatement {
|
|||||||
Error(withMessage: "Could not parse a P4 type from \(typeref.text!)"))
|
Error(withMessage: "Could not parse a P4 type from \(typeref.text!)"))
|
||||||
}
|
}
|
||||||
|
|
||||||
var initializer: EvaluatableExpression? = .none
|
var initializer: P4Expression? = .none
|
||||||
|
|
||||||
// If there is an initializer, it must be an expression.
|
// If there is an initializer, it must be an expression.
|
||||||
if let initializer_expression = maybe_rvalue {
|
if let initializer_expression = maybe_rvalue {
|
||||||
@@ -249,40 +272,59 @@ extension VariableDeclarationStatement: CompilableStatement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Result.Ok(
|
return Result.Ok(
|
||||||
(
|
|
||||||
VariableDeclarationStatement(
|
VariableDeclarationStatement(
|
||||||
identifier: parsed_variablename, withInitializer: initializer),
|
identifier: TypedIdentifier(id: parsed_variablename, withType: declaration_p4_type),
|
||||||
// Context with updated names to include the newly declared name.
|
withInitializer: initializer),
|
||||||
context.update(
|
|
||||||
newInstances: context.instances.declare(
|
|
||||||
identifier: parsed_variablename, withValue: (declaration_p4_type, .none)))
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ExpressionStatement: CompilableStatement {
|
extension VariableDeclarationStatement: CompilableStatement {
|
||||||
public static func Compile(
|
public static func CompileStatement(
|
||||||
node: Node, withContext context: CompilerContext
|
node: Node, withContext context: CompilerContext
|
||||||
) -> Result<(EvaluatableStatement, CompilerContext)> {
|
) -> Result<P4Statement> {
|
||||||
#RequireNodeType<Node, (EvaluatableStatement, CompilerContext)>(
|
return switch Compile(node: node, withContext: context) {
|
||||||
node: node, type: "expressionStatement", nice_type_name: "expression statement")
|
case .Ok(let res): .Ok(res)
|
||||||
|
|
||||||
let expression_node = node.child(at: 0)!
|
|
||||||
|
|
||||||
return switch Expression.Compile(node: expression_node, withContext: context) {
|
|
||||||
case .Ok(let expression): .Ok((ExpressionStatement(expression), context))
|
|
||||||
case .Error(let e): .Error(e)
|
case .Error(let e): .Error(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ParserAssignmentStatement: CompilableStatement {
|
extension ExpressionStatement: Compilable {
|
||||||
|
public typealias C = ExpressionStatement
|
||||||
public static func Compile(
|
public static func Compile(
|
||||||
node: Node, withContext context: CompilerContext
|
node: Node, withContext context: CompilerContext
|
||||||
) -> Result<(EvaluatableStatement, CompilerContext)> {
|
) -> Result<ExpressionStatement> {
|
||||||
|
#RequireNodeType<Node, (P4Statement)>(
|
||||||
|
node: node, type: "expressionStatement", nice_type_name: "expression statement")
|
||||||
|
|
||||||
#RequireNodeType<Node, (EvaluatableStatement, CompilerContext)>(
|
let expression_node = node.child(at: 0)!
|
||||||
|
|
||||||
|
return switch Expression.Compile(node: expression_node, withContext: context) {
|
||||||
|
case .Ok(let expression): .Ok(ExpressionStatement(expression))
|
||||||
|
case .Error(let e): .Error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ExpressionStatement: CompilableStatement {
|
||||||
|
public static func CompileStatement(
|
||||||
|
node: Node, withContext context: CompilerContext
|
||||||
|
) -> Result<P4Statement> {
|
||||||
|
return switch Compile(node: node, withContext: context) {
|
||||||
|
case .Ok(let res): .Ok(res)
|
||||||
|
case .Error(let e): .Error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ParserAssignmentStatement: Compilable {
|
||||||
|
public typealias C = ParserAssignmentStatement
|
||||||
|
public static func Compile(
|
||||||
|
node: Node, withContext context: CompilerContext
|
||||||
|
) -> Result<ParserAssignmentStatement> {
|
||||||
|
|
||||||
|
#RequireNodeType<Node, (P4Statement)>(
|
||||||
node: node, type: "assignmentStatement", nice_type_name: "assignment statement")
|
node: node, type: "assignmentStatement", nice_type_name: "assignment statement")
|
||||||
|
|
||||||
guard let lvalue_node = node.child(at: 0),
|
guard let lvalue_node = node.child(at: 0),
|
||||||
@@ -323,20 +365,30 @@ extension ParserAssignmentStatement: CompilableStatement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Result.Ok(
|
return Result.Ok(
|
||||||
(
|
|
||||||
ParserAssignmentStatement(
|
ParserAssignmentStatement(
|
||||||
withLValue: lvalue_identifier,
|
withLValue: lvalue_identifier,
|
||||||
withValue: rvalue
|
withValue: rvalue
|
||||||
), context
|
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ReturnStatement: CompilableStatement {
|
extension ParserAssignmentStatement: CompilableStatement {
|
||||||
|
public static func CompileStatement(
|
||||||
|
node: Node, withContext context: CompilerContext
|
||||||
|
) -> Result<P4Statement> {
|
||||||
|
return switch Compile(node: node, withContext: context) {
|
||||||
|
case .Ok(let res): .Ok(res)
|
||||||
|
case .Error(let e): .Error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ReturnStatement: Compilable {
|
||||||
|
public typealias C = ReturnStatement
|
||||||
public static func Compile(
|
public static func Compile(
|
||||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Common.Result<(any Common.EvaluatableStatement, CompilerContext)> {
|
) -> Result<ReturnStatement> {
|
||||||
#RequireNodeType<Node, (EvaluatableStatement, CompilerContext)>(
|
#RequireNodeType<Node, (P4Statement)>(
|
||||||
node: node, type: "return_statement", nice_type_name: "return statement")
|
node: node, type: "return_statement", nice_type_name: "return statement")
|
||||||
|
|
||||||
let expression_node = node.child(at: 1)!
|
let expression_node = node.child(at: 1)!
|
||||||
@@ -344,7 +396,7 @@ extension ReturnStatement: CompilableStatement {
|
|||||||
return switch Expression.Compile(node: expression_node, withContext: context) {
|
return switch Expression.Compile(node: expression_node, withContext: context) {
|
||||||
case .Ok(let result):
|
case .Ok(let result):
|
||||||
if result.type().baseType().eq(rhs: context.expected_type!.baseType()) {
|
if result.type().baseType().eq(rhs: context.expected_type!.baseType()) {
|
||||||
.Ok((ReturnStatement(result), context))
|
.Ok(ReturnStatement(result))
|
||||||
} else {
|
} else {
|
||||||
.Error(
|
.Error(
|
||||||
ErrorWithLocation(
|
ErrorWithLocation(
|
||||||
@@ -358,18 +410,184 @@ extension ReturnStatement: CompilableStatement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ApplyStatement: CompilableStatement {
|
extension ReturnStatement: CompilableStatement {
|
||||||
|
public static func CompileStatement(
|
||||||
|
node: Node, withContext context: CompilerContext
|
||||||
|
) -> Result<P4Statement> {
|
||||||
|
return switch Compile(node: node, withContext: context) {
|
||||||
|
case .Ok(let res): .Ok(res)
|
||||||
|
case .Error(let e): .Error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ApplyStatement: Compilable {
|
||||||
|
public typealias C = ApplyStatement
|
||||||
public static func Compile(
|
public static func Compile(
|
||||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Common.Result<(any Common.EvaluatableStatement, CompilerContext)> {
|
) -> Result<ApplyStatement> {
|
||||||
#RequireNodeType<Node, (EvaluatableStatement, CompilerContext)>(
|
#RequireNodeType<Node, (P4Statement)>(
|
||||||
node: node, type: "apply_statement", nice_type_name: "apply statement")
|
node: node, type: "apply_statement", nice_type_name: "apply statement")
|
||||||
|
|
||||||
let expression_node = node.child(at: 1)!
|
let expression_node = node.child(at: 1)!
|
||||||
|
|
||||||
return switch BlockStatement.Compile(node: expression_node, withContext: context) {
|
return switch BlockStatement.Compile(node: expression_node, withContext: context) {
|
||||||
case .Ok((let statement, let updated_context)):
|
case .Ok(let statement):
|
||||||
.Ok((ApplyStatement(statement as! BlockStatement), updated_context))
|
.Ok(ApplyStatement(statement as! BlockStatement))
|
||||||
|
case .Error(let e): .Error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ApplyStatement: CompilableStatement {
|
||||||
|
public static func CompileStatement(
|
||||||
|
node: Node, withContext context: CompilerContext
|
||||||
|
) -> Result<P4Statement> {
|
||||||
|
return switch Compile(node: node, withContext: context) {
|
||||||
|
case .Ok(let res): .Ok(res)
|
||||||
|
case .Error(let e): .Error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Instantiation: Compilable {
|
||||||
|
public typealias C = Instantiation
|
||||||
|
public static func Compile(
|
||||||
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
|
) -> Result<Instantiation> {
|
||||||
|
|
||||||
|
let expression = node
|
||||||
|
#RequireNodeType<Node, (Instantiation)>(
|
||||||
|
node: expression, type: "instantiation", nice_type_name: "instantiation statement")
|
||||||
|
|
||||||
|
var walker = Walker(node: expression)
|
||||||
|
var current_node: Node? = .none
|
||||||
|
|
||||||
|
#MustOr(
|
||||||
|
result: current_node, thing: walker.getNext(),
|
||||||
|
or: Result<Instantiation>.Error(
|
||||||
|
ErrorWithLocation(
|
||||||
|
sourceLocation: node.toSourceLocation(), withError: "Missing function call component")))
|
||||||
|
|
||||||
|
let maybe_instantiated_type_name = Identifier.Compile(
|
||||||
|
node: current_node!, withContext: context)
|
||||||
|
guard case .Ok(let instantiated_type_name) = maybe_instantiated_type_name else {
|
||||||
|
return Result.Error(maybe_instantiated_type_name.error()!)
|
||||||
|
}
|
||||||
|
|
||||||
|
var maybe_instantiated_type: Result<(P4Lang.Parser?, Declaration?)> =
|
||||||
|
switch context.types.lookup(identifier: instantiated_type_name) {
|
||||||
|
case .Ok(let looked_up):
|
||||||
|
switch looked_up {
|
||||||
|
/// TODO: Further filter instantiable things.
|
||||||
|
case let instantiated_parser as P4Lang.Parser:
|
||||||
|
Result<(P4Lang.Parser?, Declaration?)>.Ok((instantiated_parser, .none)) // What we found is actually a parser declaration
|
||||||
|
default:
|
||||||
|
Result<(P4Lang.Parser?, Declaration?)>.Error(
|
||||||
|
ErrorWithLocation(
|
||||||
|
sourceLocation: current_node!.toSourceLocation(),
|
||||||
|
withError: "\(instantiated_type_name) cannot be instantiated"))
|
||||||
|
}
|
||||||
|
case .Error(let e): Result<(P4Lang.Parser?, Declaration?)>.Error(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
maybe_instantiated_type =
|
||||||
|
if case .Error(let e) = maybe_instantiated_type {
|
||||||
|
switch context.externs.lookup(identifier: instantiated_type_name) {
|
||||||
|
case .Ok(let callee as Declaration):
|
||||||
|
// Now, make sure that it is a function declaration!
|
||||||
|
switch callee.identifier.type.baseType() {
|
||||||
|
case is P4Lang.Parser: Result.Ok((.none, callee))
|
||||||
|
default:
|
||||||
|
.Error(
|
||||||
|
ErrorWithLocation(
|
||||||
|
sourceLocation: current_node!.toSourceLocation(),
|
||||||
|
withError: "\(instantiated_type_name) cannot be instantiated"))
|
||||||
|
}
|
||||||
|
default: .Error(e)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
maybe_instantiated_type
|
||||||
|
}
|
||||||
|
|
||||||
|
guard case .Ok(let callee) = maybe_instantiated_type else {
|
||||||
|
return .Error(maybe_instantiated_type.error()!)
|
||||||
|
}
|
||||||
|
|
||||||
|
walker.next()
|
||||||
|
|
||||||
|
#MustOr(
|
||||||
|
result: current_node, thing: walker.getNext(),
|
||||||
|
or: Result<Instantiation>.Error(
|
||||||
|
ErrorWithLocation(
|
||||||
|
sourceLocation: node.toSourceLocation(), withError: "Missing instantiation component")))
|
||||||
|
|
||||||
|
let maybe_argument_list = ArgumentList.Compile(node: current_node!, withContext: context)
|
||||||
|
|
||||||
|
guard case .Ok(let arguments) = maybe_argument_list else {
|
||||||
|
return .Error(maybe_argument_list.error()!)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now, compare the arguments with the parameters:
|
||||||
|
|
||||||
|
let params =
|
||||||
|
switch callee {
|
||||||
|
case (.some(let callee), .none): Optional<ParameterList>.some(callee.parameters)
|
||||||
|
case (.none, .some(let callee)):
|
||||||
|
Optional<ParameterList>.some((callee.ffi!.type().baseType() as! P4Lang.Parser).parameters)
|
||||||
|
default: Optional<ParameterList>.none
|
||||||
|
}
|
||||||
|
|
||||||
|
guard case .some(let params) = params else {
|
||||||
|
return Result.Error(
|
||||||
|
ErrorWithLocation(
|
||||||
|
sourceLocation: node.toSourceLocation(),
|
||||||
|
withError:
|
||||||
|
"Could not lookup the parameters for the instantiated parser (\(instantiated_type_name))"
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
if case .Error(let e) = arguments.compatible(params) {
|
||||||
|
return .Error(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
walker.next()
|
||||||
|
|
||||||
|
#MustOr(
|
||||||
|
result: current_node, thing: walker.getNext(),
|
||||||
|
or: Result<Instantiation>.Error(
|
||||||
|
ErrorWithLocation(
|
||||||
|
sourceLocation: node.toSourceLocation(), withError: "Missing instantiation name")))
|
||||||
|
|
||||||
|
let name = Identifier.Compile(node: current_node!, withContext: context)
|
||||||
|
guard case .Ok(let name) = name else {
|
||||||
|
return .Error(name.error()!)
|
||||||
|
}
|
||||||
|
|
||||||
|
let inst: Result<Instantiation> =
|
||||||
|
switch callee {
|
||||||
|
case (.some(let callee), .none):
|
||||||
|
.Ok(Instantiation(named: name, ofType: callee, withArguments: arguments))
|
||||||
|
case (.none, .some(let callee)):
|
||||||
|
.Ok(Instantiation(named: name, ofType: callee, withArguments: arguments))
|
||||||
|
default:
|
||||||
|
Result.Error(
|
||||||
|
ErrorWithLocation(
|
||||||
|
sourceLocation: node.toSourceLocation(),
|
||||||
|
withError:
|
||||||
|
"Unexpected error occurred calling function named (\(instantiated_type_name))"
|
||||||
|
))
|
||||||
|
}
|
||||||
|
return inst
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Instantiation: CompilableStatement {
|
||||||
|
public static func CompileStatement(
|
||||||
|
node: Node, withContext context: CompilerContext
|
||||||
|
) -> Result<P4Statement> {
|
||||||
|
return switch Compile(node: node, withContext: context) {
|
||||||
|
case .Ok(let res): .Ok(res)
|
||||||
case .Error(let e): .Error(e)
|
case .Error(let e): .Error(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,95 +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 <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
import Common
|
|
||||||
|
|
||||||
public protocol Visitable {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public protocol LanguageVisitor<Context> {
|
|
||||||
associatedtype Context
|
|
||||||
|
|
||||||
// Program
|
|
||||||
func visit(_ program: Program, _ c: VisitorContext<Context>) -> Result<VisitorContext<Context>>
|
|
||||||
|
|
||||||
// Parser
|
|
||||||
func visit(_ parser: Parser, _ c: VisitorContext<Context>) -> Result<VisitorContext<Context>>
|
|
||||||
func visit(
|
|
||||||
_ parser_state: InstantiatedParserState, _ c: VisitorContext<Context>
|
|
||||||
) -> Result<VisitorContext<Context>>
|
|
||||||
|
|
||||||
// Statements
|
|
||||||
func visit(
|
|
||||||
_ variable_declaration: VariableDeclarationStatement, _ c: VisitorContext<Context>
|
|
||||||
) -> Result<VisitorContext<Context>>
|
|
||||||
func visit(
|
|
||||||
_ conditional: ConditionalStatement, _ c: VisitorContext<Context>
|
|
||||||
) -> Result<VisitorContext<Context>>
|
|
||||||
func visit(
|
|
||||||
_ block: BlockStatement, _ c: VisitorContext<Context>
|
|
||||||
) -> Result<VisitorContext<Context>>
|
|
||||||
func visit(
|
|
||||||
_ rtn: ReturnStatement, _ c: VisitorContext<Context>
|
|
||||||
) -> Result<VisitorContext<Context>>
|
|
||||||
func visit(
|
|
||||||
_ apply: ApplyStatement, _ c: VisitorContext<Context>
|
|
||||||
) -> Result<VisitorContext<Context>>
|
|
||||||
|
|
||||||
// Expressions
|
|
||||||
func visit(
|
|
||||||
_ keyset: KeysetExpression, _ c: VisitorContext<Context>
|
|
||||||
) -> Result<VisitorContext<Context>>
|
|
||||||
func visit(
|
|
||||||
_ select_case: SelectCaseExpression, _ c: VisitorContext<Context>
|
|
||||||
) -> Result<VisitorContext<Context>>
|
|
||||||
func visit(
|
|
||||||
_ select: SelectExpression, _ c: VisitorContext<Context>
|
|
||||||
) -> Result<VisitorContext<Context>>
|
|
||||||
func visit(
|
|
||||||
_ array_access: ArrayAccessExpression, _ c: VisitorContext<Context>
|
|
||||||
) -> Result<VisitorContext<Context>>
|
|
||||||
func visit(
|
|
||||||
_ field_access: FieldAccessExpression, _ c: VisitorContext<Context>
|
|
||||||
) -> Result<VisitorContext<Context>>
|
|
||||||
func visit(
|
|
||||||
_ function_call: FunctionCall, _ c: VisitorContext<Context>
|
|
||||||
) -> Result<VisitorContext<Context>>
|
|
||||||
func visit(
|
|
||||||
_ binary_operator: BinaryOperatorExpression, _ c: VisitorContext<Context>
|
|
||||||
) -> Result<VisitorContext<Context>>
|
|
||||||
|
|
||||||
// Declarations
|
|
||||||
func visit(_ decl: Declaration, _ c: VisitorContext<Context>) -> Result<VisitorContext<Context>>
|
|
||||||
func visit(
|
|
||||||
_ extern_decl: ExternDeclaration, _ c: VisitorContext<Context>
|
|
||||||
) -> Result<VisitorContext<Context>>
|
|
||||||
func visit(
|
|
||||||
_ func_decl: FunctionDeclaration, _ c: VisitorContext<Context>
|
|
||||||
) -> Result<VisitorContext<Context>>
|
|
||||||
|
|
||||||
// Control
|
|
||||||
func visit(_ action: Action, _ c: VisitorContext<Context>) -> Result<VisitorContext<Context>>
|
|
||||||
func visit(
|
|
||||||
_ table_key_entry: TableKeyEntry, _ c: VisitorContext<Context>
|
|
||||||
) -> Result<VisitorContext<Context>>
|
|
||||||
func visit(
|
|
||||||
_ table_property_list: TablePropertyList, _ c: VisitorContext<Context>
|
|
||||||
) -> Result<VisitorContext<Context>>
|
|
||||||
func visit(_ table: Table, _ c: VisitorContext<Context>) -> Result<VisitorContext<Context>>
|
|
||||||
func visit(_ control: Control, _ c: VisitorContext<Context>) -> Result<VisitorContext<Context>>
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ public struct Declaration: P4Type {
|
|||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
public var description: String {
|
public var description: String {
|
||||||
return "Extern \(self.identifier)"
|
return self.extern ? "Extern " : "" + "\(self.identifier)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,3 +130,15 @@ public struct FunctionDeclaration: P4Type, P4DataValue {
|
|||||||
self.body = body
|
self.body = body
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct Instantiation {
|
||||||
|
public let name: Identifier
|
||||||
|
public let tipe: P4Type
|
||||||
|
public let arguments: ArgumentList
|
||||||
|
|
||||||
|
public init(named name: Identifier, ofType tipe: P4Type, withArguments arguments: ArgumentList) {
|
||||||
|
self.name = name
|
||||||
|
self.tipe = tipe
|
||||||
|
self.arguments = arguments
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -18,9 +18,9 @@
|
|||||||
import Common
|
import Common
|
||||||
|
|
||||||
public struct KeysetExpression {
|
public struct KeysetExpression {
|
||||||
public let key: EvaluatableExpression
|
public let key: P4Expression
|
||||||
|
|
||||||
public init(_ key: EvaluatableExpression) {
|
public init(_ key: P4Expression) {
|
||||||
self.key = key
|
self.key = key
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,11 +65,11 @@ public struct SelectCaseExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public struct SelectExpression {
|
public struct SelectExpression {
|
||||||
public let selector: EvaluatableExpression
|
public let selector: P4Expression
|
||||||
public let case_expressions: [SelectCaseExpression]
|
public let case_expressions: [SelectCaseExpression]
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
withSelector selector: EvaluatableExpression,
|
withSelector selector: P4Expression,
|
||||||
withSelectCaseExpressions sces: [SelectCaseExpression]
|
withSelectCaseExpressions sces: [SelectCaseExpression]
|
||||||
) {
|
) {
|
||||||
self.selector = selector
|
self.selector = selector
|
||||||
@@ -105,13 +105,13 @@ public struct BinaryOperatorExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public struct ArrayAccessExpression {
|
public struct ArrayAccessExpression {
|
||||||
public let indexor: EvaluatableExpression
|
public let indexor: P4Expression
|
||||||
public let name: EvaluatableExpression
|
public let name: P4Expression
|
||||||
public let type: P4Array
|
public let type: P4Array
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
withName name: EvaluatableExpression, withType type: P4Array,
|
withName name: P4Expression, withType type: P4Array,
|
||||||
withIndexor indexor: EvaluatableExpression
|
withIndexor indexor: P4Expression
|
||||||
) {
|
) {
|
||||||
self.name = name
|
self.name = name
|
||||||
self.type = type
|
self.type = type
|
||||||
@@ -121,9 +121,9 @@ public struct ArrayAccessExpression {
|
|||||||
|
|
||||||
public struct FieldAccessExpression {
|
public struct FieldAccessExpression {
|
||||||
public let field: P4StructFieldIdentifier
|
public let field: P4StructFieldIdentifier
|
||||||
public let strct: EvaluatableExpression
|
public let strct: P4Expression
|
||||||
|
|
||||||
public init(withStruct strct: EvaluatableExpression, withField field: P4StructFieldIdentifier) {
|
public init(withStruct strct: P4Expression, withField field: P4StructFieldIdentifier) {
|
||||||
self.strct = strct
|
self.strct = strct
|
||||||
self.field = field
|
self.field = field
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-13
@@ -22,11 +22,11 @@ public struct LocalElements {}
|
|||||||
public struct LocalElement {}
|
public struct LocalElement {}
|
||||||
|
|
||||||
public struct ParserAssignmentStatement {
|
public struct ParserAssignmentStatement {
|
||||||
public let lvalue: EvaluatableLValueExpression
|
public let lvalue: P4LValueExpression
|
||||||
public let value: EvaluatableExpression
|
public let value: P4Expression
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
withLValue lvalue: EvaluatableLValueExpression, withValue value: EvaluatableExpression
|
withLValue lvalue: P4LValueExpression, withValue value: P4Expression
|
||||||
) {
|
) {
|
||||||
self.lvalue = lvalue
|
self.lvalue = lvalue
|
||||||
self.value = value
|
self.value = value
|
||||||
@@ -34,12 +34,9 @@ public struct ParserAssignmentStatement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A P4 Parser State
|
/// A P4 Parser State
|
||||||
///
|
|
||||||
/// Note: A P4 Parser State is both a type and a value.
|
|
||||||
/// This "bare" parser state represents the state more as a type than a value.
|
|
||||||
public class ParserState: P4Type, Equatable, CustomStringConvertible {
|
public class ParserState: P4Type, Equatable, CustomStringConvertible {
|
||||||
let name: Identifier
|
let name: Identifier
|
||||||
public let statements: [EvaluatableStatement]
|
public let statements: [P4Statement]
|
||||||
|
|
||||||
public static func == (lhs: ParserState, rhs: ParserState) -> Bool {
|
public static func == (lhs: ParserState, rhs: ParserState) -> Bool {
|
||||||
return lhs.eq(rhs: rhs)
|
return lhs.eq(rhs: rhs)
|
||||||
@@ -60,12 +57,12 @@ public class ParserState: P4Type, Equatable, CustomStringConvertible {
|
|||||||
return self.name
|
return self.name
|
||||||
}
|
}
|
||||||
|
|
||||||
public func getStatements() -> [EvaluatableStatement] {
|
public func getStatements() -> [P4Statement] {
|
||||||
return self.statements
|
return self.statements
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a ParserState
|
/// Construct a ParserState
|
||||||
public init(_ name: Identifier, _ statements: [EvaluatableStatement] = Array()) {
|
public init(_ name: Identifier, _ statements: [P4Statement] = Array()) {
|
||||||
self.name = name
|
self.name = name
|
||||||
self.statements = statements
|
self.statements = statements
|
||||||
}
|
}
|
||||||
@@ -100,7 +97,7 @@ public class ParserStateDirectTransition: ParserState {
|
|||||||
/// Construct a ParserState
|
/// Construct a ParserState
|
||||||
public init(
|
public init(
|
||||||
name: Identifier, withNextState next_state: InstantiatedParserState,
|
name: Identifier, withNextState next_state: InstantiatedParserState,
|
||||||
withStatements stmts: [EvaluatableStatement] = Array(),
|
withStatements stmts: [P4Statement] = Array(),
|
||||||
) {
|
) {
|
||||||
self.next_state = next_state
|
self.next_state = next_state
|
||||||
self.next_state_identifier = .none
|
self.next_state_identifier = .none
|
||||||
@@ -109,7 +106,7 @@ public class ParserStateDirectTransition: ParserState {
|
|||||||
|
|
||||||
public init(
|
public init(
|
||||||
name: Identifier, withNextStateIdentifier next_state_id: Identifier,
|
name: Identifier, withNextStateIdentifier next_state_id: Identifier,
|
||||||
withStatements stmts: [EvaluatableStatement] = Array(),
|
withStatements stmts: [P4Statement] = Array(),
|
||||||
) {
|
) {
|
||||||
self.next_state = .none
|
self.next_state = .none
|
||||||
self.next_state_identifier = next_state_id
|
self.next_state_identifier = next_state_id
|
||||||
@@ -129,7 +126,7 @@ public class ParserStateDirectTransition: ParserState {
|
|||||||
public class ParserStateNoTransition: ParserState {
|
public class ParserStateNoTransition: ParserState {
|
||||||
/// Construct a ParserState
|
/// Construct a ParserState
|
||||||
public init(
|
public init(
|
||||||
name: Identifier, withStatements stmts: [EvaluatableStatement] = Array(),
|
name: Identifier, withStatements stmts: [P4Statement] = Array(),
|
||||||
) {
|
) {
|
||||||
super.init(name, stmts)
|
super.init(name, stmts)
|
||||||
}
|
}
|
||||||
@@ -145,7 +142,7 @@ public class ParserStateSelectTransition: ParserState {
|
|||||||
|
|
||||||
public init(
|
public init(
|
||||||
name: Identifier, withTransitionExpression te: SelectExpression,
|
name: Identifier, withTransitionExpression te: SelectExpression,
|
||||||
withStatements stmts: [EvaluatableStatement] = Array()
|
withStatements stmts: [P4Statement] = Array()
|
||||||
) {
|
) {
|
||||||
self.te = te
|
self.te = te
|
||||||
super.init(name, stmts)
|
super.init(name, stmts)
|
||||||
|
|||||||
@@ -18,9 +18,9 @@
|
|||||||
import Common
|
import Common
|
||||||
|
|
||||||
public struct ExpressionStatement {
|
public struct ExpressionStatement {
|
||||||
public let expression: EvaluatableExpression
|
public let expression: P4Expression
|
||||||
|
|
||||||
public init(_ expr: EvaluatableExpression) {
|
public init(_ expr: P4Expression) {
|
||||||
self.expression = expr
|
self.expression = expr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import Common
|
||||||
|
|
||||||
|
public protocol Visitable {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public protocol LanguageVisitor<Context> {
|
||||||
|
associatedtype Context
|
||||||
|
|
||||||
|
// Program
|
||||||
|
func visit(_ program: Program, _ c: VisitorContext<Context>) -> Result<VisitorContext<Context>>
|
||||||
|
|
||||||
|
// Parser
|
||||||
|
func visit(_ parser: Parser, _ c: VisitorContext<Context>) -> Result<VisitorContext<Context>>
|
||||||
|
func visit(
|
||||||
|
_ parser_state: InstantiatedParserState, _ c: VisitorContext<Context>
|
||||||
|
) -> Result<VisitorContext<Context>>
|
||||||
|
|
||||||
|
// Statements
|
||||||
|
func visit(
|
||||||
|
_ variable_declaration: VariableDeclarationStatement, _ c: VisitorContext<Context>
|
||||||
|
) -> Result<VisitorContext<Context>>
|
||||||
|
func visit(
|
||||||
|
_ conditional: ConditionalStatement, _ c: VisitorContext<Context>
|
||||||
|
) -> Result<VisitorContext<Context>>
|
||||||
|
func visit(
|
||||||
|
_ block: BlockStatement, _ c: VisitorContext<Context>
|
||||||
|
) -> Result<VisitorContext<Context>>
|
||||||
|
func visit(
|
||||||
|
_ rtn: ReturnStatement, _ c: VisitorContext<Context>
|
||||||
|
) -> Result<VisitorContext<Context>>
|
||||||
|
func visit(
|
||||||
|
_ apply: ApplyStatement, _ c: VisitorContext<Context>
|
||||||
|
) -> Result<VisitorContext<Context>>
|
||||||
|
|
||||||
|
// Expressions
|
||||||
|
func visit(
|
||||||
|
_ keyset: KeysetExpression, _ c: VisitorContext<Context>
|
||||||
|
) -> Result<VisitorContext<Context>>
|
||||||
|
func visit(
|
||||||
|
_ select_case: SelectCaseExpression, _ c: VisitorContext<Context>
|
||||||
|
) -> Result<VisitorContext<Context>>
|
||||||
|
func visit(
|
||||||
|
_ select: SelectExpression, _ c: VisitorContext<Context>
|
||||||
|
) -> Result<VisitorContext<Context>>
|
||||||
|
func visit(
|
||||||
|
_ array_access: ArrayAccessExpression, _ c: VisitorContext<Context>
|
||||||
|
) -> Result<VisitorContext<Context>>
|
||||||
|
func visit(
|
||||||
|
_ field_access: FieldAccessExpression, _ c: VisitorContext<Context>
|
||||||
|
) -> Result<VisitorContext<Context>>
|
||||||
|
func visit(
|
||||||
|
_ function_call: FunctionCall, _ c: VisitorContext<Context>
|
||||||
|
) -> Result<VisitorContext<Context>>
|
||||||
|
func visit(
|
||||||
|
_ binary_operator: BinaryOperatorExpression, _ c: VisitorContext<Context>
|
||||||
|
) -> Result<VisitorContext<Context>>
|
||||||
|
|
||||||
|
// Declarations
|
||||||
|
func visit(_ decl: Declaration, _ c: VisitorContext<Context>) -> Result<VisitorContext<Context>>
|
||||||
|
func visit(
|
||||||
|
_ extern_decl: ExternDeclaration, _ c: VisitorContext<Context>
|
||||||
|
) -> Result<VisitorContext<Context>>
|
||||||
|
func visit(
|
||||||
|
_ func_decl: FunctionDeclaration, _ c: VisitorContext<Context>
|
||||||
|
) -> Result<VisitorContext<Context>>
|
||||||
|
|
||||||
|
// Control
|
||||||
|
func visit(_ action: Action, _ c: VisitorContext<Context>) -> Result<VisitorContext<Context>>
|
||||||
|
func visit(
|
||||||
|
_ table_key_entry: TableKeyEntry, _ c: VisitorContext<Context>
|
||||||
|
) -> Result<VisitorContext<Context>>
|
||||||
|
func visit(
|
||||||
|
_ table_property_list: TablePropertyList, _ c: VisitorContext<Context>
|
||||||
|
) -> Result<VisitorContext<Context>>
|
||||||
|
func visit(_ table: Table, _ c: VisitorContext<Context>) -> Result<VisitorContext<Context>>
|
||||||
|
func visit(_ control: Control, _ c: VisitorContext<Context>) -> Result<VisitorContext<Context>>
|
||||||
|
}
|
||||||
@@ -20,28 +20,28 @@ import Common
|
|||||||
public struct Statement {}
|
public struct Statement {}
|
||||||
|
|
||||||
public struct VariableDeclarationStatement {
|
public struct VariableDeclarationStatement {
|
||||||
public var initializer: EvaluatableExpression
|
public var initializer: P4Expression
|
||||||
public var identifier: Identifier
|
public var identifier: TypedIdentifier
|
||||||
public init(identifier: Identifier, withInitializer initializer: EvaluatableExpression) {
|
public init(identifier: TypedIdentifier, withInitializer initializer: P4Expression) {
|
||||||
self.identifier = identifier
|
self.identifier = identifier
|
||||||
self.initializer = initializer
|
self.initializer = initializer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct ConditionalStatement {
|
public struct ConditionalStatement {
|
||||||
public var condition: EvaluatableExpression
|
public var condition: P4Expression
|
||||||
public var thenn: EvaluatableStatement
|
public var thenn: P4Statement
|
||||||
public var elss: EvaluatableStatement?
|
public var elss: P4Statement?
|
||||||
|
|
||||||
public init(condition: EvaluatableExpression, withThen thenn: EvaluatableStatement) {
|
public init(condition: P4Expression, withThen thenn: P4Statement) {
|
||||||
self.condition = condition
|
self.condition = condition
|
||||||
self.thenn = thenn
|
self.thenn = thenn
|
||||||
self.elss = .none
|
self.elss = .none
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
condition: EvaluatableExpression, withThen thenn: EvaluatableStatement,
|
condition: P4Expression, withThen thenn: P4Statement,
|
||||||
andElse elss: EvaluatableStatement
|
andElse elss: P4Statement
|
||||||
) {
|
) {
|
||||||
self.condition = condition
|
self.condition = condition
|
||||||
self.thenn = thenn
|
self.thenn = thenn
|
||||||
@@ -50,18 +50,18 @@ public struct ConditionalStatement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public struct BlockStatement {
|
public struct BlockStatement {
|
||||||
public var statements: [EvaluatableStatement]
|
public var statements: [P4Statement]
|
||||||
|
|
||||||
public init(_ statements: [EvaluatableStatement]) {
|
public init(_ statements: [P4Statement]) {
|
||||||
self.statements = statements
|
self.statements = statements
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct ReturnStatement {
|
public struct ReturnStatement {
|
||||||
public let value: EvaluatableExpression
|
public let value: P4Expression
|
||||||
|
|
||||||
public init(_ value: EvaluatableExpression) {
|
public init(_ value: P4Expression) {
|
||||||
self.value = value
|
self.value = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ public func Call<T>(
|
|||||||
param_direction == Direction.InOut || param_direction == Direction.Out
|
param_direction == Direction.InOut || param_direction == Direction.Out
|
||||||
{
|
{
|
||||||
// Let's make sure that it is an evaluatable l value!
|
// Let's make sure that it is an evaluatable l value!
|
||||||
guard let arg_lvalue = argument.argument as? EvaluatableLValueExpression else {
|
guard let arg_lvalue = argument.argument as? P4LValueExpression else {
|
||||||
return (
|
return (
|
||||||
.Error(Error(withMessage: "(in)out parameter argument is not lvalue")),
|
.Error(Error(withMessage: "(in)out parameter argument is not lvalue")),
|
||||||
updated_execution.exit_scope()
|
updated_execution.exit_scope()
|
||||||
|
|||||||
@@ -91,10 +91,14 @@ extension Control: LibraryCallable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Action: EvaluatableStatement {
|
extension Action: P4Statement {
|
||||||
|
public func effect(context: Common.CompilerContext) -> Common.CompilerContext {
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
|
||||||
public func evaluate(
|
public func evaluate(
|
||||||
execution: Common.ProgramExecution
|
execution: Common.ProgramExecution
|
||||||
) -> (Common.ControlFlow, Common.ProgramExecution) {
|
) -> (ControlFlow, Common.ProgramExecution) {
|
||||||
if let body = self.body {
|
if let body = self.body {
|
||||||
return body.evaluate(execution: execution)
|
return body.evaluate(execution: execution)
|
||||||
}
|
}
|
||||||
|
|||||||
+134
-108
@@ -22,88 +22,11 @@ extension SelectCaseExpression: EvaluatableExpression {
|
|||||||
public func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution) {
|
public func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution) {
|
||||||
return (execution.scopes.lookup(identifier: next_state_identifier), execution)
|
return (execution.scopes.lookup(identifier: next_state_identifier), execution)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func type() -> P4QualifiedType {
|
public func type() -> P4QualifiedType {
|
||||||
return P4QualifiedType(AnyParserState)
|
return P4QualifiedType(AnyParserState)
|
||||||
}
|
}
|
||||||
}
|
public func effect(context: CompilerContext) -> CompilerContext {
|
||||||
|
return context
|
||||||
extension SelectExpression: EvaluatableExpression {
|
|
||||||
public func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution) {
|
|
||||||
switch execution.evaluator.EvaluateExpression(self.selector, inExecution: execution) {
|
|
||||||
case (.Ok(let selector_value), let updated_execution):
|
|
||||||
for sce in self.case_expressions {
|
|
||||||
if case (.Ok(let kse), let updated_execution) = updated_execution.evaluator
|
|
||||||
.EvaluateExpression(
|
|
||||||
sce.key, inExecution: updated_execution),
|
|
||||||
kse.eq(selector_value)
|
|
||||||
{
|
|
||||||
//let result = sce.evaluate(execution: updated_execution)
|
|
||||||
let result = updated_execution.evaluator.EvaluateExpression(
|
|
||||||
sce, inExecution: updated_execution)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (.Error(Error(withMessage: "No key matched the selector")), updated_execution)
|
|
||||||
case (.Error(let e), let updated_execution): return (.Error(e), updated_execution)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public func type() -> P4QualifiedType {
|
|
||||||
return P4QualifiedType(AnyParserState)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Variables are evaluatable because they can be looked up by identifiers.
|
|
||||||
extension TypedIdentifier: EvaluatableExpression {
|
|
||||||
public func type() -> P4QualifiedType {
|
|
||||||
return self.type
|
|
||||||
}
|
|
||||||
|
|
||||||
public func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution) {
|
|
||||||
return (execution.scopes.lookup(identifier: self), execution)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Variables are evaluatable because they can be looked up by identifiers.
|
|
||||||
extension TypedIdentifier: EvaluatableLValueExpression {
|
|
||||||
public func set(
|
|
||||||
to: P4Value, inScopes scopes: Common.VarValueScopes,
|
|
||||||
duringExecution execution: ProgramExecution
|
|
||||||
) -> Common.Result<(Common.VarValueScopes, P4Value)> {
|
|
||||||
if case .Error(let e) = scopes.lookup(identifier: self) {
|
|
||||||
return .Error(e)
|
|
||||||
}
|
|
||||||
|
|
||||||
return .Ok((scopes.set(identifier: self, withValue: to), to))
|
|
||||||
}
|
|
||||||
|
|
||||||
public func check(
|
|
||||||
to: any Common.EvaluatableExpression, inScopes scopes: Common.StaticVarValueScopes
|
|
||||||
) -> Result<()> {
|
|
||||||
guard case .Ok(let type) = scopes.lookup(identifier: self) else {
|
|
||||||
return .Error(Error(withMessage: "Cannot assign to identifier not in scope"))
|
|
||||||
}
|
|
||||||
|
|
||||||
return switch type.0.assignableFromType(to.type()) {
|
|
||||||
case TypeCheckResults.IncompatibleTypes:
|
|
||||||
.Error(
|
|
||||||
Error(
|
|
||||||
withMessage:
|
|
||||||
"Cannot assign value with type \(to.type()) to identifier \(self) with type \(type.0)"))
|
|
||||||
case TypeCheckResults.ReadOnly:
|
|
||||||
.Error(
|
|
||||||
Error(
|
|
||||||
withMessage:
|
|
||||||
"Cannot assign value with type \(to.type()) to identifier \(self) that is read only"))
|
|
||||||
case TypeCheckResults.WrongDirection:
|
|
||||||
.Error(
|
|
||||||
Error(
|
|
||||||
withMessage:
|
|
||||||
"Cannot assign value with type \(to.type()) to identifier \(self) that is in parameter")
|
|
||||||
)
|
|
||||||
case TypeCheckResults.Ok: .Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,7 +109,7 @@ public func binary_divide_operator_evaluator(left: P4Value, right: P4Value) -> P
|
|||||||
}
|
}
|
||||||
|
|
||||||
// swift-format-ignore
|
// swift-format-ignore
|
||||||
public typealias BinaryOperatorChecker = (EvaluatableExpression, EvaluatableExpression) -> Result<()>
|
public typealias BinaryOperatorChecker = (EvaluatableExpression, P4Expression) -> Result<()>
|
||||||
|
|
||||||
public func binary_and_or_operator_checker(
|
public func binary_and_or_operator_checker(
|
||||||
left: EvaluatableExpression, right: EvaluatableExpression
|
left: EvaluatableExpression, right: EvaluatableExpression
|
||||||
@@ -211,6 +134,10 @@ public func binary_int_math_operator_checker(
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension BinaryOperatorExpression: EvaluatableExpression {
|
extension BinaryOperatorExpression: EvaluatableExpression {
|
||||||
|
public func effect(context: CompilerContext) -> CompilerContext {
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
|
||||||
public func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution) {
|
public func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution) {
|
||||||
let updated_execution = execution
|
let updated_execution = execution
|
||||||
//let maybe_evaluated_left = self.left.evaluate(execution: updated_execution)
|
//let maybe_evaluated_left = self.left.evaluate(execution: updated_execution)
|
||||||
@@ -235,7 +162,11 @@ extension BinaryOperatorExpression: EvaluatableExpression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ArrayAccessExpression: EvaluatableExpression {
|
extension ArrayAccessExpression: EvaluatableExpression, EvaluatableLValueExpression {
|
||||||
|
|
||||||
|
public func effect(context: CompilerContext) -> CompilerContext {
|
||||||
|
return context
|
||||||
|
}
|
||||||
public func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution) {
|
public func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution) {
|
||||||
let updated_execution = execution
|
let updated_execution = execution
|
||||||
//let maybe_name = self.name.evaluate(execution: updated_execution)
|
//let maybe_name = self.name.evaluate(execution: updated_execution)
|
||||||
@@ -267,9 +198,7 @@ extension ArrayAccessExpression: EvaluatableExpression {
|
|||||||
public func type() -> P4QualifiedType {
|
public func type() -> P4QualifiedType {
|
||||||
return self.type.value_type()
|
return self.type.value_type()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
extension ArrayAccessExpression: EvaluatableLValueExpression {
|
|
||||||
public func set(
|
public func set(
|
||||||
to: P4Value, inScopes scopes: Common.VarValueScopes,
|
to: P4Value, inScopes scopes: Common.VarValueScopes,
|
||||||
duringExecution execution: ProgramExecution
|
duringExecution execution: ProgramExecution
|
||||||
@@ -352,35 +281,13 @@ extension ArrayAccessExpression: EvaluatableLValueExpression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension FieldAccessExpression: EvaluatableExpression {
|
extension FieldAccessExpression: EvaluatableExpression, EvaluatableLValueExpression {
|
||||||
public func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution) {
|
|
||||||
|
|
||||||
let updated_execution = execution
|
|
||||||
//let maybe_struct = self.strct.evaluate(execution: updated_execution)
|
|
||||||
let maybe_struct = updated_execution.evaluator.EvaluateExpression(
|
|
||||||
self.strct, inExecution: updated_execution)
|
|
||||||
guard case (.Ok(let strct), let updated_execution) = maybe_struct else {
|
|
||||||
return maybe_struct
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let struct_strct = strct.dataValue() as? P4StructValue else {
|
|
||||||
return (.Error(Error(withMessage: "\(strct) does not identify a struct")), updated_execution)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// TODO: Create a default value?
|
|
||||||
guard let value = struct_strct.get(field: self.field) else {
|
|
||||||
return (.Error(Error(withMessage: "Missing value")), updated_execution)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (.Ok(value), updated_execution)
|
|
||||||
}
|
|
||||||
|
|
||||||
public func type() -> P4QualifiedType {
|
public func type() -> P4QualifiedType {
|
||||||
return self.field.type
|
return self.field.type
|
||||||
}
|
}
|
||||||
|
public func effect(context: CompilerContext) -> CompilerContext {
|
||||||
|
return context
|
||||||
}
|
}
|
||||||
|
|
||||||
extension FieldAccessExpression: EvaluatableLValueExpression {
|
|
||||||
public func set(
|
public func set(
|
||||||
to: P4Value, inScopes scopes: Common.VarValueScopes,
|
to: P4Value, inScopes scopes: Common.VarValueScopes,
|
||||||
duringExecution execution: ProgramExecution
|
duringExecution execution: ProgramExecution
|
||||||
@@ -459,9 +366,33 @@ extension FieldAccessExpression: EvaluatableLValueExpression {
|
|||||||
default: .Error(Error(withMessage: "Cannot assign to field \(self.field) of \(self.strct)"))
|
default: .Error(Error(withMessage: "Cannot assign to field \(self.field) of \(self.strct)"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution) {
|
||||||
|
|
||||||
|
let updated_execution = execution
|
||||||
|
//let maybe_struct = self.strct.evaluate(execution: updated_execution)
|
||||||
|
let maybe_struct = updated_execution.evaluator.EvaluateExpression(
|
||||||
|
self.strct, inExecution: updated_execution)
|
||||||
|
guard case (.Ok(let strct), let updated_execution) = maybe_struct else {
|
||||||
|
return maybe_struct
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let struct_strct = strct.dataValue() as? P4StructValue else {
|
||||||
|
return (.Error(Error(withMessage: "\(strct) does not identify a struct")), updated_execution)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// TODO: Create a default value?
|
||||||
|
guard let value = struct_strct.get(field: self.field) else {
|
||||||
|
return (.Error(Error(withMessage: "Missing value")), updated_execution)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (.Ok(value), updated_execution)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension KeysetExpression: EvaluatableExpression {
|
extension KeysetExpression: EvaluatableExpression {
|
||||||
|
public func effect(context: CompilerContext) -> CompilerContext {
|
||||||
|
return context
|
||||||
|
}
|
||||||
public func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution) {
|
public func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution) {
|
||||||
//return self.key.evaluate(execution: execution)
|
//return self.key.evaluate(execution: execution)
|
||||||
return execution.evaluator.EvaluateExpression(self.key, inExecution: execution)
|
return execution.evaluator.EvaluateExpression(self.key, inExecution: execution)
|
||||||
@@ -473,6 +404,10 @@ extension KeysetExpression: EvaluatableExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension FunctionCall: EvaluatableExpression {
|
extension FunctionCall: EvaluatableExpression {
|
||||||
|
|
||||||
|
public func effect(context: CompilerContext) -> CompilerContext {
|
||||||
|
return context
|
||||||
|
}
|
||||||
public func evaluate(
|
public func evaluate(
|
||||||
execution: Common.ProgramExecution
|
execution: Common.ProgramExecution
|
||||||
) -> (Common.Result<P4Value>, ProgramExecution) {
|
) -> (Common.Result<P4Value>, ProgramExecution) {
|
||||||
@@ -533,4 +468,95 @@ extension P4Value: EvaluatableExpression {
|
|||||||
public func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution) {
|
public func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution) {
|
||||||
return (.Ok(self), execution)
|
return (.Ok(self), execution)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func effect(context: CompilerContext) -> CompilerContext {
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SelectExpression: EvaluatableExpression {
|
||||||
|
public func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution) {
|
||||||
|
switch execution.evaluator.EvaluateExpression(self.selector, inExecution: execution) {
|
||||||
|
case (.Ok(let selector_value), let updated_execution):
|
||||||
|
for sce in self.case_expressions {
|
||||||
|
if case (.Ok(let kse), let updated_execution) = updated_execution.evaluator
|
||||||
|
.EvaluateExpression(
|
||||||
|
sce.key, inExecution: updated_execution),
|
||||||
|
kse.eq(selector_value)
|
||||||
|
{
|
||||||
|
//let result = sce.evaluate(execution: updated_execution)
|
||||||
|
let result = updated_execution.evaluator.EvaluateExpression(
|
||||||
|
sce, inExecution: updated_execution)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (.Error(Error(withMessage: "No key matched the selector")), updated_execution)
|
||||||
|
case (.Error(let e), let updated_execution): return (.Error(e), updated_execution)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func type() -> P4QualifiedType {
|
||||||
|
return P4QualifiedType(AnyParserState)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func effect(context: CompilerContext) -> CompilerContext {
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Variables are evaluatable because they can be looked up by identifiers.
|
||||||
|
extension TypedIdentifier: EvaluatableExpression, EvaluatableLValueExpression {
|
||||||
|
public func evaluate(
|
||||||
|
execution: Common.ProgramExecution
|
||||||
|
) -> (Common.Result<Common.P4Value>, Common.ProgramExecution) {
|
||||||
|
return (execution.scopes.lookup(identifier: self), execution)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func set(
|
||||||
|
to: P4Value, inScopes scopes: Common.VarValueScopes,
|
||||||
|
duringExecution execution: ProgramExecution
|
||||||
|
) -> Common.Result<(Common.VarValueScopes, P4Value)> {
|
||||||
|
if case .Error(let e) = scopes.lookup(identifier: self) {
|
||||||
|
return .Error(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
return .Ok((scopes.set(identifier: self, withValue: to), to))
|
||||||
|
}
|
||||||
|
|
||||||
|
public func type() -> P4QualifiedType {
|
||||||
|
return self.type
|
||||||
|
}
|
||||||
|
|
||||||
|
public func effect(context: CompilerContext) -> CompilerContext {
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
|
||||||
|
// Variables are evaluatable because they can be looked up by identifiers.
|
||||||
|
public func check(
|
||||||
|
to: P4Expression, inScopes scopes: Common.StaticVarValueScopes
|
||||||
|
) -> Result<()> {
|
||||||
|
guard case .Ok(let type) = scopes.lookup(identifier: self) else {
|
||||||
|
return .Error(Error(withMessage: "Cannot assign to identifier not in scope"))
|
||||||
|
}
|
||||||
|
|
||||||
|
return switch type.0.assignableFromType(to.type()) {
|
||||||
|
case TypeCheckResults.IncompatibleTypes:
|
||||||
|
.Error(
|
||||||
|
Error(
|
||||||
|
withMessage:
|
||||||
|
"Cannot assign value with type \(to.type()) to identifier \(self) with type \(type.0)"))
|
||||||
|
case TypeCheckResults.ReadOnly:
|
||||||
|
.Error(
|
||||||
|
Error(
|
||||||
|
withMessage:
|
||||||
|
"Cannot assign value with type \(to.type()) to identifier \(self) that is read only"))
|
||||||
|
case TypeCheckResults.WrongDirection:
|
||||||
|
.Error(
|
||||||
|
Error(
|
||||||
|
withMessage:
|
||||||
|
"Cannot assign value with type \(to.type()) to identifier \(self) that is in parameter")
|
||||||
|
)
|
||||||
|
case TypeCheckResults.Ok: .Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,11 @@
|
|||||||
import Common
|
import Common
|
||||||
import P4Lang
|
import P4Lang
|
||||||
|
|
||||||
extension ParserAssignmentStatement: EvaluatableStatement {
|
extension ParserAssignmentStatement: P4Statement {
|
||||||
|
public func effect(context: Common.CompilerContext) -> Common.CompilerContext {
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
|
||||||
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
|
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
|
||||||
let updated_execution = execution
|
let updated_execution = execution
|
||||||
//let result = self.value.evaluate(execution: updated_execution)
|
//let result = self.value.evaluate(execution: updated_execution)
|
||||||
@@ -192,3 +196,19 @@ extension ParserValue: LibraryCallable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension ParserState: P4Statement {
|
||||||
|
public func evaluate(
|
||||||
|
execution: Common.ProgramExecution
|
||||||
|
) -> (Common.ControlFlow, Common.ProgramExecution) {
|
||||||
|
return (
|
||||||
|
ControlFlow.Error,
|
||||||
|
execution.setError(error: Error(withMessage: "Cannot evaluate unspecialized parser state"))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func effect(context: Common.CompilerContext) -> Common.CompilerContext {
|
||||||
|
return context.update(
|
||||||
|
newTypes: context.types.declare(identifier: self.getName(), withValue: self))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -18,7 +18,11 @@
|
|||||||
import Common
|
import Common
|
||||||
import P4Lang
|
import P4Lang
|
||||||
|
|
||||||
extension BlockStatement: EvaluatableStatement {
|
extension BlockStatement: P4Statement {
|
||||||
|
public func effect(context: Common.CompilerContext) -> Common.CompilerContext {
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
|
||||||
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
|
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
|
||||||
return execution.evaluator.ExecuteStatements(
|
return execution.evaluator.ExecuteStatements(
|
||||||
self.statements, inExecution: execution
|
self.statements, inExecution: execution
|
||||||
@@ -38,7 +42,14 @@ extension BlockStatement: EvaluatableStatement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension VariableDeclarationStatement: EvaluatableStatement {
|
extension VariableDeclarationStatement: P4Statement {
|
||||||
|
public func effect(context: Common.CompilerContext) -> Common.CompilerContext {
|
||||||
|
return context.update(
|
||||||
|
newInstances: context.instances.declare(
|
||||||
|
identifier: self.identifier, withValue: (self.identifier.type(), .none)))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
|
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
|
||||||
guard
|
guard
|
||||||
//case (.Ok(let initial_value), let execution) = self.initializer.evaluate(execution: execution)
|
//case (.Ok(let initial_value), let execution) = self.initializer.evaluate(execution: execution)
|
||||||
@@ -56,7 +67,11 @@ extension VariableDeclarationStatement: EvaluatableStatement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ConditionalStatement: EvaluatableStatement {
|
extension ConditionalStatement: P4Statement {
|
||||||
|
public func effect(context: Common.CompilerContext) -> Common.CompilerContext {
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
|
||||||
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
|
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
|
||||||
guard
|
guard
|
||||||
//case (.Ok(let evaluated_condition), let execution) = self.condition.evaluate(execution: execution)
|
//case (.Ok(let evaluated_condition), let execution) = self.condition.evaluate(execution: execution)
|
||||||
@@ -105,7 +120,11 @@ extension ConditionalStatement: EvaluatableStatement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ExpressionStatement: EvaluatableStatement {
|
extension ExpressionStatement: P4Statement {
|
||||||
|
public func effect(context: Common.CompilerContext) -> Common.CompilerContext {
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
|
||||||
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
|
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
|
||||||
|
|
||||||
// Evaluate, there might be side effects!
|
// Evaluate, there might be side effects!
|
||||||
@@ -118,7 +137,12 @@ extension ExpressionStatement: EvaluatableStatement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ReturnStatement: EvaluatableStatement {
|
extension ReturnStatement: P4Statement {
|
||||||
|
public func effect(context: Common.CompilerContext) -> Common.CompilerContext {
|
||||||
|
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
|
||||||
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
|
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
|
||||||
//return switch self.value.evaluate(execution: execution) {
|
//return switch self.value.evaluate(execution: execution) {
|
||||||
return switch execution.evaluator.EvaluateExpression(self.value, inExecution: execution) {
|
return switch execution.evaluator.EvaluateExpression(self.value, inExecution: execution) {
|
||||||
@@ -128,8 +152,42 @@ extension ReturnStatement: EvaluatableStatement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ApplyStatement: EvaluatableStatement {
|
extension ApplyStatement: P4Statement {
|
||||||
|
public func effect(context: Common.CompilerContext) -> Common.CompilerContext {
|
||||||
|
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
|
||||||
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
|
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
|
||||||
return (ControlFlow.Next, execution)
|
return (ControlFlow.Next, execution)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension Instantiation: P4Statement {
|
||||||
|
public func effect(context: Common.CompilerContext) -> Common.CompilerContext {
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
|
||||||
|
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
|
||||||
|
return (ControlFlow.Next, execution)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Declaration: P4Statement {
|
||||||
|
public func effect(context: Common.CompilerContext) -> Common.CompilerContext {
|
||||||
|
if self.extern {
|
||||||
|
return context.update(
|
||||||
|
newExterns: context.externs.declare(
|
||||||
|
identifier: self.identifier, withValue: self))
|
||||||
|
}
|
||||||
|
|
||||||
|
return context.update(
|
||||||
|
newTypes: context.types.declare(
|
||||||
|
identifier: self.identifier, withValue: self.identifier.type().baseType()))
|
||||||
|
}
|
||||||
|
|
||||||
|
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
|
||||||
|
//// TODO
|
||||||
|
return (ControlFlow.Next, execution)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ import P4Lang
|
|||||||
let result = try! #require(p.parse(simple))
|
let result = try! #require(p.parse(simple))
|
||||||
|
|
||||||
#expect(
|
#expect(
|
||||||
#RequireErrorResult<(EvaluatableStatement, CompilerContext)>(
|
#RequireErrorResult<ParserAssignmentStatement>(
|
||||||
ErrorWithLocation(sourceLocation: SourceLocation(2, 154), withError: "Did not find assignment statement"),
|
ErrorWithLocation(sourceLocation: SourceLocation(2, 154), withError: "Did not find assignment statement"),
|
||||||
ParserAssignmentStatement.Compile( // Note: Calling ParserAssignmentStatement compilation directly.
|
ParserAssignmentStatement.Compile( // Note: Calling ParserAssignmentStatement compilation directly.
|
||||||
node: result.rootNode!, withContext: CompilerContext())))
|
node: result.rootNode!, withContext: CompilerContext())))
|
||||||
@@ -182,3 +182,16 @@ import P4Lang
|
|||||||
|
|
||||||
#expect(#RequireOkResult(SpecialCompilers.ProgramCompiler.Compile(simple)))
|
#expect(#RequireOkResult(SpecialCompilers.ProgramCompiler.Compile(simple)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test func test_simple_compiler_with_instantiation() async throws {
|
||||||
|
let simple_instantiation_program = """
|
||||||
|
parser MainParser() {
|
||||||
|
state start {
|
||||||
|
transition accept;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
MainParser() mp;
|
||||||
|
"""
|
||||||
|
#expect(#RequireOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_instantiation_program)))
|
||||||
|
}
|
||||||
@@ -68,7 +68,7 @@ export default grammar({
|
|||||||
|
|
||||||
|
|
||||||
// Instantiation
|
// Instantiation
|
||||||
instantiation: $ => seq($.typeRef, '(', optional($.parameter_list), ')', $.identifier),
|
instantiation: $ => seq($.typeRef, $.arguments, $.identifier),
|
||||||
|
|
||||||
// Declarations
|
// Declarations
|
||||||
declaration: $ => seq(choice($.parserDeclaration, $.parserTypeDeclaration, $.type_declaration, $.function_declaration, $.control_declaration, $.extern_declaration)),
|
declaration: $ => seq(choice($.parserDeclaration, $.parserTypeDeclaration, $.type_declaration, $.function_declaration, $.control_declaration, $.extern_declaration)),
|
||||||
|
|||||||
Reference in New Issue
Block a user