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:
@@ -24,30 +24,30 @@ import TreeSitterP4
|
||||
|
||||
func parameter_list_compiler(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(ParameterList, CompilerContext)> {
|
||||
) -> Common.Result<ParameterList> {
|
||||
|
||||
var walker = Walker(node: node)
|
||||
var current_node: Node? = .none
|
||||
|
||||
if node.text == ")" {
|
||||
// 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")
|
||||
|
||||
var parameters: ParameterList = ParameterList([])
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(ParameterList, CompilerContext)>.Error(
|
||||
or: Result<ParameterList>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing parameter list component")))
|
||||
|
||||
if current_node?.nodeType == "parameter_list" {
|
||||
switch parameter_list_compiler(node: current_node!, withContext: context) {
|
||||
case .Ok(let (ps, _)):
|
||||
case .Ok(let ps):
|
||||
parameters = ps
|
||||
case .Error(let e): return Result.Error(e)
|
||||
}
|
||||
@@ -56,13 +56,13 @@ func parameter_list_compiler(
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(ParameterList, CompilerContext)>.Error(
|
||||
or: Result<ParameterList>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing parameter list component")))
|
||||
|
||||
// If this is a ')', we are done.
|
||||
if current_node?.text == ")" {
|
||||
return Result.Ok((parameters, context))
|
||||
return Result.Ok(parameters)
|
||||
}
|
||||
|
||||
// If this is a comma, we skip it!
|
||||
@@ -72,26 +72,26 @@ func parameter_list_compiler(
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(ParameterList, CompilerContext)>.Error(
|
||||
or: Result<ParameterList>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing parameter list component")))
|
||||
|
||||
// Otherwise, there should be one parameter left!
|
||||
switch Parameter.Compile(node: current_node!, withContext: context) {
|
||||
case .Ok(let (parsed_parameter, updated_context)):
|
||||
return Result.Ok((parameters.addParameter(parsed_parameter), updated_context))
|
||||
case .Ok(let parsed_parameter):
|
||||
return Result.Ok(parameters.addParameter(parsed_parameter))
|
||||
case .Error(let e): return Result.Error(e)
|
||||
}
|
||||
}
|
||||
|
||||
extension ParameterList: Compilable {
|
||||
public typealias T = ParameterList
|
||||
public typealias C = ParameterList
|
||||
public static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(ParameterList, CompilerContext)> {
|
||||
) -> Common.Result<ParameterList> {
|
||||
|
||||
let parameter_node = node
|
||||
#RequireNodeType<Node, (ParameterList, CompilerContext)>(
|
||||
#RequireNodeType<Node, ParameterList>(
|
||||
node: parameter_node, type: "parameters", nice_type_name: "Parameters")
|
||||
|
||||
var walker = Walker(node: parameter_node)
|
||||
@@ -100,7 +100,7 @@ extension ParameterList: Compilable {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(ParameterList, CompilerContext)>.Error(
|
||||
or: Result<ParameterList>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing '(' in parameter list component")))
|
||||
@@ -108,7 +108,7 @@ extension ParameterList: Compilable {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(ParameterList, CompilerContext)>.Error(
|
||||
or: Result<ParameterList>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing parameter list component")))
|
||||
|
||||
@@ -117,12 +117,12 @@ extension ParameterList: Compilable {
|
||||
}
|
||||
|
||||
extension Direction: Compilable {
|
||||
public typealias T = Direction
|
||||
public typealias C = Direction
|
||||
public static func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<(Direction, CompilerContext)> {
|
||||
) -> Result<Direction> {
|
||||
let direction_node = node
|
||||
#RequireNodeType<Node, (Direction, CompilerContext)>(
|
||||
#RequireNodeType<Node, Direction>(
|
||||
node: direction_node, type: "direction", nice_type_name: "direction")
|
||||
let directions = [
|
||||
"in": Direction.In,
|
||||
@@ -137,17 +137,17 @@ extension Direction: Compilable {
|
||||
withError: "\(direction_node.text!) is not a valid direction"))
|
||||
}
|
||||
|
||||
return .Ok((parsed_direction, context))
|
||||
return .Ok(parsed_direction)
|
||||
}
|
||||
}
|
||||
|
||||
extension Parameter: Compilable {
|
||||
public typealias T = Parameter
|
||||
public typealias C = Parameter
|
||||
public static func Compile(
|
||||
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")
|
||||
|
||||
var walker = Walker(node: node)
|
||||
@@ -155,7 +155,7 @@ extension Parameter: Compilable {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(Parameter, CompilerContext)>.Error(
|
||||
or: Result<Parameter>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing parameter declaration component")))
|
||||
@@ -171,7 +171,7 @@ extension Parameter: Compilable {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(Parameter, CompilerContext)>.Error(
|
||||
or: Result<Parameter>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing parameter declaration component")))
|
||||
@@ -181,7 +181,7 @@ extension Parameter: Compilable {
|
||||
if current_node!.nodeType == "direction" {
|
||||
|
||||
let maybe_parsed_direction = Direction.Compile(node: current_node!, withContext: context)
|
||||
guard case .Ok((let parsed_direction, _)) = maybe_parsed_direction else {
|
||||
guard case .Ok(let parsed_direction) = maybe_parsed_direction else {
|
||||
return .Error(maybe_parsed_direction.error()!)
|
||||
}
|
||||
direction = parsed_direction
|
||||
@@ -191,7 +191,7 @@ extension Parameter: Compilable {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(Parameter, CompilerContext)>.Error(
|
||||
or: Result<Parameter>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing parameter declaration component")))
|
||||
@@ -213,7 +213,7 @@ extension Parameter: Compilable {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(Parameter, CompilerContext)>.Error(
|
||||
or: Result<Parameter>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing parameter declaration component")))
|
||||
@@ -233,43 +233,41 @@ extension Parameter: Compilable {
|
||||
}
|
||||
|
||||
return Result.Ok(
|
||||
(
|
||||
Parameter(
|
||||
identifier: parameter_name,
|
||||
withType: direction != nil
|
||||
? parameter_type.update(addAttribute: P4TypeQualifier.Direction(direction!))
|
||||
: parameter_type),
|
||||
context
|
||||
))
|
||||
Parameter(
|
||||
identifier: parameter_name,
|
||||
withType: direction != nil
|
||||
? parameter_type.update(addAttribute: P4TypeQualifier.Direction(direction!))
|
||||
: parameter_type),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func argument_list_compiler(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(ArgumentList, CompilerContext)> {
|
||||
) -> Common.Result<ArgumentList> {
|
||||
|
||||
var walker = Walker(node: node)
|
||||
var current_node: Node? = .none
|
||||
|
||||
if node.text == ")" {
|
||||
// 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")
|
||||
|
||||
var arguments: ArgumentList = ArgumentList([])
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(ArgumentList, CompilerContext)>.Error(
|
||||
or: Result<ArgumentList>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing argument list component")))
|
||||
|
||||
if current_node?.nodeType == "argument_list" {
|
||||
switch argument_list_compiler(node: current_node!, withContext: context) {
|
||||
case .Ok(let (ps, _)):
|
||||
case .Ok(let ps):
|
||||
arguments = ps
|
||||
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.
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(ArgumentList, CompilerContext)>.Error(
|
||||
or: Result<ArgumentList>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing argument list component")))
|
||||
|
||||
// If this is a ')', we are done.
|
||||
if current_node?.text == ")" {
|
||||
return Result.Ok((arguments, context))
|
||||
return Result.Ok(arguments)
|
||||
}
|
||||
|
||||
// If this is a comma, we skip it!
|
||||
@@ -296,27 +294,27 @@ func argument_list_compiler(
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(ArgumentList, CompilerContext)>.Error(
|
||||
or: Result<ArgumentList>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing argument list component")))
|
||||
|
||||
// Otherwise, there should be one argument left!
|
||||
switch Argument.Compile(node: current_node!, withContext: context) {
|
||||
case .Ok(let (ce, updated_context)):
|
||||
case .Ok(let ce):
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
extension ArgumentList: Compilable {
|
||||
public typealias T = ArgumentList
|
||||
public typealias C = ArgumentList
|
||||
public static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(ArgumentList, CompilerContext)> {
|
||||
) -> Common.Result<ArgumentList> {
|
||||
|
||||
let argument_node = node
|
||||
#RequireNodeType<Node, (ArgumentList, CompilerContext)>(
|
||||
#RequireNodeType<Node, ArgumentList>(
|
||||
node: argument_node, type: "arguments", nice_type_name: "arguments")
|
||||
|
||||
var walker = Walker(node: argument_node)
|
||||
@@ -324,7 +322,7 @@ extension ArgumentList: Compilable {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(ArgumentList, CompilerContext)>.Error(
|
||||
or: Result<ArgumentList>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing '(' in argument list component")))
|
||||
@@ -333,7 +331,7 @@ extension ArgumentList: Compilable {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(ArgumentList, CompilerContext)>.Error(
|
||||
or: Result<ArgumentList>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing argument list component")))
|
||||
|
||||
@@ -342,25 +340,25 @@ extension ArgumentList: Compilable {
|
||||
}
|
||||
|
||||
extension Argument: Compilable {
|
||||
public typealias T = EvaluatableExpression
|
||||
public typealias C = P4Expression
|
||||
public static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(EvaluatableExpression, CompilerContext)> {
|
||||
) -> Common.Result<P4Expression> {
|
||||
let argument_node = node
|
||||
#RequireNodeType<Node, (EvaluatableExpression, CompilerContext)>(
|
||||
#RequireNodeType<Node, P4Expression>(
|
||||
node: argument_node, type: "argument", nice_type_name: "argument")
|
||||
|
||||
let expression_node = node.child(at: 0)!
|
||||
|
||||
return switch Expression.Compile(node: expression_node, withContext: context) {
|
||||
case .Ok(let compiled_expression): .Ok((compiled_expression, context))
|
||||
case .Ok(let compiled_expression): .Ok(compiled_expression)
|
||||
case .Error(let e): .Error(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func ContainsInvalidStatements(
|
||||
statement: EvaluatableStatement, invalids: [EvaluatableStatement.Type]
|
||||
statement: P4Statement, invalids: [P4Statement.Type]
|
||||
) -> Bool {
|
||||
for es in invalids {
|
||||
if type(of: statement) == es {
|
||||
@@ -370,8 +368,7 @@ func ContainsInvalidStatements(
|
||||
return false
|
||||
}
|
||||
|
||||
func ContainsInvalidStatements(block: BlockStatement, invalids: [EvaluatableStatement.Type]) -> Bool
|
||||
{
|
||||
func ContainsInvalidStatements(block: BlockStatement, invalids: [P4Statement.Type]) -> Bool {
|
||||
return block.statements.contains { statement in
|
||||
for es in invalids {
|
||||
if type(of: statement) == es {
|
||||
|
||||
@@ -34,124 +34,3 @@ public func ConfigureP4Parser() -> Result<SwiftTreeSitter.Parser> {
|
||||
|
||||
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 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(
|
||||
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,
|
||||
"control_declaration": Control.self,
|
||||
"type_declaration": P4Struct.self,
|
||||
"parserDeclaration": Parser.self,
|
||||
/// ASSUME: Type declarations are struct declarations.
|
||||
"extern_declaration": ExternDeclaration.self,
|
||||
]
|
||||
|
||||
guard let declaration_compiler = declaration_compilers[node.nodeType!] else {
|
||||
return .Ok(.none)
|
||||
guard let declaration_compiler = declaration_compilers[declaration_node.nodeType!] else {
|
||||
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(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(Declaration, CompilerContext)?> {
|
||||
) -> Common.Result<Declaration> {
|
||||
let function_declaration_node = node
|
||||
#RequireNodeType<Node, (ParameterList, CompilerContext)>(
|
||||
#RequireNodeType<Node, ParameterList>(
|
||||
node: function_declaration_node, type: "function_declaration",
|
||||
nice_type_name: "Function Declaration")
|
||||
|
||||
@@ -59,7 +87,7 @@ extension FunctionDeclaration: CompilableDeclaration {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||
or: Result<Declaration>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: function_declaration_node.toSourceLocation(),
|
||||
withError: "Missing function declaration component")))
|
||||
@@ -72,7 +100,7 @@ extension FunctionDeclaration: CompilableDeclaration {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||
or: Result<Declaration>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: function_declaration_node.toSourceLocation(),
|
||||
withError: "Missing function declaration component")))
|
||||
@@ -85,17 +113,16 @@ extension FunctionDeclaration: CompilableDeclaration {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||
or: Result<Declaration>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: function_declaration_node.toSourceLocation(),
|
||||
withError: "Missing function declaration component")))
|
||||
|
||||
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 {
|
||||
return .Error(maybe_function_parameters.error()!)
|
||||
}
|
||||
context = updated_context
|
||||
|
||||
var function_body: BlockStatement? = .none
|
||||
|
||||
@@ -113,10 +140,10 @@ extension FunctionDeclaration: CompilableDeclaration {
|
||||
withContext: context.update(newInstances: function_scope).update(
|
||||
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()!)
|
||||
}
|
||||
function_body = (parsed_function_body as! BlockStatement)
|
||||
function_body = parsed_function_body
|
||||
} else {
|
||||
|
||||
// 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
|
||||
// extern context -- the wrapping extern declaration will take care of that.
|
||||
return .Ok(
|
||||
(
|
||||
function_declaration,
|
||||
context.extern_context
|
||||
? context
|
||||
: context.update(
|
||||
newTypes: context.types.declare(
|
||||
identifier: function_name, withValue: function_declaration.identifier.type.baseType())
|
||||
)
|
||||
))
|
||||
function_declaration,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
extension P4Struct: CompilableDeclaration {
|
||||
extension P4Struct: Compilable {
|
||||
public typealias C = Declaration
|
||||
static public func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<(Declaration, CompilerContext)?> {
|
||||
) -> Result<Declaration> {
|
||||
let struct_declaration_node = node.child(at: 0)!
|
||||
var walker = Walker(node: struct_declaration_node)
|
||||
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
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: currentNode, thing: walker.getNext(),
|
||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||
or: Result<Declaration>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: struct_declaration_node.toSourceLocation(),
|
||||
withError: "Missing function declaration component")))
|
||||
@@ -185,7 +208,7 @@ extension P4Struct: CompilableDeclaration {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: currentNode, thing: walker.getNext(),
|
||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||
or: Result<Declaration>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: struct_declaration_node.toSourceLocation(),
|
||||
withError: "Missing function declaration component")))
|
||||
@@ -197,15 +220,7 @@ extension P4Struct: CompilableDeclaration {
|
||||
id: struct_identifier,
|
||||
withType: P4QualifiedType(
|
||||
P4Struct(withName: struct_identifier, andFields: P4StructFields([])))))
|
||||
return Result.Ok(
|
||||
(
|
||||
struc,
|
||||
context.extern_context
|
||||
? context
|
||||
: context.update(
|
||||
newTypes: context.types.declare(
|
||||
identifier: struct_identifier, withValue: struc.identifier.type.baseType()))
|
||||
))
|
||||
return Result.Ok(struc)
|
||||
}
|
||||
|
||||
var parse_errs: (any Errorable)? = .none
|
||||
@@ -217,13 +232,12 @@ extension P4Struct: CompilableDeclaration {
|
||||
switch VariableDeclarationStatement.Compile(
|
||||
node: declaration_field, withContext: current_context)
|
||||
{
|
||||
case .Ok((let declaration, let updated_context)):
|
||||
case .Ok(let declaration):
|
||||
let variable_declaration = declaration as! VariableDeclarationStatement
|
||||
parsed_fields.append(
|
||||
P4StructFieldIdentifier(
|
||||
id: variable_declaration.identifier, withType: variable_declaration.initializer.type()
|
||||
))
|
||||
current_context = updated_context
|
||||
case .Error(let e):
|
||||
parse_errs =
|
||||
if let e = parse_errs {
|
||||
@@ -245,24 +259,19 @@ extension P4Struct: CompilableDeclaration {
|
||||
withType: P4QualifiedType(
|
||||
P4Struct(
|
||||
withName: struct_identifier, andFields: P4StructFields(parsed_fields)))))
|
||||
return .Ok(
|
||||
(
|
||||
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()))
|
||||
))
|
||||
return .Ok(declared_struct)
|
||||
}
|
||||
}
|
||||
|
||||
extension P4Lang.Parser: CompilableDeclaration {
|
||||
extension P4Lang.Parser: Compilable {
|
||||
public typealias C = Declaration
|
||||
|
||||
public static func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<(Declaration, CompilerContext)?> {
|
||||
) -> Result<Declaration> {
|
||||
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 walker = Walker(node: parser_node)
|
||||
@@ -270,7 +279,7 @@ extension P4Lang.Parser: CompilableDeclaration {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||
or: Result<Declaration>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: parser_node.toSourceLocation(),
|
||||
withError: "Missing elements of parser declaration")))
|
||||
@@ -294,7 +303,7 @@ extension P4Lang.Parser: CompilableDeclaration {
|
||||
|
||||
#MustOr(
|
||||
result: type_node_child, thing: type_node_walker.getNext(),
|
||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||
or: Result<Declaration>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: parser_node.toSourceLocation(),
|
||||
withError: "Missing elements of parser type in parser declaration")))
|
||||
@@ -310,7 +319,7 @@ extension P4Lang.Parser: CompilableDeclaration {
|
||||
type_node_walker.next()
|
||||
#MustOr(
|
||||
result: type_node_child, thing: type_node_walker.getNext(),
|
||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||
or: Result<Declaration>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: type_node_child!.toSourceLocation(),
|
||||
withError: "Missing name in parser type declaration")))
|
||||
@@ -324,15 +333,14 @@ extension P4Lang.Parser: CompilableDeclaration {
|
||||
type_node_walker.next()
|
||||
#MustOr(
|
||||
result: type_node_child, thing: type_node_walker.getNext(),
|
||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||
or: Result<Declaration>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: type_node_child!.toSourceLocation(),
|
||||
withError: "Missing parser parameters")))
|
||||
|
||||
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
|
||||
current_context = updated_context
|
||||
case .Error(let e):
|
||||
return .Error(e)
|
||||
}
|
||||
@@ -348,7 +356,7 @@ extension P4Lang.Parser: CompilableDeclaration {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||
or: Result<Declaration>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: parser_node.toSourceLocation(),
|
||||
withError: "Missing parser declaration component")))
|
||||
@@ -356,7 +364,7 @@ extension P4Lang.Parser: CompilableDeclaration {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||
or: Result<Declaration>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: parser_node.toSourceLocation(),
|
||||
withError: "Missing elements of parser declaration")))
|
||||
@@ -371,7 +379,7 @@ extension P4Lang.Parser: CompilableDeclaration {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||
or: Result<Declaration>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: parser_node.toSourceLocation(),
|
||||
withError: "Missing body of parser declaration")))
|
||||
@@ -381,7 +389,7 @@ extension P4Lang.Parser: CompilableDeclaration {
|
||||
}
|
||||
|
||||
/// TODO: Handle extern parsers.
|
||||
switch SpecialCompilers.Compile(
|
||||
switch SpecialCompilers.CompileParserBody(
|
||||
withName: parser_name!, withParameters: parameter_list, node: current_node!,
|
||||
withContext: current_context)
|
||||
{
|
||||
@@ -390,24 +398,21 @@ extension P4Lang.Parser: CompilableDeclaration {
|
||||
TypedIdentifier(id: parser.name, withType: P4QualifiedType(parser)))
|
||||
// Create a new context with the name of the parser that was just compiled in scope.
|
||||
return .Ok(
|
||||
(
|
||||
parser_declaration,
|
||||
context.extern_context
|
||||
? context
|
||||
: updated_context.update(
|
||||
newTypes: updated_context.types.declare(identifier: parser.name, withValue: parser))
|
||||
))
|
||||
parser_declaration,
|
||||
)
|
||||
case Result.Error(let error): return .Error(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Control: CompilableDeclaration {
|
||||
extension Control: Compilable {
|
||||
public typealias C = Declaration
|
||||
public static func Compile(
|
||||
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 current_node: Node? = .none
|
||||
@@ -417,7 +422,7 @@ extension Control: CompilableDeclaration {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||
or: Result<Declaration>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing control declaration component")))
|
||||
@@ -433,18 +438,17 @@ extension Control: CompilableDeclaration {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||
or: Result<Declaration>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing control declaration component")))
|
||||
|
||||
let maybe_control_parameters = ParameterList.Compile(
|
||||
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 {
|
||||
return .Error(maybe_control_parameters.error()!)
|
||||
}
|
||||
local_context = updated_context
|
||||
|
||||
// Before continuing, make sure to put the parameters into context.
|
||||
var control_scope = local_context.instances.enter()
|
||||
@@ -459,7 +463,7 @@ extension Control: CompilableDeclaration {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||
or: Result<Declaration>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing control declaration component")))
|
||||
@@ -476,12 +480,11 @@ extension Control: CompilableDeclaration {
|
||||
let maybe_action_declaration = Action.Compile(
|
||||
node: current_node, withContext: local_context)
|
||||
guard
|
||||
case .Ok((let action_declaration, let updated_context)) = maybe_action_declaration
|
||||
case .Ok(let action_declaration) = maybe_action_declaration
|
||||
else {
|
||||
return .Error(maybe_action_declaration.error()!)
|
||||
}
|
||||
actions.append(action_declaration)
|
||||
local_context = updated_context
|
||||
// Now, add the declaration into the context.
|
||||
local_context = local_context.update(
|
||||
newTypes: local_context.types.declare(
|
||||
@@ -490,22 +493,20 @@ extension Control: CompilableDeclaration {
|
||||
let maybe_table_declaration = Table.Compile(
|
||||
node: current_node, withContext: local_context)
|
||||
guard
|
||||
case .Ok((let table_declaration, let updated_context)) = maybe_table_declaration
|
||||
case .Ok(let table_declaration) = maybe_table_declaration
|
||||
else {
|
||||
return .Error(maybe_table_declaration.error()!)
|
||||
}
|
||||
tables.append(table_declaration)
|
||||
local_context = updated_context
|
||||
} else if current_node.nodeType == "apply_statement" {
|
||||
// When we see an apply, that is it for the actions and the tables.
|
||||
let maybe_apply_statement = ApplyStatement.Compile(
|
||||
node: current_node, withContext: local_context)
|
||||
guard
|
||||
case .Ok((let apply_statement, let updated_context)) = maybe_apply_statement
|
||||
case .Ok(let apply_statement) = maybe_apply_statement
|
||||
else {
|
||||
return .Error(maybe_apply_statement.error()!)
|
||||
}
|
||||
local_context = updated_context
|
||||
apply = (apply_statement as! ApplyStatement)
|
||||
|
||||
// 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
|
||||
// (and not the one that we entered to do the parsing of this Control).
|
||||
return .Ok(
|
||||
(
|
||||
declared_control,
|
||||
context.extern_context
|
||||
? context
|
||||
: context.update(
|
||||
newTypes: context.types.declare(
|
||||
identifier: control_name, withValue: control))
|
||||
))
|
||||
return .Ok(declared_control)
|
||||
}
|
||||
}
|
||||
|
||||
extension Action: Compilable {
|
||||
public typealias T = Action
|
||||
public typealias C = Action
|
||||
public static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(Action, CompilerContext)> {
|
||||
#RequireNodeType<Node, (P4Type, CompilerContext)>(
|
||||
) -> Result<Action> {
|
||||
#RequireNodeType<Node, P4Type>(
|
||||
node: node, type: "action_declaration", nice_type_name: "Action Declaration")
|
||||
|
||||
var walker = Walker(node: node)
|
||||
@@ -584,7 +577,7 @@ extension Action: Compilable {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(Action, CompilerContext)>.Error(
|
||||
or: Result<Action>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing action declaration component"
|
||||
))
|
||||
@@ -601,7 +594,7 @@ extension Action: Compilable {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(Action, CompilerContext)>.Error(
|
||||
or: Result<Action>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing action declaration component"
|
||||
))
|
||||
@@ -609,11 +602,10 @@ extension Action: Compilable {
|
||||
|
||||
let maybe_action_parameters = ParameterList.Compile(
|
||||
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 {
|
||||
return .Error(maybe_action_parameters.error()!)
|
||||
}
|
||||
current_context = updated_context
|
||||
|
||||
// Check whether the parameters are in the proper order.
|
||||
let remaining_parameters = action_parameters.parameters.drop(while: {
|
||||
@@ -629,7 +621,7 @@ extension Action: Compilable {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(Action, CompilerContext)>.Error(
|
||||
or: Result<Action>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing action declaration component"
|
||||
))
|
||||
@@ -644,29 +636,26 @@ extension Action: Compilable {
|
||||
|
||||
let maybe_action_body = BlockStatement.Compile(
|
||||
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()!)
|
||||
}
|
||||
|
||||
/// TODO: Actions cannot contain switches!
|
||||
|
||||
return .Ok(
|
||||
(
|
||||
Action(
|
||||
named: action_name, withParameters: action_parameters,
|
||||
withBody: (action_body as! BlockStatement)),
|
||||
current_context
|
||||
))
|
||||
Action(
|
||||
named: action_name, withParameters: action_parameters,
|
||||
withBody: (action_body as! BlockStatement)))
|
||||
}
|
||||
}
|
||||
|
||||
extension TableKeyEntry: Compilable {
|
||||
public typealias T = TableKeyEntry
|
||||
public typealias C = TableKeyEntry
|
||||
public static func Compile(
|
||||
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")
|
||||
|
||||
var walker = Walker(node: node)
|
||||
@@ -677,7 +666,7 @@ extension TableKeyEntry: Compilable {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(TableKeyEntry, CompilerContext)>.Error(
|
||||
or: Result<TableKeyEntry>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing table key entry declaration component")))
|
||||
@@ -693,31 +682,31 @@ extension TableKeyEntry: Compilable {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(TableKeyEntry, CompilerContext)>.Error(
|
||||
or: Result<TableKeyEntry>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing table key entry declaration component")))
|
||||
|
||||
let maybe_match_type = TableKeyMatchType.Compile(
|
||||
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 .Ok((TableKeyEntry(keyset_expression as! KeysetExpression, match_type), current_context))
|
||||
return .Ok(TableKeyEntry(keyset_expression as! KeysetExpression, match_type))
|
||||
}
|
||||
}
|
||||
|
||||
extension TableKeyMatchType: Compilable {
|
||||
public typealias T = TableKeyMatchType
|
||||
public typealias C = TableKeyMatchType
|
||||
public static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(TableKeyMatchType, CompilerContext)> {
|
||||
#RequireNodeType<Node, (TableKeyMatchType, CompilerContext)>(
|
||||
) -> Result<TableKeyMatchType> {
|
||||
#RequireNodeType<Node, TableKeyMatchType>(
|
||||
node: node, type: "table_key_match_type", nice_type_name: "Table Key Match Type")
|
||||
|
||||
if node.text! == "exact" {
|
||||
return .Ok((TableKeyMatchType.Exact, context))
|
||||
return .Ok(TableKeyMatchType.Exact)
|
||||
}
|
||||
return .Error(
|
||||
ErrorWithLocation(
|
||||
@@ -727,11 +716,11 @@ extension TableKeyMatchType: Compilable {
|
||||
}
|
||||
|
||||
extension TableKeys: Compilable {
|
||||
public typealias T = TableKeys
|
||||
public typealias C = TableKeys
|
||||
public static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(TableKeys, CompilerContext)> {
|
||||
#RequireNodeType<Node, (TableKeyMatchType, CompilerContext)>(
|
||||
) -> Result<TableKeys> {
|
||||
#RequireNodeType<Node, TableKeyMatchType>(
|
||||
node: node, type: "table_keys", nice_type_name: "Table Keys")
|
||||
|
||||
var walker = Walker(node: node)
|
||||
@@ -746,7 +735,7 @@ extension TableKeys: Compilable {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(TableKeys, CompilerContext)>.Error(
|
||||
or: Result<TableKeys>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
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
|
||||
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)
|
||||
}
|
||||
}
|
||||
@@ -769,16 +758,16 @@ extension TableKeys: Compilable {
|
||||
}.joined(separator: ";"))))
|
||||
}
|
||||
|
||||
return .Ok((TableKeys(withEntries: keys), context))
|
||||
return .Ok(TableKeys(withEntries: keys))
|
||||
}
|
||||
}
|
||||
|
||||
extension TableActionsProperty: Compilable {
|
||||
public typealias T = TableActionsProperty
|
||||
public typealias C = TableActionsProperty
|
||||
public static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(TableActionsProperty, CompilerContext)> {
|
||||
#RequireNodeType<Node, (TableActionsProperty, CompilerContext)>(
|
||||
) -> Result<TableActionsProperty> {
|
||||
#RequireNodeType<Node, TableActionsProperty>(
|
||||
node: node, type: "table_actions", nice_type_name: "Table Actions")
|
||||
|
||||
var walker = Walker(node: node)
|
||||
@@ -793,7 +782,7 @@ extension TableActionsProperty: Compilable {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(TableActionsProperty, CompilerContext)>.Error(
|
||||
or: Result<TableActionsProperty>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing table actions declaration component in control declaration"))
|
||||
@@ -828,16 +817,16 @@ extension TableActionsProperty: Compilable {
|
||||
}.joined(separator: ";"))))
|
||||
}
|
||||
|
||||
return .Ok((TableActionsProperty(actions), context))
|
||||
return .Ok(TableActionsProperty(actions))
|
||||
}
|
||||
}
|
||||
extension TablePropertyList: Compilable {
|
||||
public typealias T = TablePropertyList
|
||||
public typealias C = TablePropertyList
|
||||
public static func Compile(
|
||||
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")
|
||||
|
||||
var current_context = context
|
||||
@@ -849,15 +838,13 @@ extension TablePropertyList: Compilable {
|
||||
node.enumerateNamedChildren { child in
|
||||
if child.nodeType == "table_keys" {
|
||||
switch TableKeys.Compile(node: child, withContext: current_context) {
|
||||
case .Ok((let table_key, let updated_context)):
|
||||
current_context = updated_context
|
||||
case .Ok(let table_key):
|
||||
keys.append(table_key)
|
||||
case .Error(let e): errors.append(e)
|
||||
}
|
||||
} else if child.nodeType == "table_actions" {
|
||||
switch TableActionsProperty.Compile(node: child, withContext: current_context) {
|
||||
case .Ok((let table_action_property, let updated_context)):
|
||||
current_context = updated_context
|
||||
case .Ok(let table_action_property):
|
||||
actions.append(table_action_property)
|
||||
case .Error(let e): errors.append(e)
|
||||
}
|
||||
@@ -900,19 +887,19 @@ extension TablePropertyList: Compilable {
|
||||
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 {
|
||||
public typealias T = Table
|
||||
public typealias C = Table
|
||||
public static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(Table, CompilerContext)> {
|
||||
) -> Result<Table> {
|
||||
|
||||
let table_declaration_node = node
|
||||
#RequireNodeType<Node, (P4Type, CompilerContext)>(
|
||||
#RequireNodeType<Node, Table>(
|
||||
node: table_declaration_node, type: "table_declaration", nice_type_name: "Table Declaration")
|
||||
|
||||
var walker = Walker(node: table_declaration_node)
|
||||
@@ -924,7 +911,7 @@ extension Table: Compilable {
|
||||
walker.next() // Skip the XXX?
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(Table, CompilerContext)>.Error(
|
||||
or: Result<Table>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing table declaration component")
|
||||
))
|
||||
@@ -942,46 +929,43 @@ extension Table: Compilable {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(Table, CompilerContext)>.Error(
|
||||
or: Result<Table>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing table declaration component")
|
||||
))
|
||||
|
||||
let maybe_table_property_list = TablePropertyList.Compile(
|
||||
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 .Ok(
|
||||
(Table(withName: table_name, withPropertyList: table_property_list), current_context))
|
||||
return .Ok(Table(withName: table_name, withPropertyList: table_property_list))
|
||||
}
|
||||
}
|
||||
|
||||
extension ExternDeclaration: CompilableDeclaration {
|
||||
extension ExternDeclaration: Compilable {
|
||||
public typealias C = Declaration
|
||||
public static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(Declaration, CompilerContext)?> {
|
||||
) -> Result<Declaration> {
|
||||
let extern_declaration_node = node
|
||||
#RequireNodeType<Node, (Declaration, CompilerContext)>(
|
||||
#RequireNodeType<Node, Declaration>(
|
||||
node: extern_declaration_node, type: "extern_declaration",
|
||||
nice_type_name: "Extern Declaration")
|
||||
|
||||
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")
|
||||
let declarationed_node = declaration_node.child(at: 0)!
|
||||
|
||||
let maybe_declared = Declaration.Compile(
|
||||
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()!)
|
||||
}
|
||||
|
||||
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
|
||||
// with the matching "stuff".
|
||||
|
||||
@@ -1000,11 +984,7 @@ extension ExternDeclaration: CompilableDeclaration {
|
||||
let extern_declaration = Declaration(extern: declared, ffi: found_ffi)
|
||||
|
||||
return .Ok(
|
||||
(
|
||||
extern_declaration,
|
||||
context.update(
|
||||
newExterns: context.externs.declare(
|
||||
identifier: declared.identifier, withValue: extern_declaration))
|
||||
))
|
||||
extern_declaration,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,22 +21,10 @@ import P4Runtime
|
||||
import SwiftTreeSitter
|
||||
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 {
|
||||
static func compile(
|
||||
public static func compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Result<EvaluatableExpression?> {
|
||||
) -> Result<P4Expression?> {
|
||||
|
||||
let node = node.child(at: 0)!
|
||||
#SkipUnlessNodeType<SwiftTreeSitter.Node>(
|
||||
@@ -57,9 +45,9 @@ extension TypedIdentifier: CompilableExpression {
|
||||
}
|
||||
|
||||
extension TypedIdentifier: CompilableLValueExpression {
|
||||
static func compile_as_lvalue(
|
||||
public static func compile_as_lvalue(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Result<EvaluatableLValueExpression?> {
|
||||
) -> Result<P4LValueExpression?> {
|
||||
|
||||
let expression = node.child(at: 0)!
|
||||
#SkipUnlessNodeType<SwiftTreeSitter.Node>(
|
||||
@@ -77,9 +65,9 @@ extension TypedIdentifier: CompilableLValueExpression {
|
||||
}
|
||||
|
||||
extension P4BooleanValue: CompilableExpression {
|
||||
static func compile(
|
||||
public static func compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Result<EvaluatableExpression?> {
|
||||
) -> Result<P4Expression?> {
|
||||
let node = node.child(at: 0)!
|
||||
#SkipUnlessNodeType<SwiftTreeSitter.Node>(
|
||||
node: node, type: "booleanLiteralExpression")
|
||||
@@ -98,9 +86,9 @@ extension P4BooleanValue: CompilableExpression {
|
||||
}
|
||||
|
||||
extension P4IntValue: CompilableExpression {
|
||||
static func compile(
|
||||
public static func compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Result<EvaluatableExpression?> {
|
||||
) -> Result<P4Expression?> {
|
||||
let node = node.child(at: 0)!
|
||||
|
||||
#SkipUnlessNodesTypes<SwiftTreeSitter.Node>(
|
||||
@@ -147,9 +135,9 @@ extension P4IntValue: CompilableExpression {
|
||||
}
|
||||
|
||||
extension P4StringValue: CompilableExpression {
|
||||
static func compile(
|
||||
public static func compile(
|
||||
node: SwiftTreeSitter.Node, withContext scopes: CompilerContext
|
||||
) -> Result<EvaluatableExpression?> {
|
||||
) -> Result<P4Expression?> {
|
||||
let node = node.child(at: 0)!
|
||||
#SkipUnlessNodeType<SwiftTreeSitter.Node>(
|
||||
node: node, type: "string_literal")
|
||||
@@ -158,12 +146,12 @@ extension P4StringValue: CompilableExpression {
|
||||
}
|
||||
|
||||
extension KeysetExpression: CompilableExpression {
|
||||
static func compile(
|
||||
public static func compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(any Common.EvaluatableExpression)?> {
|
||||
) -> Result<P4Expression?> {
|
||||
let keyset_expression_node = node.child(at: 0)!
|
||||
|
||||
#RequireNodesType<Node, EvaluatableExpression>(
|
||||
#RequireNodesType<Node, P4Expression>(
|
||||
nodes: keyset_expression_node, type: ["expression", "default_keyset"],
|
||||
nice_type_names: ["expression", "default keyset"])
|
||||
|
||||
@@ -186,12 +174,12 @@ extension KeysetExpression: CompilableExpression {
|
||||
struct Expression {
|
||||
public static func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<EvaluatableExpression> {
|
||||
#RequireNodeType<Node, EvaluatableExpression>(
|
||||
) -> Result<P4Expression> {
|
||||
#RequireNodeType<Node, P4Expression>(
|
||||
node: node, type: "expression", nice_type_name: "expression")
|
||||
|
||||
let expression_node = node.child(at: 0)!
|
||||
#RequireNodesType<Node, EvaluatableExpression>(
|
||||
#RequireNodesType<Node, P4Expression>(
|
||||
nodes: expression_node, type: ["grouped_expression", "simple_expression"],
|
||||
nice_type_names: ["grouped expression", "simple expression"])
|
||||
|
||||
@@ -223,12 +211,12 @@ struct Expression {
|
||||
struct LValue {
|
||||
public static func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<EvaluatableLValueExpression> {
|
||||
#RequireNodeType<Node, EvaluatableExpression>(
|
||||
) -> Result<P4LValueExpression> {
|
||||
#RequireNodeType<Node, P4Expression>(
|
||||
node: node, type: "expression", nice_type_name: "expression")
|
||||
|
||||
let expression_node = node.child(at: 0)!
|
||||
#RequireNodesType<Node, EvaluatableExpression>(
|
||||
#RequireNodesType<Node, P4Expression>(
|
||||
nodes: expression_node, type: ["grouped_expression", "simple_expression"],
|
||||
nice_type_names: ["grouped expression", "simple expression"])
|
||||
|
||||
@@ -268,9 +256,9 @@ struct Identifier {
|
||||
}
|
||||
|
||||
extension SelectExpression: CompilableExpression {
|
||||
static func compile(
|
||||
public static func compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<EvaluatableExpression?> {
|
||||
) -> Result<P4Expression?> {
|
||||
#RequireNodeType<Node, (SelectExpression, CompilerContext)>(
|
||||
node: node, type: "selectExpression", nice_type_name: "parser select expression")
|
||||
|
||||
@@ -330,9 +318,9 @@ extension SelectExpression: CompilableExpression {
|
||||
}
|
||||
|
||||
extension SelectCaseExpression: CompilableExpression {
|
||||
static func compile(
|
||||
public static func compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<EvaluatableExpression?> {
|
||||
) -> Result<P4Expression?> {
|
||||
if node.nodeType != "selectCase" {
|
||||
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 {
|
||||
static func compile(
|
||||
public static func compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Result<(EvaluatableExpression)?> {
|
||||
) -> Result<(P4Expression)?> {
|
||||
let expression = node.child(at: 0)!
|
||||
|
||||
#SkipUnlessNodeType<Node>(
|
||||
@@ -398,20 +411,20 @@ extension BinaryOperatorExpression: CompilableExpression {
|
||||
var current_node: Node? = .none
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<EvaluatableExpression?>.Error(
|
||||
or: Result<P4Expression?>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Malformed binary operator expression"
|
||||
)))
|
||||
|
||||
/// TODO: This macro cannot handle new lines in the arrays
|
||||
// swift-format-ignore
|
||||
#RequireNodesType<Node, EvaluatableExpression?>(
|
||||
#RequireNodesType<Node, P4Expression?>(
|
||||
nodes: binary_operator_expression_node,
|
||||
type: ["binaryEqualOperatorExpression", "binaryLessThanOperatorExpression", "binaryLessThanEqualOperatorExpression", "binaryGreaterThanOperatorExpression", "binaryGreaterThanEqualOperatorExpression", "binaryAndOperatorExpression", "binaryOrOperatorExpression", "binaryAddOperatorExpression", "binarySubtractOperatorExpression", "binaryMultiplyOperatorExpression", "binaryDivideOperatorExpression"],
|
||||
nice_type_names: [ "binary equal operator", "binary less than operator", "binary less than or equal to operator", "binary greater than operator", "binary greater than or equal to operator", "binary and operator", "binary or operator", "binary add operator", "binary subtract operator", "binary multiply operator", "binary divide operator"])
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<EvaluatableExpression?>.Error(
|
||||
or: Result<P4Expression?>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing LHS for binary operator expression")))
|
||||
@@ -421,7 +434,7 @@ extension BinaryOperatorExpression: CompilableExpression {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<EvaluatableExpression?>.Error(
|
||||
or: Result<P4Expression?>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing binary operator for binary operator expression")))
|
||||
@@ -429,7 +442,7 @@ extension BinaryOperatorExpression: CompilableExpression {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<EvaluatableExpression?>.Error(
|
||||
or: Result<P4Expression?>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing RHS for binary operator expression")))
|
||||
@@ -520,9 +533,9 @@ extension BinaryOperatorExpression: CompilableExpression {
|
||||
}
|
||||
|
||||
extension ArrayAccessExpression: CompilableExpression {
|
||||
static func compile(
|
||||
public static func compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<EvaluatableExpression?> {
|
||||
) -> Result<P4Expression?> {
|
||||
let expression = node.child(at: 0)!
|
||||
|
||||
#SkipUnlessNodeType<Node>(
|
||||
@@ -535,11 +548,11 @@ extension ArrayAccessExpression: CompilableExpression {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<EvaluatableExpression?>.Error(
|
||||
or: Result<P4Expression?>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Malformed array access expression")))
|
||||
|
||||
#RequireNodeType<Node, EvaluatableExpression?>(
|
||||
#RequireNodeType<Node, P4Expression?>(
|
||||
node: current_node!, type: "expression",
|
||||
nice_type_name: "array identifier expression")
|
||||
let array_access_identifier_node = current_node!
|
||||
@@ -547,7 +560,7 @@ extension ArrayAccessExpression: CompilableExpression {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<EvaluatableExpression?>.Error(
|
||||
or: Result<P4Expression?>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing [ for array access expression")))
|
||||
@@ -556,12 +569,12 @@ extension ArrayAccessExpression: CompilableExpression {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<EvaluatableExpression?>.Error(
|
||||
or: Result<P4Expression?>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing indexor expression for array access expression")))
|
||||
|
||||
#RequireNodeType<Node, EvaluatableExpression?>(
|
||||
#RequireNodeType<Node, P4Expression?>(
|
||||
node: current_node!, type: "expression",
|
||||
nice_type_name: "array indexor expression")
|
||||
|
||||
@@ -595,9 +608,9 @@ extension ArrayAccessExpression: CompilableExpression {
|
||||
}
|
||||
|
||||
extension FieldAccessExpression: CompilableExpression {
|
||||
static func compile(
|
||||
public static func compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(any Common.EvaluatableExpression)?> {
|
||||
) -> Result<P4Expression?> {
|
||||
let expression = node.child(at: 0)!
|
||||
|
||||
#SkipUnlessNodeType<Node>(
|
||||
@@ -610,11 +623,11 @@ extension FieldAccessExpression: CompilableExpression {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<EvaluatableExpression?>.Error(
|
||||
or: Result<P4Expression?>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Malformed field access expression")))
|
||||
|
||||
#RequireNodeType<Node, EvaluatableExpression?>(
|
||||
#RequireNodeType<Node, P4Expression?>(
|
||||
node: current_node!, type: "expression",
|
||||
nice_type_name: "struct identifier expression")
|
||||
let struct_identifier_node = current_node!
|
||||
@@ -622,7 +635,7 @@ extension FieldAccessExpression: CompilableExpression {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<EvaluatableExpression?>.Error(
|
||||
or: Result<P4Expression?>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing . for field access expression")))
|
||||
@@ -630,12 +643,12 @@ extension FieldAccessExpression: CompilableExpression {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<EvaluatableExpression?>.Error(
|
||||
or: Result<P4Expression?>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing field name for field access expression")))
|
||||
|
||||
#RequireNodeType<Node, EvaluatableExpression?>(
|
||||
#RequireNodeType<Node, P4Expression?>(
|
||||
node: current_node!, type: "identifier",
|
||||
nice_type_name: "field name")
|
||||
|
||||
@@ -677,9 +690,9 @@ extension FieldAccessExpression: CompilableExpression {
|
||||
}
|
||||
|
||||
extension FieldAccessExpression: CompilableLValueExpression {
|
||||
static func compile_as_lvalue(
|
||||
public static func compile_as_lvalue(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Result<EvaluatableLValueExpression?> {
|
||||
) -> Result<P4LValueExpression?> {
|
||||
let expression = node.child(at: 0)!
|
||||
#SkipUnlessNodeType<Node>(
|
||||
node: expression, type: "fieldAccessExpression")
|
||||
@@ -696,9 +709,9 @@ extension FieldAccessExpression: CompilableLValueExpression {
|
||||
}
|
||||
|
||||
extension ArrayAccessExpression: CompilableLValueExpression {
|
||||
static func compile_as_lvalue(
|
||||
public static func compile_as_lvalue(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Result<EvaluatableLValueExpression?> {
|
||||
) -> Result<P4LValueExpression?> {
|
||||
let expression = node.child(at: 0)!
|
||||
#SkipUnlessNodeType<Node>(
|
||||
node: expression, type: "arrayAccessExpression")
|
||||
@@ -715,9 +728,9 @@ extension ArrayAccessExpression: CompilableLValueExpression {
|
||||
}
|
||||
|
||||
extension FunctionCall: CompilableExpression {
|
||||
static func compile(
|
||||
public static func compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<EvaluatableExpression?> {
|
||||
) -> Result<P4Expression?> {
|
||||
|
||||
let expression = node.child(at: 0)!
|
||||
#SkipUnlessNodeType<Node>(
|
||||
@@ -728,7 +741,7 @@ extension FunctionCall: CompilableExpression {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<EvaluatableExpression?>.Error(
|
||||
or: Result<P4Expression?>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing function call component")))
|
||||
|
||||
@@ -780,13 +793,13 @@ extension FunctionCall: CompilableExpression {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<EvaluatableExpression?>.Error(
|
||||
or: Result<P4Expression?>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing function call component")))
|
||||
|
||||
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()!)
|
||||
}
|
||||
|
||||
|
||||
@@ -23,10 +23,10 @@ import TreeSitterExtensions
|
||||
import TreeSitterP4
|
||||
|
||||
extension Statement: Compilable {
|
||||
public typealias T = EvaluatableStatement
|
||||
public typealias C = P4Statement
|
||||
public static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(EvaluatableStatement, CompilerContext)> {
|
||||
) -> Result<P4Statement> {
|
||||
|
||||
if node.nodeType != "parserStatement" && node.nodeType != "statement" {
|
||||
return Result.Error(
|
||||
@@ -51,9 +51,9 @@ extension Statement: Compilable {
|
||||
withError:
|
||||
"Unparseable statement type (\(statement.nodeType ?? "Unknown Statement Type"))"))
|
||||
}
|
||||
switch parser.Compile(node: statement, withContext: context) {
|
||||
case Result.Ok(let (parsed, updated_context)):
|
||||
return .Ok((parsed, updated_context))
|
||||
switch parser.CompileStatement(node: statement, withContext: context) {
|
||||
case Result.Ok(let parsed):
|
||||
return .Ok(parsed)
|
||||
case Result.Error(let e):
|
||||
return .Error(
|
||||
ErrorWithLocation(
|
||||
@@ -62,11 +62,12 @@ extension Statement: Compilable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension LocalElements: Compilable {
|
||||
public typealias T = EvaluatableStatement
|
||||
public typealias C = P4Statement
|
||||
public static func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<(EvaluatableStatement, CompilerContext)> {
|
||||
) -> Result<P4Statement> {
|
||||
let localElementsParsers: [String: CompilableStatement.Type] = [
|
||||
"variableDeclaration": VariableDeclarationStatement.self
|
||||
]
|
||||
@@ -78,9 +79,9 @@ extension LocalElements: Compilable {
|
||||
withError: "Unparseable statement type (\(node.nodeType ?? "Unknown Statement Type"))"))
|
||||
}
|
||||
|
||||
switch parser.Compile(node: node, withContext: context) {
|
||||
case Result.Ok(let (parsed, parsed_updated_scopes)):
|
||||
return Result.Ok((parsed, parsed_updated_scopes))
|
||||
switch parser.CompileStatement(node: node, withContext: context) {
|
||||
case Result.Ok(let parsed):
|
||||
return Result.Ok(parsed)
|
||||
case Result.Error(let e):
|
||||
return Result.Error(Error(withMessage: "Failed to parse local element: \(e)"))
|
||||
}
|
||||
@@ -88,10 +89,10 @@ extension LocalElements: Compilable {
|
||||
}
|
||||
|
||||
extension ParserState: Compilable {
|
||||
public typealias T = ParserState
|
||||
public typealias C = ParserState
|
||||
public static func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<(ParserState, CompilerContext)> {
|
||||
) -> Result<ParserState> {
|
||||
var walker = Walker(node: node)
|
||||
|
||||
var current_node: Node? = .none
|
||||
@@ -107,7 +108,7 @@ extension ParserState: Compilable {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(ParserState, CompilerContext)>.Error(
|
||||
or: Result<ParserState>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing elements in parser state declaration")))
|
||||
@@ -125,7 +126,7 @@ extension ParserState: Compilable {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(ParserState, CompilerContext)>.Error(
|
||||
or: Result<ParserState>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing elements in parser state declaration")))
|
||||
@@ -141,22 +142,20 @@ extension ParserState: Compilable {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(ParserState, CompilerContext)>.Error(
|
||||
or: Result<ParserState>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing body of state declaration")
|
||||
))
|
||||
|
||||
var errors: (any Errorable)? = .none
|
||||
var current_context = context
|
||||
var parsed_s: [EvaluatableStatement] = Array()
|
||||
var parsed_s: [P4Statement] = Array()
|
||||
|
||||
if current_node!.nodeType == "parserStatements" {
|
||||
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
|
||||
current_context = updated_context
|
||||
case .Error(let error):
|
||||
errors =
|
||||
if let errors = errors {
|
||||
@@ -174,13 +173,13 @@ extension ParserState: Compilable {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(ParserState, CompilerContext)>.Error(
|
||||
or: Result<ParserState>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing transition statement of state declaration")))
|
||||
|
||||
return SpecialCompilers.TransitionStatement.Compile(
|
||||
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 TreeSitterP4
|
||||
|
||||
public protocol CompilableStatement {
|
||||
static func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<(EvaluatableStatement, CompilerContext)>
|
||||
}
|
||||
|
||||
public protocol CompilableValue {
|
||||
static func CompileValue(withValue value: String) -> Result<P4DataValue>
|
||||
}
|
||||
@@ -38,19 +32,27 @@ public protocol CompilableType {
|
||||
) -> Result<P4Type?>
|
||||
}
|
||||
|
||||
public protocol CompilableDeclaration {
|
||||
/// Info
|
||||
///
|
||||
/// Extensions should update the context with the newly declared item _unless_
|
||||
/// they are in an extern context (``CompilerContext.extern_context``).
|
||||
static func Compile(
|
||||
public protocol CompilableExpression {
|
||||
static func compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<(Declaration, CompilerContext)?>
|
||||
) -> Result<P4Expression?>
|
||||
}
|
||||
|
||||
public protocol Compilable<T> {
|
||||
associatedtype T
|
||||
public protocol CompilableLValueExpression {
|
||||
static func compile_as_lvalue(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<P4LValueExpression?>
|
||||
}
|
||||
|
||||
public protocol Compilable<C> {
|
||||
associatedtype C
|
||||
static func Compile(
|
||||
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 TreeSitterP4
|
||||
|
||||
protocol AnyCompilable {
|
||||
static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(Any, CompilerContext)>
|
||||
}
|
||||
|
||||
public struct SpecialCompilers {
|
||||
public struct TransitionStatement {
|
||||
static func Compile(
|
||||
node: Node, forState state_identifier: Common.Identifier,
|
||||
withStatements stmts: [EvaluatableStatement], withContext context: CompilerContext
|
||||
) -> Result<(ParserState, CompilerContext)> {
|
||||
withStatements stmts: [P4Statement], withContext context: CompilerContext
|
||||
) -> Result<ParserState> {
|
||||
|
||||
#RequireNodeType<Node, (EvaluatableStatement, CompilerContext)>(
|
||||
#RequireNodeType<Node, P4Statement>(
|
||||
node: node, type: "parserTransitionStatement", nice_type_name: "parser transition statement"
|
||||
)
|
||||
|
||||
@@ -58,19 +64,18 @@ public struct SpecialCompilers {
|
||||
switch next_state {
|
||||
case (_, .some(let instance)):
|
||||
return .Ok(
|
||||
(
|
||||
ParserStateDirectTransition(
|
||||
name: state_identifier,
|
||||
withNextState: instance.dataValue() as! InstantiatedParserState,
|
||||
withStatements: stmts), context
|
||||
))
|
||||
ParserStateDirectTransition(
|
||||
name: state_identifier,
|
||||
withNextState: instance.dataValue() as! InstantiatedParserState,
|
||||
withStatements: stmts,
|
||||
)
|
||||
)
|
||||
case (_, .none):
|
||||
return .Ok(
|
||||
(
|
||||
ParserStateDirectTransition(
|
||||
name: state_identifier,
|
||||
withNextStateIdentifier: next_state_id, withStatements: stmts), context
|
||||
))
|
||||
ParserStateDirectTransition(
|
||||
name: state_identifier,
|
||||
withNextStateIdentifier: next_state_id, withStatements: stmts)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -95,12 +100,11 @@ public struct SpecialCompilers {
|
||||
{
|
||||
case .Ok(let tse):
|
||||
.Ok(
|
||||
(
|
||||
ParserStateSelectTransition(
|
||||
name: state_identifier, withTransitionExpression: tse as! SelectExpression,
|
||||
withStatements: stmts,
|
||||
), context
|
||||
))
|
||||
ParserStateSelectTransition(
|
||||
name: state_identifier, withTransitionExpression: tse as! SelectExpression,
|
||||
withStatements: stmts,
|
||||
)
|
||||
)
|
||||
case .Error(let e): .Error(e)
|
||||
}
|
||||
}
|
||||
@@ -109,7 +113,7 @@ public struct SpecialCompilers {
|
||||
public struct Statements {
|
||||
static func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<([EvaluatableStatement], CompilerContext)> {
|
||||
) -> Result<[P4Statement]> {
|
||||
if node.nodeType != "statements" && node.nodeType != "parserStatements" {
|
||||
return Result.Error(
|
||||
ErrorWithLocation(
|
||||
@@ -118,15 +122,15 @@ public struct SpecialCompilers {
|
||||
|
||||
var errors: (any Errorable)? = .none
|
||||
var current_context = context
|
||||
var parsed_s: [EvaluatableStatement] = Array()
|
||||
var parsed_s: [P4Statement] = Array()
|
||||
|
||||
node.enumerateNamedChildren { node in
|
||||
switch Statement.Compile(
|
||||
node: node, withContext: current_context)
|
||||
{
|
||||
case .Ok((let parsed_statement, let updated_context)):
|
||||
current_context = updated_context
|
||||
case .Ok(let parsed_statement):
|
||||
parsed_s.append(parsed_statement)
|
||||
current_context = parsed_statement.effect(context: current_context)
|
||||
case .Error(let e):
|
||||
errors =
|
||||
if let errors = errors {
|
||||
@@ -141,11 +145,20 @@ public struct SpecialCompilers {
|
||||
return .Error(errors)
|
||||
}
|
||||
|
||||
return Result.Ok((parsed_s, current_context))
|
||||
return Result.Ok(parsed_s)
|
||||
}
|
||||
|
||||
static func effect(statements: [P4Statement], context: CompilerContext) -> CompilerContext {
|
||||
var current = context
|
||||
for s in statements {
|
||||
current = s.effect(context: current)
|
||||
}
|
||||
return current
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static func Compile(
|
||||
static func CompileParserBody(
|
||||
withName name: Common.Identifier, withParameters parameters: ParameterList, node: Node,
|
||||
withContext context: CompilerContext
|
||||
) -> Result<(P4Lang.Parser, CompilerContext)> {
|
||||
@@ -167,9 +180,10 @@ public struct SpecialCompilers {
|
||||
node: parser_state,
|
||||
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)
|
||||
current_context = updated_context
|
||||
case Result.Error(let e): error = e
|
||||
}
|
||||
}
|
||||
@@ -245,43 +259,35 @@ public struct SpecialCompilers {
|
||||
|
||||
// Try to parse all top-level declarations.
|
||||
result?.rootNode?.enumerateNamedChildren { (declaration_node: Node) in
|
||||
let specific_declaration_node = declaration_node.child(at: 0)!
|
||||
|
||||
let declaration_parsers: [CompilableDeclaration.Type] = [
|
||||
Declaration.self, P4Lang.Parser.self,
|
||||
let declaration_parsers: [String: CompilableStatement.Type] = [
|
||||
"declaration": Declaration.self,
|
||||
"instantiation": Instantiation.self,
|
||||
]
|
||||
var found_parser = false
|
||||
|
||||
for parser in declaration_parsers {
|
||||
switch parser.Compile(node: specific_declaration_node, withContext: compilation_context) {
|
||||
case .Ok(.none): {}()
|
||||
case .Ok(.some((_, let updated_context))):
|
||||
found_parser = true
|
||||
compilation_context = updated_context
|
||||
break
|
||||
if let parser = declaration_parsers[declaration_node.nodeType!] {
|
||||
let r = parser.CompileStatement(node: declaration_node, withContext: compilation_context)
|
||||
switch r {
|
||||
case .Ok(let compiled):
|
||||
compilation_context = compiled.effect(context: compilation_context)
|
||||
case .Error(let e):
|
||||
found_parser = true
|
||||
errors =
|
||||
if let errors = errors {
|
||||
errors.append(error: e)
|
||||
} else {
|
||||
e
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// If none of the declaration parsers chose to parse, that's an error, too!
|
||||
if !found_parser {
|
||||
let no_parser_error = ErrorWithLocation(
|
||||
sourceLocation: specific_declaration_node.toSourceLocation(),
|
||||
withError: "Could not find parser for declaration node"
|
||||
)
|
||||
}
|
||||
} else {
|
||||
let e = ErrorWithLocation(
|
||||
sourceLocation: declaration_node.toSourceLocation(),
|
||||
withError:
|
||||
"\(declaration_node.nodeType!) cannot be at a P4 program top level")
|
||||
errors =
|
||||
if let errors = errors {
|
||||
errors.append(error: no_parser_error)
|
||||
errors.append(error: e)
|
||||
} else {
|
||||
no_parser_error
|
||||
e
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -313,4 +319,5 @@ public struct SpecialCompilers {
|
||||
return Result.Ok(program)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,11 +22,12 @@ import SwiftTreeSitter
|
||||
import TreeSitterExtensions
|
||||
import TreeSitterP4
|
||||
|
||||
extension BlockStatement: CompilableStatement {
|
||||
extension BlockStatement: Compilable {
|
||||
public typealias C = BlockStatement
|
||||
public static func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<(EvaluatableStatement, CompilerContext)> {
|
||||
#RequireNodeType<Node, (EvaluatableStatement, CompilerContext)>(
|
||||
) -> Result<BlockStatement> {
|
||||
#RequireNodeType<Node, (P4Statement)>(
|
||||
node: node, type: "blockStatement", nice_type_name: "block statement")
|
||||
|
||||
var walker = Walker(node: node)
|
||||
@@ -34,7 +35,7 @@ extension BlockStatement: CompilableStatement {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(EvaluatableStatement, CompilerContext)>.Error(
|
||||
or: Result<BlockStatement>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Malformed block statement")))
|
||||
|
||||
@@ -45,23 +46,21 @@ extension BlockStatement: CompilableStatement {
|
||||
withError: "Missing { on block statement"))
|
||||
}
|
||||
|
||||
var statements: [EvaluatableStatement] = Array()
|
||||
var statements: [P4Statement] = Array()
|
||||
var parse_err: (any Errorable)? = .none
|
||||
var current_context = context
|
||||
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(EvaluatableStatement, CompilerContext)>.Error(
|
||||
or: Result<BlockStatement>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Malformed block statement")))
|
||||
|
||||
if current_node!.nodeType == "statements" {
|
||||
switch SpecialCompilers.Statements.Compile(
|
||||
node: current_node!, withContext: current_context)
|
||||
node: current_node!, withContext: context)
|
||||
{
|
||||
case .Ok(let (parsed_statements, updated_context)):
|
||||
current_context = updated_context
|
||||
case .Ok(let parsed_statements):
|
||||
statements = parsed_statements
|
||||
case .Error(let error):
|
||||
parse_err = error
|
||||
@@ -76,7 +75,7 @@ extension BlockStatement: CompilableStatement {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(EvaluatableStatement, CompilerContext)>.Error(
|
||||
or: Result<BlockStatement>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Malformed block statement")))
|
||||
|
||||
@@ -87,16 +86,28 @@ extension BlockStatement: CompilableStatement {
|
||||
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(
|
||||
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")
|
||||
|
||||
let maybe_condition_expression = node.child(at: 2)
|
||||
@@ -128,7 +139,7 @@ extension ConditionalStatement: CompilableStatement {
|
||||
}
|
||||
|
||||
guard
|
||||
case .Ok((let thenns, _)) = Statement.Compile(
|
||||
case .Ok(let thenns) = Statement.Compile(
|
||||
node: thens, withContext: context)
|
||||
else {
|
||||
return Result.Error(
|
||||
@@ -137,7 +148,7 @@ extension ConditionalStatement: CompilableStatement {
|
||||
"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) {
|
||||
.some(
|
||||
Statement.Compile(
|
||||
@@ -148,7 +159,7 @@ extension ConditionalStatement: CompilableStatement {
|
||||
|
||||
if let parsed_elss = optional_elss {
|
||||
guard
|
||||
case .Ok((let elss, _)) = parsed_elss
|
||||
case .Ok(let elss) = parsed_elss
|
||||
else {
|
||||
return Result.Error(
|
||||
Error(
|
||||
@@ -156,18 +167,30 @@ extension ConditionalStatement: CompilableStatement {
|
||||
"Could not parse the else block in a conditional statement"))
|
||||
}
|
||||
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(
|
||||
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")
|
||||
|
||||
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!)"))
|
||||
}
|
||||
|
||||
var initializer: EvaluatableExpression? = .none
|
||||
var initializer: P4Expression? = .none
|
||||
|
||||
// If there is an initializer, it must be an expression.
|
||||
if let initializer_expression = maybe_rvalue {
|
||||
@@ -249,40 +272,59 @@ extension VariableDeclarationStatement: CompilableStatement {
|
||||
}
|
||||
|
||||
return Result.Ok(
|
||||
(
|
||||
VariableDeclarationStatement(
|
||||
identifier: parsed_variablename, withInitializer: initializer),
|
||||
// Context with updated names to include the newly declared name.
|
||||
context.update(
|
||||
newInstances: context.instances.declare(
|
||||
identifier: parsed_variablename, withValue: (declaration_p4_type, .none)))
|
||||
)
|
||||
VariableDeclarationStatement(
|
||||
identifier: TypedIdentifier(id: parsed_variablename, withType: declaration_p4_type),
|
||||
withInitializer: initializer),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
extension ExpressionStatement: CompilableStatement {
|
||||
public static func Compile(
|
||||
extension VariableDeclarationStatement: CompilableStatement {
|
||||
public static func CompileStatement(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<(EvaluatableStatement, CompilerContext)> {
|
||||
#RequireNodeType<Node, (EvaluatableStatement, CompilerContext)>(
|
||||
node: node, type: "expressionStatement", nice_type_name: "expression statement")
|
||||
|
||||
let expression_node = node.child(at: 0)!
|
||||
|
||||
return switch Expression.Compile(node: expression_node, withContext: context) {
|
||||
case .Ok(let expression): .Ok((ExpressionStatement(expression), context))
|
||||
) -> Result<P4Statement> {
|
||||
return switch Compile(node: node, withContext: context) {
|
||||
case .Ok(let res): .Ok(res)
|
||||
case .Error(let e): .Error(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension ParserAssignmentStatement: CompilableStatement {
|
||||
extension ExpressionStatement: Compilable {
|
||||
public typealias C = ExpressionStatement
|
||||
public static func Compile(
|
||||
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")
|
||||
|
||||
guard let lvalue_node = node.child(at: 0),
|
||||
@@ -323,20 +365,30 @@ extension ParserAssignmentStatement: CompilableStatement {
|
||||
}
|
||||
|
||||
return Result.Ok(
|
||||
(
|
||||
ParserAssignmentStatement(
|
||||
withLValue: lvalue_identifier,
|
||||
withValue: rvalue
|
||||
), context
|
||||
ParserAssignmentStatement(
|
||||
withLValue: lvalue_identifier,
|
||||
withValue: rvalue
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
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(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(any Common.EvaluatableStatement, CompilerContext)> {
|
||||
#RequireNodeType<Node, (EvaluatableStatement, CompilerContext)>(
|
||||
) -> Result<ReturnStatement> {
|
||||
#RequireNodeType<Node, (P4Statement)>(
|
||||
node: node, type: "return_statement", nice_type_name: "return statement")
|
||||
|
||||
let expression_node = node.child(at: 1)!
|
||||
@@ -344,7 +396,7 @@ extension ReturnStatement: CompilableStatement {
|
||||
return switch Expression.Compile(node: expression_node, withContext: context) {
|
||||
case .Ok(let result):
|
||||
if result.type().baseType().eq(rhs: context.expected_type!.baseType()) {
|
||||
.Ok((ReturnStatement(result), context))
|
||||
.Ok(ReturnStatement(result))
|
||||
} else {
|
||||
.Error(
|
||||
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(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(any Common.EvaluatableStatement, CompilerContext)> {
|
||||
#RequireNodeType<Node, (EvaluatableStatement, CompilerContext)>(
|
||||
) -> Result<ApplyStatement> {
|
||||
#RequireNodeType<Node, (P4Statement)>(
|
||||
node: node, type: "apply_statement", nice_type_name: "apply statement")
|
||||
|
||||
let expression_node = node.child(at: 1)!
|
||||
|
||||
return switch BlockStatement.Compile(node: expression_node, withContext: context) {
|
||||
case .Ok((let statement, let updated_context)):
|
||||
.Ok((ApplyStatement(statement as! BlockStatement), updated_context))
|
||||
case .Ok(let statement):
|
||||
.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)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user