common, codegen: Implement Visitor And Use For CodeGen
Continuous Integration / Grammar Tests (push) Successful in 4m6s
Continuous Integration / Library Format Tests (push) Successful in 5m5s
Continuous Integration / Library Tests (push) Successful in 9m0s
Continuous Integration / Cli Tests (push) Successful in 4m57s

Implement a generic visitor for components of a P4 program and use
it to start P4 code generation (according to the behavioral model).

Signed-off-by: Will Hawkins <hawkinsw@obs.cr>
This commit is contained in:
Will Hawkins
2026-05-15 08:14:20 -04:00
parent f1f20e96a2
commit 12fa43d9f9
7 changed files with 678 additions and 18 deletions
+60 -17
View File
@@ -18,6 +18,7 @@
import ArgumentParser
import Common
import P4Compiler
import P4Runtime
import SystemPackage
@main
@@ -26,7 +27,7 @@ struct Cli: ParsableCommand {
static let configuration = CommandConfiguration(
abstract: "P4CE compiler, interpreter and debugger.",
subcommands: [Compile.self])
subcommands: [Compile.self, CodeGen.self])
}
struct CliOptions: ParsableArguments {
@@ -50,30 +51,72 @@ extension Cli {
let prep = SourceCodePreprocessor(sm)
let file = FilePath(options.path)
let maybe_source = prep.preprocess(file)
guard case .Ok(let source) = maybe_source else {
let formatter = FormatterAnsi()
print(ErrorWithLabel("Preprocessor Error", maybe_source.error()!).format(formatter))
return
}
let maybe_program = Program.Compile(source.getSource())
guard case .Ok(_) = maybe_program else {
let formatter = FormatterAnsi()
print(ErrorWithLabel("Compiler Error", maybe_source.error()!).format(formatter))
return
}
let success_formatter: any Formattable =
let formatter: any Formattable =
if parent.plain != 0 {
FormatterPlain()
} else {
FormatterAnsi()
}
let maybe_source = prep.preprocess(file)
guard case .Ok(let source) = maybe_source else {
print(ErrorWithLabel("Preprocessor Error", maybe_source.error()!).format(formatter))
return
}
let maybe_program = Program.Compile(source.getSource())
guard case .Ok(_) = maybe_program else {
print(ErrorWithLabel("Compiler Error", maybe_source.error()!).format(formatter))
return
}
print(
success_formatter.formatWithStyle(
formatter.formatWithStyle(
"Success", Style(StyleColor.Green, [StyleFormat.Underline])))
}
}
}
extension Cli {
struct CodeGen: ParsableCommand {
static let configuration = CommandConfiguration(abstract: "Generate P4CE code.")
@ParentCommand var parent: Cli
@OptionGroup var options: CliOptions
mutating func run() {
let sm = SourceManager(options.search.map { FilePath($0) })
let prep = SourceCodePreprocessor(sm)
let file = FilePath(options.path)
let formatter: any Formattable =
if parent.plain != 0 {
FormatterPlain()
} else {
FormatterAnsi()
}
let maybe_source = prep.preprocess(file)
guard case .Ok(let source) = maybe_source else {
print(ErrorWithLabel("Preprocessor Error", maybe_source.error()!).format(formatter))
return
}
let maybe_program = Program.Compile(source.getSource())
guard case .Ok(let program) = maybe_program else {
print(ErrorWithLabel("Compiler Error", maybe_source.error()!).format(formatter))
return
}
let maybe_codegen = P4Runtime.CodeGenerator().codeGen(program)
guard case .Ok(let codegen) = maybe_codegen else {
let formatter = FormatterAnsi()
print(ErrorWithLabel("Code Generation Error", maybe_codegen.error()!).format(formatter))
return
}
print("\(codegen.getGeneratedCode())")
}
}
}