compiler, testing: Build System for Compilation
The compilation code was written as a precursor for implementation with macros. The updates in this commit make the switch. There is still plenty to do: 1. Comment Walker. 2. Comment Macros. Signed-off-by: Will Hawkins <hawkinsw@obs.cr>
This commit is contained in:
+2
-1
@@ -75,7 +75,8 @@ let package = Package(
|
|||||||
),
|
),
|
||||||
.testTarget(
|
.testTarget(
|
||||||
name: "Tests",
|
name: "Tests",
|
||||||
dependencies: ["P4Compiler", "P4Runtime", "P4Lang", "Macros", "TreeSitterExtensions", "Common"]
|
dependencies: ["P4Compiler", "P4Runtime", "P4Lang", "Macros", "TreeSitterExtensions", "Common"],
|
||||||
|
swiftSettings: [.enableExperimentalFeature("CodeItemMacros")],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -148,5 +148,8 @@ public func Map<T, U>(input: T, block: (T) -> U) -> U {
|
|||||||
nodes: N, type: [String], nice_type_names: [String]
|
nodes: N, type: [String], nice_type_names: [String]
|
||||||
) =
|
) =
|
||||||
#externalMacro(module: "Macros", type: "RequireNodesType")
|
#externalMacro(module: "Macros", type: "RequireNodesType")
|
||||||
@freestanding(codeItem) public macro SkipUnlessNodeType<N, T>(node: N, type: String) =
|
@freestanding(codeItem) public macro SkipUnlessNodeType<N>(node: N, type: String) =
|
||||||
#externalMacro(module: "Macros", type: "SkipUnlessNodeType")
|
#externalMacro(module: "Macros", type: "SkipUnlessNodeType")
|
||||||
|
|
||||||
|
@freestanding(codeItem) public macro MustOr<E, N>(result: E, thing: E?, or: N) =
|
||||||
|
#externalMacro(module: "Macros", type: "MustOr")
|
||||||
|
|||||||
@@ -225,10 +225,38 @@ public struct SkipUnlessNodeType: CodeItemMacro {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct MustOr: CodeItemMacro {
|
||||||
|
public static func expansion(
|
||||||
|
of node: some FreestandingMacroExpansionSyntax, in context: some MacroExpansionContext
|
||||||
|
) throws -> [CodeBlockItemSyntax] {
|
||||||
|
let arguments = node.arguments.indices
|
||||||
|
|
||||||
|
var arg_index = arguments.startIndex
|
||||||
|
let result = node.arguments[arg_index].expression
|
||||||
|
|
||||||
|
arg_index = arguments.index(after: arg_index)
|
||||||
|
let thing = node.arguments[arg_index].expression
|
||||||
|
|
||||||
|
arg_index = arguments.index(after: arg_index)
|
||||||
|
let or = node.arguments[arg_index].expression
|
||||||
|
|
||||||
|
return [
|
||||||
|
CodeBlockItemSyntax(
|
||||||
|
"""
|
||||||
|
if let __thing = \(thing) {
|
||||||
|
\(result) = __thing
|
||||||
|
} else {
|
||||||
|
return \(or)
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@main
|
@main
|
||||||
struct P4Macros: CompilerPlugin {
|
struct P4Macros: CompilerPlugin {
|
||||||
var providingMacros: [Macro.Type] = [
|
var providingMacros: [Macro.Type] = [
|
||||||
RequireResult.self, RequireErrorResult.self, UseOkResult.self, UseErrorResult.self,
|
RequireResult.self, RequireErrorResult.self, UseOkResult.self, UseErrorResult.self,
|
||||||
RequireNodeType.self, SkipUnlessNodeType.self, RequireNodesType.self,
|
RequireNodeType.self, SkipUnlessNodeType.self, RequireNodesType.self, MustOr.self,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
+115
-117
@@ -26,9 +26,8 @@ func parameter_list_compiler(
|
|||||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Common.Result<(ParameterList, CompilerContext)> {
|
) -> Common.Result<(ParameterList, CompilerContext)> {
|
||||||
|
|
||||||
var currentChildIdx = 0
|
var walker = Walker(node: node)
|
||||||
var currentChildIdxSafe = 1
|
var current_node: Node? = .none
|
||||||
var currentChild: Node? = .none
|
|
||||||
|
|
||||||
if node.text == ")" {
|
if node.text == ")" {
|
||||||
// There are no parameters!
|
// There are no parameters!
|
||||||
@@ -40,49 +39,45 @@ func parameter_list_compiler(
|
|||||||
|
|
||||||
var parameters: ParameterList = ParameterList([])
|
var parameters: ParameterList = ParameterList([])
|
||||||
|
|
||||||
if node.childCount < currentChildIdxSafe {
|
#MustOr(
|
||||||
return Result.Error(
|
result: current_node, thing: walker.getNext(),
|
||||||
ErrorOnNode(node: node, withError: "Missing parameter list component"))
|
or: Result<(ParameterList, CompilerContext)>.Error(
|
||||||
}
|
ErrorOnNode(
|
||||||
|
node: node, withError: "Missing parameter list component")))
|
||||||
|
|
||||||
currentChild = node.child(at: currentChildIdx)
|
if current_node?.nodeType == "parameter_list" {
|
||||||
if currentChild?.nodeType == "parameter_list" {
|
switch parameter_list_compiler(node: current_node!, withContext: context) {
|
||||||
switch parameter_list_compiler(node: currentChild!, withContext: context) {
|
|
||||||
case .Ok(let (ps, _)):
|
case .Ok(let (ps, _)):
|
||||||
parameters = ps
|
parameters = ps
|
||||||
case .Error(let e): return Result.Error(e)
|
case .Error(let e): return Result.Error(e)
|
||||||
}
|
}
|
||||||
|
walker.next()
|
||||||
currentChildIdx += 1
|
|
||||||
currentChildIdxSafe += 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We may have moved nodes, check/reset currentChild.
|
#MustOr(
|
||||||
if node.childCount < currentChildIdxSafe {
|
result: current_node, thing: walker.getNext(),
|
||||||
return Result.Error(
|
or: Result<(ParameterList, CompilerContext)>.Error(
|
||||||
ErrorOnNode(node: node, withError: "Missing parameter list component"))
|
ErrorOnNode(
|
||||||
}
|
node: node, withError: "Missing parameter list component")))
|
||||||
currentChild = node.child(at: currentChildIdx)
|
|
||||||
|
|
||||||
// If this is a ')', we are done.
|
// If this is a ')', we are done.
|
||||||
if currentChild?.text == ")" {
|
if current_node?.text == ")" {
|
||||||
return Result.Ok((parameters, context))
|
return Result.Ok((parameters, context))
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is a comma, we skip it!
|
// If this is a comma, we skip it!
|
||||||
if currentChild?.text == "," {
|
if current_node?.text == "," {
|
||||||
currentChildIdx += 1
|
walker.next()
|
||||||
currentChildIdxSafe += 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if node.childCount < currentChildIdxSafe {
|
#MustOr(
|
||||||
return Result.Error(
|
result: current_node, thing: walker.getNext(),
|
||||||
ErrorOnNode(node: node, withError: "Missing parameter list component"))
|
or: Result<(ParameterList, CompilerContext)>.Error(
|
||||||
}
|
ErrorOnNode(
|
||||||
currentChild = node.child(at: currentChildIdx)
|
node: node, withError: "Missing parameter list component")))
|
||||||
|
|
||||||
// Otherwise, there should be one parameter left!
|
// Otherwise, there should be one parameter left!
|
||||||
switch Parameter.Compile(node: currentChild!, withContext: context) {
|
switch Parameter.Compile(node: current_node!, withContext: context) {
|
||||||
case .Ok(let (parsed_parameter, updated_context)):
|
case .Ok(let (parsed_parameter, updated_context)):
|
||||||
return Result.Ok((parameters.addParameter(parsed_parameter), updated_context))
|
return Result.Ok((parameters.addParameter(parsed_parameter), updated_context))
|
||||||
case .Error(let e): return Result.Error(e)
|
case .Error(let e): return Result.Error(e)
|
||||||
@@ -99,24 +94,24 @@ extension ParameterList: Compilable {
|
|||||||
#RequireNodeType<Node, (ParameterList, CompilerContext)>(
|
#RequireNodeType<Node, (ParameterList, CompilerContext)>(
|
||||||
node: parameter_node, type: "parameters", nice_type_name: "Parameters")
|
node: parameter_node, type: "parameters", nice_type_name: "Parameters")
|
||||||
|
|
||||||
var currentChildIdx = 0
|
var walker = Walker(node: parameter_node)
|
||||||
var currentChildIdxSafe = 1
|
|
||||||
|
|
||||||
// Let's eat the '(' before we start ...
|
var current_node: Node? = .none
|
||||||
if parameter_node.childCount < currentChildIdxSafe {
|
|
||||||
return .Error(
|
|
||||||
ErrorOnNode(node: parameter_node, withError: "Missing '(' in parameter list component"))
|
|
||||||
}
|
|
||||||
|
|
||||||
currentChildIdx += 1
|
#MustOr(
|
||||||
currentChildIdxSafe += 1
|
result: current_node, thing: walker.getNext(),
|
||||||
if parameter_node.childCount < currentChildIdxSafe {
|
or: Result<(ParameterList, CompilerContext)>.Error(
|
||||||
return .Error(
|
ErrorOnNode(
|
||||||
ErrorOnNode(node: parameter_node, withError: "Missing parameter list component"))
|
node: node, withError: "Missing '(' in parameter list component")))
|
||||||
}
|
|
||||||
let currentChild = parameter_node.child(at: currentChildIdx)
|
|
||||||
|
|
||||||
return parameter_list_compiler(node: currentChild!, withContext: context)
|
walker.next()
|
||||||
|
#MustOr(
|
||||||
|
result: current_node, thing: walker.getNext(),
|
||||||
|
or: Result<(ParameterList, CompilerContext)>.Error(
|
||||||
|
ErrorOnNode(
|
||||||
|
node: node, withError: "Missing parameter list component")))
|
||||||
|
|
||||||
|
return parameter_list_compiler(node: current_node!, withContext: context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,74 +148,80 @@ extension Parameter: Compilable {
|
|||||||
#RequireNodeType<Node, (EvaluatableStatement, CompilerContext)>(
|
#RequireNodeType<Node, (EvaluatableStatement, CompilerContext)>(
|
||||||
node: node, type: "parameter", nice_type_name: "parameter")
|
node: node, type: "parameter", nice_type_name: "parameter")
|
||||||
|
|
||||||
var currentChildIdx = 0
|
var walker = Walker(node: node)
|
||||||
var currentChildIdxSafe = 1
|
var current_node: Node? = .none
|
||||||
var currentChild: Node? = .none
|
|
||||||
|
|
||||||
if node.childCount < currentChildIdxSafe {
|
#MustOr(
|
||||||
return .Error(
|
result: current_node, thing: walker.getNext(),
|
||||||
ErrorOnNode(node: node, withError: "Missing parameter declaration component"))
|
or: Result<(Parameter, CompilerContext)>.Error(
|
||||||
}
|
ErrorOnNode(
|
||||||
|
node: node, withError: "Missing parameter declaration component")))
|
||||||
currentChild = node.child(at: currentChildIdx)
|
|
||||||
|
|
||||||
// Annotation?
|
// Annotation?
|
||||||
if currentChild!.nodeType == "annotations" {
|
if current_node!.nodeType == "annotations" {
|
||||||
return .Error(
|
return .Error(
|
||||||
ErrorOnNode(
|
ErrorOnNode(
|
||||||
node: currentChild!,
|
node: current_node!,
|
||||||
withError: "Annotations in parameter declarations are not yet handled"))
|
withError: "Annotations in parameter declarations are not yet handled"))
|
||||||
// Will increment indexes here.
|
// Will increment indexes here.
|
||||||
}
|
}
|
||||||
currentChild = node.child(at: currentChildIdx)
|
|
||||||
|
#MustOr(
|
||||||
|
result: current_node, thing: walker.getNext(),
|
||||||
|
or: Result<(Parameter, CompilerContext)>.Error(
|
||||||
|
ErrorOnNode(
|
||||||
|
node: node, withError: "Missing parameter declaration component")))
|
||||||
|
|
||||||
var direction: Direction? = .none
|
var direction: Direction? = .none
|
||||||
// Direction?
|
// Direction?
|
||||||
if currentChild!.nodeType == "direction" {
|
if current_node!.nodeType == "direction" {
|
||||||
|
|
||||||
let maybe_parsed_direction = Direction.Compile(node: currentChild!, withContext: context)
|
let maybe_parsed_direction = Direction.Compile(node: current_node!, withContext: context)
|
||||||
guard case .Ok((let parsed_direction, _)) = maybe_parsed_direction else {
|
guard case .Ok((let parsed_direction, _)) = maybe_parsed_direction else {
|
||||||
return .Error(maybe_parsed_direction.error()!)
|
return .Error(maybe_parsed_direction.error()!)
|
||||||
}
|
}
|
||||||
direction = parsed_direction
|
direction = parsed_direction
|
||||||
|
|
||||||
currentChildIdx += 1
|
walker.next()
|
||||||
currentChildIdxSafe += 1
|
|
||||||
}
|
}
|
||||||
currentChild = node.child(at: currentChildIdx)
|
|
||||||
|
|
||||||
if currentChild!.nodeType != "typeRef" {
|
#MustOr(
|
||||||
|
result: current_node, thing: walker.getNext(),
|
||||||
|
or: Result<(Parameter, CompilerContext)>.Error(
|
||||||
|
ErrorOnNode(
|
||||||
|
node: node, withError: "Missing parameter declaration component")))
|
||||||
|
|
||||||
|
if current_node!.nodeType != "typeRef" {
|
||||||
return Result.Error(
|
return Result.Error(
|
||||||
ErrorOnNode(
|
ErrorOnNode(
|
||||||
node: node, withError: "Did not find type name for parameter declaration"))
|
node: node, withError: "Did not find type name for parameter declaration"))
|
||||||
}
|
}
|
||||||
|
|
||||||
guard
|
guard
|
||||||
case .Ok(let parameter_type) = Types.CompileType(type: currentChild!, withContext: context)
|
case .Ok(let parameter_type) = Types.CompileType(type: current_node!, withContext: context)
|
||||||
else {
|
else {
|
||||||
return Result.Error(
|
return Result.Error(
|
||||||
Error(withMessage: "Could not parse a P4 type from \(currentChild!.text!)"))
|
Error(withMessage: "Could not parse a P4 type from \(current_node!.text!)"))
|
||||||
}
|
}
|
||||||
|
|
||||||
currentChildIdx += 1
|
walker.next()
|
||||||
currentChildIdxSafe += 1
|
#MustOr(
|
||||||
if node.childCount < currentChildIdxSafe {
|
result: current_node, thing: walker.getNext(),
|
||||||
return .Error(
|
or: Result<(Parameter, CompilerContext)>.Error(
|
||||||
ErrorOnNode(node: node, withError: "Missing parameter declaration component"))
|
ErrorOnNode(
|
||||||
}
|
node: node, withError: "Missing parameter declaration component")))
|
||||||
|
|
||||||
currentChild = node.child(at: currentChildIdx)
|
if current_node!.nodeType != "identifier" {
|
||||||
if currentChild!.nodeType != "identifier" {
|
|
||||||
return Result.Error(
|
return Result.Error(
|
||||||
ErrorOnNode(
|
ErrorOnNode(
|
||||||
node: node, withError: "Did not find identifier for parameter statement"))
|
node: node, withError: "Did not find identifier for parameter statement"))
|
||||||
}
|
}
|
||||||
|
|
||||||
guard
|
guard
|
||||||
case .Ok(let parameter_name) = Identifier.Compile(node: currentChild!, withContext: context)
|
case .Ok(let parameter_name) = Identifier.Compile(node: current_node!, withContext: context)
|
||||||
else {
|
else {
|
||||||
return Result.Error(
|
return Result.Error(
|
||||||
Error(withMessage: "Could not parse a parameter name from \(currentChild!.text!)"))
|
Error(withMessage: "Could not parse a parameter name from \(current_node!.text!)"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result.Ok(
|
return Result.Ok(
|
||||||
@@ -239,9 +240,8 @@ func argument_list_compiler(
|
|||||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Common.Result<(ArgumentList, CompilerContext)> {
|
) -> Common.Result<(ArgumentList, CompilerContext)> {
|
||||||
|
|
||||||
var currentChildIdx = 0
|
var walker = Walker(node: node)
|
||||||
var currentChildIdxSafe = 1
|
var current_node: Node? = .none
|
||||||
var currentChild: Node? = .none
|
|
||||||
|
|
||||||
if node.text == ")" {
|
if node.text == ")" {
|
||||||
// There are no arguments!
|
// There are no arguments!
|
||||||
@@ -253,49 +253,47 @@ func argument_list_compiler(
|
|||||||
|
|
||||||
var arguments: ArgumentList = ArgumentList([])
|
var arguments: ArgumentList = ArgumentList([])
|
||||||
|
|
||||||
if node.childCount < currentChildIdxSafe {
|
#MustOr(
|
||||||
return Result.Error(
|
result: current_node, thing: walker.getNext(),
|
||||||
ErrorOnNode(node: node, withError: "Missing argument list component"))
|
or: Result<(ArgumentList, CompilerContext)>.Error(
|
||||||
}
|
ErrorOnNode(
|
||||||
|
node: node, withError: "Missing argument list component")))
|
||||||
|
|
||||||
currentChild = node.child(at: currentChildIdx)
|
if current_node?.nodeType == "argument_list" {
|
||||||
if currentChild?.nodeType == "argument_list" {
|
switch argument_list_compiler(node: current_node!, withContext: context) {
|
||||||
switch argument_list_compiler(node: currentChild!, withContext: context) {
|
|
||||||
case .Ok(let (ps, _)):
|
case .Ok(let (ps, _)):
|
||||||
arguments = ps
|
arguments = ps
|
||||||
case .Error(let e): return Result.Error(e)
|
case .Error(let e): return Result.Error(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
currentChildIdx += 1
|
walker.next()
|
||||||
currentChildIdxSafe += 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We may have moved nodes, check/reset currentChild.
|
// We may have moved nodes, check/reset current_node.
|
||||||
if node.childCount < currentChildIdxSafe {
|
#MustOr(
|
||||||
return Result.Error(
|
result: current_node, thing: walker.getNext(),
|
||||||
ErrorOnNode(node: node, withError: "Missing argument list component"))
|
or: Result<(ArgumentList, CompilerContext)>.Error(
|
||||||
}
|
ErrorOnNode(
|
||||||
currentChild = node.child(at: currentChildIdx)
|
node: node, withError: "Missing argument list component")))
|
||||||
|
|
||||||
// If this is a ')', we are done.
|
// If this is a ')', we are done.
|
||||||
if currentChild?.text == ")" {
|
if current_node?.text == ")" {
|
||||||
return Result.Ok((arguments, context))
|
return Result.Ok((arguments, context))
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is a comma, we skip it!
|
// If this is a comma, we skip it!
|
||||||
if currentChild?.text == "," {
|
if current_node?.text == "," {
|
||||||
currentChildIdx += 1
|
walker.next()
|
||||||
currentChildIdxSafe += 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if node.childCount < currentChildIdxSafe {
|
#MustOr(
|
||||||
return Result.Error(
|
result: current_node, thing: walker.getNext(),
|
||||||
ErrorOnNode(node: node, withError: "Missing argument list component"))
|
or: Result<(ArgumentList, CompilerContext)>.Error(
|
||||||
}
|
ErrorOnNode(
|
||||||
currentChild = node.child(at: currentChildIdx)
|
node: node, withError: "Missing argument list component")))
|
||||||
|
|
||||||
// Otherwise, there should be one argument left!
|
// Otherwise, there should be one argument left!
|
||||||
switch Argument.Compile(node: currentChild!, withContext: context) {
|
switch Argument.Compile(node: current_node!, withContext: context) {
|
||||||
case .Ok(let (ce, updated_context)):
|
case .Ok(let (ce, updated_context)):
|
||||||
return Result.Ok(
|
return Result.Ok(
|
||||||
(arguments.addArgument(Argument(ce, atIndex: arguments.count() + 1)), updated_context))
|
(arguments.addArgument(Argument(ce, atIndex: arguments.count() + 1)), updated_context))
|
||||||
@@ -313,24 +311,24 @@ extension ArgumentList: Compilable {
|
|||||||
#RequireNodeType<Node, (ArgumentList, CompilerContext)>(
|
#RequireNodeType<Node, (ArgumentList, CompilerContext)>(
|
||||||
node: argument_node, type: "arguments", nice_type_name: "arguments")
|
node: argument_node, type: "arguments", nice_type_name: "arguments")
|
||||||
|
|
||||||
var currentChildIdx = 0
|
var walker = Walker(node: argument_node)
|
||||||
var currentChildIdxSafe = 1
|
var current_node: Node? = .none
|
||||||
|
|
||||||
// Let's eat the '(' before we start ...
|
#MustOr(
|
||||||
if argument_node.childCount < currentChildIdxSafe {
|
result: current_node, thing: walker.getNext(),
|
||||||
return .Error(
|
or: Result<(ArgumentList, CompilerContext)>.Error(
|
||||||
ErrorOnNode(node: argument_node, withError: "Missing '(' in argument list component"))
|
ErrorOnNode(
|
||||||
}
|
node: node, withError: "Missing '(' in argument list component")))
|
||||||
|
|
||||||
currentChildIdx += 1
|
walker.next()
|
||||||
currentChildIdxSafe += 1
|
|
||||||
if argument_node.childCount < currentChildIdxSafe {
|
|
||||||
return .Error(
|
|
||||||
ErrorOnNode(node: argument_node, withError: "Missing argument list component"))
|
|
||||||
}
|
|
||||||
let currentChild = argument_node.child(at: currentChildIdx)
|
|
||||||
|
|
||||||
return argument_list_compiler(node: currentChild!, withContext: context)
|
#MustOr(
|
||||||
|
result: current_node, thing: walker.getNext(),
|
||||||
|
or: Result<(ArgumentList, CompilerContext)>.Error(
|
||||||
|
ErrorOnNode(
|
||||||
|
node: node, withError: "Missing argument list component")))
|
||||||
|
|
||||||
|
return argument_list_compiler(node: current_node!, withContext: context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -51,46 +51,42 @@ extension FunctionDeclaration: CompilableDeclaration {
|
|||||||
node: function_declaration_node, type: "function_declaration",
|
node: function_declaration_node, type: "function_declaration",
|
||||||
nice_type_name: "Function Declaration")
|
nice_type_name: "Function Declaration")
|
||||||
|
|
||||||
|
var walker = Walker(node: function_declaration_node)
|
||||||
var context = context
|
var context = context
|
||||||
var currentChildIdx = 0
|
|
||||||
var currentChildIdxSafe = 1
|
|
||||||
var currentChild: Node? = .none
|
|
||||||
if function_declaration_node.childCount < currentChildIdxSafe {
|
|
||||||
return Result.Error(
|
|
||||||
ErrorOnNode(
|
|
||||||
node: function_declaration_node, withError: "Missing function declaration component"))
|
|
||||||
}
|
|
||||||
currentChild = function_declaration_node.child(at: currentChildIdx)
|
|
||||||
|
|
||||||
let maybe_function_type = Types.CompileType(type: currentChild!, withContext: context)
|
var current_node: Node? = .none
|
||||||
|
|
||||||
|
#MustOr(
|
||||||
|
result: current_node, thing: walker.getNext(),
|
||||||
|
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||||
|
ErrorOnNode(
|
||||||
|
node: function_declaration_node, withError: "Missing function declaration component")))
|
||||||
|
|
||||||
|
let maybe_function_type = Types.CompileType(type: current_node!, withContext: context)
|
||||||
guard case .Ok(let function_type) = maybe_function_type else {
|
guard case .Ok(let function_type) = maybe_function_type else {
|
||||||
return .Error(maybe_function_type.error()!)
|
return .Error(maybe_function_type.error()!)
|
||||||
}
|
}
|
||||||
|
|
||||||
currentChildIdx += 1
|
walker.next()
|
||||||
currentChildIdxSafe += 1
|
#MustOr(
|
||||||
if function_declaration_node.childCount < currentChildIdxSafe {
|
result: current_node, thing: walker.getNext(),
|
||||||
return Result.Error(
|
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||||
ErrorOnNode(
|
ErrorOnNode(
|
||||||
node: function_declaration_node, withError: "Missing function declaration component"))
|
node: function_declaration_node, withError: "Missing function declaration component")))
|
||||||
}
|
|
||||||
currentChild = function_declaration_node.child(at: currentChildIdx)
|
|
||||||
|
|
||||||
let maybe_function_name = Identifier.Compile(node: currentChild!, withContext: context)
|
let maybe_function_name = Identifier.Compile(node: current_node!, withContext: context)
|
||||||
guard case .Ok(let function_name) = maybe_function_name else {
|
guard case .Ok(let function_name) = maybe_function_name else {
|
||||||
return .Error(maybe_function_name.error()!)
|
return .Error(maybe_function_name.error()!)
|
||||||
}
|
}
|
||||||
|
|
||||||
currentChildIdx += 1
|
walker.next()
|
||||||
currentChildIdxSafe += 1
|
#MustOr(
|
||||||
if function_declaration_node.childCount < currentChildIdxSafe {
|
result: current_node, thing: walker.getNext(),
|
||||||
return Result.Error(
|
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||||
ErrorOnNode(
|
ErrorOnNode(
|
||||||
node: function_declaration_node, withError: "Missing function declaration component"))
|
node: function_declaration_node, withError: "Missing function declaration component")))
|
||||||
}
|
|
||||||
currentChild = function_declaration_node.child(at: currentChildIdx)
|
|
||||||
|
|
||||||
let maybe_function_parameters = ParameterList.Compile(node: currentChild!, withContext: context)
|
let maybe_function_parameters = ParameterList.Compile(node: current_node!, withContext: context)
|
||||||
guard case .Ok((let function_parameters, let updated_context)) = maybe_function_parameters
|
guard case .Ok((let function_parameters, let updated_context)) = maybe_function_parameters
|
||||||
else {
|
else {
|
||||||
return .Error(maybe_function_parameters.error()!)
|
return .Error(maybe_function_parameters.error()!)
|
||||||
@@ -99,11 +95,8 @@ extension FunctionDeclaration: CompilableDeclaration {
|
|||||||
|
|
||||||
var function_body: BlockStatement? = .none
|
var function_body: BlockStatement? = .none
|
||||||
|
|
||||||
currentChildIdx += 1
|
walker.next()
|
||||||
currentChildIdxSafe += 1
|
if let body = walker.getNext() {
|
||||||
if currentChildIdxSafe <= function_declaration_node.childCount {
|
|
||||||
currentChild = function_declaration_node.child(at: currentChildIdx)
|
|
||||||
|
|
||||||
// Add the parameters into scope.
|
// Add the parameters into scope.
|
||||||
var function_scope = context.instances.enter()
|
var function_scope = context.instances.enter()
|
||||||
for parameter in function_parameters.parameters {
|
for parameter in function_parameters.parameters {
|
||||||
@@ -112,7 +105,7 @@ extension FunctionDeclaration: CompilableDeclaration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let maybe_function_body = BlockStatement.Compile(
|
let maybe_function_body = BlockStatement.Compile(
|
||||||
node: currentChild!,
|
node: body,
|
||||||
withContext: context.update(newInstances: function_scope).update(
|
withContext: context.update(newInstances: function_scope).update(
|
||||||
newExpectation: function_type))
|
newExpectation: function_type))
|
||||||
|
|
||||||
@@ -160,59 +153,38 @@ extension P4Struct: CompilableDeclaration {
|
|||||||
static public func Compile(
|
static public func Compile(
|
||||||
node: Node, withContext context: CompilerContext
|
node: Node, withContext context: CompilerContext
|
||||||
) -> Result<(Declaration, CompilerContext)?> {
|
) -> Result<(Declaration, CompilerContext)?> {
|
||||||
|
|
||||||
let struct_declaration_node = node.child(at: 0)!
|
let struct_declaration_node = node.child(at: 0)!
|
||||||
var currentChildIdx = 0
|
var walker = Walker(node: struct_declaration_node)
|
||||||
var currentChildIdxSafe = 1
|
var currentNode: Node? = .none
|
||||||
|
|
||||||
var currentChild: Node? = .none
|
#SkipUnlessNodeType(node: struct_declaration_node, type: "struct_declaration")
|
||||||
|
|
||||||
guard let node_type = struct_declaration_node.nodeType,
|
|
||||||
node_type == "struct_declaration"
|
|
||||||
else {
|
|
||||||
return Result.Error(
|
|
||||||
ErrorOnNode(node: struct_declaration_node, withError: "Did not find a struct declaration"))
|
|
||||||
}
|
|
||||||
|
|
||||||
if struct_declaration_node.childCount < currentChildIdxSafe {
|
|
||||||
return Result.Error(
|
|
||||||
ErrorOnNode(
|
|
||||||
node: struct_declaration_node, withError: "Missing elements in struct declaration"))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip the keyword struct
|
// Skip the keyword struct
|
||||||
currentChildIdx += 1
|
walker.next()
|
||||||
currentChildIdxSafe += 1
|
#MustOr(
|
||||||
if struct_declaration_node.childCount < currentChildIdxSafe {
|
result: currentNode, thing: walker.getNext(),
|
||||||
return Result.Error(
|
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||||
ErrorOnNode(
|
ErrorOnNode(
|
||||||
node: struct_declaration_node, withError: "Missing elements in struct declaration"))
|
node: struct_declaration_node, withError: "Missing function declaration component")))
|
||||||
}
|
|
||||||
|
|
||||||
// The name of the struct type.
|
// The name of the struct type.
|
||||||
currentChild = struct_declaration_node.child(at: currentChildIdx)
|
|
||||||
let maybe_struct_identifier = Identifier.Compile(
|
let maybe_struct_identifier = Identifier.Compile(
|
||||||
node: currentChild!, withContext: context)
|
node: currentNode!, withContext: context)
|
||||||
guard case Result.Ok(let struct_identifier) = maybe_struct_identifier else {
|
guard case Result.Ok(let struct_identifier) = maybe_struct_identifier else {
|
||||||
return Result.Error(maybe_struct_identifier.error()!)
|
return Result.Error(maybe_struct_identifier.error()!)
|
||||||
}
|
}
|
||||||
|
walker.next()
|
||||||
currentChildIdx += 1
|
|
||||||
currentChildIdxSafe += 1
|
|
||||||
|
|
||||||
// Skip the '{'
|
// Skip the '{'
|
||||||
currentChildIdx += 1
|
walker.next()
|
||||||
currentChildIdxSafe += 1
|
#MustOr(
|
||||||
if struct_declaration_node.childCount < currentChildIdxSafe {
|
result: currentNode, thing: walker.getNext(),
|
||||||
return Result.Error(
|
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||||
ErrorOnNode(
|
ErrorOnNode(
|
||||||
node: struct_declaration_node, withError: "Missing element of struct declaration"))
|
node: struct_declaration_node, withError: "Missing function declaration component")))
|
||||||
}
|
|
||||||
|
|
||||||
currentChild = struct_declaration_node.child(at: currentChildIdx)
|
|
||||||
|
|
||||||
// If there are no fields, it will be a "}"
|
// If there are no fields, it will be a "}"
|
||||||
if currentChild!.nodeType == "}" {
|
if currentNode!.nodeType == "}" {
|
||||||
let struc = Declaration(
|
let struc = Declaration(
|
||||||
TypedIdentifier(
|
TypedIdentifier(
|
||||||
id: struct_identifier,
|
id: struct_identifier,
|
||||||
@@ -232,8 +204,8 @@ extension P4Struct: CompilableDeclaration {
|
|||||||
var current_context = context
|
var current_context = context
|
||||||
var parsed_fields: [P4StructFieldIdentifier] = Array()
|
var parsed_fields: [P4StructFieldIdentifier] = Array()
|
||||||
|
|
||||||
if currentChild!.nodeType == "struct_declaration_fields" {
|
if currentNode!.nodeType == "struct_declaration_fields" {
|
||||||
currentChild!.enumerateNamedChildren { declaration_field in
|
currentNode!.enumerateNamedChildren { declaration_field in
|
||||||
switch VariableDeclarationStatement.Compile(
|
switch VariableDeclarationStatement.Compile(
|
||||||
node: declaration_field, withContext: current_context)
|
node: declaration_field, withContext: current_context)
|
||||||
{
|
{
|
||||||
@@ -281,75 +253,67 @@ extension P4Lang.Parser: CompilableDeclaration {
|
|||||||
node: Node, withContext context: CompilerContext
|
node: Node, withContext context: CompilerContext
|
||||||
) -> Result<(Declaration, CompilerContext)?> {
|
) -> Result<(Declaration, CompilerContext)?> {
|
||||||
let parser_node = node
|
let parser_node = node
|
||||||
#SkipUnlessNodeType<Node, (P4DataType, CompilerContext)?>(
|
#SkipUnlessNodeType<Node>(node: parser_node, type: "parserDeclaration")
|
||||||
node: parser_node, type: "parserDeclaration")
|
|
||||||
|
|
||||||
var current_context = context
|
var current_context = context
|
||||||
|
|
||||||
var currentChildIdx = 0
|
var walker = Walker(node: parser_node)
|
||||||
var currentChildIdxSafe = 1
|
var current_node: Node? = .none
|
||||||
var currentChild: Node? = .none
|
|
||||||
|
|
||||||
if parser_node.childCount < currentChildIdxSafe {
|
#MustOr(
|
||||||
|
result: current_node, thing: walker.getNext(),
|
||||||
|
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||||
|
ErrorOnNode(
|
||||||
|
node: parser_node, withError: "Missing elements of parser declaration")))
|
||||||
|
|
||||||
|
if current_node!.nodeType != "parserType" {
|
||||||
return .Error(
|
return .Error(
|
||||||
ErrorOnNode(node: parser_node, withError: "Missing elements of parser declaration"))
|
ErrorOnNode(node: current_node!, withError: "Missing type for parser declaration"))
|
||||||
}
|
}
|
||||||
|
|
||||||
currentChild = parser_node.child(at: currentChildIdx)
|
let type_node = current_node
|
||||||
if currentChild!.nodeType != "parserType" {
|
|
||||||
return .Error(
|
|
||||||
ErrorOnNode(node: currentChild!, withError: "Missing type for parser declaration"))
|
|
||||||
}
|
|
||||||
|
|
||||||
let type_node = currentChild
|
|
||||||
var parser_name: Common.Identifier? = .none
|
var parser_name: Common.Identifier? = .none
|
||||||
|
|
||||||
// TODO: Handle parser parameter lists.
|
// TODO: Handle parser parameter lists.
|
||||||
var parameter_list = ParameterList()
|
var parameter_list = ParameterList()
|
||||||
|
|
||||||
do {
|
do {
|
||||||
// Parse the parser type (type_node)
|
var type_node_walker = Walker(node: type_node!)
|
||||||
var currentChildIdx = 0
|
var type_node_child: Node? = .none
|
||||||
var currentChildIdxSafe = 1
|
|
||||||
|
|
||||||
if type_node!.childCount < currentChildIdxSafe {
|
#MustOr(
|
||||||
|
result: type_node_child, thing: type_node_walker.getNext(),
|
||||||
|
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||||
|
ErrorOnNode(
|
||||||
|
node: parser_node, withError: "Missing elements of parser type in parser declaration")))
|
||||||
|
|
||||||
|
if type_node_child!.nodeType == "annotations" {
|
||||||
return .Error(
|
return .Error(
|
||||||
ErrorOnNode(
|
ErrorOnNode(
|
||||||
node: parser_node, withError: "Missing elements of parser type in parser declaration"))
|
node: type_node_child!, withError: "Annotations in parser type are not yet handled."))
|
||||||
}
|
|
||||||
|
|
||||||
var currentChild = type_node!.child(at: currentChildIdx)
|
|
||||||
if currentChild!.nodeType == "annotations" {
|
|
||||||
return .Error(
|
|
||||||
ErrorOnNode(
|
|
||||||
node: currentChild!, withError: "Annotations in parser type are not yet handled."))
|
|
||||||
// Will increment indexes here.
|
// Will increment indexes here.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip the parser keyword
|
type_node_walker.next()
|
||||||
currentChildIdx += 1
|
#MustOr(
|
||||||
currentChildIdxSafe += 1
|
result: type_node_child, thing: type_node_walker.getNext(),
|
||||||
if type_node!.childCount < currentChildIdxSafe {
|
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||||
return .Error(
|
ErrorOnNode(
|
||||||
ErrorOnNode(node: type_node!, withError: "Missing name in parser type declaration"))
|
node: type_node_child!, withError: "Missing name in parser type declaration")))
|
||||||
}
|
|
||||||
currentChild = type_node?.child(at: currentChildIdx)
|
|
||||||
|
|
||||||
switch Identifier.Compile(node: currentChild!, withContext: current_context) {
|
switch Identifier.Compile(node: type_node_child!, withContext: current_context) {
|
||||||
case .Ok(let id): parser_name = id
|
case .Ok(let id): parser_name = id
|
||||||
case .Error(let e):
|
case .Error(let e):
|
||||||
return .Error(e)
|
return .Error(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
currentChildIdx += 1
|
type_node_walker.next()
|
||||||
currentChildIdxSafe += 1
|
#MustOr(
|
||||||
if type_node!.childCount < currentChildIdxSafe {
|
result: type_node_child, thing: type_node_walker.getNext(),
|
||||||
return .Error(
|
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||||
ErrorOnNode(node: type_node!, withError: "Missing parser parameters"))
|
ErrorOnNode(
|
||||||
}
|
node: type_node_child!, withError: "Missing parser parameters")))
|
||||||
|
|
||||||
currentChild = type_node?.child(at: currentChildIdx)
|
switch ParameterList.Compile(node: type_node_child!, withContext: current_context) {
|
||||||
switch ParameterList.Compile(node: currentChild!, withContext: current_context) {
|
|
||||||
case .Ok(let (parsed_parameter_list, updated_context)):
|
case .Ok(let (parsed_parameter_list, updated_context)):
|
||||||
parameter_list = parsed_parameter_list
|
parameter_list = parsed_parameter_list
|
||||||
current_context = updated_context
|
current_context = updated_context
|
||||||
@@ -365,37 +329,38 @@ extension P4Lang.Parser: CompilableDeclaration {
|
|||||||
identifier: parameter.name, withValue: parameter.type))
|
identifier: parameter.name, withValue: parameter.type))
|
||||||
}
|
}
|
||||||
|
|
||||||
currentChildIdx += 1
|
walker.next()
|
||||||
currentChildIdxSafe += 1
|
#MustOr(
|
||||||
if parser_node.childCount < currentChildIdxSafe {
|
result: current_node, thing: walker.getNext(),
|
||||||
return .Error(
|
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||||
ErrorOnNode(node: parser_node, withError: "Missing parser declaration component"))
|
ErrorOnNode(
|
||||||
}
|
node: parser_node, withError: "Missing parser declaration component")))
|
||||||
|
|
||||||
// Skip the '{'
|
walker.next()
|
||||||
currentChildIdx += 1
|
#MustOr(
|
||||||
currentChildIdxSafe += 1
|
result: current_node, thing: walker.getNext(),
|
||||||
if parser_node.childCount < currentChildIdxSafe {
|
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||||
return .Error((Error(withMessage: "Missing body of parser declaration")))
|
ErrorOnNode(
|
||||||
}
|
node: parser_node, withError: "Missing elements of parser declaration")))
|
||||||
currentChild = parser_node.child(at: currentChildIdx)
|
|
||||||
|
|
||||||
if currentChild!.nodeType == "parserLocalElements" {
|
if current_node!.nodeType == "parserLocalElements" {
|
||||||
return .Error(
|
return .Error(
|
||||||
ErrorOnNode(node: currentChild!, withError: "Parser Local Elements are not yet handled."))
|
ErrorOnNode(node: current_node!, withError: "Parser Local Elements are not yet handled."))
|
||||||
// Will increment indexes here.
|
// Will increment indexes here.
|
||||||
}
|
}
|
||||||
|
|
||||||
if parser_node.childCount < currentChildIdxSafe {
|
#MustOr(
|
||||||
return .Error((Error(withMessage: "Missing body of parser declaration")))
|
result: current_node, thing: walker.getNext(),
|
||||||
}
|
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||||
|
ErrorOnNode(
|
||||||
|
node: parser_node, withError: "Missing body of parser declaration")))
|
||||||
|
|
||||||
if currentChild!.nodeType != "parserStates" {
|
if current_node!.nodeType != "parserStates" {
|
||||||
return .Error(Error(withMessage: "Missing parser states in parser declaration"))
|
return .Error(Error(withMessage: "Missing parser states in parser declaration"))
|
||||||
}
|
}
|
||||||
|
|
||||||
switch Parser.Compile(
|
switch Parser.Compile(
|
||||||
withName: parser_name!, withParameters: parameter_list, node: currentChild!,
|
withName: parser_name!, withParameters: parameter_list, node: current_node!,
|
||||||
withContext: current_context)
|
withContext: current_context)
|
||||||
{
|
{
|
||||||
case Result.Ok((let parser, let updated_context)):
|
case Result.Ok((let parser, let updated_context)):
|
||||||
@@ -421,47 +386,37 @@ extension Control: CompilableDeclaration {
|
|||||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Common.Result<(Declaration, CompilerContext)?> {
|
) -> Common.Result<(Declaration, CompilerContext)?> {
|
||||||
|
|
||||||
#SkipUnlessNodeType<Node, (P4DataType, CompilerContext)?>(
|
#SkipUnlessNodeType<Node>(node: node, type: "control_declaration")
|
||||||
node: node, type: "control_declaration")
|
|
||||||
|
|
||||||
var currentChildIdx = 0
|
var walker = Walker(node: node)
|
||||||
var currentChildIdxSafe = 1
|
var current_node: Node? = .none
|
||||||
var currentChild: Node? = .none
|
|
||||||
|
|
||||||
var local_context = context
|
var local_context = context
|
||||||
|
|
||||||
// Skip control keyword
|
walker.next()
|
||||||
if node.childCount < currentChildIdxSafe {
|
#MustOr(
|
||||||
return .Error(
|
result: current_node, thing: walker.getNext(),
|
||||||
ErrorOnNode(node: node, withError: "Missing control declaration component"))
|
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||||
}
|
ErrorOnNode(
|
||||||
|
node: node, withError: "Missing control declaration component")))
|
||||||
currentChildIdx += 1
|
|
||||||
currentChildIdxSafe += 1
|
|
||||||
if node.childCount < currentChildIdxSafe {
|
|
||||||
return .Error(
|
|
||||||
ErrorOnNode(node: node, withError: "Missing control declaration component"))
|
|
||||||
}
|
|
||||||
currentChild = node.child(at: currentChildIdx)
|
|
||||||
|
|
||||||
guard
|
guard
|
||||||
case .Ok(let control_name) = Identifier.Compile(
|
case .Ok(let control_name) = Identifier.Compile(
|
||||||
node: currentChild!, withContext: local_context)
|
node: current_node!, withContext: local_context)
|
||||||
else {
|
else {
|
||||||
return Result.Error(
|
return Result.Error(
|
||||||
Error(withMessage: "Could not parse a parameter name from \(currentChild!.text!)"))
|
Error(withMessage: "Could not parse a parameter name from \(current_node!.text!)"))
|
||||||
}
|
}
|
||||||
|
|
||||||
currentChildIdx += 1
|
walker.next()
|
||||||
currentChildIdxSafe += 1
|
#MustOr(
|
||||||
if node.childCount < currentChildIdxSafe {
|
result: current_node, thing: walker.getNext(),
|
||||||
return .Error(
|
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||||
ErrorOnNode(node: node, withError: "Missing control declaration component"))
|
ErrorOnNode(
|
||||||
}
|
node: node, withError: "Missing control declaration component")))
|
||||||
currentChild = node.child(at: currentChildIdx)
|
|
||||||
|
|
||||||
let maybe_control_parameters = ParameterList.Compile(
|
let maybe_control_parameters = ParameterList.Compile(
|
||||||
node: currentChild!, withContext: local_context)
|
node: current_node!, withContext: local_context)
|
||||||
guard case .Ok((let control_parameters, let updated_context)) = maybe_control_parameters
|
guard case .Ok((let control_parameters, let updated_context)) = maybe_control_parameters
|
||||||
else {
|
else {
|
||||||
return .Error(maybe_control_parameters.error()!)
|
return .Error(maybe_control_parameters.error()!)
|
||||||
@@ -476,26 +431,26 @@ extension Control: CompilableDeclaration {
|
|||||||
}
|
}
|
||||||
local_context = local_context.update(newInstances: control_scope)
|
local_context = local_context.update(newInstances: control_scope)
|
||||||
|
|
||||||
|
walker.next()
|
||||||
// Skip the '{'
|
// Skip the '{'
|
||||||
currentChildIdx += 2
|
walker.next()
|
||||||
currentChildIdxSafe += 2
|
#MustOr(
|
||||||
if node.childCount < currentChildIdxSafe {
|
result: current_node, thing: walker.getNext(),
|
||||||
return .Error(
|
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||||
ErrorOnNode(node: node, withError: "Missing control declaration component"))
|
ErrorOnNode(
|
||||||
}
|
node: node, withError: "Missing control declaration component")))
|
||||||
|
|
||||||
var actions: [Action] = Array()
|
var actions: [Action] = Array()
|
||||||
var tables: [Table] = Array()
|
var tables: [Table] = Array()
|
||||||
var apply: ApplyStatement? = .none
|
var apply: ApplyStatement? = .none
|
||||||
|
|
||||||
// Because the final child
|
// Because the final child
|
||||||
// is the '}'.
|
// is the '}'.
|
||||||
// \/\/
|
// \/\/
|
||||||
for currentChildIdx in currentChildIdx..<(node.childCount - 1) {
|
let body_parse_results = walker.overUntil(n: node.childCount - 1) { current_node in
|
||||||
let currentChild = node.child(at: currentChildIdx)!
|
if current_node.nodeType == "action_declaration" {
|
||||||
if currentChild.nodeType == "action_declaration" {
|
|
||||||
let maybe_action_declaration = Action.Compile(
|
let maybe_action_declaration = Action.Compile(
|
||||||
node: currentChild, withContext: local_context)
|
node: current_node, withContext: local_context)
|
||||||
guard
|
guard
|
||||||
case .Ok((let action_declaration, let updated_context)) = maybe_action_declaration
|
case .Ok((let action_declaration, let updated_context)) = maybe_action_declaration
|
||||||
else {
|
else {
|
||||||
@@ -503,9 +458,9 @@ extension Control: CompilableDeclaration {
|
|||||||
}
|
}
|
||||||
actions.append(action_declaration)
|
actions.append(action_declaration)
|
||||||
local_context = updated_context
|
local_context = updated_context
|
||||||
} else if currentChild.nodeType == "table_declaration" {
|
} else if current_node.nodeType == "table_declaration" {
|
||||||
let maybe_table_declaration = Table.Compile(
|
let maybe_table_declaration = Table.Compile(
|
||||||
node: currentChild, withContext: local_context)
|
node: current_node, withContext: local_context)
|
||||||
guard
|
guard
|
||||||
case .Ok((let table_declaration, let updated_context)) = maybe_table_declaration
|
case .Ok((let table_declaration, let updated_context)) = maybe_table_declaration
|
||||||
else {
|
else {
|
||||||
@@ -513,10 +468,10 @@ extension Control: CompilableDeclaration {
|
|||||||
}
|
}
|
||||||
tables.append(table_declaration)
|
tables.append(table_declaration)
|
||||||
local_context = updated_context
|
local_context = updated_context
|
||||||
} else if currentChild.nodeType == "apply_statement" {
|
} else if current_node.nodeType == "apply_statement" {
|
||||||
// When we see an apply, that is it for the actions and the tables.
|
// When we see an apply, that is it for the actions and the tables.
|
||||||
let maybe_apply_statement = ApplyStatement.Compile(
|
let maybe_apply_statement = ApplyStatement.Compile(
|
||||||
node: currentChild, withContext: local_context)
|
node: current_node, withContext: local_context)
|
||||||
guard
|
guard
|
||||||
case .Ok((let apply_statement, let updated_context)) = maybe_apply_statement
|
case .Ok((let apply_statement, let updated_context)) = maybe_apply_statement
|
||||||
else {
|
else {
|
||||||
@@ -526,18 +481,23 @@ extension Control: CompilableDeclaration {
|
|||||||
apply = (apply_statement as! ApplyStatement)
|
apply = (apply_statement as! ApplyStatement)
|
||||||
|
|
||||||
// The apply is the last thing in a control declaration.
|
// The apply is the last thing in a control declaration.
|
||||||
break
|
// But, that is handled by the compiler.
|
||||||
} else {
|
} else {
|
||||||
return .Error(
|
return .Error(
|
||||||
ErrorOnNode(node: currentChild, withError: "Uknown node type in control declaration"))
|
ErrorOnNode(node: current_node, withError: "Uknown node type in control declaration"))
|
||||||
}
|
}
|
||||||
|
return .Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
if case .Error(let e) = body_parse_results {
|
||||||
|
return .Error(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
// There should only be a single table!
|
// There should only be a single table!
|
||||||
// TODO: Check the semantics here.
|
/// TODO: Check the semantics here.
|
||||||
if tables.count > 1 {
|
if tables.count > 1 {
|
||||||
// TODO: Make this error message better.
|
/// TODO: Make this error message better.
|
||||||
// IDEA: Add a "compilation context" for the error message into the `CompilationContext`
|
/// IDEA: Add a "compilation context" for the error message into the `CompilationContext`
|
||||||
// that can be retrieved to make the error messages nicer.
|
// that can be retrieved to make the error messages nicer.
|
||||||
return .Error(
|
return .Error(
|
||||||
ErrorOnNode(node: node, withError: "More than one table in control declaration"))
|
ErrorOnNode(node: node, withError: "More than one table in control declaration"))
|
||||||
@@ -580,50 +540,48 @@ extension Action: Compilable {
|
|||||||
#RequireNodeType<Node, (P4DataType, CompilerContext)>(
|
#RequireNodeType<Node, (P4DataType, CompilerContext)>(
|
||||||
node: node, type: "action_declaration", nice_type_name: "Action Declaration")
|
node: node, type: "action_declaration", nice_type_name: "Action Declaration")
|
||||||
|
|
||||||
var currentChildIdx = 1
|
var walker = Walker(node: node)
|
||||||
var currentChildIdxSafe = 2
|
var current_node: Node? = .none
|
||||||
var currentChild: Node? = .none
|
|
||||||
var current_context = context
|
var current_context = context
|
||||||
|
|
||||||
// Skip action keyword
|
// Skip action keyword
|
||||||
if node.childCount < currentChildIdxSafe {
|
walker.next()
|
||||||
return .Error(
|
|
||||||
|
#MustOr(
|
||||||
|
result: current_node, thing: walker.getNext(),
|
||||||
|
or: Result<(P4Lang.Action, CompilerContext)>.Error(
|
||||||
ErrorOnNode(node: node, withError: "Missing action declaration component"))
|
ErrorOnNode(node: node, withError: "Missing action declaration component"))
|
||||||
}
|
)
|
||||||
currentChild = node.child(at: currentChildIdx)
|
|
||||||
|
|
||||||
guard
|
guard
|
||||||
case .Ok(let action_name) = Identifier.Compile(
|
case .Ok(let action_name) = Identifier.Compile(
|
||||||
node: currentChild!, withContext: current_context)
|
node: current_node!, withContext: current_context)
|
||||||
else {
|
else {
|
||||||
return Result.Error(
|
return Result.Error(
|
||||||
Error(withMessage: "Could not parse an action name from \(currentChild!.text!)"))
|
Error(withMessage: "Could not parse an action name from \(current_node!.text!)"))
|
||||||
}
|
}
|
||||||
|
|
||||||
currentChildIdx += 1
|
walker.next()
|
||||||
currentChildIdxSafe += 1
|
#MustOr(
|
||||||
if node.childCount < currentChildIdxSafe {
|
result: current_node, thing: walker.getNext(),
|
||||||
return .Error(
|
or: Result<(P4Lang.Action, CompilerContext)>.Error(
|
||||||
ErrorOnNode(node: node, withError: "Missing action declaration component"))
|
ErrorOnNode(node: node, withError: "Missing action declaration component"))
|
||||||
}
|
)
|
||||||
currentChild = node.child(at: currentChildIdx)
|
|
||||||
|
|
||||||
let maybe_action_parameters = ParameterList.Compile(
|
let maybe_action_parameters = ParameterList.Compile(
|
||||||
node: currentChild!, withContext: current_context)
|
node: current_node!, withContext: current_context)
|
||||||
guard case .Ok((let action_parameters, let updated_context)) = maybe_action_parameters
|
guard case .Ok((let action_parameters, let updated_context)) = maybe_action_parameters
|
||||||
else {
|
else {
|
||||||
return .Error(maybe_action_parameters.error()!)
|
return .Error(maybe_action_parameters.error()!)
|
||||||
}
|
}
|
||||||
current_context = updated_context
|
current_context = updated_context
|
||||||
|
|
||||||
currentChildIdx += 1
|
walker.next()
|
||||||
currentChildIdxSafe += 1
|
#MustOr(
|
||||||
if node.childCount < currentChildIdxSafe {
|
result: current_node, thing: walker.getNext(),
|
||||||
return Result.Error(
|
or: Result<(P4Lang.Action, CompilerContext)>.Error(
|
||||||
ErrorOnNode(
|
ErrorOnNode(node: node, withError: "Missing action declaration component"))
|
||||||
node: node, withError: "Missing action declaration component"))
|
)
|
||||||
}
|
|
||||||
currentChild = node.child(at: currentChildIdx)
|
|
||||||
|
|
||||||
// Add the parameters into scope.
|
// Add the parameters into scope.
|
||||||
var function_scope = context.instances.enter()
|
var function_scope = context.instances.enter()
|
||||||
@@ -633,12 +591,12 @@ extension Action: Compilable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let maybe_action_body = BlockStatement.Compile(
|
let maybe_action_body = BlockStatement.Compile(
|
||||||
node: currentChild!, withContext: context.update(newInstances: function_scope))
|
node: current_node!, withContext: context.update(newInstances: function_scope))
|
||||||
guard case .Ok((let action_body, _)) = maybe_action_body else {
|
guard case .Ok((let action_body, _)) = maybe_action_body else {
|
||||||
return .Error(maybe_action_body.error()!)
|
return .Error(maybe_action_body.error()!)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Actions cannot contain switches!
|
/// TODO: Actions cannot contain switches!
|
||||||
|
|
||||||
return .Ok(
|
return .Ok(
|
||||||
(
|
(
|
||||||
@@ -659,35 +617,35 @@ extension TableKeyEntry: Compilable {
|
|||||||
#RequireNodeType<Node, (P4DataType, CompilerContext)>(
|
#RequireNodeType<Node, (P4DataType, CompilerContext)>(
|
||||||
node: node, type: "table_key_entry", nice_type_name: "Table Key Entry")
|
node: node, type: "table_key_entry", nice_type_name: "Table Key Entry")
|
||||||
|
|
||||||
var currentChildIdx = 0
|
var walker = Walker(node: node)
|
||||||
var currentChildIdxSafe = 1
|
|
||||||
var currentChild: Node? = .none
|
var current_node: Node? = .none
|
||||||
|
|
||||||
let current_context = context
|
let current_context = context
|
||||||
|
|
||||||
if node.childCount < currentChildIdxSafe {
|
#MustOr(
|
||||||
return .Error(
|
result: current_node, thing: walker.getNext(),
|
||||||
ErrorOnNode(node: node, withError: "Missing table key entry declaration component"))
|
or: Result<(P4Lang.TableKeyEntry, CompilerContext)>.Error(
|
||||||
}
|
ErrorOnNode(
|
||||||
currentChild = node.child(at: currentChildIdx)
|
node: node, withError: "Missing table key entry declaration component")))
|
||||||
|
|
||||||
let maybe_keyset_expression = KeysetExpression.compile(
|
let maybe_keyset_expression = KeysetExpression.compile(
|
||||||
node: currentChild!, withContext: current_context)
|
node: current_node!, withContext: current_context)
|
||||||
guard case .Ok(let keyset_expression) = maybe_keyset_expression else {
|
guard case .Ok(let keyset_expression) = maybe_keyset_expression else {
|
||||||
return Result.Error(maybe_keyset_expression.error()!)
|
return Result.Error(maybe_keyset_expression.error()!)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
walker.next()
|
||||||
// Skip the ':'
|
// Skip the ':'
|
||||||
currentChildIdx += 2
|
walker.next()
|
||||||
currentChildIdxSafe += 2
|
#MustOr(
|
||||||
if node.childCount < currentChildIdxSafe {
|
result: current_node, thing: walker.getNext(),
|
||||||
return .Error(
|
or: Result<(P4Lang.TableKeyEntry, CompilerContext)>.Error(
|
||||||
ErrorOnNode(node: node, withError: "Missing table key entry declaration component"))
|
ErrorOnNode(
|
||||||
}
|
node: node, withError: "Missing table key entry declaration component")))
|
||||||
currentChild = node.child(at: currentChildIdx)
|
|
||||||
|
|
||||||
let maybe_match_type = TableKeyMatchType.Compile(
|
let maybe_match_type = TableKeyMatchType.Compile(
|
||||||
node: currentChild!, withContext: current_context)
|
node: current_node!, withContext: current_context)
|
||||||
guard case .Ok((let match_type, _)) = maybe_match_type else {
|
guard case .Ok((let match_type, _)) = maybe_match_type else {
|
||||||
return .Error(maybe_match_type.error()!)
|
return .Error(maybe_match_type.error()!)
|
||||||
}
|
}
|
||||||
@@ -719,26 +677,29 @@ extension TableKeys: Compilable {
|
|||||||
#RequireNodeType<Node, (TableKeyMatchType, CompilerContext)>(
|
#RequireNodeType<Node, (TableKeyMatchType, CompilerContext)>(
|
||||||
node: node, type: "table_keys", nice_type_name: "Table Keys")
|
node: node, type: "table_keys", nice_type_name: "Table Keys")
|
||||||
|
|
||||||
|
var walker = Walker(node: node)
|
||||||
// Skip the
|
// Skip the
|
||||||
// keys = {
|
// keys = {
|
||||||
// 0 1 2
|
// 1 2 3
|
||||||
let currentChildIdx = 3
|
walker.next() // 1
|
||||||
let currentChildIdxSafe = 4
|
walker.next() // 2
|
||||||
var currentChild: Node? = .none
|
walker.next() // 3
|
||||||
|
|
||||||
|
var current_node: Node? = .none
|
||||||
var current_context = context
|
var current_context = context
|
||||||
|
|
||||||
if node.childCount < currentChildIdxSafe {
|
#MustOr(
|
||||||
return .Error(
|
result: current_node, thing: walker.getNext(),
|
||||||
|
or: Result<(P4Lang.TableKeys, CompilerContext)>.Error(
|
||||||
ErrorOnNode(
|
ErrorOnNode(
|
||||||
node: node, withError: "Missing table keys declaration component in control declaration"))
|
node: node, withError: "Missing table keys declaration component in control declaration"))
|
||||||
}
|
)
|
||||||
currentChild = node.child(at: currentChildIdx)
|
|
||||||
|
|
||||||
var entries: [TableKeyEntry] = Array()
|
var entries: [TableKeyEntry] = Array()
|
||||||
var errors: [Error] = Array()
|
var errors: [Error] = Array()
|
||||||
|
|
||||||
currentChild!.enumerateNamedChildren { entry in
|
current_node!.enumerateNamedChildren { entry in
|
||||||
switch TableKeyEntry.Compile(node: currentChild!, withContext: current_context) {
|
switch TableKeyEntry.Compile(node: current_node!, withContext: current_context) {
|
||||||
case .Ok((let keyset_expression, let updated_context)):
|
case .Ok((let keyset_expression, let updated_context)):
|
||||||
entries.append(keyset_expression)
|
entries.append(keyset_expression)
|
||||||
current_context = updated_context
|
current_context = updated_context
|
||||||
@@ -823,37 +784,38 @@ extension Table: Compilable {
|
|||||||
#RequireNodeType<Node, (P4DataType, CompilerContext)>(
|
#RequireNodeType<Node, (P4DataType, CompilerContext)>(
|
||||||
node: table_declaration_node, type: "table_declaration", nice_type_name: "Table Declaration")
|
node: table_declaration_node, type: "table_declaration", nice_type_name: "Table Declaration")
|
||||||
|
|
||||||
var currentChildIdx = 1
|
var walker = Walker(node: table_declaration_node)
|
||||||
var currentChildIdxSafe = 2
|
|
||||||
var currentChild: Node? = .none
|
var current_node: Node? = .none
|
||||||
|
|
||||||
let current_context = context
|
let current_context = context
|
||||||
|
|
||||||
if table_declaration_node.childCount < currentChildIdxSafe {
|
walker.next() // Skip the XXX?
|
||||||
return .Error(
|
#MustOr(
|
||||||
ErrorOnNode(node: table_declaration_node, withError: "Missing table declaration component"))
|
result: current_node, thing: walker.getNext(),
|
||||||
}
|
or: Result<(P4Lang.Table, CompilerContext)>.Error(
|
||||||
currentChild = table_declaration_node.child(at: currentChildIdx)
|
ErrorOnNode(
|
||||||
|
node: node, withError: "Missing table declaration component")))
|
||||||
|
|
||||||
guard
|
guard
|
||||||
case .Ok(let table_name) = Identifier.Compile(
|
case .Ok(let table_name) = Identifier.Compile(
|
||||||
node: currentChild!, withContext: current_context)
|
node: current_node!, withContext: current_context)
|
||||||
else {
|
else {
|
||||||
return Result.Error(
|
return Result.Error(
|
||||||
Error(withMessage: "Could not parse a table name from \(currentChild!.text!)"))
|
Error(withMessage: "Could not parse a table name from \(current_node!.text!)"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
walker.next()
|
||||||
// Skip the '{'
|
// Skip the '{'
|
||||||
currentChildIdx += 2
|
walker.next()
|
||||||
currentChildIdxSafe += 2
|
#MustOr(
|
||||||
if table_declaration_node.childCount < currentChildIdxSafe {
|
result: current_node, thing: walker.getNext(),
|
||||||
return .Error(
|
or: Result<(P4Lang.Table, CompilerContext)>.Error(
|
||||||
ErrorOnNode(node: table_declaration_node, withError: "Missing table declaration component"))
|
ErrorOnNode(
|
||||||
}
|
node: node, withError: "Missing table declaration component")))
|
||||||
currentChild = table_declaration_node.child(at: currentChildIdx)
|
|
||||||
|
|
||||||
let maybe_table_property_list = TablePropertyList.Compile(
|
let maybe_table_property_list = TablePropertyList.Compile(
|
||||||
node: currentChild!, withContext: current_context)
|
node: current_node!, withContext: current_context)
|
||||||
guard case .Ok((let table_property_list, _)) = maybe_table_property_list else {
|
guard case .Ok((let table_property_list, _)) = maybe_table_property_list else {
|
||||||
return Result.Error(maybe_table_property_list.error()!)
|
return Result.Error(maybe_table_property_list.error()!)
|
||||||
}
|
}
|
||||||
|
|||||||
+105
-125
@@ -39,7 +39,7 @@ extension TypedIdentifier: CompilableExpression {
|
|||||||
) -> Result<EvaluatableExpression?> {
|
) -> Result<EvaluatableExpression?> {
|
||||||
|
|
||||||
let node = node.child(at: 0)!
|
let node = node.child(at: 0)!
|
||||||
#SkipUnlessNodeType<SwiftTreeSitter.Node, EvaluatableExpression?>(
|
#SkipUnlessNodeType<SwiftTreeSitter.Node>(
|
||||||
node: node, type: "identifier")
|
node: node, type: "identifier")
|
||||||
|
|
||||||
guard
|
guard
|
||||||
@@ -59,7 +59,7 @@ extension TypedIdentifier: CompilableLValueExpression {
|
|||||||
) -> Result<EvaluatableLValueExpression?> {
|
) -> Result<EvaluatableLValueExpression?> {
|
||||||
|
|
||||||
let expression = node.child(at: 0)!
|
let expression = node.child(at: 0)!
|
||||||
#SkipUnlessNodeType<SwiftTreeSitter.Node, EvaluatableExpression?>(
|
#SkipUnlessNodeType<SwiftTreeSitter.Node>(
|
||||||
node: expression, type: "identifier")
|
node: expression, type: "identifier")
|
||||||
|
|
||||||
let maybe_parsed_expression = TypedIdentifier.compile(node: node, withContext: context)
|
let maybe_parsed_expression = TypedIdentifier.compile(node: node, withContext: context)
|
||||||
@@ -78,7 +78,7 @@ extension P4BooleanValue: CompilableExpression {
|
|||||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Result<EvaluatableExpression?> {
|
) -> Result<EvaluatableExpression?> {
|
||||||
let node = node.child(at: 0)!
|
let node = node.child(at: 0)!
|
||||||
#SkipUnlessNodeType<SwiftTreeSitter.Node, EvaluatableExpression?>(
|
#SkipUnlessNodeType<SwiftTreeSitter.Node>(
|
||||||
node: node, type: "booleanLiteralExpression")
|
node: node, type: "booleanLiteralExpression")
|
||||||
|
|
||||||
if node.text == "false" {
|
if node.text == "false" {
|
||||||
@@ -97,7 +97,7 @@ extension P4IntValue: CompilableExpression {
|
|||||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Result<EvaluatableExpression?> {
|
) -> Result<EvaluatableExpression?> {
|
||||||
let node = node.child(at: 0)!
|
let node = node.child(at: 0)!
|
||||||
#SkipUnlessNodeType<SwiftTreeSitter.Node, EvaluatableExpression?>(node: node, type: "integer")
|
#SkipUnlessNodeType<SwiftTreeSitter.Node>(node: node, type: "integer")
|
||||||
if let parsed_int = Int(node.text!) {
|
if let parsed_int = Int(node.text!) {
|
||||||
return .Ok(P4Value(P4IntValue(withValue: parsed_int)))
|
return .Ok(P4Value(P4IntValue(withValue: parsed_int)))
|
||||||
} else {
|
} else {
|
||||||
@@ -111,7 +111,7 @@ extension P4StringValue: CompilableExpression {
|
|||||||
node: SwiftTreeSitter.Node, withContext scopes: CompilerContext
|
node: SwiftTreeSitter.Node, withContext scopes: CompilerContext
|
||||||
) -> Result<EvaluatableExpression?> {
|
) -> Result<EvaluatableExpression?> {
|
||||||
let node = node.child(at: 0)!
|
let node = node.child(at: 0)!
|
||||||
#SkipUnlessNodeType<SwiftTreeSitter.Node, EvaluatableExpression?>(
|
#SkipUnlessNodeType<SwiftTreeSitter.Node>(
|
||||||
node: node, type: "string_literal")
|
node: node, type: "string_literal")
|
||||||
return .Ok(P4Value(P4StringValue(withValue: node.text!)))
|
return .Ok(P4Value(P4StringValue(withValue: node.text!)))
|
||||||
}
|
}
|
||||||
@@ -339,20 +339,18 @@ extension BinaryOperatorExpression: CompilableExpression {
|
|||||||
) -> Result<(EvaluatableExpression)?> {
|
) -> Result<(EvaluatableExpression)?> {
|
||||||
let expression = node.child(at: 0)!
|
let expression = node.child(at: 0)!
|
||||||
|
|
||||||
#SkipUnlessNodeType<Node, EvaluatableExpression?>(
|
#SkipUnlessNodeType<Node>(
|
||||||
node: expression, type: "binaryOperatorExpression")
|
node: expression, type: "binaryOperatorExpression")
|
||||||
|
|
||||||
var currentChildIdx = 0
|
let binary_operator_expression_node = expression.child(at: 0)!
|
||||||
var currentChildIdxSafe = 1
|
var walker = Walker(node: binary_operator_expression_node)
|
||||||
var currentChild: Node? = .none
|
|
||||||
|
|
||||||
if expression.childCount < currentChildIdxSafe {
|
var current_node: Node? = .none
|
||||||
return Result.Error(
|
#MustOr(
|
||||||
ErrorOnNode(node: node, withError: "Malformed binary operator expression"))
|
result: current_node, thing: walker.getNext(),
|
||||||
}
|
or: Result<EvaluatableExpression?>.Error(
|
||||||
currentChild = expression.child(at: currentChildIdx)
|
ErrorOnNode(
|
||||||
|
node: node, withError: "Malformed binary operator expression")))
|
||||||
let binary_operator_expression_node = currentChild!
|
|
||||||
|
|
||||||
// TODO: This macro cannot handle new lines in the arrays
|
// TODO: This macro cannot handle new lines in the arrays
|
||||||
// swift-format-ignore
|
// swift-format-ignore
|
||||||
@@ -360,32 +358,29 @@ extension BinaryOperatorExpression: CompilableExpression {
|
|||||||
nodes: binary_operator_expression_node,
|
nodes: binary_operator_expression_node,
|
||||||
type: ["binaryEqualOperatorExpression", "binaryLessThanOperatorExpression", "binaryLessThanEqualOperatorExpression", "binaryGreaterThanOperatorExpression", "binaryGreaterThanEqualOperatorExpression", "binaryAndOperatorExpression", "binaryOrOperatorExpression", "binaryAddOperatorExpression", "binarySubtractOperatorExpression", "binaryMultiplyOperatorExpression", "binaryDivideOperatorExpression"],
|
type: ["binaryEqualOperatorExpression", "binaryLessThanOperatorExpression", "binaryLessThanEqualOperatorExpression", "binaryGreaterThanOperatorExpression", "binaryGreaterThanEqualOperatorExpression", "binaryAndOperatorExpression", "binaryOrOperatorExpression", "binaryAddOperatorExpression", "binarySubtractOperatorExpression", "binaryMultiplyOperatorExpression", "binaryDivideOperatorExpression"],
|
||||||
nice_type_names: [ "binary equal operator", "binary less than operator", "binary less than or equal to operator", "binary greater than operator", "binary greater than or equal to operator", "binary and operator", "binary or operator", "binary add operator", "binary subtract operator", "binary multiply operator", "binary divide operator"])
|
nice_type_names: [ "binary equal operator", "binary less than operator", "binary less than or equal to operator", "binary greater than operator", "binary greater than or equal to operator", "binary and operator", "binary or operator", "binary add operator", "binary subtract operator", "binary multiply operator", "binary divide operator"])
|
||||||
|
#MustOr(
|
||||||
|
result: current_node, thing: walker.getNext(),
|
||||||
|
or: Result<EvaluatableExpression?>.Error(
|
||||||
|
ErrorOnNode(
|
||||||
|
node: node, withError: "Missing LHS for binary operator expression")))
|
||||||
|
|
||||||
if binary_operator_expression_node.childCount < currentChildIdxSafe {
|
let left_hand_side_raw = current_node!
|
||||||
return Result.Error(
|
|
||||||
ErrorOnNode(node: node, withError: "Missing LHS for binary operator expression"))
|
|
||||||
}
|
|
||||||
currentChild = binary_operator_expression_node.child(at: currentChildIdx)
|
|
||||||
let left_hand_side_raw = currentChild!
|
|
||||||
|
|
||||||
currentChildIdx = currentChildIdx + 1
|
walker.next()
|
||||||
currentChildIdxSafe = currentChildIdxSafe + 1
|
#MustOr(
|
||||||
if binary_operator_expression_node.childCount < currentChildIdxSafe {
|
result: current_node, thing: walker.getNext(),
|
||||||
return Result.Error(
|
or: Result<EvaluatableExpression?>.Error(
|
||||||
ErrorOnNode(node: node, withError: "Missing binary operator for binary operator expression")
|
ErrorOnNode(
|
||||||
)
|
node: node, withError: "Missing binary operator for binary operator expression")))
|
||||||
}
|
|
||||||
currentChild = binary_operator_expression_node.child(at: currentChildIdx)
|
|
||||||
|
|
||||||
currentChildIdx = currentChildIdx + 1
|
walker.next()
|
||||||
currentChildIdxSafe = currentChildIdxSafe + 1
|
#MustOr(
|
||||||
if binary_operator_expression_node.childCount < currentChildIdxSafe {
|
result: current_node, thing: walker.getNext(),
|
||||||
return Result.Error(
|
or: Result<EvaluatableExpression?>.Error(
|
||||||
ErrorOnNode(node: node, withError: "Missing binary operator for binary operator expression")
|
ErrorOnNode(
|
||||||
)
|
node: node, withError: "Missing RHS for binary operator expression")))
|
||||||
}
|
|
||||||
currentChild = binary_operator_expression_node.child(at: currentChildIdx)
|
let right_hand_side_raw = current_node!
|
||||||
let right_hand_side_raw = currentChild!
|
|
||||||
|
|
||||||
let maybe_left_hand_side = Expression.Compile(node: left_hand_side_raw, withContext: context)
|
let maybe_left_hand_side = Expression.Compile(node: left_hand_side_raw, withContext: context)
|
||||||
guard case Result.Ok(let left_hand_side) = maybe_left_hand_side else {
|
guard case Result.Ok(let left_hand_side) = maybe_left_hand_side else {
|
||||||
@@ -465,54 +460,48 @@ extension BinaryOperatorExpression: CompilableExpression {
|
|||||||
extension ArrayAccessExpression: CompilableExpression {
|
extension ArrayAccessExpression: CompilableExpression {
|
||||||
static func compile(
|
static func compile(
|
||||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Common.Result<(any Common.EvaluatableExpression)?> {
|
) -> Common.Result<EvaluatableExpression?> {
|
||||||
let expression = node.child(at: 0)!
|
let expression = node.child(at: 0)!
|
||||||
|
|
||||||
#SkipUnlessNodeType<Node, EvaluatableExpression?>(
|
#SkipUnlessNodeType<Node>(
|
||||||
node: expression, type: "arrayAccessExpression")
|
node: expression, type: "arrayAccessExpression")
|
||||||
|
|
||||||
let array_access_expression_node = expression
|
let array_access_expression_node = expression
|
||||||
|
|
||||||
var currentChildIdx = 0
|
var walker = Walker(node: array_access_expression_node)
|
||||||
var currentChildIdxSafe = 1
|
var current_node: Node? = .none
|
||||||
var currentChild: Node? = .none
|
|
||||||
|
|
||||||
// What is the "name" of the array?
|
#MustOr(
|
||||||
if array_access_expression_node.childCount < currentChildIdxSafe {
|
result: current_node, thing: walker.getNext(),
|
||||||
return Result.Error(
|
or: Result<EvaluatableExpression?>.Error(
|
||||||
ErrorOnNode(node: node, withError: "Malformed array access expression"))
|
ErrorOnNode(
|
||||||
}
|
node: node, withError: "Malformed array access expression")))
|
||||||
currentChild = expression.child(at: currentChildIdx)
|
|
||||||
|
|
||||||
#RequireNodeType<Node, EvaluatableExpression?>(
|
#RequireNodeType<Node, EvaluatableExpression?>(
|
||||||
node: currentChild!, type: "expression",
|
node: current_node!, type: "expression",
|
||||||
nice_type_name: "array identifier expression")
|
nice_type_name: "array identifier expression")
|
||||||
let array_access_identifier_node = currentChild!
|
let array_access_identifier_node = current_node!
|
||||||
|
|
||||||
// Check for the [
|
walker.next()
|
||||||
currentChildIdx = currentChildIdx + 1
|
#MustOr(
|
||||||
currentChildIdxSafe = currentChildIdxSafe + 1
|
result: current_node, thing: walker.getNext(),
|
||||||
if array_access_expression_node.childCount < currentChildIdxSafe {
|
or: Result<EvaluatableExpression?>.Error(
|
||||||
return Result.Error(
|
ErrorOnNode(
|
||||||
ErrorOnNode(node: node, withError: "Missing [ for array access expression")
|
node: node, withError: "Missing [ for array access expression")))
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// What is the indexor of the array?
|
walker.next()
|
||||||
currentChildIdx = currentChildIdx + 1
|
|
||||||
currentChildIdxSafe = currentChildIdxSafe + 1
|
#MustOr(
|
||||||
if array_access_expression_node.childCount < currentChildIdxSafe {
|
result: current_node, thing: walker.getNext(),
|
||||||
return Result.Error(
|
or: Result<EvaluatableExpression?>.Error(
|
||||||
ErrorOnNode(node: node, withError: "Missing indexor expression for array access expression")
|
ErrorOnNode(
|
||||||
)
|
node: node, withError: "Missing indexor expression for array access expression")))
|
||||||
}
|
|
||||||
currentChild = array_access_expression_node.child(at: currentChildIdx)
|
|
||||||
|
|
||||||
#RequireNodeType<Node, EvaluatableExpression?>(
|
#RequireNodeType<Node, EvaluatableExpression?>(
|
||||||
node: currentChild!, type: "expression",
|
node: current_node!, type: "expression",
|
||||||
nice_type_name: "array indexor expression")
|
nice_type_name: "array indexor expression")
|
||||||
|
|
||||||
let array_access_indexor_node = currentChild!
|
let array_access_indexor_node = current_node!
|
||||||
|
|
||||||
let maybe_array_identifier = Expression.Compile(
|
let maybe_array_identifier = Expression.Compile(
|
||||||
node: array_access_identifier_node, withContext: context)
|
node: array_access_identifier_node, withContext: context)
|
||||||
@@ -547,51 +536,44 @@ extension FieldAccessExpression: CompilableExpression {
|
|||||||
) -> Common.Result<(any Common.EvaluatableExpression)?> {
|
) -> Common.Result<(any Common.EvaluatableExpression)?> {
|
||||||
let expression = node.child(at: 0)!
|
let expression = node.child(at: 0)!
|
||||||
|
|
||||||
#SkipUnlessNodeType<Node, EvaluatableExpression?>(
|
#SkipUnlessNodeType<Node>(
|
||||||
node: expression, type: "fieldAccessExpression")
|
node: expression, type: "fieldAccessExpression")
|
||||||
|
|
||||||
let field_access_expression_node = expression
|
let field_access_expression_node = expression
|
||||||
|
|
||||||
var currentChildIdx = 0
|
var walker = Walker(node: field_access_expression_node)
|
||||||
var currentChildIdxSafe = 1
|
var current_node: Node? = .none
|
||||||
var currentChild: Node? = .none
|
|
||||||
|
|
||||||
// What is the "name" of the struct?
|
#MustOr(
|
||||||
if field_access_expression_node.childCount < currentChildIdxSafe {
|
result: current_node, thing: walker.getNext(),
|
||||||
return Result.Error(
|
or: Result<EvaluatableExpression?>.Error(
|
||||||
ErrorOnNode(node: node, withError: "Malformed field access expression"))
|
ErrorOnNode(
|
||||||
}
|
node: node, withError: "Malformed field access expression")))
|
||||||
currentChild = expression.child(at: currentChildIdx)
|
|
||||||
|
|
||||||
#RequireNodeType<Node, EvaluatableExpression?>(
|
#RequireNodeType<Node, EvaluatableExpression?>(
|
||||||
node: currentChild!, type: "expression",
|
node: current_node!, type: "expression",
|
||||||
nice_type_name: "struct identifier expression")
|
nice_type_name: "struct identifier expression")
|
||||||
let struct_identifier_node = currentChild!
|
let struct_identifier_node = current_node!
|
||||||
|
|
||||||
// Check for the .
|
walker.next()
|
||||||
currentChildIdx = currentChildIdx + 1
|
#MustOr(
|
||||||
currentChildIdxSafe = currentChildIdxSafe + 1
|
result: current_node, thing: walker.getNext(),
|
||||||
if field_access_expression_node.childCount < currentChildIdxSafe {
|
or: Result<EvaluatableExpression?>.Error(
|
||||||
return Result.Error(
|
ErrorOnNode(
|
||||||
ErrorOnNode(node: node, withError: "Missing . for field access expression")
|
node: node, withError: "Missing . for field access expression")))
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// What is the field of the struct?
|
walker.next()
|
||||||
currentChildIdx = currentChildIdx + 1
|
#MustOr(
|
||||||
currentChildIdxSafe = currentChildIdxSafe + 1
|
result: current_node, thing: walker.getNext(),
|
||||||
if field_access_expression_node.childCount < currentChildIdxSafe {
|
or: Result<EvaluatableExpression?>.Error(
|
||||||
return Result.Error(
|
ErrorOnNode(
|
||||||
ErrorOnNode(node: node, withError: "Missing field name for field access expression")
|
node: node, withError: "Missing field name for field access expression")))
|
||||||
)
|
|
||||||
}
|
|
||||||
currentChild = field_access_expression_node.child(at: currentChildIdx)
|
|
||||||
|
|
||||||
#RequireNodeType<Node, EvaluatableExpression?>(
|
#RequireNodeType<Node, EvaluatableExpression?>(
|
||||||
node: currentChild!, type: "identifier",
|
node: current_node!, type: "identifier",
|
||||||
nice_type_name: "field name")
|
nice_type_name: "field name")
|
||||||
|
|
||||||
let field_name_node = currentChild!
|
let field_name_node = current_node!
|
||||||
|
|
||||||
// Make sure that the identifier really identifies a struct.
|
// Make sure that the identifier really identifies a struct.
|
||||||
let maybe_struct_identifier = Expression.Compile(
|
let maybe_struct_identifier = Expression.Compile(
|
||||||
@@ -633,7 +615,7 @@ extension FieldAccessExpression: CompilableLValueExpression {
|
|||||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Result<EvaluatableLValueExpression?> {
|
) -> Result<EvaluatableLValueExpression?> {
|
||||||
let expression = node.child(at: 0)!
|
let expression = node.child(at: 0)!
|
||||||
#SkipUnlessNodeType<Node, EvaluatableExpression?>(
|
#SkipUnlessNodeType<Node>(
|
||||||
node: expression, type: "fieldAccessExpression")
|
node: expression, type: "fieldAccessExpression")
|
||||||
|
|
||||||
let maybe_parsed_expression = FieldAccessExpression.compile(node: node, withContext: context)
|
let maybe_parsed_expression = FieldAccessExpression.compile(node: node, withContext: context)
|
||||||
@@ -652,7 +634,7 @@ extension ArrayAccessExpression: CompilableLValueExpression {
|
|||||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Result<EvaluatableLValueExpression?> {
|
) -> Result<EvaluatableLValueExpression?> {
|
||||||
let expression = node.child(at: 0)!
|
let expression = node.child(at: 0)!
|
||||||
#SkipUnlessNodeType<Node, EvaluatableExpression?>(
|
#SkipUnlessNodeType<Node>(
|
||||||
node: expression, type: "arrayAccessExpression")
|
node: expression, type: "arrayAccessExpression")
|
||||||
|
|
||||||
let maybe_parsed_expression = ArrayAccessExpression.compile(node: node, withContext: context)
|
let maybe_parsed_expression = ArrayAccessExpression.compile(node: node, withContext: context)
|
||||||
@@ -672,22 +654,20 @@ extension FunctionCall: CompilableExpression {
|
|||||||
) -> Result<EvaluatableExpression?> {
|
) -> Result<EvaluatableExpression?> {
|
||||||
|
|
||||||
let expression = node.child(at: 0)!
|
let expression = node.child(at: 0)!
|
||||||
#SkipUnlessNodeType<Node, EvaluatableExpression?>(
|
#SkipUnlessNodeType<Node>(
|
||||||
node: expression, type: "function_call")
|
node: expression, type: "function_call")
|
||||||
|
|
||||||
var currentChildIdx = 0
|
var walker = Walker(node: expression)
|
||||||
var currentChildIdxSafe = 1
|
var current_node: Node? = .none
|
||||||
var currentChild: Node? = .none
|
|
||||||
|
|
||||||
if expression.childCount < currentChildIdxSafe {
|
#MustOr(
|
||||||
return Result.Error(
|
result: current_node, thing: walker.getNext(),
|
||||||
ErrorOnNode(node: node, withError: "Missing function call component"))
|
or: Result<EvaluatableExpression?>.Error(
|
||||||
}
|
ErrorOnNode(
|
||||||
|
node: node, withError: "Missing function call component")))
|
||||||
currentChild = expression.child(at: currentChildIdx)
|
|
||||||
|
|
||||||
let maybe_callee_name = Identifier.Compile(
|
let maybe_callee_name = Identifier.Compile(
|
||||||
node: currentChild!, withContext: context)
|
node: current_node!, withContext: context)
|
||||||
guard case .Ok(let callee_name) = maybe_callee_name else {
|
guard case .Ok(let callee_name) = maybe_callee_name else {
|
||||||
return Result.Error(maybe_callee_name.error()!)
|
return Result.Error(maybe_callee_name.error()!)
|
||||||
}
|
}
|
||||||
@@ -700,7 +680,7 @@ extension FunctionCall: CompilableExpression {
|
|||||||
Result<(FunctionDeclaration?, Declaration?)>.Ok((callee, .none)) // What we found is actually a function declaration
|
Result<(FunctionDeclaration?, Declaration?)>.Ok((callee, .none)) // What we found is actually a function declaration
|
||||||
default:
|
default:
|
||||||
Result<(FunctionDeclaration?, Declaration?)>.Error(
|
Result<(FunctionDeclaration?, Declaration?)>.Error(
|
||||||
ErrorOnNode(node: currentChild!, withError: "\(callee_name) is not a function"))
|
ErrorOnNode(node: current_node!, withError: "\(callee_name) is not a function"))
|
||||||
}
|
}
|
||||||
case .Error(let e): Result<(FunctionDeclaration?, Declaration?)>.Error(e)
|
case .Error(let e): Result<(FunctionDeclaration?, Declaration?)>.Error(e)
|
||||||
}
|
}
|
||||||
@@ -713,7 +693,7 @@ extension FunctionCall: CompilableExpression {
|
|||||||
switch callee.identifier.type.dataType() {
|
switch callee.identifier.type.dataType() {
|
||||||
case is FunctionDeclaration: Result.Ok((.none, callee))
|
case is FunctionDeclaration: Result.Ok((.none, callee))
|
||||||
default:
|
default:
|
||||||
.Error(ErrorOnNode(node: currentChild!, withError: "\(callee_name) is not a function"))
|
.Error(ErrorOnNode(node: current_node!, withError: "\(callee_name) is not a function"))
|
||||||
}
|
}
|
||||||
default: .Error(e)
|
default: .Error(e)
|
||||||
}
|
}
|
||||||
@@ -725,15 +705,15 @@ extension FunctionCall: CompilableExpression {
|
|||||||
return .Error(maybe_callee.error()!)
|
return .Error(maybe_callee.error()!)
|
||||||
}
|
}
|
||||||
|
|
||||||
currentChildIdx += 1
|
walker.next()
|
||||||
currentChildIdxSafe += 1
|
|
||||||
if expression.childCount < currentChildIdxSafe {
|
|
||||||
return Result.Error(
|
|
||||||
ErrorOnNode(node: node, withError: "Missing function call component"))
|
|
||||||
}
|
|
||||||
currentChild = expression.child(at: currentChildIdx)
|
|
||||||
|
|
||||||
let maybe_argument_list = ArgumentList.Compile(node: currentChild!, withContext: context)
|
#MustOr(
|
||||||
|
result: current_node, thing: walker.getNext(),
|
||||||
|
or: Result<EvaluatableExpression?>.Error(
|
||||||
|
ErrorOnNode(
|
||||||
|
node: node, 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()!)
|
return .Error(maybe_argument_list.error()!)
|
||||||
|
|||||||
@@ -179,11 +179,9 @@ public struct Parser {
|
|||||||
static func Compile(
|
static func Compile(
|
||||||
node: Node, withContext context: CompilerContext
|
node: Node, withContext context: CompilerContext
|
||||||
) -> Result<(InstantiatedParserState, CompilerContext)> {
|
) -> Result<(InstantiatedParserState, CompilerContext)> {
|
||||||
|
var walker = Walker(node: node)
|
||||||
|
|
||||||
var currentChildIdx = 0
|
var current_node: Node? = .none
|
||||||
var currentChildIdxSafe = 1
|
|
||||||
|
|
||||||
var currentChild: Node? = .none
|
|
||||||
|
|
||||||
guard let node_type = node.nodeType,
|
guard let node_type = node.nodeType,
|
||||||
node_type == "parserState"
|
node_type == "parserState"
|
||||||
@@ -192,50 +190,50 @@ public struct Parser {
|
|||||||
ErrorOnNode(node: node, withError: "Did not find a parser state declaration"))
|
ErrorOnNode(node: node, withError: "Did not find a parser state declaration"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if node.childCount < currentChildIdxSafe {
|
#MustOr(
|
||||||
return Result.Error(
|
result: current_node, thing: walker.getNext(),
|
||||||
ErrorOnNode(node: node, withError: "Missing elements in parser state declaration"))
|
or: Result<(InstantiatedParserState, CompilerContext)>.Error(
|
||||||
}
|
ErrorOnNode(
|
||||||
|
node: node, withError: "Missing elements in parser state declaration")))
|
||||||
|
|
||||||
currentChild = node.child(at: currentChildIdx)
|
if current_node!.nodeType == "annotations" {
|
||||||
if currentChild!.nodeType == "annotations" {
|
|
||||||
return Result.Error(
|
return Result.Error(
|
||||||
ErrorOnNode(
|
ErrorOnNode(
|
||||||
node: currentChild!, withError: "Annotations in parser state are not yet handled."))
|
node: current_node!, withError: "Annotations in parser state are not yet handled."))
|
||||||
|
|
||||||
// Would increment here.
|
// Would increment here.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip the keyword state
|
// Skip the keyword state
|
||||||
currentChildIdx += 1
|
walker.next()
|
||||||
currentChildIdxSafe += 1
|
#MustOr(
|
||||||
if node.childCount < currentChildIdxSafe {
|
result: current_node, thing: walker.getNext(),
|
||||||
return Result.Error(
|
or: Result<(InstantiatedParserState, CompilerContext)>.Error(
|
||||||
ErrorOnNode(node: node, withError: "Missing elements in parser state declaration"))
|
ErrorOnNode(
|
||||||
}
|
node: node, withError: "Missing elements in parser state declaration")))
|
||||||
|
|
||||||
currentChild = node.child(at: currentChildIdx)
|
|
||||||
let maybe_state_identifier = Identifier.Compile(
|
let maybe_state_identifier = Identifier.Compile(
|
||||||
node: currentChild!, withContext: context)
|
node: current_node!, withContext: context)
|
||||||
guard case Result.Ok(let state_identifier) = maybe_state_identifier else {
|
guard case Result.Ok(let state_identifier) = maybe_state_identifier else {
|
||||||
return Result.Error(maybe_state_identifier.error()!)
|
return Result.Error(maybe_state_identifier.error()!)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
walker.next()
|
||||||
// Skip the '{'
|
// Skip the '{'
|
||||||
currentChildIdx += 2
|
walker.next()
|
||||||
currentChildIdxSafe += 2
|
#MustOr(
|
||||||
|
result: current_node, thing: walker.getNext(),
|
||||||
|
or: Result<(InstantiatedParserState, CompilerContext)>.Error(
|
||||||
|
ErrorOnNode(
|
||||||
|
node: node, withError: "Missing body of state declaration")))
|
||||||
|
|
||||||
var parse_errs: [Error] = Array()
|
var parse_errs: [Error] = Array()
|
||||||
var current_context = context
|
var current_context = context
|
||||||
var parsed_s: [EvaluatableStatement] = Array()
|
var parsed_s: [EvaluatableStatement] = Array()
|
||||||
|
|
||||||
if node.childCount < currentChildIdxSafe {
|
if current_node!.nodeType == "parserStatements" {
|
||||||
return Result.Error(ErrorOnNode(node: node, withError: "Missing body of state declaration"))
|
|
||||||
}
|
|
||||||
currentChild = node.child(at: currentChildIdx)
|
|
||||||
if currentChild!.nodeType == "parserStatements" {
|
|
||||||
switch Statements.Compile(
|
switch Statements.Compile(
|
||||||
node: currentChild!, withContext: current_context)
|
node: current_node!, withContext: current_context)
|
||||||
{
|
{
|
||||||
case .Ok(let (state_statements, updated_context)):
|
case .Ok(let (state_statements, updated_context)):
|
||||||
parsed_s = state_statements
|
parsed_s = state_statements
|
||||||
@@ -243,8 +241,7 @@ public struct Parser {
|
|||||||
case .Error(let error):
|
case .Error(let error):
|
||||||
parse_errs.append(error)
|
parse_errs.append(error)
|
||||||
}
|
}
|
||||||
currentChildIdx += 1
|
walker.next()
|
||||||
currentChildIdxSafe += 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !parse_errs.isEmpty {
|
if !parse_errs.isEmpty {
|
||||||
@@ -255,13 +252,14 @@ public struct Parser {
|
|||||||
}.joined(separator: ";")))
|
}.joined(separator: ";")))
|
||||||
}
|
}
|
||||||
|
|
||||||
if node.childCount < currentChildIdxSafe {
|
#MustOr(
|
||||||
return Result.Error(
|
result: current_node, thing: walker.getNext(),
|
||||||
ErrorOnNode(node: node, withError: "Missing transition statement of state declaration"))
|
or: Result<(InstantiatedParserState, CompilerContext)>.Error(
|
||||||
}
|
ErrorOnNode(
|
||||||
currentChild = node.child(at: currentChildIdx)
|
node: node, withError: "Missing transition statement of state declaration")))
|
||||||
|
|
||||||
return TransitionStatement.Compile(
|
return TransitionStatement.Compile(
|
||||||
node: currentChild!, forState: state_identifier, withStatements: parsed_s,
|
node: current_node!, forState: state_identifier, withStatements: parsed_s,
|
||||||
withContext: current_context)
|
withContext: current_context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,34 +29,32 @@ extension BlockStatement: CompilableStatement {
|
|||||||
#RequireNodeType<Node, (EvaluatableStatement, CompilerContext)>(
|
#RequireNodeType<Node, (EvaluatableStatement, CompilerContext)>(
|
||||||
node: node, type: "blockStatement", nice_type_name: "block statement")
|
node: node, type: "blockStatement", nice_type_name: "block statement")
|
||||||
|
|
||||||
var currentChildIdx = 0
|
var walker = Walker(node: node)
|
||||||
var currentChildIdxSafe = 1
|
var current_node: Node? = .none
|
||||||
var currentChild: Node? = .none
|
|
||||||
|
|
||||||
if node.childCount < currentChildIdxSafe {
|
#MustOr(
|
||||||
|
result: current_node, thing: walker.getNext(),
|
||||||
|
or: Result<(EvaluatableStatement, CompilerContext)>.Error(
|
||||||
|
ErrorOnNode(node: node, withError: "Malformed block statement")))
|
||||||
|
|
||||||
|
if current_node!.nodeType != "{" {
|
||||||
return Result.Error(
|
return Result.Error(
|
||||||
ErrorOnNode(node: node, withError: "Malformed block statement"))
|
ErrorOnNode(node: current_node!, withError: "Missing { on block statement"))
|
||||||
}
|
}
|
||||||
currentChild = node.child(at: currentChildIdx)
|
|
||||||
if currentChild!.nodeType != "{" {
|
|
||||||
return Result.Error(
|
|
||||||
ErrorOnNode(node: currentChild!, withError: "Missing { on block statement"))
|
|
||||||
}
|
|
||||||
currentChildIdx += 1
|
|
||||||
currentChildIdxSafe += 1
|
|
||||||
|
|
||||||
var statements: [EvaluatableStatement] = Array()
|
var statements: [EvaluatableStatement] = Array()
|
||||||
var parse_err: Error? = .none
|
var parse_err: Error? = .none
|
||||||
var current_context = context
|
var current_context = context
|
||||||
|
|
||||||
if node.childCount < currentChildIdxSafe {
|
walker.next()
|
||||||
return Result.Error(
|
#MustOr(
|
||||||
ErrorOnNode(node: node, withError: "Malformed block statement"))
|
result: current_node, thing: walker.getNext(),
|
||||||
}
|
or: Result<(EvaluatableStatement, CompilerContext)>.Error(
|
||||||
currentChild = node.child(at: currentChildIdx)
|
ErrorOnNode(node: node, withError: "Malformed block statement")))
|
||||||
if currentChild!.nodeType == "statements" {
|
|
||||||
|
if current_node!.nodeType == "statements" {
|
||||||
switch Parser.Statements.Compile(
|
switch Parser.Statements.Compile(
|
||||||
node: currentChild!, withContext: current_context)
|
node: current_node!, withContext: current_context)
|
||||||
{
|
{
|
||||||
case .Ok(let (parsed_statements, updated_context)):
|
case .Ok(let (parsed_statements, updated_context)):
|
||||||
current_context = updated_context
|
current_context = updated_context
|
||||||
@@ -65,22 +63,21 @@ extension BlockStatement: CompilableStatement {
|
|||||||
parse_err = error
|
parse_err = error
|
||||||
}
|
}
|
||||||
|
|
||||||
currentChildIdx += 1
|
walker.next()
|
||||||
currentChildIdxSafe += 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let err = parse_err {
|
if let err = parse_err {
|
||||||
return .Error(err)
|
return .Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if node.childCount < currentChildIdxSafe {
|
#MustOr(
|
||||||
|
result: current_node, thing: walker.getNext(),
|
||||||
|
or: Result<(EvaluatableStatement, CompilerContext)>.Error(
|
||||||
|
ErrorOnNode(node: node, withError: "Malformed block statement")))
|
||||||
|
|
||||||
|
if current_node!.nodeType != "}" {
|
||||||
return Result.Error(
|
return Result.Error(
|
||||||
ErrorOnNode(node: node, withError: "Malformed block statement"))
|
ErrorOnNode(node: current_node!, withError: "Missing } on block statement"))
|
||||||
}
|
|
||||||
currentChild = node.child(at: currentChildIdx)
|
|
||||||
if currentChild!.nodeType != "}" {
|
|
||||||
return Result.Error(
|
|
||||||
ErrorOnNode(node: currentChild!, withError: "Missing } on block statement"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return .Ok((BlockStatement(statements), current_context))
|
return .Ok((BlockStatement(statements), current_context))
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
// p4rse, Copyright 2026, Will Hawkins
|
||||||
|
//
|
||||||
|
// This file is part of p4rse.
|
||||||
|
//
|
||||||
|
// This file is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import Common
|
||||||
|
import SwiftTreeSitter
|
||||||
|
import TreeSitterP4
|
||||||
|
|
||||||
|
public struct Walker {
|
||||||
|
var currentChildIdx: Int
|
||||||
|
let childCount: Int
|
||||||
|
let node: Node
|
||||||
|
|
||||||
|
public init(node: Node) {
|
||||||
|
self.currentChildIdx = 0
|
||||||
|
self.childCount = node.childCount
|
||||||
|
self.node = node
|
||||||
|
}
|
||||||
|
|
||||||
|
public mutating func next() {
|
||||||
|
self.currentChildIdx += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
public func getNext() -> Node? {
|
||||||
|
// If it is safe, then return the node!
|
||||||
|
if self.currentChildIdx < self.childCount {
|
||||||
|
return self.node.child(at: self.currentChildIdx)!
|
||||||
|
}
|
||||||
|
return .none
|
||||||
|
}
|
||||||
|
|
||||||
|
public func overUntil(n: Int, todo: (Node) -> Result<()>) -> Result<()> {
|
||||||
|
for currentChildIdx in currentChildIdx..<n {
|
||||||
|
let currentChild = node.child(at: currentChildIdx)!
|
||||||
|
if case Result.Error(let e) = todo(currentChild) {
|
||||||
|
return Result<()>.Error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Result.Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -64,7 +64,6 @@ public struct FunctionDeclaration: P4DataType, P4DataValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func eq(rhs: any Common.P4DataType) -> Bool {
|
public func eq(rhs: any Common.P4DataType) -> Bool {
|
||||||
print("Checking a type: me: \(self) vs them: \(rhs)!")
|
|
||||||
switch rhs {
|
switch rhs {
|
||||||
case let frhs as FunctionDeclaration:
|
case let frhs as FunctionDeclaration:
|
||||||
return frhs.tipe.eq(self.tipe) && frhs.params == self.params
|
return frhs.tipe.eq(self.tipe) && frhs.params == self.params
|
||||||
|
|||||||
@@ -107,6 +107,36 @@ import P4Lang
|
|||||||
#expect(#RequireOkResult(Program.Compile(simple_parser_declaration)))
|
#expect(#RequireOkResult(Program.Compile(simple_parser_declaration)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test func test_simple_control_declaration_with_multiple_tables() async throws {
|
||||||
|
let simple_parser_declaration = """
|
||||||
|
control simple(bool x, bool y, bool a, bool b) {
|
||||||
|
action a() {
|
||||||
|
}
|
||||||
|
table t {
|
||||||
|
key = {
|
||||||
|
x: exact;
|
||||||
|
y: exact;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
table u {
|
||||||
|
key = {
|
||||||
|
a: exact;
|
||||||
|
b: exact;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
apply {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
"""
|
||||||
|
#expect(
|
||||||
|
#RequireErrorResult(
|
||||||
|
Error(
|
||||||
|
withMessage: "{0, 215}: More than one table in control declaration"
|
||||||
|
),
|
||||||
|
Program.Compile(simple_parser_declaration))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@Test func test_simple_control_declaration_with_action_using_parameter() async throws {
|
@Test func test_simple_control_declaration_with_action_using_parameter() async throws {
|
||||||
let simple_parser_declaration = """
|
let simple_parser_declaration = """
|
||||||
control simple(bool x, bool y) {
|
control simple(bool x, bool y) {
|
||||||
@@ -151,3 +181,35 @@ import P4Lang
|
|||||||
Program.Compile(simple_parser_declaration))
|
Program.Compile(simple_parser_declaration))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test func test_simple_control_declaration_with_element_after_apply() async throws {
|
||||||
|
let simple_parser_declaration = """
|
||||||
|
control simple(bool x, bool y) {
|
||||||
|
action a(int z) {
|
||||||
|
z = false;
|
||||||
|
}
|
||||||
|
table t {
|
||||||
|
key = {
|
||||||
|
x: exact;
|
||||||
|
y: exact;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
apply {
|
||||||
|
}
|
||||||
|
table x {
|
||||||
|
key = {
|
||||||
|
x: exact;
|
||||||
|
y: exact;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
"""
|
||||||
|
#expect(
|
||||||
|
#RequireErrorResult(
|
||||||
|
Error(
|
||||||
|
withMessage:
|
||||||
|
"Could not compile the P4 program"
|
||||||
|
),
|
||||||
|
Program.Compile(simple_parser_declaration))
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
// p4rse, Copyright 2026, Will Hawkins
|
||||||
|
//
|
||||||
|
// This file is part of p4rse.
|
||||||
|
//
|
||||||
|
// This file is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import Common
|
||||||
|
import Foundation
|
||||||
|
import Macros
|
||||||
|
import P4Lang
|
||||||
|
import P4Runtime
|
||||||
|
import SwiftTreeSitter
|
||||||
|
import Testing
|
||||||
|
import TreeSitter
|
||||||
|
import TreeSitterP4
|
||||||
|
|
||||||
|
@testable import Macros
|
||||||
|
|
||||||
|
func wrapper_test_mustor() -> Int {
|
||||||
|
let x: Int? = 2
|
||||||
|
var i = 0
|
||||||
|
#MustOr(result: i, thing: x, or: 1)
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
|
func wrapper_test_mustor_none() -> Int {
|
||||||
|
let x: Int? = .none
|
||||||
|
var i = 0
|
||||||
|
#MustOr(result: i, thing: x, or: 1)
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test func test_mustor() async throws {
|
||||||
|
#expect(wrapper_test_mustor() == 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test func test_mustor_none() async throws {
|
||||||
|
#expect(wrapper_test_mustor_none() == 1)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user