Start Rewrite
Continuous Integration / Grammar Tests (push) Successful in 3m54s
Continuous Integration / Library Format Tests (push) Failing after 4m49s
Continuous Integration / Library Tests (push) Successful in 7m40s

Signed-off-by: Will Hawkins <hawkinsw@obs.cr>
This commit is contained in:
Will Hawkins
2026-06-12 06:24:53 -04:00
parent 6908d9a91d
commit b9ff228362
73 changed files with 1779 additions and 11477 deletions
+45 -143
View File
@@ -16,22 +16,14 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import Common
import P4Lang
import P4Runtime
import SwiftTreeSitter
import TreeSitterExtensions
import TreeSitterP4
protocol AnyCompilable {
static func Compile(
node: SwiftTreeSitter.Node, withContext context: CompilerContext
) -> Common.Result<(Any, CompilerContext)>
}
extension TransitionStatement: Compilable {
extension AST.TransitionStatement: Compilable {
public static func Compile(
node: Node, withContext context: CompilerContext
) -> Result<ParserState> {
node: Node, withContext context: ASTCompilerContext
) -> Result<AST.AnState> {
guard let state_identifier = context.lexical_context_name else {
return .Error(
@@ -71,51 +63,27 @@ extension TransitionStatement: Compilable {
// 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(
let maybe_parsed_next_state_id = AST.Identifier.CompileExpression(
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,
)
)
case (_, .none):
return .Ok(
ParserStateDirectTransition(
name: state_identifier,
withNextStateIdentifier: next_state_id, withStatements: stmts)
)
}
} 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()!)"
))
switch maybe_parsed_next_state_id {
case .Ok(let next_state_id):
return .Ok(
AST.ParserStateDirectTransition(
name: (state_identifier),
withNextStateIdentifier: next_state_id as! AST.Identifier, withStatements: stmts))
case .Error(let e):
return .Error(e)
}
}
// We know that the next node is a select expression.
return
switch SelectExpression.compile(node: next_node, withContext: context)
switch AST.SelectExpression.CompileExpression(node: next_node, withContext: context)
{
case .Ok(let tse):
.Ok(
ParserStateSelectTransition(
name: state_identifier, withTransitionExpression: tse as! SelectExpression,
AST.ParserStateSelectTransition(
name: state_identifier, withTransitionExpression: tse as! AST.SelectExpression,
withStatements: stmts,
)
)
@@ -127,8 +95,8 @@ extension TransitionStatement: Compilable {
public struct SpecialCompilers {
public struct Statements {
static func Compile(
node: Node, withContext context: CompilerContext
) -> Result<[P4Statement]> {
node: Node, withContext context: ASTCompilerContext
) -> Result<[AST.AnStatement]> {
if node.nodeType != "statements" && node.nodeType != "parserStatements" {
return Result.Error(
ErrorWithLocation(
@@ -136,16 +104,14 @@ public struct SpecialCompilers {
}
var errors: (any Errorable)? = .none
var current_context = context
var parsed_s: [P4Statement] = Array()
var parsed_s: [AST.AnStatement] = Array()
node.enumerateNamedChildren { node in
switch Statement.Compile(
node: node, withContext: current_context)
switch AST.Statement.Compile(
node: node, withContext: context)
{
case .Ok(let parsed_statement):
parsed_s.append(parsed_statement)
current_context = parsed_statement.effect(context: current_context)
case .Error(let e):
errors =
if let errors = errors {
@@ -162,28 +128,18 @@ public struct SpecialCompilers {
return Result.Ok(parsed_s)
}
static func effect(statements: [P4Statement], context: CompilerContext) -> CompilerContext {
var current = context
for s in statements {
current = s.effect(context: current)
}
return current
}
}
static func CompileParserBody(
withName name: Common.Identifier, withParameters parameters: ParameterList, node: Node,
withContext context: CompilerContext
) -> Result<P4Lang.Parser> {
withName name: AST.Identifier, withParameters parameters: AST.ParameterList, node: Node,
withContext context: ASTCompilerContext
) -> Result<AST.Parser> {
var parser = P4Lang.Parser(withName: name, withParameters: parameters)
var parser = AST.Parser(withName: name, withParameters: parameters)
// Build a state from each one listed.
var error: (any Errorable)? = .none
var errors: (any Errorable)? = .none
var current_context = context
/// TODO: Assert that there is only one.
node.enumerateNamedChildren { parser_state in
if parser_state.nodeType != "parserState" {
@@ -191,53 +147,32 @@ public struct SpecialCompilers {
}
// Parse a state in a nested scope.
switch ParserState.Compile(
switch AST.ParserState.Compile(
node: parser_state,
withContext: context.update(newInstances: current_context.instances.enter()))
withContext: context)
{
case Result.Ok(let state):
let statement = state as P4Statement
current_context = statement.effect(context: current_context)
// All states are instances inside the parser.
parser.states = parser.states.append(state: state)
case Result.Error(let e): error = e
case Result.Error(let e):
errors =
if let errors = errors {
errors.append(error: e)
} else {
e
}
}
}
if let error = error {
return .Error(error)
if let errors = errors {
return .Error(errors)
}
return Result.Ok(parser)
return .Ok(parser)
}
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> {
public static func Compile(_ source: String) -> Result<AST.Program> {
let maybe_parser = ConfigureP4Parser()
guard case .Ok(let p) = maybe_parser else {
@@ -252,38 +187,25 @@ public struct SpecialCompilers {
return Result.Error(Error(withMessage: "Could not compile the P4 program"))
}
var program = P4Lang.Program()
var program = AST.Program()
// Set up a context for parsing.
var compilation_context = CompilerContext()
// Add our FFIs
compilation_context = compilation_context.update(newFFIs: ffis)
let compilation_context = ASTCompilerContext()
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 declaration_parsers: [String: CompilableStatement.Type] = [
"declaration": Declaration.self,
"instantiation": Instantiation.self,
"declaration": AST.Declaration.self,
"instantiation": AST.Instantiation.self,
]
if let parser = declaration_parsers[declaration_node.nodeType!] {
let r = parser.CompileStatement(node: declaration_node, withContext: compilation_context)
switch r {
case .Ok(let compiled):
compilation_context = compiled.effect(context: compilation_context)
program.statements = program.statements + [compiled]
case .Error(let e):
errors =
if let errors = errors {
@@ -310,28 +232,8 @@ public struct SpecialCompilers {
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)
}
}