compiler: Refactor Compiler To Remove Ambiguities
There were significant overlaps in the names of data structures between the compiler and the language that made it necessary to litter the code with P4Lang.xxxx. This refactor removes that requirement in most places (Parser is ambiguous wherever TreeSitter is used -- cannot avoid that!) Signed-off-by: Will Hawkins <hawkinsw@obs.cr>
This commit is contained in:
@@ -94,7 +94,7 @@ extension Cli {
|
||||
return
|
||||
}
|
||||
|
||||
let maybe_program = Program.Compile(source.getSource())
|
||||
let maybe_program = SpecialCompilers.ProgramCompiler.Compile(source.getSource())
|
||||
guard case .Ok(_) = maybe_program else {
|
||||
let feedback = CompilationFeedback(source, [maybe_program.error()!], formatter)
|
||||
print(feedback.feedback)
|
||||
@@ -134,7 +134,7 @@ extension Cli {
|
||||
return
|
||||
}
|
||||
|
||||
let maybe_program = Program.Compile(source.getSource())
|
||||
let maybe_program = SpecialCompilers.ProgramCompiler.Compile(source.getSource())
|
||||
guard case .Ok(let program) = maybe_program else {
|
||||
print(ErrorWithLabel("Compiler Error", maybe_source.error()!).format(formatter))
|
||||
return
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import Common
|
||||
import P4Lang
|
||||
import P4Runtime
|
||||
import SwiftTreeSitter
|
||||
import TreeSitterExtensions
|
||||
|
||||
@@ -140,7 +140,7 @@ extension FunctionDeclaration: CompilableDeclaration {
|
||||
// Do not use the updated context returned by parsing the body
|
||||
// and do not use the function_scope, either.
|
||||
// And, do not update the context if we are compiling in an
|
||||
// extern context.
|
||||
// extern context -- the wrapping extern declaration will take care of that.
|
||||
return .Ok(
|
||||
(
|
||||
function_declaration,
|
||||
@@ -381,7 +381,7 @@ extension P4Lang.Parser: CompilableDeclaration {
|
||||
}
|
||||
|
||||
/// TODO: Handle extern parsers.
|
||||
switch Parser.Compile(
|
||||
switch SpecialCompilers.Compile(
|
||||
withName: parser_name!, withParameters: parameter_list, node: current_node!,
|
||||
withContext: current_context)
|
||||
{
|
||||
@@ -393,9 +393,7 @@ extension P4Lang.Parser: CompilableDeclaration {
|
||||
(
|
||||
parser_declaration,
|
||||
context.extern_context
|
||||
? updated_context.update(
|
||||
newExterns: updated_context.externs.declare(
|
||||
identifier: parser.name, withValue: parser_declaration))
|
||||
? context
|
||||
: updated_context.update(
|
||||
newTypes: updated_context.types.declare(identifier: parser.name, withValue: parser))
|
||||
))
|
||||
@@ -561,9 +559,7 @@ extension Control: CompilableDeclaration {
|
||||
(
|
||||
declared_control,
|
||||
context.extern_context
|
||||
? context.update(
|
||||
newTypes: context.externs.declare(
|
||||
identifier: control_name, withValue: declared_control))
|
||||
? context
|
||||
: context.update(
|
||||
newTypes: context.types.declare(
|
||||
identifier: control_name, withValue: control))
|
||||
@@ -575,7 +571,7 @@ extension Action: Compilable {
|
||||
public typealias T = Action
|
||||
public static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(P4Lang.Action, CompilerContext)> {
|
||||
) -> Common.Result<(Action, CompilerContext)> {
|
||||
#RequireNodeType<Node, (P4Type, CompilerContext)>(
|
||||
node: node, type: "action_declaration", nice_type_name: "Action Declaration")
|
||||
|
||||
@@ -588,7 +584,7 @@ extension Action: Compilable {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(P4Lang.Action, CompilerContext)>.Error(
|
||||
or: Result<(Action, CompilerContext)>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing action declaration component"
|
||||
))
|
||||
@@ -605,7 +601,7 @@ extension Action: Compilable {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(P4Lang.Action, CompilerContext)>.Error(
|
||||
or: Result<(Action, CompilerContext)>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing action declaration component"
|
||||
))
|
||||
@@ -633,7 +629,7 @@ extension Action: Compilable {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(P4Lang.Action, CompilerContext)>.Error(
|
||||
or: Result<(Action, CompilerContext)>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing action declaration component"
|
||||
))
|
||||
@@ -668,7 +664,7 @@ extension TableKeyEntry: Compilable {
|
||||
public typealias T = TableKeyEntry
|
||||
public static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(P4Lang.TableKeyEntry, CompilerContext)> {
|
||||
) -> Common.Result<(TableKeyEntry, CompilerContext)> {
|
||||
|
||||
#RequireNodeType<Node, (P4Type, CompilerContext)>(
|
||||
node: node, type: "table_key_entry", nice_type_name: "Table Key Entry")
|
||||
@@ -681,7 +677,7 @@ extension TableKeyEntry: Compilable {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(P4Lang.TableKeyEntry, CompilerContext)>.Error(
|
||||
or: Result<(TableKeyEntry, CompilerContext)>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing table key entry declaration component")))
|
||||
@@ -697,7 +693,7 @@ extension TableKeyEntry: Compilable {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(P4Lang.TableKeyEntry, CompilerContext)>.Error(
|
||||
or: Result<(TableKeyEntry, CompilerContext)>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing table key entry declaration component")))
|
||||
@@ -716,7 +712,7 @@ extension TableKeyMatchType: Compilable {
|
||||
public typealias T = TableKeyMatchType
|
||||
public static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(P4Lang.TableKeyMatchType, CompilerContext)> {
|
||||
) -> Common.Result<(TableKeyMatchType, CompilerContext)> {
|
||||
#RequireNodeType<Node, (TableKeyMatchType, CompilerContext)>(
|
||||
node: node, type: "table_key_match_type", nice_type_name: "Table Key Match Type")
|
||||
|
||||
@@ -734,7 +730,7 @@ extension TableKeys: Compilable {
|
||||
public typealias T = TableKeys
|
||||
public static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(P4Lang.TableKeys, CompilerContext)> {
|
||||
) -> Common.Result<(TableKeys, CompilerContext)> {
|
||||
#RequireNodeType<Node, (TableKeyMatchType, CompilerContext)>(
|
||||
node: node, type: "table_keys", nice_type_name: "Table Keys")
|
||||
|
||||
@@ -750,7 +746,7 @@ extension TableKeys: Compilable {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(P4Lang.TableKeys, CompilerContext)>.Error(
|
||||
or: Result<(TableKeys, CompilerContext)>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing table keys declaration component in control declaration"))
|
||||
@@ -839,7 +835,7 @@ extension TablePropertyList: Compilable {
|
||||
public typealias T = TablePropertyList
|
||||
public static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(P4Lang.TablePropertyList, CompilerContext)> {
|
||||
) -> Common.Result<(TablePropertyList, CompilerContext)> {
|
||||
|
||||
#RequireNodeType<Node, (P4Type, CompilerContext)>(
|
||||
node: node, type: "table_property_list", nice_type_name: "Table Property List")
|
||||
@@ -913,7 +909,7 @@ extension Table: Compilable {
|
||||
public typealias T = Table
|
||||
public static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(P4Lang.Table, CompilerContext)> {
|
||||
) -> Common.Result<(Table, CompilerContext)> {
|
||||
|
||||
let table_declaration_node = node
|
||||
#RequireNodeType<Node, (P4Type, CompilerContext)>(
|
||||
@@ -928,7 +924,7 @@ extension Table: Compilable {
|
||||
walker.next() // Skip the XXX?
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(P4Lang.Table, CompilerContext)>.Error(
|
||||
or: Result<(Table, CompilerContext)>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing table declaration component")
|
||||
))
|
||||
@@ -946,7 +942,7 @@ extension Table: Compilable {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(P4Lang.Table, CompilerContext)>.Error(
|
||||
or: Result<(Table, CompilerContext)>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing table declaration component")
|
||||
))
|
||||
|
||||
+155
-312
@@ -22,322 +22,165 @@ import SwiftTreeSitter
|
||||
import TreeSitterExtensions
|
||||
import TreeSitterP4
|
||||
|
||||
public struct Parser {
|
||||
public struct LocalElements {
|
||||
static func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<(EvaluatableStatement, CompilerContext)> {
|
||||
let localElementsParsers: [String: CompilableStatement.Type] = [
|
||||
"variableDeclaration": VariableDeclarationStatement.self
|
||||
]
|
||||
extension Statement: Compilable {
|
||||
public typealias T = EvaluatableStatement
|
||||
public static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(EvaluatableStatement, CompilerContext)> {
|
||||
|
||||
guard let parser = localElementsParsers[node.nodeType ?? ""] else {
|
||||
return Result.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Unparseable statement type (\(node.nodeType ?? "Unknown Statement Type"))"))
|
||||
}
|
||||
|
||||
switch parser.Compile(node: node, withContext: context) {
|
||||
case Result.Ok(let (parsed, parsed_updated_scopes)):
|
||||
return Result.Ok((parsed, parsed_updated_scopes))
|
||||
case Result.Error(let e):
|
||||
return Result.Error(Error(withMessage: "Failed to parse local element: \(e)"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public struct Statement {
|
||||
static func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<(EvaluatableStatement, CompilerContext)> {
|
||||
if node.nodeType != "parserStatement" && node.nodeType != "statement" {
|
||||
return Result.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing expected parser statement")
|
||||
)
|
||||
}
|
||||
|
||||
let statement = node.child(at: 0)!
|
||||
|
||||
let statementParsers: [String: CompilableStatement.Type] = [
|
||||
"assignmentStatement": ParserAssignmentStatement.self,
|
||||
"expressionStatement": ExpressionStatement.self,
|
||||
"variableDeclaration": VariableDeclarationStatement.self,
|
||||
"conditionalStatement": ConditionalStatement.self, "blockStatement": BlockStatement.self,
|
||||
"return_statement": ReturnStatement.self,
|
||||
]
|
||||
guard let parser = statementParsers[statement.nodeType ?? ""] else {
|
||||
return Result.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: statement.toSourceLocation(),
|
||||
withError:
|
||||
"Unparseable statement type (\(statement.nodeType ?? "Unknown Statement Type"))"))
|
||||
}
|
||||
switch parser.Compile(node: statement, withContext: context) {
|
||||
case Result.Ok(let (parsed, updated_context)):
|
||||
return .Ok((parsed, updated_context))
|
||||
case Result.Error(let e):
|
||||
return .Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Failed to parse a statement element: \(e)"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public struct TransitionStatement {
|
||||
static func Compile(
|
||||
node: Node, forState state_identifier: Common.Identifier,
|
||||
withStatements stmts: [EvaluatableStatement], withContext context: CompilerContext
|
||||
) -> Result<(ParserState, CompilerContext)> {
|
||||
|
||||
#RequireNodeType<Node, (EvaluatableStatement, CompilerContext)>(
|
||||
node: node, type: "parserTransitionStatement", nice_type_name: "parser transition statement"
|
||||
if node.nodeType != "parserStatement" && node.nodeType != "statement" {
|
||||
return Result.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing expected parser statement")
|
||||
)
|
||||
|
||||
guard let tse_node = node.child(at: 1),
|
||||
tse_node.nodeType! == "transitionSelectionExpression"
|
||||
else {
|
||||
return .Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Could not find transition select expression"))
|
||||
}
|
||||
|
||||
guard let next_node = tse_node.child(at: 0) else {
|
||||
return .Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Could not find the next token in a transition selection expression"))
|
||||
}
|
||||
|
||||
// If the next node is an identifier, we have the simple form ...
|
||||
if next_node.nodeType == "identifier" {
|
||||
let maybe_parsed_next_state_id = Identifier.Compile(
|
||||
node: next_node, withContext: context)
|
||||
if case .Ok(let next_state_id) = maybe_parsed_next_state_id {
|
||||
if case .Ok(let next_state) = context.instances.lookup(identifier: next_state_id) {
|
||||
switch next_state {
|
||||
case (_, .some(let instance)):
|
||||
return .Ok(
|
||||
(
|
||||
ParserStateDirectTransition(
|
||||
name: state_identifier,
|
||||
withNextState: instance.dataValue() as! InstantiatedParserState,
|
||||
withStatements: stmts), context
|
||||
))
|
||||
case (_, .none):
|
||||
return .Ok(
|
||||
(
|
||||
ParserStateDirectTransition(
|
||||
name: state_identifier,
|
||||
withNextStateIdentifier: next_state_id, withStatements: stmts), context
|
||||
))
|
||||
}
|
||||
} else {
|
||||
|
||||
return .Error(
|
||||
Error(
|
||||
withMessage:
|
||||
"\(next_state_id) does not name a parser state in scope"
|
||||
))
|
||||
}
|
||||
} else {
|
||||
return .Error(
|
||||
Error(
|
||||
withMessage:
|
||||
"Could not parse the next state in a transition statement: \(maybe_parsed_next_state_id.error()!)"
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
// We know that the next node is a select expression.
|
||||
return
|
||||
switch SelectExpression.compile(node: next_node, withContext: context)
|
||||
{
|
||||
case .Ok(let tse):
|
||||
.Ok(
|
||||
(
|
||||
ParserStateSelectTransition(
|
||||
name: state_identifier, withTransitionExpression: tse as! SelectExpression,
|
||||
withStatements: stmts,
|
||||
), context
|
||||
))
|
||||
case .Error(let e): .Error(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public struct Statements {
|
||||
static func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<([EvaluatableStatement], CompilerContext)> {
|
||||
if node.nodeType != "statements" && node.nodeType != "parserStatements" {
|
||||
return Result.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Did not find expected statements"))
|
||||
}
|
||||
|
||||
var errors: (any Errorable)? = .none
|
||||
var current_context = context
|
||||
var parsed_s: [EvaluatableStatement] = Array()
|
||||
|
||||
node.enumerateNamedChildren { node in
|
||||
switch Statement.Compile(
|
||||
node: node, withContext: current_context)
|
||||
{
|
||||
case .Ok((let parsed_statement, let updated_context)):
|
||||
current_context = updated_context
|
||||
parsed_s.append(parsed_statement)
|
||||
case .Error(let e):
|
||||
errors =
|
||||
if let errors = errors {
|
||||
errors.append(error: e)
|
||||
} else {
|
||||
e
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let errors = errors {
|
||||
return .Error(errors)
|
||||
}
|
||||
|
||||
return Result.Ok((parsed_s, current_context))
|
||||
}
|
||||
}
|
||||
|
||||
public struct State {
|
||||
static func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<(ParserState, CompilerContext)> {
|
||||
var walker = Walker(node: node)
|
||||
|
||||
var current_node: Node? = .none
|
||||
|
||||
guard let node_type = node.nodeType,
|
||||
node_type == "parserState"
|
||||
else {
|
||||
return Result.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Did not find a parser state declaration"))
|
||||
}
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(ParserState, CompilerContext)>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing elements in parser state declaration")))
|
||||
|
||||
if current_node!.nodeType == "annotations" {
|
||||
return Result.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: current_node!.toSourceLocation(),
|
||||
withError: "Annotations in parser state are not yet handled."))
|
||||
|
||||
// Would increment here.
|
||||
}
|
||||
|
||||
// Skip the keyword state
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(ParserState, CompilerContext)>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing elements in parser state declaration")))
|
||||
|
||||
let maybe_state_identifier = Identifier.Compile(
|
||||
node: current_node!, withContext: context)
|
||||
guard case Result.Ok(let state_identifier) = maybe_state_identifier else {
|
||||
return Result.Error(maybe_state_identifier.error()!)
|
||||
}
|
||||
|
||||
walker.next()
|
||||
// Skip the '{'
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(ParserState, CompilerContext)>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing body of state declaration")
|
||||
))
|
||||
|
||||
var errors: (any Errorable)? = .none
|
||||
var current_context = context
|
||||
var parsed_s: [EvaluatableStatement] = Array()
|
||||
|
||||
if current_node!.nodeType == "parserStatements" {
|
||||
switch Statements.Compile(
|
||||
node: current_node!, withContext: current_context)
|
||||
{
|
||||
case .Ok(let (state_statements, updated_context)):
|
||||
parsed_s = state_statements
|
||||
current_context = updated_context
|
||||
case .Error(let error):
|
||||
errors =
|
||||
if let errors = errors {
|
||||
errors.append(error: error)
|
||||
} else {
|
||||
error
|
||||
}
|
||||
}
|
||||
walker.next()
|
||||
}
|
||||
|
||||
if let errors = errors {
|
||||
return .Error(errors)
|
||||
}
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(ParserState, CompilerContext)>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing transition statement of state declaration")))
|
||||
|
||||
return TransitionStatement.Compile(
|
||||
node: current_node!, forState: state_identifier, withStatements: parsed_s,
|
||||
withContext: current_context)
|
||||
}
|
||||
}
|
||||
|
||||
static func Compile(
|
||||
withName name: Common.Identifier, withParameters parameters: ParameterList, node: Node,
|
||||
withContext context: CompilerContext
|
||||
) -> Result<(P4Lang.Parser, CompilerContext)> {
|
||||
|
||||
var parser = P4Lang.Parser(withName: name, withParameters: parameters)
|
||||
|
||||
// Build a state from each one listed.
|
||||
var error: (any Errorable)? = .none
|
||||
|
||||
var current_context = context
|
||||
/// TODO: Assert that there is only one.
|
||||
node.enumerateNamedChildren { parser_state in
|
||||
if parser_state.nodeType != "parserState" {
|
||||
return
|
||||
}
|
||||
|
||||
// Parse a state in a nested scope.
|
||||
switch Parser.State.Compile(
|
||||
node: parser_state,
|
||||
withContext: context.update(newInstances: current_context.instances.enter()))
|
||||
{
|
||||
case Result.Ok(let (state, updated_context)):
|
||||
parser.states = parser.states.append(state: state)
|
||||
current_context = updated_context
|
||||
case Result.Error(let e): error = e
|
||||
}
|
||||
}
|
||||
|
||||
if let error = error {
|
||||
return .Error(error)
|
||||
}
|
||||
let statement = node.child(at: 0)!
|
||||
|
||||
return Result.Ok((parser, current_context))
|
||||
let statementParsers: [String: CompilableStatement.Type] = [
|
||||
"assignmentStatement": ParserAssignmentStatement.self,
|
||||
"expressionStatement": ExpressionStatement.self,
|
||||
"variableDeclaration": VariableDeclarationStatement.self,
|
||||
"conditionalStatement": ConditionalStatement.self, "blockStatement": BlockStatement.self,
|
||||
"return_statement": ReturnStatement.self,
|
||||
]
|
||||
guard let parser = statementParsers[statement.nodeType ?? ""] else {
|
||||
return Result.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: statement.toSourceLocation(),
|
||||
withError:
|
||||
"Unparseable statement type (\(statement.nodeType ?? "Unknown Statement Type"))"))
|
||||
}
|
||||
switch parser.Compile(node: statement, withContext: context) {
|
||||
case Result.Ok(let (parsed, updated_context)):
|
||||
return .Ok((parsed, updated_context))
|
||||
case Result.Error(let e):
|
||||
return .Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Failed to parse a statement element: \(e)"))
|
||||
}
|
||||
}
|
||||
}
|
||||
extension LocalElements: Compilable {
|
||||
public typealias T = EvaluatableStatement
|
||||
public static func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<(EvaluatableStatement, CompilerContext)> {
|
||||
let localElementsParsers: [String: CompilableStatement.Type] = [
|
||||
"variableDeclaration": VariableDeclarationStatement.self
|
||||
]
|
||||
|
||||
guard let parser = localElementsParsers[node.nodeType ?? ""] else {
|
||||
return Result.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Unparseable statement type (\(node.nodeType ?? "Unknown Statement Type"))"))
|
||||
}
|
||||
|
||||
switch parser.Compile(node: node, withContext: context) {
|
||||
case Result.Ok(let (parsed, parsed_updated_scopes)):
|
||||
return Result.Ok((parsed, parsed_updated_scopes))
|
||||
case Result.Error(let e):
|
||||
return Result.Error(Error(withMessage: "Failed to parse local element: \(e)"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension ParserState: Compilable {
|
||||
public typealias T = ParserState
|
||||
public static func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<(ParserState, CompilerContext)> {
|
||||
var walker = Walker(node: node)
|
||||
|
||||
var current_node: Node? = .none
|
||||
|
||||
guard let node_type = node.nodeType,
|
||||
node_type == "parserState"
|
||||
else {
|
||||
return Result.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Did not find a parser state declaration"))
|
||||
}
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(ParserState, CompilerContext)>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing elements in parser state declaration")))
|
||||
|
||||
if current_node!.nodeType == "annotations" {
|
||||
return Result.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: current_node!.toSourceLocation(),
|
||||
withError: "Annotations in parser state are not yet handled."))
|
||||
|
||||
// Would increment here.
|
||||
}
|
||||
|
||||
// Skip the keyword state
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(ParserState, CompilerContext)>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing elements in parser state declaration")))
|
||||
|
||||
let maybe_state_identifier = Identifier.Compile(
|
||||
node: current_node!, withContext: context)
|
||||
guard case Result.Ok(let state_identifier) = maybe_state_identifier else {
|
||||
return Result.Error(maybe_state_identifier.error()!)
|
||||
}
|
||||
|
||||
walker.next()
|
||||
// Skip the '{'
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(ParserState, CompilerContext)>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing body of state declaration")
|
||||
))
|
||||
|
||||
var errors: (any Errorable)? = .none
|
||||
var current_context = context
|
||||
var parsed_s: [EvaluatableStatement] = Array()
|
||||
|
||||
if current_node!.nodeType == "parserStatements" {
|
||||
switch SpecialCompilers.Statements.Compile(
|
||||
node: current_node!, withContext: current_context)
|
||||
{
|
||||
case .Ok(let (state_statements, updated_context)):
|
||||
parsed_s = state_statements
|
||||
current_context = updated_context
|
||||
case .Error(let error):
|
||||
errors =
|
||||
if let errors = errors {
|
||||
errors.append(error: error)
|
||||
} else {
|
||||
error
|
||||
}
|
||||
}
|
||||
walker.next()
|
||||
}
|
||||
|
||||
if let errors = errors {
|
||||
return .Error(errors)
|
||||
}
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(ParserState, CompilerContext)>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing transition statement of state declaration")))
|
||||
|
||||
return SpecialCompilers.TransitionStatement.Compile(
|
||||
node: current_node!, forState: state_identifier, withStatements: parsed_s,
|
||||
withContext: current_context)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,157 +0,0 @@
|
||||
// p4rse, Copyright 2026, Will Hawkins
|
||||
//
|
||||
// This file is part of p4rse.
|
||||
//
|
||||
// This file is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import Common
|
||||
import P4Lang
|
||||
import P4Runtime
|
||||
import SwiftTreeSitter
|
||||
import TreeSitterExtensions
|
||||
import TreeSitterP4
|
||||
|
||||
public struct Program {
|
||||
public static func Compile(_ source: String) -> Result<P4Lang.Program> {
|
||||
|
||||
// Certain names are always in scope during compilation.
|
||||
var globals = StaticVarValueScopes().enter()
|
||||
globals = globals.declare(
|
||||
identifier: accept.state().getName(),
|
||||
withValue: (P4QualifiedType(accept.type()), P4Value(accept))
|
||||
)
|
||||
.declare(
|
||||
identifier: reject.state.getName(),
|
||||
withValue: (P4QualifiedType(reject.type()), P4Value(reject)))
|
||||
|
||||
return Program.Compile(
|
||||
source, withGlobalInstances: globals, withGlobalTypes: .none, withFFIs: [])
|
||||
}
|
||||
|
||||
public static func Compile(
|
||||
_ source: String, withGlobalInstances globalInstances: StaticVarValueScopes
|
||||
) -> Result<P4Lang.Program> {
|
||||
return Program.Compile(
|
||||
source, withGlobalInstances: globalInstances, withGlobalTypes: .none, withFFIs: [])
|
||||
}
|
||||
|
||||
public static func Compile(
|
||||
_ source: String, withGlobalInstances globalInstances: StaticVarValueScopes?,
|
||||
withGlobalTypes globalTypes: TypeTypeScopes?, withFFIs ffis: [P4FFI] = Array()
|
||||
) -> Result<P4Lang.Program> {
|
||||
|
||||
let maybe_parser = ConfigureP4Parser()
|
||||
guard case .Ok(let p) = maybe_parser else {
|
||||
return .Error(maybe_parser.error()!)
|
||||
}
|
||||
|
||||
let result = p.parse(source)
|
||||
guard let tree = result,
|
||||
!tree.isError(lang: p4lang),
|
||||
!tree.containsMissing(lang: p4lang)
|
||||
else {
|
||||
return Result.Error(Error(withMessage: "Could not compile the P4 program"))
|
||||
}
|
||||
|
||||
var program = P4Lang.Program()
|
||||
|
||||
// Set up a context for parsing.
|
||||
var compilation_context = CompilerContext()
|
||||
|
||||
// Add our FFIs
|
||||
compilation_context = compilation_context.update(newFFIs: ffis)
|
||||
|
||||
var errors: (any Errorable)? = .none
|
||||
|
||||
// If the caller gave any global instances, add them here.
|
||||
if let globalInstances = globalInstances {
|
||||
compilation_context = compilation_context.update(newInstances: globalInstances)
|
||||
}
|
||||
|
||||
// If the caller gave any global types, add them here.
|
||||
if let globalTypes = globalTypes {
|
||||
compilation_context = compilation_context.update(newTypes: globalTypes)
|
||||
}
|
||||
|
||||
// Try to parse all top-level declarations.
|
||||
result?.rootNode?.enumerateNamedChildren { (declaration_node: Node) in
|
||||
let specific_declaration_node = declaration_node.child(at: 0)!
|
||||
|
||||
let declaration_parsers: [CompilableDeclaration.Type] = [
|
||||
Declaration.self, P4Lang.Parser.self,
|
||||
]
|
||||
var found_parser = false
|
||||
|
||||
for parser in declaration_parsers {
|
||||
switch parser.Compile(node: specific_declaration_node, withContext: compilation_context) {
|
||||
case .Ok(.none): {}()
|
||||
case .Ok(.some((_, let updated_context))):
|
||||
found_parser = true
|
||||
compilation_context = updated_context
|
||||
break
|
||||
case .Error(let e):
|
||||
found_parser = true
|
||||
errors =
|
||||
if let errors = errors {
|
||||
errors.append(error: e)
|
||||
} else {
|
||||
e
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// If none of the declaration parsers chose to parse, that's an error, too!
|
||||
if !found_parser {
|
||||
|
||||
let no_parser_error = ErrorWithLocation(
|
||||
sourceLocation: specific_declaration_node.toSourceLocation(),
|
||||
withError: "Could not find parser for declaration node"
|
||||
)
|
||||
errors =
|
||||
if let errors = errors {
|
||||
errors.append(error: no_parser_error)
|
||||
} else {
|
||||
no_parser_error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let errors = errors {
|
||||
return .Error(errors)
|
||||
}
|
||||
|
||||
// Any of the instances that are in the top-level scope should go into the program!
|
||||
program.instances = Array(
|
||||
compilation_context.instances.filter { (_, v) in
|
||||
v.1 != nil
|
||||
}.map { (_, v) in
|
||||
v.1!
|
||||
})
|
||||
|
||||
// Any of the types that are in the top-level scope should go into the program!
|
||||
program.types = Array(
|
||||
compilation_context.types.map { (_, v) in
|
||||
v
|
||||
})
|
||||
|
||||
// Any of the extern types that are in the top-level scope should go into the program!
|
||||
program.externs = Array(
|
||||
compilation_context.externs.map { (_, v) in
|
||||
v
|
||||
})
|
||||
|
||||
return Result.Ok(program)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,336 @@
|
||||
// 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 P4Lang
|
||||
import P4Runtime
|
||||
import SwiftTreeSitter
|
||||
import TreeSitterExtensions
|
||||
import TreeSitterP4
|
||||
|
||||
public struct SpecialCompilers {
|
||||
public struct TransitionStatement {
|
||||
static func Compile(
|
||||
node: Node, forState state_identifier: Common.Identifier,
|
||||
withStatements stmts: [EvaluatableStatement], withContext context: CompilerContext
|
||||
) -> Result<(ParserState, CompilerContext)> {
|
||||
|
||||
#RequireNodeType<Node, (EvaluatableStatement, CompilerContext)>(
|
||||
node: node, type: "parserTransitionStatement", nice_type_name: "parser transition statement"
|
||||
)
|
||||
|
||||
guard let tse_node = node.child(at: 1),
|
||||
tse_node.nodeType! == "transitionSelectionExpression"
|
||||
else {
|
||||
return .Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Could not find transition select expression"))
|
||||
}
|
||||
|
||||
guard let next_node = tse_node.child(at: 0) else {
|
||||
return .Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Could not find the next token in a transition selection expression"))
|
||||
}
|
||||
|
||||
// If the next node is an identifier, we have the simple form ...
|
||||
if next_node.nodeType == "identifier" {
|
||||
let maybe_parsed_next_state_id = Identifier.Compile(
|
||||
node: next_node, withContext: context)
|
||||
if case .Ok(let next_state_id) = maybe_parsed_next_state_id {
|
||||
if case .Ok(let next_state) = context.instances.lookup(identifier: next_state_id) {
|
||||
switch next_state {
|
||||
case (_, .some(let instance)):
|
||||
return .Ok(
|
||||
(
|
||||
ParserStateDirectTransition(
|
||||
name: state_identifier,
|
||||
withNextState: instance.dataValue() as! InstantiatedParserState,
|
||||
withStatements: stmts), context
|
||||
))
|
||||
case (_, .none):
|
||||
return .Ok(
|
||||
(
|
||||
ParserStateDirectTransition(
|
||||
name: state_identifier,
|
||||
withNextStateIdentifier: next_state_id, withStatements: stmts), context
|
||||
))
|
||||
}
|
||||
} else {
|
||||
|
||||
return .Error(
|
||||
Error(
|
||||
withMessage:
|
||||
"\(next_state_id) does not name a parser state in scope"
|
||||
))
|
||||
}
|
||||
} else {
|
||||
return .Error(
|
||||
Error(
|
||||
withMessage:
|
||||
"Could not parse the next state in a transition statement: \(maybe_parsed_next_state_id.error()!)"
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
// We know that the next node is a select expression.
|
||||
return
|
||||
switch SelectExpression.compile(node: next_node, withContext: context)
|
||||
{
|
||||
case .Ok(let tse):
|
||||
.Ok(
|
||||
(
|
||||
ParserStateSelectTransition(
|
||||
name: state_identifier, withTransitionExpression: tse as! SelectExpression,
|
||||
withStatements: stmts,
|
||||
), context
|
||||
))
|
||||
case .Error(let e): .Error(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public struct Statements {
|
||||
static func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<([EvaluatableStatement], CompilerContext)> {
|
||||
if node.nodeType != "statements" && node.nodeType != "parserStatements" {
|
||||
return Result.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Did not find expected statements"))
|
||||
}
|
||||
|
||||
var errors: (any Errorable)? = .none
|
||||
var current_context = context
|
||||
var parsed_s: [EvaluatableStatement] = Array()
|
||||
|
||||
node.enumerateNamedChildren { node in
|
||||
switch Statement.Compile(
|
||||
node: node, withContext: current_context)
|
||||
{
|
||||
case .Ok((let parsed_statement, let updated_context)):
|
||||
current_context = updated_context
|
||||
parsed_s.append(parsed_statement)
|
||||
case .Error(let e):
|
||||
errors =
|
||||
if let errors = errors {
|
||||
errors.append(error: e)
|
||||
} else {
|
||||
e
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let errors = errors {
|
||||
return .Error(errors)
|
||||
}
|
||||
|
||||
return Result.Ok((parsed_s, current_context))
|
||||
}
|
||||
}
|
||||
|
||||
static func Compile(
|
||||
withName name: Common.Identifier, withParameters parameters: ParameterList, node: Node,
|
||||
withContext context: CompilerContext
|
||||
) -> Result<(P4Lang.Parser, CompilerContext)> {
|
||||
|
||||
var parser = P4Lang.Parser(withName: name, withParameters: parameters)
|
||||
|
||||
// Build a state from each one listed.
|
||||
var error: (any Errorable)? = .none
|
||||
|
||||
var current_context = context
|
||||
/// TODO: Assert that there is only one.
|
||||
node.enumerateNamedChildren { parser_state in
|
||||
if parser_state.nodeType != "parserState" {
|
||||
return
|
||||
}
|
||||
|
||||
// Parse a state in a nested scope.
|
||||
switch ParserState.Compile(
|
||||
node: parser_state,
|
||||
withContext: context.update(newInstances: current_context.instances.enter()))
|
||||
{
|
||||
case Result.Ok(let (state, updated_context)):
|
||||
parser.states = parser.states.append(state: state)
|
||||
current_context = updated_context
|
||||
case Result.Error(let e): error = e
|
||||
}
|
||||
}
|
||||
|
||||
if let error = error {
|
||||
return .Error(error)
|
||||
}
|
||||
|
||||
return Result.Ok((parser, current_context))
|
||||
}
|
||||
|
||||
public struct ProgramCompiler {
|
||||
public static func Compile(_ source: String) -> Result<P4Lang.Program> {
|
||||
|
||||
// Certain names are always in scope during compilation.
|
||||
var globals = StaticVarValueScopes().enter()
|
||||
globals = globals.declare(
|
||||
identifier: accept.state().getName(),
|
||||
withValue: (P4QualifiedType(accept.type()), P4Value(accept))
|
||||
)
|
||||
.declare(
|
||||
identifier: reject.state.getName(),
|
||||
withValue: (P4QualifiedType(reject.type()), P4Value(reject)))
|
||||
|
||||
return ProgramCompiler.Compile(
|
||||
source, withGlobalInstances: globals, withGlobalTypes: .none, withFFIs: [])
|
||||
}
|
||||
|
||||
public static func Compile(
|
||||
_ source: String, withGlobalInstances globalInstances: StaticVarValueScopes
|
||||
) -> Result<P4Lang.Program> {
|
||||
return ProgramCompiler.Compile(
|
||||
source, withGlobalInstances: globalInstances, withGlobalTypes: .none, withFFIs: [])
|
||||
}
|
||||
|
||||
public static func Compile(
|
||||
_ source: String, withGlobalInstances globalInstances: StaticVarValueScopes?,
|
||||
withGlobalTypes globalTypes: TypeTypeScopes?, withFFIs ffis: [P4FFI] = Array()
|
||||
) -> Result<P4Lang.Program> {
|
||||
|
||||
let maybe_parser = ConfigureP4Parser()
|
||||
guard case .Ok(let p) = maybe_parser else {
|
||||
return .Error(maybe_parser.error()!)
|
||||
}
|
||||
|
||||
let result = p.parse(source)
|
||||
guard let tree = result,
|
||||
!tree.isError(lang: p4lang),
|
||||
!tree.containsMissing(lang: p4lang)
|
||||
else {
|
||||
return Result.Error(Error(withMessage: "Could not compile the P4 program"))
|
||||
}
|
||||
|
||||
var program = P4Lang.Program()
|
||||
|
||||
// Set up a context for parsing.
|
||||
var compilation_context = CompilerContext()
|
||||
|
||||
// Add our FFIs
|
||||
compilation_context = compilation_context.update(newFFIs: ffis)
|
||||
|
||||
var errors: (any Errorable)? = .none
|
||||
|
||||
// If the caller gave any global instances, add them here.
|
||||
if let globalInstances = globalInstances {
|
||||
compilation_context = compilation_context.update(newInstances: globalInstances)
|
||||
}
|
||||
|
||||
// If the caller gave any global types, add them here.
|
||||
if let globalTypes = globalTypes {
|
||||
compilation_context = compilation_context.update(newTypes: globalTypes)
|
||||
}
|
||||
|
||||
// Try to parse all top-level declarations.
|
||||
result?.rootNode?.enumerateNamedChildren { (declaration_node: Node) in
|
||||
let specific_declaration_node = declaration_node.child(at: 0)!
|
||||
|
||||
let declaration_parsers: [CompilableDeclaration.Type] = [
|
||||
Declaration.self, P4Lang.Parser.self,
|
||||
]
|
||||
var found_parser = false
|
||||
|
||||
for parser in declaration_parsers {
|
||||
switch parser.Compile(node: specific_declaration_node, withContext: compilation_context) {
|
||||
case .Ok(.none): {}()
|
||||
case .Ok(.some((_, let updated_context))):
|
||||
found_parser = true
|
||||
compilation_context = updated_context
|
||||
break
|
||||
case .Error(let e):
|
||||
found_parser = true
|
||||
errors =
|
||||
if let errors = errors {
|
||||
errors.append(error: e)
|
||||
} else {
|
||||
e
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// If none of the declaration parsers chose to parse, that's an error, too!
|
||||
if !found_parser {
|
||||
|
||||
print("spec: \(declaration_node)")
|
||||
// Try to see if it is an instantiation!
|
||||
if declaration_node.nodeType == "instantiation" {
|
||||
switch Instantiation.Compile(
|
||||
node: declaration_node, withContext: compilation_context)
|
||||
{
|
||||
case .Ok((let x, let updated_context)):
|
||||
print("instantiation: \(x)")
|
||||
compilation_context = updated_context
|
||||
case .Error(let e):
|
||||
errors =
|
||||
if let errors = errors {
|
||||
errors.append(error: e)
|
||||
} else {
|
||||
e
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let no_parser_error = ErrorWithLocation(
|
||||
sourceLocation: specific_declaration_node.toSourceLocation(),
|
||||
withError: "Could not find parser for declaration node"
|
||||
)
|
||||
errors =
|
||||
if let errors = errors {
|
||||
errors.append(error: no_parser_error)
|
||||
} else {
|
||||
no_parser_error
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let errors = errors {
|
||||
return .Error(errors)
|
||||
}
|
||||
|
||||
// Any of the instances that are in the top-level scope should go into the program!
|
||||
program.instances = Array(
|
||||
compilation_context.instances.filter { (_, v) in
|
||||
v.1 != nil
|
||||
}.map { (_, v) in
|
||||
v.1!
|
||||
})
|
||||
|
||||
// Any of the types that are in the top-level scope should go into the program!
|
||||
program.types = Array(
|
||||
compilation_context.types.map { (_, v) in
|
||||
v
|
||||
})
|
||||
|
||||
// Any of the extern types that are in the top-level scope should go into the program!
|
||||
program.externs = Array(
|
||||
compilation_context.externs.map { (_, v) in
|
||||
v
|
||||
})
|
||||
|
||||
return Result.Ok(program)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -57,7 +57,7 @@ extension BlockStatement: CompilableStatement {
|
||||
sourceLocation: node.toSourceLocation(), withError: "Malformed block statement")))
|
||||
|
||||
if current_node!.nodeType == "statements" {
|
||||
switch Parser.Statements.Compile(
|
||||
switch SpecialCompilers.Statements.Compile(
|
||||
node: current_node!, withContext: current_context)
|
||||
{
|
||||
case .Ok(let (parsed_statements, updated_context)):
|
||||
@@ -128,7 +128,7 @@ extension ConditionalStatement: CompilableStatement {
|
||||
}
|
||||
|
||||
guard
|
||||
case .Ok((let thenns, _)) = Parser.Statement.Compile(
|
||||
case .Ok((let thenns, _)) = Statement.Compile(
|
||||
node: thens, withContext: context)
|
||||
else {
|
||||
return Result.Error(
|
||||
@@ -140,7 +140,7 @@ extension ConditionalStatement: CompilableStatement {
|
||||
let optional_elss: Result<(any EvaluatableStatement, CompilerContext)>? =
|
||||
if let elss = node.child(at: 6) {
|
||||
.some(
|
||||
Parser.Statement.Compile(
|
||||
Statement.Compile(
|
||||
node: elss, withContext: context))
|
||||
} else {
|
||||
.none
|
||||
|
||||
@@ -17,13 +17,9 @@
|
||||
|
||||
import Common
|
||||
|
||||
public struct LocalElements {
|
||||
public struct LocalElements {}
|
||||
|
||||
}
|
||||
|
||||
public struct LocalElement {
|
||||
|
||||
}
|
||||
public struct LocalElement {}
|
||||
|
||||
public struct ParserAssignmentStatement {
|
||||
public let lvalue: EvaluatableLValueExpression
|
||||
@@ -94,6 +90,8 @@ public class _AnyParserState: ParserState {
|
||||
|
||||
nonisolated(unsafe) public let AnyParserState = _AnyParserState(Identifier(name: "AnyParserState"))
|
||||
|
||||
public struct TransitionStatement {}
|
||||
|
||||
public class ParserStateDirectTransition: ParserState {
|
||||
|
||||
public let next_state: InstantiatedParserState?
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
|
||||
import Common
|
||||
|
||||
public struct Statement {}
|
||||
|
||||
public struct VariableDeclarationStatement {
|
||||
public var initializer: EvaluatableExpression
|
||||
public var identifier: Identifier
|
||||
|
||||
@@ -284,8 +284,8 @@ public struct CodeGenerator: LanguageVisitor {
|
||||
return .Ok(c)
|
||||
}
|
||||
public func visit(
|
||||
_ parser_state: P4Lang.InstantiatedParserState, _ c: P4Lang.VisitorContext<Generated>
|
||||
) -> Common.Result<P4Lang.VisitorContext<Generated>> {
|
||||
_ parser_state: InstantiatedParserState, _ c: VisitorContext<Generated>
|
||||
) -> Common.Result<VisitorContext<Generated>> {
|
||||
return .Ok(c)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ extension ParserStateDirectTransitionValue: EvaluatableParserState {
|
||||
return false
|
||||
}
|
||||
|
||||
public func state() -> P4Lang.ParserState {
|
||||
public func state() -> ParserState {
|
||||
return self.state
|
||||
}
|
||||
}
|
||||
@@ -82,7 +82,7 @@ extension ParserStateNoTransitionValue: EvaluatableParserState {
|
||||
return true
|
||||
}
|
||||
|
||||
public func state() -> P4Lang.ParserState {
|
||||
public func state() -> ParserState {
|
||||
return self.state
|
||||
}
|
||||
}
|
||||
@@ -125,7 +125,7 @@ extension ParserStateSelectTransitionValue: EvaluatableParserState {
|
||||
return false
|
||||
}
|
||||
|
||||
public func state() -> P4Lang.ParserState {
|
||||
public func state() -> ParserState {
|
||||
return self.state
|
||||
}
|
||||
}
|
||||
@@ -134,7 +134,7 @@ extension ParserValue: LibraryCallable {
|
||||
public typealias T = InstantiatedParserState
|
||||
public func call(
|
||||
execution: Common.ProgramExecution, arguments: ArgumentList
|
||||
) -> (P4Lang.InstantiatedParserState, Common.ProgramExecution) {
|
||||
) -> (InstantiatedParserState, Common.ProgramExecution) {
|
||||
var execution = execution.enter_scope()
|
||||
|
||||
execution = execution.declare(
|
||||
|
||||
@@ -36,13 +36,13 @@ public struct Runtime<U, T: LibraryCallable<U>>: CustomStringConvertible {
|
||||
|
||||
/// Create a parser runtime from a P4 program
|
||||
public static func create(
|
||||
program: P4Lang.Program
|
||||
program: Program
|
||||
) -> Result<Runtime<InstantiatedParserState, ParserValue>> {
|
||||
return Runtime.create(program: program, withGlobalValues: .none)
|
||||
}
|
||||
|
||||
public static func create(
|
||||
program: P4Lang.Program, withGlobalValues initial: VarValueScopes?
|
||||
program: Program, withGlobalValues initial: VarValueScopes?
|
||||
) -> Result<Runtime<InstantiatedParserState, ParserValue>> {
|
||||
return switch program.starting_parser() {
|
||||
case .Ok(let parser):
|
||||
@@ -55,7 +55,7 @@ public struct Runtime<U, T: LibraryCallable<U>>: CustomStringConvertible {
|
||||
}
|
||||
|
||||
public static func create(
|
||||
control: P4Lang.Control, withGlobalValues initial: VarValueScopes?
|
||||
control: Control, withGlobalValues initial: VarValueScopes?
|
||||
) -> Result<Runtime<P4TableHitMissValue, Control>> {
|
||||
return .Ok(
|
||||
P4Runtime.Runtime<P4TableHitMissValue, Control>(callable: control, withGlobalValues: initial))
|
||||
|
||||
@@ -133,3 +133,9 @@ extension ApplyStatement: EvaluatableStatement {
|
||||
return (ControlFlow.Next, execution)
|
||||
}
|
||||
}
|
||||
|
||||
extension Instantiation: EvaluatableStatement {
|
||||
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
|
||||
return (ControlFlow.Next, execution)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user