compiler, runtime: Begin Runtime Refactor
Ultimately, the goal is to completely separate the compilation from the runtime to make it possible to have the interpreter/evaluator be "just another" entity that can perform meaningful work when given a parsed GP4 program. Signed-off-by: Will Hawkins <hawkinsw@obs.cr>
This commit is contained in:
@@ -42,7 +42,7 @@ public struct Parameter: CustomStringConvertible, Equatable {
|
||||
if let param_direction = self.type.direction(),
|
||||
param_direction == Direction.In || param_direction == Direction.InOut
|
||||
{
|
||||
if !(argument.argument is EvaluatableLValueExpression) {
|
||||
if !(argument.argument is P4LValueExpression) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -125,9 +125,9 @@ public struct ArgumentList {
|
||||
|
||||
public struct Argument {
|
||||
public let index: Int
|
||||
public let argument: EvaluatableExpression
|
||||
public let argument: P4Expression
|
||||
|
||||
public init(_ argument: EvaluatableExpression, atIndex index: Int) {
|
||||
public init(_ argument: P4Expression, atIndex index: Int) {
|
||||
self.argument = argument
|
||||
self.index = index
|
||||
}
|
||||
|
||||
@@ -26,3 +26,124 @@ public typealias TypeTypeScope = Scope<P4Type>
|
||||
|
||||
/// Scopes that resolve type identifiers to their types.
|
||||
public typealias TypeTypeScopes = Scopes<P4Type>
|
||||
|
||||
/// Context for compilation
|
||||
///
|
||||
/// It contains (at least) three important pieces of information:
|
||||
/// 1. Instances: A ``VarTypeScopes`` that contains information about instantiated objects
|
||||
/// (and their types) in scope
|
||||
/// 1. Types: A ``TypeTypeScopes`` that contains information about declared types in scope.
|
||||
/// 1. Expected Type: In certain situations, to typecheck an element of a P4 program requires
|
||||
/// knowledge of an expected type. For instance, when compiling a return statement, the
|
||||
/// compiler must know the return type of the function to type check.
|
||||
public struct CompilerContext {
|
||||
public let instances: StaticVarValueScopes
|
||||
public let types: TypeTypeScopes
|
||||
public let externs: TypeTypeScopes
|
||||
public let ffis: [P4FFI]
|
||||
public let expected_type: P4QualifiedType?
|
||||
public let extern_context: Bool
|
||||
|
||||
public init() {
|
||||
instances = StaticVarValueScopes().enter()
|
||||
types = TypeTypeScopes().enter()
|
||||
externs = TypeTypeScopes().enter()
|
||||
expected_type = .none
|
||||
extern_context = false
|
||||
ffis = Array()
|
||||
}
|
||||
|
||||
public init(withInstances _instances: StaticVarValueScopes, withTypes _types: TypeTypeScopes) {
|
||||
instances = _instances
|
||||
types = _types
|
||||
externs = TypeTypeScopes().enter()
|
||||
expected_type = .none
|
||||
extern_context = false
|
||||
ffis = Array()
|
||||
}
|
||||
|
||||
public init(
|
||||
withInstances _instances: StaticVarValueScopes, withTypes _types: TypeTypeScopes,
|
||||
withExpectation expectation: P4QualifiedType?, withExtern extern: Bool,
|
||||
withExterns externs: TypeTypeScopes, withFFIs foreigns: [P4FFI]
|
||||
) {
|
||||
instances = _instances
|
||||
types = _types
|
||||
expected_type = expectation
|
||||
extern_context = extern
|
||||
self.externs = externs
|
||||
ffis = foreigns
|
||||
}
|
||||
|
||||
/// Update a compiler context
|
||||
///
|
||||
/// Create a new compiler context based on the current but new instances.
|
||||
///
|
||||
/// - Parameter instances: a ``VarTypeScopes`` with the updated instances for the newly created compiler context.
|
||||
/// - Returns: A new compiler context based on the current but new instances.
|
||||
public func update(newInstances instances: StaticVarValueScopes) -> CompilerContext {
|
||||
return CompilerContext(
|
||||
withInstances: instances, withTypes: self.types, withExpectation: self.expected_type,
|
||||
withExtern: self.extern_context, withExterns: self.externs, withFFIs: self.ffis)
|
||||
}
|
||||
|
||||
/// Update a compiler context
|
||||
///
|
||||
/// Create a new compiler context based on the current but new types.
|
||||
///
|
||||
/// - Parameter types: a ``TypeTypeScopes`` with the updated types for the newly created compiler context.
|
||||
/// - Returns: A new compiler context based on the current but new types.
|
||||
public func update(newTypes types: TypeTypeScopes) -> CompilerContext {
|
||||
return CompilerContext(
|
||||
withInstances: self.instances, withTypes: types, withExpectation: self.expected_type,
|
||||
withExtern: self.extern_context, withExterns: self.externs, withFFIs: self.ffis)
|
||||
}
|
||||
|
||||
/// Update a compiler context
|
||||
///
|
||||
/// Create a new compiler context based on the current but new expected type.
|
||||
///
|
||||
/// - Parameter expectation: a ``P4Type?`` to (re)set the type the compiler is expecting.
|
||||
/// - Returns: A new compiler context based on the current but new expected type.
|
||||
public func update(newExpectation expectation: P4QualifiedType?) -> CompilerContext {
|
||||
return CompilerContext(
|
||||
withInstances: self.instances, withTypes: self.types, withExpectation: expectation,
|
||||
withExtern: self.extern_context, withExterns: self.externs, withFFIs: self.ffis)
|
||||
}
|
||||
|
||||
/// Update a compiler context
|
||||
///
|
||||
/// Create a new compiler context based on the current but new extern context value.
|
||||
///
|
||||
/// - Parameter extern: a ``Bool`` to (re)set whether the compiler is compiling in an extern context.
|
||||
/// - Returns: A new compiler context based on the current but new extern context value.
|
||||
public func update(newExtern extern: Bool) -> CompilerContext {
|
||||
return CompilerContext(
|
||||
withInstances: self.instances, withTypes: self.types, withExpectation: self.expected_type,
|
||||
withExtern: extern, withExterns: self.externs, withFFIs: self.ffis)
|
||||
}
|
||||
|
||||
/// Update a compiler context
|
||||
///
|
||||
/// Create a new compiler context based on the current but new externs.
|
||||
///
|
||||
/// - Parameter externs: a ``TypeTypeScopes`` to (re)set the list of extern-al declarations.
|
||||
/// - Returns: A new compiler context based on the current but new list of external-al declarations.
|
||||
public func update(newExterns externs: TypeTypeScopes) -> CompilerContext {
|
||||
return CompilerContext(
|
||||
withInstances: self.instances, withTypes: self.types, withExpectation: self.expected_type,
|
||||
withExtern: self.extern_context, withExterns: externs, withFFIs: self.ffis)
|
||||
}
|
||||
|
||||
/// Update a compiler context
|
||||
///
|
||||
/// Create a new compiler context based on the current but new FFIs.
|
||||
///
|
||||
/// - Parameter foreigns: an array of ``P4FFI`` to (re)set the list of foreign functions.
|
||||
/// - Returns: A new compiler context based on the current but with a new list of foreign functions.
|
||||
public func update(newFFIs foreigns: [P4FFI]) -> CompilerContext {
|
||||
return CompilerContext(
|
||||
withInstances: self.instances, withTypes: self.types, withExpectation: self.expected_type,
|
||||
withExtern: self.extern_context, withExterns: externs, withFFIs: foreigns)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,6 +109,18 @@ public struct InterloperEvaluator: ProgramExecutionEvaluator {
|
||||
|
||||
return CanonicalExecuteStatements(statements, inExecution: execution) { statement, execution in
|
||||
let (cf, value) = statement.evaluate(execution: execution)
|
||||
|
||||
let (handled_cf, handled_value) =
|
||||
if let handler = handler {
|
||||
handler(cf, value)
|
||||
} else {
|
||||
(cf, value)
|
||||
}
|
||||
if hasDebugInterloper {
|
||||
debugger!(statement, handled_cf, handled_value)
|
||||
}
|
||||
return (handled_cf, handled_value)
|
||||
/*
|
||||
let (handled_cf, handled_value) =
|
||||
if let handler = handler {
|
||||
handler(cf, value)
|
||||
@@ -119,7 +131,7 @@ public struct InterloperEvaluator: ProgramExecutionEvaluator {
|
||||
if hasDebugInterloper {
|
||||
debugger!(statement, handled_cf, handled_value)
|
||||
}
|
||||
return (handled_cf, handled_value)
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,28 +15,16 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
public protocol EvaluatableExpression {
|
||||
/// Evaluate an expression for a given execution
|
||||
/// - Parameters
|
||||
/// - execution: The execution context in which to evaluate the expression
|
||||
/// - Returns: The value of expression
|
||||
func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution)
|
||||
func type() -> P4QualifiedType
|
||||
}
|
||||
|
||||
public protocol EvaluatableStatement {
|
||||
/// Evaluate a statement for a given execution
|
||||
/// - Parameters
|
||||
/// - execution: The execution context in which to evaluate the parser statement
|
||||
/// - Returns: A tuple of
|
||||
/// 1. Whether this statement affects control flow.
|
||||
/// 2. An updated execution after evaluating the parser statement
|
||||
func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution)
|
||||
}
|
||||
|
||||
public protocol P4Type: CustomStringConvertible {
|
||||
func eq(rhs: any P4Type) -> Bool
|
||||
func def() -> P4DataValue?
|
||||
func instantiable() -> Bool
|
||||
}
|
||||
|
||||
extension P4Type {
|
||||
public func instantiable() -> Bool {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
public protocol P4DataValue: CustomStringConvertible {
|
||||
@@ -48,28 +36,6 @@ public protocol P4DataValue: CustomStringConvertible {
|
||||
func gte(rhs: P4DataValue) -> Bool
|
||||
}
|
||||
|
||||
public protocol EvaluatableLValueExpression: EvaluatableExpression {
|
||||
func set(
|
||||
to: P4Value, inScopes scopes: VarValueScopes, duringExecution execution: ProgramExecution
|
||||
) -> Result<(VarValueScopes, P4Value)>
|
||||
func check(to: EvaluatableExpression, inScopes scopes: StaticVarValueScopes) -> Result<()>
|
||||
}
|
||||
|
||||
public protocol ProgramExecutionEvaluator {
|
||||
func ExecuteStatements(
|
||||
_ statements: [EvaluatableStatement], inExecution execution: ProgramExecution,
|
||||
_ handler: ExecuteStatementResultHandlerT?
|
||||
) -> (ControlFlow, ProgramExecution)
|
||||
|
||||
func ExecuteStatements(
|
||||
_ statements: [EvaluatableStatement], inExecution execution: ProgramExecution
|
||||
) -> (ControlFlow, ProgramExecution)
|
||||
|
||||
func EvaluateExpression(
|
||||
_ expression: EvaluatableExpression, inExecution execution: ProgramExecution,
|
||||
) -> (Result<P4Value>, ProgramExecution)
|
||||
}
|
||||
|
||||
public protocol Errorable: CustomStringConvertible {
|
||||
func format(_ formatter: Formattable) -> String
|
||||
func format(_ formatter: Formattable, _ sc: SourceCode) -> String
|
||||
@@ -91,6 +57,64 @@ public protocol Formattable {
|
||||
func formatWithStyle(_ value: String, _ style: Style) -> String
|
||||
}
|
||||
|
||||
public protocol P4Statement {
|
||||
/// Evaluate a statement for a given execution
|
||||
/// - Parameters
|
||||
/// - execution: The execution context in which to evaluate the parser statement
|
||||
/// - Returns: A tuple of
|
||||
/// 1. Whether this statement affects control flow.
|
||||
/// 2. An updated execution after evaluating the parser statement
|
||||
func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution)
|
||||
|
||||
func effect(context: CompilerContext) -> CompilerContext
|
||||
}
|
||||
|
||||
public protocol P4Expression {
|
||||
func effect(context: CompilerContext) -> CompilerContext
|
||||
func type() -> P4QualifiedType
|
||||
/// Evaluate an expression for a given execution
|
||||
/// - Parameters
|
||||
/// - execution: The execution context in which to evaluate the expression
|
||||
/// - Returns: The value of expression
|
||||
func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution)
|
||||
}
|
||||
|
||||
extension P4Expression {
|
||||
func effect(context: CompilerContext) -> CompilerContext {
|
||||
return context
|
||||
}
|
||||
}
|
||||
|
||||
public protocol P4LValueExpression {
|
||||
func effect(context: CompilerContext) -> CompilerContext
|
||||
func type() -> P4QualifiedType
|
||||
func check(to: P4Expression, inScopes scopes: StaticVarValueScopes) -> Result<()>
|
||||
func set(
|
||||
to: P4Value, inScopes scopes: VarValueScopes, duringExecution execution: ProgramExecution
|
||||
) -> Result<(VarValueScopes, P4Value)>
|
||||
|
||||
}
|
||||
|
||||
/// TODO: Only generate these after going through the codegen!
|
||||
public typealias EvaluatableStatement = P4Statement
|
||||
public typealias EvaluatableLValueExpression = P4LValueExpression
|
||||
public typealias EvaluatableExpression = P4Expression
|
||||
|
||||
public protocol ProgramExecutionEvaluator {
|
||||
func ExecuteStatements(
|
||||
_ statements: [EvaluatableStatement], inExecution execution: ProgramExecution,
|
||||
_ handler: ExecuteStatementResultHandlerT?
|
||||
) -> (ControlFlow, ProgramExecution)
|
||||
|
||||
func ExecuteStatements(
|
||||
_ statements: [EvaluatableStatement], inExecution execution: ProgramExecution
|
||||
) -> (ControlFlow, ProgramExecution)
|
||||
|
||||
func EvaluateExpression(
|
||||
_ expression: EvaluatableExpression, inExecution execution: ProgramExecution,
|
||||
) -> (Result<P4Value>, ProgramExecution)
|
||||
}
|
||||
|
||||
extension ProgramExecutionEvaluator {
|
||||
public func ExecuteStatements(
|
||||
_ statements: [EvaluatableStatement], inExecution execution: ProgramExecution
|
||||
|
||||
@@ -106,3 +106,6 @@ public func Fold<T, A>(input: [T], initial: A, block: (T, A) -> A) -> A {
|
||||
|
||||
@freestanding(codeItem) public macro MustOr<E, N>(result: E, thing: E?, or: N) =
|
||||
#externalMacro(module: "Macros", type: "MustOr")
|
||||
|
||||
@attached(peer) public macro DeriveCompilableStatement() =
|
||||
#externalMacro(module: "Macros", type: "DeriveCompilableStatement")
|
||||
|
||||
@@ -439,11 +439,36 @@ public struct CliTestDeclarationMacro: PeerMacro, Sendable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct DeriveCompilableStatement: PeerMacro, Sendable {
|
||||
public static func expansion(
|
||||
of node: AttributeSyntax,
|
||||
providingPeersOf declaration: some DeclSyntaxProtocol,
|
||||
in context: some MacroExpansionContext
|
||||
) throws -> [DeclSyntax] {
|
||||
|
||||
let type_name = declaration.cast(ExtensionDeclSyntax.self).extendedType
|
||||
let implementation = DeclSyntax(
|
||||
"""
|
||||
extension VariableDeclarationStatement: CompilableStatement {
|
||||
public static func CompileStatement(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<P4Statement> {
|
||||
return switch Compile(node: node, withContext: context) {
|
||||
case .Ok(let res): .Ok(res)
|
||||
case .Error(let e): .Error(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
""")
|
||||
return [implementation]
|
||||
}
|
||||
}
|
||||
|
||||
@main
|
||||
struct P4Macros: CompilerPlugin {
|
||||
var providingMacros: [Macro.Type] = [
|
||||
RequireResult.self, RequireErrorResult.self, UseOkResult.self, UseErrorResult.self,
|
||||
RequireNodeType.self, SkipUnlessNodeType.self, SkipUnlessNodesTypes.self, RequireNodesType.self,
|
||||
MustOr.self, CliTestDeclarationMacro.self,
|
||||
MustOr.self, CliTestDeclarationMacro.self, DeriveCompilableStatement.self,
|
||||
]
|
||||
}
|
||||
|
||||
@@ -24,30 +24,30 @@ import TreeSitterP4
|
||||
|
||||
func parameter_list_compiler(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(ParameterList, CompilerContext)> {
|
||||
) -> Common.Result<ParameterList> {
|
||||
|
||||
var walker = Walker(node: node)
|
||||
var current_node: Node? = .none
|
||||
|
||||
if node.text == ")" {
|
||||
// There are no parameters!
|
||||
return Result.Ok((ParameterList([]), context))
|
||||
return Result.Ok(ParameterList([]))
|
||||
}
|
||||
|
||||
#RequireNodeType<Node, (ParameterList, CompilerContext)>(
|
||||
#RequireNodeType<Node, ParameterList>(
|
||||
node: node, type: "parameter_list", nice_type_name: "Parameter List")
|
||||
|
||||
var parameters: ParameterList = ParameterList([])
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(ParameterList, CompilerContext)>.Error(
|
||||
or: Result<ParameterList>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing parameter list component")))
|
||||
|
||||
if current_node?.nodeType == "parameter_list" {
|
||||
switch parameter_list_compiler(node: current_node!, withContext: context) {
|
||||
case .Ok(let (ps, _)):
|
||||
case .Ok(let ps):
|
||||
parameters = ps
|
||||
case .Error(let e): return Result.Error(e)
|
||||
}
|
||||
@@ -56,13 +56,13 @@ func parameter_list_compiler(
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(ParameterList, CompilerContext)>.Error(
|
||||
or: Result<ParameterList>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing parameter list component")))
|
||||
|
||||
// If this is a ')', we are done.
|
||||
if current_node?.text == ")" {
|
||||
return Result.Ok((parameters, context))
|
||||
return Result.Ok(parameters)
|
||||
}
|
||||
|
||||
// If this is a comma, we skip it!
|
||||
@@ -72,26 +72,26 @@ func parameter_list_compiler(
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(ParameterList, CompilerContext)>.Error(
|
||||
or: Result<ParameterList>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing parameter list component")))
|
||||
|
||||
// Otherwise, there should be one parameter left!
|
||||
switch Parameter.Compile(node: current_node!, withContext: context) {
|
||||
case .Ok(let (parsed_parameter, updated_context)):
|
||||
return Result.Ok((parameters.addParameter(parsed_parameter), updated_context))
|
||||
case .Ok(let parsed_parameter):
|
||||
return Result.Ok(parameters.addParameter(parsed_parameter))
|
||||
case .Error(let e): return Result.Error(e)
|
||||
}
|
||||
}
|
||||
|
||||
extension ParameterList: Compilable {
|
||||
public typealias T = ParameterList
|
||||
public typealias C = ParameterList
|
||||
public static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(ParameterList, CompilerContext)> {
|
||||
) -> Common.Result<ParameterList> {
|
||||
|
||||
let parameter_node = node
|
||||
#RequireNodeType<Node, (ParameterList, CompilerContext)>(
|
||||
#RequireNodeType<Node, ParameterList>(
|
||||
node: parameter_node, type: "parameters", nice_type_name: "Parameters")
|
||||
|
||||
var walker = Walker(node: parameter_node)
|
||||
@@ -100,7 +100,7 @@ extension ParameterList: Compilable {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(ParameterList, CompilerContext)>.Error(
|
||||
or: Result<ParameterList>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing '(' in parameter list component")))
|
||||
@@ -108,7 +108,7 @@ extension ParameterList: Compilable {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(ParameterList, CompilerContext)>.Error(
|
||||
or: Result<ParameterList>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing parameter list component")))
|
||||
|
||||
@@ -117,12 +117,12 @@ extension ParameterList: Compilable {
|
||||
}
|
||||
|
||||
extension Direction: Compilable {
|
||||
public typealias T = Direction
|
||||
public typealias C = Direction
|
||||
public static func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<(Direction, CompilerContext)> {
|
||||
) -> Result<Direction> {
|
||||
let direction_node = node
|
||||
#RequireNodeType<Node, (Direction, CompilerContext)>(
|
||||
#RequireNodeType<Node, Direction>(
|
||||
node: direction_node, type: "direction", nice_type_name: "direction")
|
||||
let directions = [
|
||||
"in": Direction.In,
|
||||
@@ -137,17 +137,17 @@ extension Direction: Compilable {
|
||||
withError: "\(direction_node.text!) is not a valid direction"))
|
||||
}
|
||||
|
||||
return .Ok((parsed_direction, context))
|
||||
return .Ok(parsed_direction)
|
||||
}
|
||||
}
|
||||
|
||||
extension Parameter: Compilable {
|
||||
public typealias T = Parameter
|
||||
public typealias C = Parameter
|
||||
public static func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<(Parameter, CompilerContext)> {
|
||||
) -> Result<Parameter> {
|
||||
|
||||
#RequireNodeType<Node, (EvaluatableStatement, CompilerContext)>(
|
||||
#RequireNodeType<Node, P4Statement>(
|
||||
node: node, type: "parameter", nice_type_name: "parameter")
|
||||
|
||||
var walker = Walker(node: node)
|
||||
@@ -155,7 +155,7 @@ extension Parameter: Compilable {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(Parameter, CompilerContext)>.Error(
|
||||
or: Result<Parameter>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing parameter declaration component")))
|
||||
@@ -171,7 +171,7 @@ extension Parameter: Compilable {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(Parameter, CompilerContext)>.Error(
|
||||
or: Result<Parameter>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing parameter declaration component")))
|
||||
@@ -181,7 +181,7 @@ extension Parameter: Compilable {
|
||||
if current_node!.nodeType == "direction" {
|
||||
|
||||
let maybe_parsed_direction = Direction.Compile(node: current_node!, withContext: context)
|
||||
guard case .Ok((let parsed_direction, _)) = maybe_parsed_direction else {
|
||||
guard case .Ok(let parsed_direction) = maybe_parsed_direction else {
|
||||
return .Error(maybe_parsed_direction.error()!)
|
||||
}
|
||||
direction = parsed_direction
|
||||
@@ -191,7 +191,7 @@ extension Parameter: Compilable {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(Parameter, CompilerContext)>.Error(
|
||||
or: Result<Parameter>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing parameter declaration component")))
|
||||
@@ -213,7 +213,7 @@ extension Parameter: Compilable {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(Parameter, CompilerContext)>.Error(
|
||||
or: Result<Parameter>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing parameter declaration component")))
|
||||
@@ -233,43 +233,41 @@ extension Parameter: Compilable {
|
||||
}
|
||||
|
||||
return Result.Ok(
|
||||
(
|
||||
Parameter(
|
||||
identifier: parameter_name,
|
||||
withType: direction != nil
|
||||
? parameter_type.update(addAttribute: P4TypeQualifier.Direction(direction!))
|
||||
: parameter_type),
|
||||
context
|
||||
))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func argument_list_compiler(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(ArgumentList, CompilerContext)> {
|
||||
) -> Common.Result<ArgumentList> {
|
||||
|
||||
var walker = Walker(node: node)
|
||||
var current_node: Node? = .none
|
||||
|
||||
if node.text == ")" {
|
||||
// There are no arguments!
|
||||
return Result.Ok((ArgumentList([]), context))
|
||||
return Result.Ok(ArgumentList([]))
|
||||
}
|
||||
|
||||
#RequireNodeType<Node, (ArgumentList, CompilerContext)>(
|
||||
#RequireNodeType<Node, ArgumentList>(
|
||||
node: node, type: "argument_list", nice_type_name: "argument List")
|
||||
|
||||
var arguments: ArgumentList = ArgumentList([])
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(ArgumentList, CompilerContext)>.Error(
|
||||
or: Result<ArgumentList>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing argument list component")))
|
||||
|
||||
if current_node?.nodeType == "argument_list" {
|
||||
switch argument_list_compiler(node: current_node!, withContext: context) {
|
||||
case .Ok(let (ps, _)):
|
||||
case .Ok(let ps):
|
||||
arguments = ps
|
||||
case .Error(let e): return Result.Error(e)
|
||||
}
|
||||
@@ -280,13 +278,13 @@ func argument_list_compiler(
|
||||
// We may have moved nodes, check/reset current_node.
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(ArgumentList, CompilerContext)>.Error(
|
||||
or: Result<ArgumentList>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing argument list component")))
|
||||
|
||||
// If this is a ')', we are done.
|
||||
if current_node?.text == ")" {
|
||||
return Result.Ok((arguments, context))
|
||||
return Result.Ok(arguments)
|
||||
}
|
||||
|
||||
// If this is a comma, we skip it!
|
||||
@@ -296,27 +294,27 @@ func argument_list_compiler(
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(ArgumentList, CompilerContext)>.Error(
|
||||
or: Result<ArgumentList>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing argument list component")))
|
||||
|
||||
// Otherwise, there should be one argument left!
|
||||
switch Argument.Compile(node: current_node!, withContext: context) {
|
||||
case .Ok(let (ce, updated_context)):
|
||||
case .Ok(let ce):
|
||||
return Result.Ok(
|
||||
(arguments.addArgument(Argument(ce, atIndex: arguments.count() + 1)), updated_context))
|
||||
arguments.addArgument(Argument(ce, atIndex: arguments.count() + 1)))
|
||||
case .Error(let e): return Result.Error(e)
|
||||
}
|
||||
}
|
||||
|
||||
extension ArgumentList: Compilable {
|
||||
public typealias T = ArgumentList
|
||||
public typealias C = ArgumentList
|
||||
public static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(ArgumentList, CompilerContext)> {
|
||||
) -> Common.Result<ArgumentList> {
|
||||
|
||||
let argument_node = node
|
||||
#RequireNodeType<Node, (ArgumentList, CompilerContext)>(
|
||||
#RequireNodeType<Node, ArgumentList>(
|
||||
node: argument_node, type: "arguments", nice_type_name: "arguments")
|
||||
|
||||
var walker = Walker(node: argument_node)
|
||||
@@ -324,7 +322,7 @@ extension ArgumentList: Compilable {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(ArgumentList, CompilerContext)>.Error(
|
||||
or: Result<ArgumentList>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing '(' in argument list component")))
|
||||
@@ -333,7 +331,7 @@ extension ArgumentList: Compilable {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(ArgumentList, CompilerContext)>.Error(
|
||||
or: Result<ArgumentList>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing argument list component")))
|
||||
|
||||
@@ -342,25 +340,25 @@ extension ArgumentList: Compilable {
|
||||
}
|
||||
|
||||
extension Argument: Compilable {
|
||||
public typealias T = EvaluatableExpression
|
||||
public typealias C = P4Expression
|
||||
public static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(EvaluatableExpression, CompilerContext)> {
|
||||
) -> Common.Result<P4Expression> {
|
||||
let argument_node = node
|
||||
#RequireNodeType<Node, (EvaluatableExpression, CompilerContext)>(
|
||||
#RequireNodeType<Node, P4Expression>(
|
||||
node: argument_node, type: "argument", nice_type_name: "argument")
|
||||
|
||||
let expression_node = node.child(at: 0)!
|
||||
|
||||
return switch Expression.Compile(node: expression_node, withContext: context) {
|
||||
case .Ok(let compiled_expression): .Ok((compiled_expression, context))
|
||||
case .Ok(let compiled_expression): .Ok(compiled_expression)
|
||||
case .Error(let e): .Error(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func ContainsInvalidStatements(
|
||||
statement: EvaluatableStatement, invalids: [EvaluatableStatement.Type]
|
||||
statement: P4Statement, invalids: [P4Statement.Type]
|
||||
) -> Bool {
|
||||
for es in invalids {
|
||||
if type(of: statement) == es {
|
||||
@@ -370,8 +368,7 @@ func ContainsInvalidStatements(
|
||||
return false
|
||||
}
|
||||
|
||||
func ContainsInvalidStatements(block: BlockStatement, invalids: [EvaluatableStatement.Type]) -> Bool
|
||||
{
|
||||
func ContainsInvalidStatements(block: BlockStatement, invalids: [P4Statement.Type]) -> Bool {
|
||||
return block.statements.contains { statement in
|
||||
for es in invalids {
|
||||
if type(of: statement) == es {
|
||||
|
||||
@@ -34,124 +34,3 @@ public func ConfigureP4Parser() -> Result<SwiftTreeSitter.Parser> {
|
||||
|
||||
return .Ok(p)
|
||||
}
|
||||
|
||||
/// Context for compilation
|
||||
///
|
||||
/// It contains (at least) three important pieces of information:
|
||||
/// 1. Instances: A ``VarTypeScopes`` that contains information about instantiated objects
|
||||
/// (and their types) in scope
|
||||
/// 1. Types: A ``TypeTypeScopes`` that contains information about declared types in scope.
|
||||
/// 1. Expected Type: In certain situations, to typecheck an element of a P4 program requires
|
||||
/// knowledge of an expected type. For instance, when compiling a return statement, the
|
||||
/// compiler must know the return type of the function to type check.
|
||||
public struct CompilerContext {
|
||||
let instances: StaticVarValueScopes
|
||||
let types: TypeTypeScopes
|
||||
let externs: TypeTypeScopes
|
||||
let ffis: [P4FFI]
|
||||
let expected_type: P4QualifiedType?
|
||||
let extern_context: Bool
|
||||
|
||||
public init() {
|
||||
instances = StaticVarValueScopes().enter()
|
||||
types = TypeTypeScopes().enter()
|
||||
externs = TypeTypeScopes().enter()
|
||||
expected_type = .none
|
||||
extern_context = false
|
||||
ffis = Array()
|
||||
}
|
||||
|
||||
public init(withInstances _instances: StaticVarValueScopes, withTypes _types: TypeTypeScopes) {
|
||||
instances = _instances
|
||||
types = _types
|
||||
externs = TypeTypeScopes().enter()
|
||||
expected_type = .none
|
||||
extern_context = false
|
||||
ffis = Array()
|
||||
}
|
||||
|
||||
public init(
|
||||
withInstances _instances: StaticVarValueScopes, withTypes _types: TypeTypeScopes,
|
||||
withExpectation expectation: P4QualifiedType?, withExtern extern: Bool,
|
||||
withExterns externs: TypeTypeScopes, withFFIs foreigns: [P4FFI]
|
||||
) {
|
||||
instances = _instances
|
||||
types = _types
|
||||
expected_type = expectation
|
||||
extern_context = extern
|
||||
self.externs = externs
|
||||
ffis = foreigns
|
||||
}
|
||||
|
||||
/// Update a compiler context
|
||||
///
|
||||
/// Create a new compiler context based on the current but new instances.
|
||||
///
|
||||
/// - Parameter instances: a ``VarTypeScopes`` with the updated instances for the newly created compiler context.
|
||||
/// - Returns: A new compiler context based on the current but new instances.
|
||||
public func update(newInstances instances: StaticVarValueScopes) -> CompilerContext {
|
||||
return CompilerContext(
|
||||
withInstances: instances, withTypes: self.types, withExpectation: self.expected_type,
|
||||
withExtern: self.extern_context, withExterns: self.externs, withFFIs: self.ffis)
|
||||
}
|
||||
|
||||
/// Update a compiler context
|
||||
///
|
||||
/// Create a new compiler context based on the current but new types.
|
||||
///
|
||||
/// - Parameter types: a ``TypeTypeScopes`` with the updated types for the newly created compiler context.
|
||||
/// - Returns: A new compiler context based on the current but new types.
|
||||
public func update(newTypes types: TypeTypeScopes) -> CompilerContext {
|
||||
return CompilerContext(
|
||||
withInstances: self.instances, withTypes: types, withExpectation: self.expected_type,
|
||||
withExtern: self.extern_context, withExterns: self.externs, withFFIs: self.ffis)
|
||||
}
|
||||
|
||||
/// Update a compiler context
|
||||
///
|
||||
/// Create a new compiler context based on the current but new expected type.
|
||||
///
|
||||
/// - Parameter expectation: a ``P4Type?`` to (re)set the type the compiler is expecting.
|
||||
/// - Returns: A new compiler context based on the current but new expected type.
|
||||
public func update(newExpectation expectation: P4QualifiedType?) -> CompilerContext {
|
||||
return CompilerContext(
|
||||
withInstances: self.instances, withTypes: self.types, withExpectation: expectation,
|
||||
withExtern: self.extern_context, withExterns: self.externs, withFFIs: self.ffis)
|
||||
}
|
||||
|
||||
/// Update a compiler context
|
||||
///
|
||||
/// Create a new compiler context based on the current but new extern context value.
|
||||
///
|
||||
/// - Parameter extern: a ``Bool`` to (re)set whether the compiler is compiling in an extern context.
|
||||
/// - Returns: A new compiler context based on the current but new extern context value.
|
||||
public func update(newExtern extern: Bool) -> CompilerContext {
|
||||
return CompilerContext(
|
||||
withInstances: self.instances, withTypes: self.types, withExpectation: self.expected_type,
|
||||
withExtern: extern, withExterns: self.externs, withFFIs: self.ffis)
|
||||
}
|
||||
|
||||
/// Update a compiler context
|
||||
///
|
||||
/// Create a new compiler context based on the current but new externs.
|
||||
///
|
||||
/// - Parameter externs: a ``TypeTypeScopes`` to (re)set the list of extern-al declarations.
|
||||
/// - Returns: A new compiler context based on the current but new list of external-al declarations.
|
||||
public func update(newExterns externs: TypeTypeScopes) -> CompilerContext {
|
||||
return CompilerContext(
|
||||
withInstances: self.instances, withTypes: self.types, withExpectation: self.expected_type,
|
||||
withExtern: self.extern_context, withExterns: externs, withFFIs: self.ffis)
|
||||
}
|
||||
|
||||
/// Update a compiler context
|
||||
///
|
||||
/// Create a new compiler context based on the current but new FFIs.
|
||||
///
|
||||
/// - Parameter foreigns: an array of ``P4FFI`` to (re)set the list of foreign functions.
|
||||
/// - Returns: A new compiler context based on the current but with a new list of foreign functions.
|
||||
public func update(newFFIs foreigns: [P4FFI]) -> CompilerContext {
|
||||
return CompilerContext(
|
||||
withInstances: self.instances, withTypes: self.types, withExpectation: self.expected_type,
|
||||
withExtern: self.extern_context, withExterns: externs, withFFIs: foreigns)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,33 +22,61 @@ import SwiftTreeSitter
|
||||
import TreeSitterExtensions
|
||||
import TreeSitterP4
|
||||
|
||||
extension Declaration: CompilableDeclaration {
|
||||
extension Declaration: CompilableStatement {
|
||||
public static func CompileStatement(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<P4Statement> {
|
||||
return switch Compile(node: node, withContext: context) {
|
||||
case .Ok(let res): .Ok(res)
|
||||
case .Error(let e): .Error(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Declaration: Compilable {
|
||||
public typealias C = Declaration
|
||||
public static func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<(Declaration, CompilerContext)?> {
|
||||
) -> Result<Declaration> {
|
||||
|
||||
let declaration_compilers: [String: CompilableDeclaration.Type] = [
|
||||
// Be kind to our user -- if we are at a declaration node, dive into it!
|
||||
let declaration_node =
|
||||
if node.nodeType == "declaration" {
|
||||
node.child(at: 0)!
|
||||
} else {
|
||||
node
|
||||
}
|
||||
|
||||
let declaration_compilers: [String: any Compilable<Declaration>.Type] = [
|
||||
"function_declaration": FunctionDeclaration.self,
|
||||
"control_declaration": Control.self,
|
||||
"type_declaration": P4Struct.self,
|
||||
"parserDeclaration": Parser.self,
|
||||
/// ASSUME: Type declarations are struct declarations.
|
||||
"extern_declaration": ExternDeclaration.self,
|
||||
]
|
||||
|
||||
guard let declaration_compiler = declaration_compilers[node.nodeType!] else {
|
||||
return .Ok(.none)
|
||||
guard let declaration_compiler = declaration_compilers[declaration_node.nodeType!] else {
|
||||
return .Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Could not find parser for declaration \(declaration_node.nodeType!)"))
|
||||
}
|
||||
|
||||
return declaration_compiler.Compile(node: node, withContext: context)
|
||||
return declaration_compiler.Compile(node: declaration_node, withContext: context).map {
|
||||
result in
|
||||
.Ok(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension FunctionDeclaration: CompilableDeclaration {
|
||||
extension FunctionDeclaration: Compilable {
|
||||
public typealias C = Declaration
|
||||
public static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(Declaration, CompilerContext)?> {
|
||||
) -> Common.Result<Declaration> {
|
||||
let function_declaration_node = node
|
||||
#RequireNodeType<Node, (ParameterList, CompilerContext)>(
|
||||
#RequireNodeType<Node, ParameterList>(
|
||||
node: function_declaration_node, type: "function_declaration",
|
||||
nice_type_name: "Function Declaration")
|
||||
|
||||
@@ -59,7 +87,7 @@ extension FunctionDeclaration: CompilableDeclaration {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||
or: Result<Declaration>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: function_declaration_node.toSourceLocation(),
|
||||
withError: "Missing function declaration component")))
|
||||
@@ -72,7 +100,7 @@ extension FunctionDeclaration: CompilableDeclaration {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||
or: Result<Declaration>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: function_declaration_node.toSourceLocation(),
|
||||
withError: "Missing function declaration component")))
|
||||
@@ -85,17 +113,16 @@ extension FunctionDeclaration: CompilableDeclaration {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||
or: Result<Declaration>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: function_declaration_node.toSourceLocation(),
|
||||
withError: "Missing function declaration component")))
|
||||
|
||||
let maybe_function_parameters = ParameterList.Compile(node: current_node!, withContext: context)
|
||||
guard case .Ok((let function_parameters, let updated_context)) = maybe_function_parameters
|
||||
guard case .Ok(let function_parameters) = maybe_function_parameters
|
||||
else {
|
||||
return .Error(maybe_function_parameters.error()!)
|
||||
}
|
||||
context = updated_context
|
||||
|
||||
var function_body: BlockStatement? = .none
|
||||
|
||||
@@ -113,10 +140,10 @@ extension FunctionDeclaration: CompilableDeclaration {
|
||||
withContext: context.update(newInstances: function_scope).update(
|
||||
newExpectation: function_type))
|
||||
|
||||
guard case .Ok((let parsed_function_body, _)) = maybe_function_body else {
|
||||
guard case .Ok(let parsed_function_body) = maybe_function_body else {
|
||||
return .Error(maybe_function_body.error()!)
|
||||
}
|
||||
function_body = (parsed_function_body as! BlockStatement)
|
||||
function_body = parsed_function_body
|
||||
} else {
|
||||
|
||||
// If we are in an extern context, no body is okay!
|
||||
@@ -142,33 +169,29 @@ extension FunctionDeclaration: CompilableDeclaration {
|
||||
// And, do not update the context if we are compiling in an
|
||||
// extern context -- the wrapping extern declaration will take care of that.
|
||||
return .Ok(
|
||||
(
|
||||
function_declaration,
|
||||
context.extern_context
|
||||
? context
|
||||
: context.update(
|
||||
newTypes: context.types.declare(
|
||||
identifier: function_name, withValue: function_declaration.identifier.type.baseType())
|
||||
)
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
extension P4Struct: CompilableDeclaration {
|
||||
extension P4Struct: Compilable {
|
||||
public typealias C = Declaration
|
||||
static public func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<(Declaration, CompilerContext)?> {
|
||||
) -> Result<Declaration> {
|
||||
let struct_declaration_node = node.child(at: 0)!
|
||||
var walker = Walker(node: struct_declaration_node)
|
||||
var currentNode: Node? = .none
|
||||
|
||||
#SkipUnlessNodeType(node: struct_declaration_node, type: "struct_declaration")
|
||||
#RequireNodeType<Node, Result<Declaration>>(
|
||||
node: struct_declaration_node, type: "struct_declaration",
|
||||
nice_type_name: "struct declaration")
|
||||
|
||||
// Skip the keyword struct
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: currentNode, thing: walker.getNext(),
|
||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||
or: Result<Declaration>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: struct_declaration_node.toSourceLocation(),
|
||||
withError: "Missing function declaration component")))
|
||||
@@ -185,7 +208,7 @@ extension P4Struct: CompilableDeclaration {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: currentNode, thing: walker.getNext(),
|
||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||
or: Result<Declaration>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: struct_declaration_node.toSourceLocation(),
|
||||
withError: "Missing function declaration component")))
|
||||
@@ -197,15 +220,7 @@ extension P4Struct: CompilableDeclaration {
|
||||
id: struct_identifier,
|
||||
withType: P4QualifiedType(
|
||||
P4Struct(withName: struct_identifier, andFields: P4StructFields([])))))
|
||||
return Result.Ok(
|
||||
(
|
||||
struc,
|
||||
context.extern_context
|
||||
? context
|
||||
: context.update(
|
||||
newTypes: context.types.declare(
|
||||
identifier: struct_identifier, withValue: struc.identifier.type.baseType()))
|
||||
))
|
||||
return Result.Ok(struc)
|
||||
}
|
||||
|
||||
var parse_errs: (any Errorable)? = .none
|
||||
@@ -217,13 +232,12 @@ extension P4Struct: CompilableDeclaration {
|
||||
switch VariableDeclarationStatement.Compile(
|
||||
node: declaration_field, withContext: current_context)
|
||||
{
|
||||
case .Ok((let declaration, let updated_context)):
|
||||
case .Ok(let declaration):
|
||||
let variable_declaration = declaration as! VariableDeclarationStatement
|
||||
parsed_fields.append(
|
||||
P4StructFieldIdentifier(
|
||||
id: variable_declaration.identifier, withType: variable_declaration.initializer.type()
|
||||
))
|
||||
current_context = updated_context
|
||||
case .Error(let e):
|
||||
parse_errs =
|
||||
if let e = parse_errs {
|
||||
@@ -245,24 +259,19 @@ extension P4Struct: CompilableDeclaration {
|
||||
withType: P4QualifiedType(
|
||||
P4Struct(
|
||||
withName: struct_identifier, andFields: P4StructFields(parsed_fields)))))
|
||||
return .Ok(
|
||||
(
|
||||
declared_struct,
|
||||
current_context.extern_context
|
||||
? current_context
|
||||
: current_context.update(
|
||||
newTypes: current_context.types.declare(
|
||||
identifier: struct_identifier, withValue: declared_struct.identifier.type.baseType()))
|
||||
))
|
||||
return .Ok(declared_struct)
|
||||
}
|
||||
}
|
||||
|
||||
extension P4Lang.Parser: CompilableDeclaration {
|
||||
extension P4Lang.Parser: Compilable {
|
||||
public typealias C = Declaration
|
||||
|
||||
public static func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<(Declaration, CompilerContext)?> {
|
||||
) -> Result<Declaration> {
|
||||
let parser_node = node
|
||||
#SkipUnlessNodeType<Node>(node: parser_node, type: "parserDeclaration")
|
||||
#RequireNodeType<Node, Result<Declaration>>(
|
||||
node: parser_node, type: "parserDeclaration", nice_type_name: "parser declaration")
|
||||
var current_context = context
|
||||
|
||||
var walker = Walker(node: parser_node)
|
||||
@@ -270,7 +279,7 @@ extension P4Lang.Parser: CompilableDeclaration {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||
or: Result<Declaration>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: parser_node.toSourceLocation(),
|
||||
withError: "Missing elements of parser declaration")))
|
||||
@@ -294,7 +303,7 @@ extension P4Lang.Parser: CompilableDeclaration {
|
||||
|
||||
#MustOr(
|
||||
result: type_node_child, thing: type_node_walker.getNext(),
|
||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||
or: Result<Declaration>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: parser_node.toSourceLocation(),
|
||||
withError: "Missing elements of parser type in parser declaration")))
|
||||
@@ -310,7 +319,7 @@ extension P4Lang.Parser: CompilableDeclaration {
|
||||
type_node_walker.next()
|
||||
#MustOr(
|
||||
result: type_node_child, thing: type_node_walker.getNext(),
|
||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||
or: Result<Declaration>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: type_node_child!.toSourceLocation(),
|
||||
withError: "Missing name in parser type declaration")))
|
||||
@@ -324,15 +333,14 @@ extension P4Lang.Parser: CompilableDeclaration {
|
||||
type_node_walker.next()
|
||||
#MustOr(
|
||||
result: type_node_child, thing: type_node_walker.getNext(),
|
||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||
or: Result<Declaration>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: type_node_child!.toSourceLocation(),
|
||||
withError: "Missing parser parameters")))
|
||||
|
||||
switch ParameterList.Compile(node: type_node_child!, withContext: current_context) {
|
||||
case .Ok(let (parsed_parameter_list, updated_context)):
|
||||
case .Ok(let parsed_parameter_list):
|
||||
parameter_list = parsed_parameter_list
|
||||
current_context = updated_context
|
||||
case .Error(let e):
|
||||
return .Error(e)
|
||||
}
|
||||
@@ -348,7 +356,7 @@ extension P4Lang.Parser: CompilableDeclaration {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||
or: Result<Declaration>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: parser_node.toSourceLocation(),
|
||||
withError: "Missing parser declaration component")))
|
||||
@@ -356,7 +364,7 @@ extension P4Lang.Parser: CompilableDeclaration {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||
or: Result<Declaration>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: parser_node.toSourceLocation(),
|
||||
withError: "Missing elements of parser declaration")))
|
||||
@@ -371,7 +379,7 @@ extension P4Lang.Parser: CompilableDeclaration {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||
or: Result<Declaration>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: parser_node.toSourceLocation(),
|
||||
withError: "Missing body of parser declaration")))
|
||||
@@ -381,7 +389,7 @@ extension P4Lang.Parser: CompilableDeclaration {
|
||||
}
|
||||
|
||||
/// TODO: Handle extern parsers.
|
||||
switch SpecialCompilers.Compile(
|
||||
switch SpecialCompilers.CompileParserBody(
|
||||
withName: parser_name!, withParameters: parameter_list, node: current_node!,
|
||||
withContext: current_context)
|
||||
{
|
||||
@@ -390,24 +398,21 @@ extension P4Lang.Parser: CompilableDeclaration {
|
||||
TypedIdentifier(id: parser.name, withType: P4QualifiedType(parser)))
|
||||
// Create a new context with the name of the parser that was just compiled in scope.
|
||||
return .Ok(
|
||||
(
|
||||
parser_declaration,
|
||||
context.extern_context
|
||||
? context
|
||||
: updated_context.update(
|
||||
newTypes: updated_context.types.declare(identifier: parser.name, withValue: parser))
|
||||
))
|
||||
)
|
||||
case Result.Error(let error): return .Error(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Control: CompilableDeclaration {
|
||||
extension Control: Compilable {
|
||||
public typealias C = Declaration
|
||||
public static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(Declaration, CompilerContext)?> {
|
||||
) -> Common.Result<Declaration> {
|
||||
|
||||
#SkipUnlessNodeType<Node>(node: node, type: "control_declaration")
|
||||
#RequireNodeType<Node, Result<Declaration>>(
|
||||
node: node, type: "control_declaration", nice_type_name: "control declaration")
|
||||
|
||||
var walker = Walker(node: node)
|
||||
var current_node: Node? = .none
|
||||
@@ -417,7 +422,7 @@ extension Control: CompilableDeclaration {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||
or: Result<Declaration>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing control declaration component")))
|
||||
@@ -433,18 +438,17 @@ extension Control: CompilableDeclaration {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||
or: Result<Declaration>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing control declaration component")))
|
||||
|
||||
let maybe_control_parameters = ParameterList.Compile(
|
||||
node: current_node!, withContext: local_context)
|
||||
guard case .Ok((let control_parameters, let updated_context)) = maybe_control_parameters
|
||||
guard case .Ok(let control_parameters) = maybe_control_parameters
|
||||
else {
|
||||
return .Error(maybe_control_parameters.error()!)
|
||||
}
|
||||
local_context = updated_context
|
||||
|
||||
// Before continuing, make sure to put the parameters into context.
|
||||
var control_scope = local_context.instances.enter()
|
||||
@@ -459,7 +463,7 @@ extension Control: CompilableDeclaration {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(Declaration, CompilerContext)?>.Error(
|
||||
or: Result<Declaration>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing control declaration component")))
|
||||
@@ -476,12 +480,11 @@ extension Control: CompilableDeclaration {
|
||||
let maybe_action_declaration = Action.Compile(
|
||||
node: current_node, withContext: local_context)
|
||||
guard
|
||||
case .Ok((let action_declaration, let updated_context)) = maybe_action_declaration
|
||||
case .Ok(let action_declaration) = maybe_action_declaration
|
||||
else {
|
||||
return .Error(maybe_action_declaration.error()!)
|
||||
}
|
||||
actions.append(action_declaration)
|
||||
local_context = updated_context
|
||||
// Now, add the declaration into the context.
|
||||
local_context = local_context.update(
|
||||
newTypes: local_context.types.declare(
|
||||
@@ -490,22 +493,20 @@ extension Control: CompilableDeclaration {
|
||||
let maybe_table_declaration = Table.Compile(
|
||||
node: current_node, withContext: local_context)
|
||||
guard
|
||||
case .Ok((let table_declaration, let updated_context)) = maybe_table_declaration
|
||||
case .Ok(let table_declaration) = maybe_table_declaration
|
||||
else {
|
||||
return .Error(maybe_table_declaration.error()!)
|
||||
}
|
||||
tables.append(table_declaration)
|
||||
local_context = updated_context
|
||||
} else if current_node.nodeType == "apply_statement" {
|
||||
// When we see an apply, that is it for the actions and the tables.
|
||||
let maybe_apply_statement = ApplyStatement.Compile(
|
||||
node: current_node, withContext: local_context)
|
||||
guard
|
||||
case .Ok((let apply_statement, let updated_context)) = maybe_apply_statement
|
||||
case .Ok(let apply_statement) = maybe_apply_statement
|
||||
else {
|
||||
return .Error(maybe_apply_statement.error()!)
|
||||
}
|
||||
local_context = updated_context
|
||||
apply = (apply_statement as! ApplyStatement)
|
||||
|
||||
// The apply is the last thing in a control declaration.
|
||||
@@ -555,24 +556,16 @@ extension Control: CompilableDeclaration {
|
||||
|
||||
// Don't forget to add the newly declared Control to the instance that we were given
|
||||
// (and not the one that we entered to do the parsing of this Control).
|
||||
return .Ok(
|
||||
(
|
||||
declared_control,
|
||||
context.extern_context
|
||||
? context
|
||||
: context.update(
|
||||
newTypes: context.types.declare(
|
||||
identifier: control_name, withValue: control))
|
||||
))
|
||||
return .Ok(declared_control)
|
||||
}
|
||||
}
|
||||
|
||||
extension Action: Compilable {
|
||||
public typealias T = Action
|
||||
public typealias C = Action
|
||||
public static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(Action, CompilerContext)> {
|
||||
#RequireNodeType<Node, (P4Type, CompilerContext)>(
|
||||
) -> Result<Action> {
|
||||
#RequireNodeType<Node, P4Type>(
|
||||
node: node, type: "action_declaration", nice_type_name: "Action Declaration")
|
||||
|
||||
var walker = Walker(node: node)
|
||||
@@ -584,7 +577,7 @@ extension Action: Compilable {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(Action, CompilerContext)>.Error(
|
||||
or: Result<Action>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing action declaration component"
|
||||
))
|
||||
@@ -601,7 +594,7 @@ extension Action: Compilable {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(Action, CompilerContext)>.Error(
|
||||
or: Result<Action>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing action declaration component"
|
||||
))
|
||||
@@ -609,11 +602,10 @@ extension Action: Compilable {
|
||||
|
||||
let maybe_action_parameters = ParameterList.Compile(
|
||||
node: current_node!, withContext: current_context)
|
||||
guard case .Ok((let action_parameters, let updated_context)) = maybe_action_parameters
|
||||
guard case .Ok(let action_parameters) = maybe_action_parameters
|
||||
else {
|
||||
return .Error(maybe_action_parameters.error()!)
|
||||
}
|
||||
current_context = updated_context
|
||||
|
||||
// Check whether the parameters are in the proper order.
|
||||
let remaining_parameters = action_parameters.parameters.drop(while: {
|
||||
@@ -629,7 +621,7 @@ extension Action: Compilable {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(Action, CompilerContext)>.Error(
|
||||
or: Result<Action>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing action declaration component"
|
||||
))
|
||||
@@ -644,29 +636,26 @@ extension Action: Compilable {
|
||||
|
||||
let maybe_action_body = BlockStatement.Compile(
|
||||
node: current_node!, withContext: context.update(newInstances: function_scope))
|
||||
guard case .Ok((let action_body, _)) = maybe_action_body else {
|
||||
guard case .Ok(let action_body) = maybe_action_body else {
|
||||
return .Error(maybe_action_body.error()!)
|
||||
}
|
||||
|
||||
/// TODO: Actions cannot contain switches!
|
||||
|
||||
return .Ok(
|
||||
(
|
||||
Action(
|
||||
named: action_name, withParameters: action_parameters,
|
||||
withBody: (action_body as! BlockStatement)),
|
||||
current_context
|
||||
))
|
||||
withBody: (action_body as! BlockStatement)))
|
||||
}
|
||||
}
|
||||
|
||||
extension TableKeyEntry: Compilable {
|
||||
public typealias T = TableKeyEntry
|
||||
public typealias C = TableKeyEntry
|
||||
public static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(TableKeyEntry, CompilerContext)> {
|
||||
) -> Result<TableKeyEntry> {
|
||||
|
||||
#RequireNodeType<Node, (P4Type, CompilerContext)>(
|
||||
#RequireNodeType<Node, TableKeyEntry>(
|
||||
node: node, type: "table_key_entry", nice_type_name: "Table Key Entry")
|
||||
|
||||
var walker = Walker(node: node)
|
||||
@@ -677,7 +666,7 @@ extension TableKeyEntry: Compilable {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(TableKeyEntry, CompilerContext)>.Error(
|
||||
or: Result<TableKeyEntry>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing table key entry declaration component")))
|
||||
@@ -693,31 +682,31 @@ extension TableKeyEntry: Compilable {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(TableKeyEntry, CompilerContext)>.Error(
|
||||
or: Result<TableKeyEntry>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing table key entry declaration component")))
|
||||
|
||||
let maybe_match_type = TableKeyMatchType.Compile(
|
||||
node: current_node!, withContext: current_context)
|
||||
guard case .Ok((let match_type, _)) = maybe_match_type else {
|
||||
guard case .Ok(let match_type) = maybe_match_type else {
|
||||
return .Error(maybe_match_type.error()!)
|
||||
}
|
||||
|
||||
return .Ok((TableKeyEntry(keyset_expression as! KeysetExpression, match_type), current_context))
|
||||
return .Ok(TableKeyEntry(keyset_expression as! KeysetExpression, match_type))
|
||||
}
|
||||
}
|
||||
|
||||
extension TableKeyMatchType: Compilable {
|
||||
public typealias T = TableKeyMatchType
|
||||
public typealias C = TableKeyMatchType
|
||||
public static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(TableKeyMatchType, CompilerContext)> {
|
||||
#RequireNodeType<Node, (TableKeyMatchType, CompilerContext)>(
|
||||
) -> Result<TableKeyMatchType> {
|
||||
#RequireNodeType<Node, TableKeyMatchType>(
|
||||
node: node, type: "table_key_match_type", nice_type_name: "Table Key Match Type")
|
||||
|
||||
if node.text! == "exact" {
|
||||
return .Ok((TableKeyMatchType.Exact, context))
|
||||
return .Ok(TableKeyMatchType.Exact)
|
||||
}
|
||||
return .Error(
|
||||
ErrorWithLocation(
|
||||
@@ -727,11 +716,11 @@ extension TableKeyMatchType: Compilable {
|
||||
}
|
||||
|
||||
extension TableKeys: Compilable {
|
||||
public typealias T = TableKeys
|
||||
public typealias C = TableKeys
|
||||
public static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(TableKeys, CompilerContext)> {
|
||||
#RequireNodeType<Node, (TableKeyMatchType, CompilerContext)>(
|
||||
) -> Result<TableKeys> {
|
||||
#RequireNodeType<Node, TableKeyMatchType>(
|
||||
node: node, type: "table_keys", nice_type_name: "Table Keys")
|
||||
|
||||
var walker = Walker(node: node)
|
||||
@@ -746,7 +735,7 @@ extension TableKeys: Compilable {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(TableKeys, CompilerContext)>.Error(
|
||||
or: Result<TableKeys>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing table keys declaration component in control declaration"))
|
||||
@@ -754,7 +743,7 @@ extension TableKeys: Compilable {
|
||||
|
||||
let (keys, errors) = walker.try_map(n: node.childCount - 1, onlyNamed: true) { current_node in
|
||||
return switch TableKeyEntry.Compile(node: current_node, withContext: context) {
|
||||
case .Ok((let keyset_expression, _)): .Ok(keyset_expression)
|
||||
case .Ok(let keyset_expression): .Ok(keyset_expression)
|
||||
case .Error(let e): .Error(e)
|
||||
}
|
||||
}
|
||||
@@ -769,16 +758,16 @@ extension TableKeys: Compilable {
|
||||
}.joined(separator: ";"))))
|
||||
}
|
||||
|
||||
return .Ok((TableKeys(withEntries: keys), context))
|
||||
return .Ok(TableKeys(withEntries: keys))
|
||||
}
|
||||
}
|
||||
|
||||
extension TableActionsProperty: Compilable {
|
||||
public typealias T = TableActionsProperty
|
||||
public typealias C = TableActionsProperty
|
||||
public static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(TableActionsProperty, CompilerContext)> {
|
||||
#RequireNodeType<Node, (TableActionsProperty, CompilerContext)>(
|
||||
) -> Result<TableActionsProperty> {
|
||||
#RequireNodeType<Node, TableActionsProperty>(
|
||||
node: node, type: "table_actions", nice_type_name: "Table Actions")
|
||||
|
||||
var walker = Walker(node: node)
|
||||
@@ -793,7 +782,7 @@ extension TableActionsProperty: Compilable {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(TableActionsProperty, CompilerContext)>.Error(
|
||||
or: Result<TableActionsProperty>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing table actions declaration component in control declaration"))
|
||||
@@ -828,16 +817,16 @@ extension TableActionsProperty: Compilable {
|
||||
}.joined(separator: ";"))))
|
||||
}
|
||||
|
||||
return .Ok((TableActionsProperty(actions), context))
|
||||
return .Ok(TableActionsProperty(actions))
|
||||
}
|
||||
}
|
||||
extension TablePropertyList: Compilable {
|
||||
public typealias T = TablePropertyList
|
||||
public typealias C = TablePropertyList
|
||||
public static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(TablePropertyList, CompilerContext)> {
|
||||
) -> Result<TablePropertyList> {
|
||||
|
||||
#RequireNodeType<Node, (P4Type, CompilerContext)>(
|
||||
#RequireNodeType<Node, TablePropertyList>(
|
||||
node: node, type: "table_property_list", nice_type_name: "Table Property List")
|
||||
|
||||
var current_context = context
|
||||
@@ -849,15 +838,13 @@ extension TablePropertyList: Compilable {
|
||||
node.enumerateNamedChildren { child in
|
||||
if child.nodeType == "table_keys" {
|
||||
switch TableKeys.Compile(node: child, withContext: current_context) {
|
||||
case .Ok((let table_key, let updated_context)):
|
||||
current_context = updated_context
|
||||
case .Ok(let table_key):
|
||||
keys.append(table_key)
|
||||
case .Error(let e): errors.append(e)
|
||||
}
|
||||
} else if child.nodeType == "table_actions" {
|
||||
switch TableActionsProperty.Compile(node: child, withContext: current_context) {
|
||||
case .Ok((let table_action_property, let updated_context)):
|
||||
current_context = updated_context
|
||||
case .Ok(let table_action_property):
|
||||
actions.append(table_action_property)
|
||||
case .Error(let e): errors.append(e)
|
||||
}
|
||||
@@ -900,19 +887,19 @@ extension TablePropertyList: Compilable {
|
||||
actions.append(TableActionsProperty())
|
||||
}
|
||||
|
||||
return .Ok((TablePropertyList(withActions: actions[0], withKeys: keys[0]), current_context))
|
||||
return .Ok(TablePropertyList(withActions: actions[0], withKeys: keys[0]))
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
extension Table: Compilable {
|
||||
public typealias T = Table
|
||||
public typealias C = Table
|
||||
public static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(Table, CompilerContext)> {
|
||||
) -> Result<Table> {
|
||||
|
||||
let table_declaration_node = node
|
||||
#RequireNodeType<Node, (P4Type, CompilerContext)>(
|
||||
#RequireNodeType<Node, Table>(
|
||||
node: table_declaration_node, type: "table_declaration", nice_type_name: "Table Declaration")
|
||||
|
||||
var walker = Walker(node: table_declaration_node)
|
||||
@@ -924,7 +911,7 @@ extension Table: Compilable {
|
||||
walker.next() // Skip the XXX?
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(Table, CompilerContext)>.Error(
|
||||
or: Result<Table>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing table declaration component")
|
||||
))
|
||||
@@ -942,46 +929,43 @@ extension Table: Compilable {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(Table, CompilerContext)>.Error(
|
||||
or: Result<Table>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing table declaration component")
|
||||
))
|
||||
|
||||
let maybe_table_property_list = TablePropertyList.Compile(
|
||||
node: current_node!, withContext: current_context)
|
||||
guard case .Ok((let table_property_list, _)) = maybe_table_property_list else {
|
||||
guard case .Ok(let table_property_list) = maybe_table_property_list else {
|
||||
return Result.Error(maybe_table_property_list.error()!)
|
||||
}
|
||||
|
||||
return .Ok(
|
||||
(Table(withName: table_name, withPropertyList: table_property_list), current_context))
|
||||
return .Ok(Table(withName: table_name, withPropertyList: table_property_list))
|
||||
}
|
||||
}
|
||||
|
||||
extension ExternDeclaration: CompilableDeclaration {
|
||||
extension ExternDeclaration: Compilable {
|
||||
public typealias C = Declaration
|
||||
public static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(Declaration, CompilerContext)?> {
|
||||
) -> Result<Declaration> {
|
||||
let extern_declaration_node = node
|
||||
#RequireNodeType<Node, (Declaration, CompilerContext)>(
|
||||
#RequireNodeType<Node, Declaration>(
|
||||
node: extern_declaration_node, type: "extern_declaration",
|
||||
nice_type_name: "Extern Declaration")
|
||||
|
||||
let declaration_node = extern_declaration_node.child(at: 1)!
|
||||
#RequireNodeType<Node, (Declaration, CompilerContext)>(
|
||||
#RequireNodeType<Node, Declaration>(
|
||||
node: declaration_node, type: "declaration", nice_type_name: "Declaration")
|
||||
let declarationed_node = declaration_node.child(at: 0)!
|
||||
|
||||
let maybe_declared = Declaration.Compile(
|
||||
node: declarationed_node, withContext: context.update(newExtern: true))
|
||||
|
||||
guard case .Ok(let maybe_declared) = maybe_declared else {
|
||||
guard case .Ok(let declared) = maybe_declared else {
|
||||
return .Error(maybe_declared.error()!)
|
||||
}
|
||||
|
||||
guard case .some((let declared, _)) = maybe_declared else {
|
||||
return .Ok(.none)
|
||||
}
|
||||
|
||||
// Before we are okay with this declaration, it must already be registered as an extern
|
||||
// with the matching "stuff".
|
||||
|
||||
@@ -1000,11 +984,7 @@ extension ExternDeclaration: CompilableDeclaration {
|
||||
let extern_declaration = Declaration(extern: declared, ffi: found_ffi)
|
||||
|
||||
return .Ok(
|
||||
(
|
||||
extern_declaration,
|
||||
context.update(
|
||||
newExterns: context.externs.declare(
|
||||
identifier: declared.identifier, withValue: extern_declaration))
|
||||
))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,22 +21,10 @@ import P4Runtime
|
||||
import SwiftTreeSitter
|
||||
import TreeSitterP4
|
||||
|
||||
protocol CompilableExpression {
|
||||
static func compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<EvaluatableExpression?>
|
||||
}
|
||||
|
||||
protocol CompilableLValueExpression {
|
||||
static func compile_as_lvalue(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<EvaluatableLValueExpression?>
|
||||
}
|
||||
|
||||
extension TypedIdentifier: CompilableExpression {
|
||||
static func compile(
|
||||
public static func compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Result<EvaluatableExpression?> {
|
||||
) -> Result<P4Expression?> {
|
||||
|
||||
let node = node.child(at: 0)!
|
||||
#SkipUnlessNodeType<SwiftTreeSitter.Node>(
|
||||
@@ -57,9 +45,9 @@ extension TypedIdentifier: CompilableExpression {
|
||||
}
|
||||
|
||||
extension TypedIdentifier: CompilableLValueExpression {
|
||||
static func compile_as_lvalue(
|
||||
public static func compile_as_lvalue(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Result<EvaluatableLValueExpression?> {
|
||||
) -> Result<P4LValueExpression?> {
|
||||
|
||||
let expression = node.child(at: 0)!
|
||||
#SkipUnlessNodeType<SwiftTreeSitter.Node>(
|
||||
@@ -77,9 +65,9 @@ extension TypedIdentifier: CompilableLValueExpression {
|
||||
}
|
||||
|
||||
extension P4BooleanValue: CompilableExpression {
|
||||
static func compile(
|
||||
public static func compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Result<EvaluatableExpression?> {
|
||||
) -> Result<P4Expression?> {
|
||||
let node = node.child(at: 0)!
|
||||
#SkipUnlessNodeType<SwiftTreeSitter.Node>(
|
||||
node: node, type: "booleanLiteralExpression")
|
||||
@@ -98,9 +86,9 @@ extension P4BooleanValue: CompilableExpression {
|
||||
}
|
||||
|
||||
extension P4IntValue: CompilableExpression {
|
||||
static func compile(
|
||||
public static func compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Result<EvaluatableExpression?> {
|
||||
) -> Result<P4Expression?> {
|
||||
let node = node.child(at: 0)!
|
||||
|
||||
#SkipUnlessNodesTypes<SwiftTreeSitter.Node>(
|
||||
@@ -147,9 +135,9 @@ extension P4IntValue: CompilableExpression {
|
||||
}
|
||||
|
||||
extension P4StringValue: CompilableExpression {
|
||||
static func compile(
|
||||
public static func compile(
|
||||
node: SwiftTreeSitter.Node, withContext scopes: CompilerContext
|
||||
) -> Result<EvaluatableExpression?> {
|
||||
) -> Result<P4Expression?> {
|
||||
let node = node.child(at: 0)!
|
||||
#SkipUnlessNodeType<SwiftTreeSitter.Node>(
|
||||
node: node, type: "string_literal")
|
||||
@@ -158,12 +146,12 @@ extension P4StringValue: CompilableExpression {
|
||||
}
|
||||
|
||||
extension KeysetExpression: CompilableExpression {
|
||||
static func compile(
|
||||
public static func compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(any Common.EvaluatableExpression)?> {
|
||||
) -> Result<P4Expression?> {
|
||||
let keyset_expression_node = node.child(at: 0)!
|
||||
|
||||
#RequireNodesType<Node, EvaluatableExpression>(
|
||||
#RequireNodesType<Node, P4Expression>(
|
||||
nodes: keyset_expression_node, type: ["expression", "default_keyset"],
|
||||
nice_type_names: ["expression", "default keyset"])
|
||||
|
||||
@@ -186,12 +174,12 @@ extension KeysetExpression: CompilableExpression {
|
||||
struct Expression {
|
||||
public static func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<EvaluatableExpression> {
|
||||
#RequireNodeType<Node, EvaluatableExpression>(
|
||||
) -> Result<P4Expression> {
|
||||
#RequireNodeType<Node, P4Expression>(
|
||||
node: node, type: "expression", nice_type_name: "expression")
|
||||
|
||||
let expression_node = node.child(at: 0)!
|
||||
#RequireNodesType<Node, EvaluatableExpression>(
|
||||
#RequireNodesType<Node, P4Expression>(
|
||||
nodes: expression_node, type: ["grouped_expression", "simple_expression"],
|
||||
nice_type_names: ["grouped expression", "simple expression"])
|
||||
|
||||
@@ -223,12 +211,12 @@ struct Expression {
|
||||
struct LValue {
|
||||
public static func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<EvaluatableLValueExpression> {
|
||||
#RequireNodeType<Node, EvaluatableExpression>(
|
||||
) -> Result<P4LValueExpression> {
|
||||
#RequireNodeType<Node, P4Expression>(
|
||||
node: node, type: "expression", nice_type_name: "expression")
|
||||
|
||||
let expression_node = node.child(at: 0)!
|
||||
#RequireNodesType<Node, EvaluatableExpression>(
|
||||
#RequireNodesType<Node, P4Expression>(
|
||||
nodes: expression_node, type: ["grouped_expression", "simple_expression"],
|
||||
nice_type_names: ["grouped expression", "simple expression"])
|
||||
|
||||
@@ -268,9 +256,9 @@ struct Identifier {
|
||||
}
|
||||
|
||||
extension SelectExpression: CompilableExpression {
|
||||
static func compile(
|
||||
public static func compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<EvaluatableExpression?> {
|
||||
) -> Result<P4Expression?> {
|
||||
#RequireNodeType<Node, (SelectExpression, CompilerContext)>(
|
||||
node: node, type: "selectExpression", nice_type_name: "parser select expression")
|
||||
|
||||
@@ -330,9 +318,9 @@ extension SelectExpression: CompilableExpression {
|
||||
}
|
||||
|
||||
extension SelectCaseExpression: CompilableExpression {
|
||||
static func compile(
|
||||
public static func compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<EvaluatableExpression?> {
|
||||
) -> Result<P4Expression?> {
|
||||
if node.nodeType != "selectCase" {
|
||||
return Result.Error(Error(withMessage: "Expected select case not found"))
|
||||
}
|
||||
@@ -383,10 +371,35 @@ extension SelectCaseExpression: CompilableExpression {
|
||||
}
|
||||
}
|
||||
|
||||
// swift-format-ignore
|
||||
public typealias BinaryOperatorChecker = (P4Expression, P4Expression) -> Result<()>
|
||||
|
||||
public func binary_and_or_operator_checker(
|
||||
left: P4Expression, right: P4Expression
|
||||
) -> Result<()> {
|
||||
// Check that both are Boolean-typed things!
|
||||
if !(left.type().baseType().eq(rhs: P4Boolean()) && right.type().baseType().eq(rhs: P4Boolean()))
|
||||
{
|
||||
return .Error(Error(withMessage: "And/Or on operands with non-bool type is not allowed"))
|
||||
}
|
||||
return .Ok(())
|
||||
}
|
||||
|
||||
public func binary_int_math_operator_checker(
|
||||
left: P4Expression, right: P4Expression
|
||||
) -> Result<()> {
|
||||
// Check that both are int-typed things!
|
||||
if !(left.type().baseType().eq(rhs: P4Int()) && right.type().baseType().eq(rhs: P4Int())) {
|
||||
return .Error(
|
||||
Error(withMessage: "Mathematical operation on operands with non-int type is not allowed"))
|
||||
}
|
||||
return .Ok(())
|
||||
}
|
||||
|
||||
extension BinaryOperatorExpression: CompilableExpression {
|
||||
static func compile(
|
||||
public static func compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Result<(EvaluatableExpression)?> {
|
||||
) -> Result<(P4Expression)?> {
|
||||
let expression = node.child(at: 0)!
|
||||
|
||||
#SkipUnlessNodeType<Node>(
|
||||
@@ -398,20 +411,20 @@ extension BinaryOperatorExpression: CompilableExpression {
|
||||
var current_node: Node? = .none
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<EvaluatableExpression?>.Error(
|
||||
or: Result<P4Expression?>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Malformed binary operator expression"
|
||||
)))
|
||||
|
||||
/// TODO: This macro cannot handle new lines in the arrays
|
||||
// swift-format-ignore
|
||||
#RequireNodesType<Node, EvaluatableExpression?>(
|
||||
#RequireNodesType<Node, P4Expression?>(
|
||||
nodes: binary_operator_expression_node,
|
||||
type: ["binaryEqualOperatorExpression", "binaryLessThanOperatorExpression", "binaryLessThanEqualOperatorExpression", "binaryGreaterThanOperatorExpression", "binaryGreaterThanEqualOperatorExpression", "binaryAndOperatorExpression", "binaryOrOperatorExpression", "binaryAddOperatorExpression", "binarySubtractOperatorExpression", "binaryMultiplyOperatorExpression", "binaryDivideOperatorExpression"],
|
||||
nice_type_names: [ "binary equal operator", "binary less than operator", "binary less than or equal to operator", "binary greater than operator", "binary greater than or equal to operator", "binary and operator", "binary or operator", "binary add operator", "binary subtract operator", "binary multiply operator", "binary divide operator"])
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<EvaluatableExpression?>.Error(
|
||||
or: Result<P4Expression?>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing LHS for binary operator expression")))
|
||||
@@ -421,7 +434,7 @@ extension BinaryOperatorExpression: CompilableExpression {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<EvaluatableExpression?>.Error(
|
||||
or: Result<P4Expression?>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing binary operator for binary operator expression")))
|
||||
@@ -429,7 +442,7 @@ extension BinaryOperatorExpression: CompilableExpression {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<EvaluatableExpression?>.Error(
|
||||
or: Result<P4Expression?>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing RHS for binary operator expression")))
|
||||
@@ -520,9 +533,9 @@ extension BinaryOperatorExpression: CompilableExpression {
|
||||
}
|
||||
|
||||
extension ArrayAccessExpression: CompilableExpression {
|
||||
static func compile(
|
||||
public static func compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<EvaluatableExpression?> {
|
||||
) -> Result<P4Expression?> {
|
||||
let expression = node.child(at: 0)!
|
||||
|
||||
#SkipUnlessNodeType<Node>(
|
||||
@@ -535,11 +548,11 @@ extension ArrayAccessExpression: CompilableExpression {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<EvaluatableExpression?>.Error(
|
||||
or: Result<P4Expression?>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Malformed array access expression")))
|
||||
|
||||
#RequireNodeType<Node, EvaluatableExpression?>(
|
||||
#RequireNodeType<Node, P4Expression?>(
|
||||
node: current_node!, type: "expression",
|
||||
nice_type_name: "array identifier expression")
|
||||
let array_access_identifier_node = current_node!
|
||||
@@ -547,7 +560,7 @@ extension ArrayAccessExpression: CompilableExpression {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<EvaluatableExpression?>.Error(
|
||||
or: Result<P4Expression?>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing [ for array access expression")))
|
||||
@@ -556,12 +569,12 @@ extension ArrayAccessExpression: CompilableExpression {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<EvaluatableExpression?>.Error(
|
||||
or: Result<P4Expression?>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing indexor expression for array access expression")))
|
||||
|
||||
#RequireNodeType<Node, EvaluatableExpression?>(
|
||||
#RequireNodeType<Node, P4Expression?>(
|
||||
node: current_node!, type: "expression",
|
||||
nice_type_name: "array indexor expression")
|
||||
|
||||
@@ -595,9 +608,9 @@ extension ArrayAccessExpression: CompilableExpression {
|
||||
}
|
||||
|
||||
extension FieldAccessExpression: CompilableExpression {
|
||||
static func compile(
|
||||
public static func compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(any Common.EvaluatableExpression)?> {
|
||||
) -> Result<P4Expression?> {
|
||||
let expression = node.child(at: 0)!
|
||||
|
||||
#SkipUnlessNodeType<Node>(
|
||||
@@ -610,11 +623,11 @@ extension FieldAccessExpression: CompilableExpression {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<EvaluatableExpression?>.Error(
|
||||
or: Result<P4Expression?>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Malformed field access expression")))
|
||||
|
||||
#RequireNodeType<Node, EvaluatableExpression?>(
|
||||
#RequireNodeType<Node, P4Expression?>(
|
||||
node: current_node!, type: "expression",
|
||||
nice_type_name: "struct identifier expression")
|
||||
let struct_identifier_node = current_node!
|
||||
@@ -622,7 +635,7 @@ extension FieldAccessExpression: CompilableExpression {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<EvaluatableExpression?>.Error(
|
||||
or: Result<P4Expression?>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing . for field access expression")))
|
||||
@@ -630,12 +643,12 @@ extension FieldAccessExpression: CompilableExpression {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<EvaluatableExpression?>.Error(
|
||||
or: Result<P4Expression?>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing field name for field access expression")))
|
||||
|
||||
#RequireNodeType<Node, EvaluatableExpression?>(
|
||||
#RequireNodeType<Node, P4Expression?>(
|
||||
node: current_node!, type: "identifier",
|
||||
nice_type_name: "field name")
|
||||
|
||||
@@ -677,9 +690,9 @@ extension FieldAccessExpression: CompilableExpression {
|
||||
}
|
||||
|
||||
extension FieldAccessExpression: CompilableLValueExpression {
|
||||
static func compile_as_lvalue(
|
||||
public static func compile_as_lvalue(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Result<EvaluatableLValueExpression?> {
|
||||
) -> Result<P4LValueExpression?> {
|
||||
let expression = node.child(at: 0)!
|
||||
#SkipUnlessNodeType<Node>(
|
||||
node: expression, type: "fieldAccessExpression")
|
||||
@@ -696,9 +709,9 @@ extension FieldAccessExpression: CompilableLValueExpression {
|
||||
}
|
||||
|
||||
extension ArrayAccessExpression: CompilableLValueExpression {
|
||||
static func compile_as_lvalue(
|
||||
public static func compile_as_lvalue(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Result<EvaluatableLValueExpression?> {
|
||||
) -> Result<P4LValueExpression?> {
|
||||
let expression = node.child(at: 0)!
|
||||
#SkipUnlessNodeType<Node>(
|
||||
node: expression, type: "arrayAccessExpression")
|
||||
@@ -715,9 +728,9 @@ extension ArrayAccessExpression: CompilableLValueExpression {
|
||||
}
|
||||
|
||||
extension FunctionCall: CompilableExpression {
|
||||
static func compile(
|
||||
public static func compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<EvaluatableExpression?> {
|
||||
) -> Result<P4Expression?> {
|
||||
|
||||
let expression = node.child(at: 0)!
|
||||
#SkipUnlessNodeType<Node>(
|
||||
@@ -728,7 +741,7 @@ extension FunctionCall: CompilableExpression {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<EvaluatableExpression?>.Error(
|
||||
or: Result<P4Expression?>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing function call component")))
|
||||
|
||||
@@ -780,13 +793,13 @@ extension FunctionCall: CompilableExpression {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<EvaluatableExpression?>.Error(
|
||||
or: Result<P4Expression?>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing function call component")))
|
||||
|
||||
let maybe_argument_list = ArgumentList.Compile(node: current_node!, withContext: context)
|
||||
|
||||
guard case .Ok((let arguments, _)) = maybe_argument_list else {
|
||||
guard case .Ok(let arguments) = maybe_argument_list else {
|
||||
return .Error(maybe_argument_list.error()!)
|
||||
}
|
||||
|
||||
|
||||
@@ -23,10 +23,10 @@ import TreeSitterExtensions
|
||||
import TreeSitterP4
|
||||
|
||||
extension Statement: Compilable {
|
||||
public typealias T = EvaluatableStatement
|
||||
public typealias C = P4Statement
|
||||
public static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(EvaluatableStatement, CompilerContext)> {
|
||||
) -> Result<P4Statement> {
|
||||
|
||||
if node.nodeType != "parserStatement" && node.nodeType != "statement" {
|
||||
return Result.Error(
|
||||
@@ -51,9 +51,9 @@ extension Statement: Compilable {
|
||||
withError:
|
||||
"Unparseable statement type (\(statement.nodeType ?? "Unknown Statement Type"))"))
|
||||
}
|
||||
switch parser.Compile(node: statement, withContext: context) {
|
||||
case Result.Ok(let (parsed, updated_context)):
|
||||
return .Ok((parsed, updated_context))
|
||||
switch parser.CompileStatement(node: statement, withContext: context) {
|
||||
case Result.Ok(let parsed):
|
||||
return .Ok(parsed)
|
||||
case Result.Error(let e):
|
||||
return .Error(
|
||||
ErrorWithLocation(
|
||||
@@ -62,11 +62,12 @@ extension Statement: Compilable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension LocalElements: Compilable {
|
||||
public typealias T = EvaluatableStatement
|
||||
public typealias C = P4Statement
|
||||
public static func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<(EvaluatableStatement, CompilerContext)> {
|
||||
) -> Result<P4Statement> {
|
||||
let localElementsParsers: [String: CompilableStatement.Type] = [
|
||||
"variableDeclaration": VariableDeclarationStatement.self
|
||||
]
|
||||
@@ -78,9 +79,9 @@ extension LocalElements: Compilable {
|
||||
withError: "Unparseable statement type (\(node.nodeType ?? "Unknown Statement Type"))"))
|
||||
}
|
||||
|
||||
switch parser.Compile(node: node, withContext: context) {
|
||||
case Result.Ok(let (parsed, parsed_updated_scopes)):
|
||||
return Result.Ok((parsed, parsed_updated_scopes))
|
||||
switch parser.CompileStatement(node: node, withContext: context) {
|
||||
case Result.Ok(let parsed):
|
||||
return Result.Ok(parsed)
|
||||
case Result.Error(let e):
|
||||
return Result.Error(Error(withMessage: "Failed to parse local element: \(e)"))
|
||||
}
|
||||
@@ -88,10 +89,10 @@ extension LocalElements: Compilable {
|
||||
}
|
||||
|
||||
extension ParserState: Compilable {
|
||||
public typealias T = ParserState
|
||||
public typealias C = ParserState
|
||||
public static func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<(ParserState, CompilerContext)> {
|
||||
) -> Result<ParserState> {
|
||||
var walker = Walker(node: node)
|
||||
|
||||
var current_node: Node? = .none
|
||||
@@ -107,7 +108,7 @@ extension ParserState: Compilable {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(ParserState, CompilerContext)>.Error(
|
||||
or: Result<ParserState>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing elements in parser state declaration")))
|
||||
@@ -125,7 +126,7 @@ extension ParserState: Compilable {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(ParserState, CompilerContext)>.Error(
|
||||
or: Result<ParserState>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing elements in parser state declaration")))
|
||||
@@ -141,22 +142,20 @@ extension ParserState: Compilable {
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(ParserState, CompilerContext)>.Error(
|
||||
or: Result<ParserState>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing body of state declaration")
|
||||
))
|
||||
|
||||
var errors: (any Errorable)? = .none
|
||||
var current_context = context
|
||||
var parsed_s: [EvaluatableStatement] = Array()
|
||||
var parsed_s: [P4Statement] = Array()
|
||||
|
||||
if current_node!.nodeType == "parserStatements" {
|
||||
switch SpecialCompilers.Statements.Compile(
|
||||
node: current_node!, withContext: current_context)
|
||||
node: current_node!, withContext: context)
|
||||
{
|
||||
case .Ok(let (state_statements, updated_context)):
|
||||
case .Ok(let state_statements):
|
||||
parsed_s = state_statements
|
||||
current_context = updated_context
|
||||
case .Error(let error):
|
||||
errors =
|
||||
if let errors = errors {
|
||||
@@ -174,13 +173,13 @@ extension ParserState: Compilable {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(ParserState, CompilerContext)>.Error(
|
||||
or: Result<ParserState>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError: "Missing transition statement of state declaration")))
|
||||
|
||||
return SpecialCompilers.TransitionStatement.Compile(
|
||||
node: current_node!, forState: state_identifier, withStatements: parsed_s,
|
||||
withContext: current_context)
|
||||
withContext: SpecialCompilers.Statements.effect(statements: parsed_s, context: context))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,12 +22,6 @@ import SwiftTreeSitter
|
||||
import TreeSitterExtensions
|
||||
import TreeSitterP4
|
||||
|
||||
public protocol CompilableStatement {
|
||||
static func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<(EvaluatableStatement, CompilerContext)>
|
||||
}
|
||||
|
||||
public protocol CompilableValue {
|
||||
static func CompileValue(withValue value: String) -> Result<P4DataValue>
|
||||
}
|
||||
@@ -38,19 +32,27 @@ public protocol CompilableType {
|
||||
) -> Result<P4Type?>
|
||||
}
|
||||
|
||||
public protocol CompilableDeclaration {
|
||||
/// Info
|
||||
///
|
||||
/// Extensions should update the context with the newly declared item _unless_
|
||||
/// they are in an extern context (``CompilerContext.extern_context``).
|
||||
static func Compile(
|
||||
public protocol CompilableExpression {
|
||||
static func compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<(Declaration, CompilerContext)?>
|
||||
) -> Result<P4Expression?>
|
||||
}
|
||||
|
||||
public protocol Compilable<T> {
|
||||
associatedtype T
|
||||
public protocol CompilableLValueExpression {
|
||||
static func compile_as_lvalue(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<P4LValueExpression?>
|
||||
}
|
||||
|
||||
public protocol Compilable<C> {
|
||||
associatedtype C
|
||||
static func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<(T, CompilerContext)>
|
||||
) -> Result<C>
|
||||
}
|
||||
|
||||
public protocol CompilableStatement {
|
||||
static func CompileStatement(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<P4Statement>
|
||||
}
|
||||
|
||||
@@ -22,14 +22,20 @@ import SwiftTreeSitter
|
||||
import TreeSitterExtensions
|
||||
import TreeSitterP4
|
||||
|
||||
protocol AnyCompilable {
|
||||
static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(Any, CompilerContext)>
|
||||
}
|
||||
|
||||
public struct SpecialCompilers {
|
||||
public struct TransitionStatement {
|
||||
static func Compile(
|
||||
node: Node, forState state_identifier: Common.Identifier,
|
||||
withStatements stmts: [EvaluatableStatement], withContext context: CompilerContext
|
||||
) -> Result<(ParserState, CompilerContext)> {
|
||||
withStatements stmts: [P4Statement], withContext context: CompilerContext
|
||||
) -> Result<ParserState> {
|
||||
|
||||
#RequireNodeType<Node, (EvaluatableStatement, CompilerContext)>(
|
||||
#RequireNodeType<Node, P4Statement>(
|
||||
node: node, type: "parserTransitionStatement", nice_type_name: "parser transition statement"
|
||||
)
|
||||
|
||||
@@ -58,19 +64,18 @@ public struct SpecialCompilers {
|
||||
switch next_state {
|
||||
case (_, .some(let instance)):
|
||||
return .Ok(
|
||||
(
|
||||
ParserStateDirectTransition(
|
||||
name: state_identifier,
|
||||
withNextState: instance.dataValue() as! InstantiatedParserState,
|
||||
withStatements: stmts), context
|
||||
))
|
||||
withStatements: stmts,
|
||||
)
|
||||
)
|
||||
case (_, .none):
|
||||
return .Ok(
|
||||
(
|
||||
ParserStateDirectTransition(
|
||||
name: state_identifier,
|
||||
withNextStateIdentifier: next_state_id, withStatements: stmts), context
|
||||
))
|
||||
withNextStateIdentifier: next_state_id, withStatements: stmts)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -95,12 +100,11 @@ public struct SpecialCompilers {
|
||||
{
|
||||
case .Ok(let tse):
|
||||
.Ok(
|
||||
(
|
||||
ParserStateSelectTransition(
|
||||
name: state_identifier, withTransitionExpression: tse as! SelectExpression,
|
||||
withStatements: stmts,
|
||||
), context
|
||||
))
|
||||
)
|
||||
)
|
||||
case .Error(let e): .Error(e)
|
||||
}
|
||||
}
|
||||
@@ -109,7 +113,7 @@ public struct SpecialCompilers {
|
||||
public struct Statements {
|
||||
static func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<([EvaluatableStatement], CompilerContext)> {
|
||||
) -> Result<[P4Statement]> {
|
||||
if node.nodeType != "statements" && node.nodeType != "parserStatements" {
|
||||
return Result.Error(
|
||||
ErrorWithLocation(
|
||||
@@ -118,15 +122,15 @@ public struct SpecialCompilers {
|
||||
|
||||
var errors: (any Errorable)? = .none
|
||||
var current_context = context
|
||||
var parsed_s: [EvaluatableStatement] = Array()
|
||||
var parsed_s: [P4Statement] = Array()
|
||||
|
||||
node.enumerateNamedChildren { node in
|
||||
switch Statement.Compile(
|
||||
node: node, withContext: current_context)
|
||||
{
|
||||
case .Ok((let parsed_statement, let updated_context)):
|
||||
current_context = updated_context
|
||||
case .Ok(let parsed_statement):
|
||||
parsed_s.append(parsed_statement)
|
||||
current_context = parsed_statement.effect(context: current_context)
|
||||
case .Error(let e):
|
||||
errors =
|
||||
if let errors = errors {
|
||||
@@ -141,11 +145,20 @@ public struct SpecialCompilers {
|
||||
return .Error(errors)
|
||||
}
|
||||
|
||||
return Result.Ok((parsed_s, current_context))
|
||||
}
|
||||
return Result.Ok(parsed_s)
|
||||
}
|
||||
|
||||
static func Compile(
|
||||
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, CompilerContext)> {
|
||||
@@ -167,9 +180,10 @@ public struct SpecialCompilers {
|
||||
node: parser_state,
|
||||
withContext: context.update(newInstances: current_context.instances.enter()))
|
||||
{
|
||||
case Result.Ok(let (state, updated_context)):
|
||||
case Result.Ok(let state):
|
||||
let statement = state as P4Statement
|
||||
current_context = statement.effect(context: current_context)
|
||||
parser.states = parser.states.append(state: state)
|
||||
current_context = updated_context
|
||||
case Result.Error(let e): error = e
|
||||
}
|
||||
}
|
||||
@@ -245,43 +259,35 @@ public struct SpecialCompilers {
|
||||
|
||||
// Try to parse all top-level declarations.
|
||||
result?.rootNode?.enumerateNamedChildren { (declaration_node: Node) in
|
||||
let specific_declaration_node = declaration_node.child(at: 0)!
|
||||
|
||||
let declaration_parsers: [CompilableDeclaration.Type] = [
|
||||
Declaration.self, P4Lang.Parser.self,
|
||||
let declaration_parsers: [String: CompilableStatement.Type] = [
|
||||
"declaration": Declaration.self,
|
||||
"instantiation": Instantiation.self,
|
||||
]
|
||||
var found_parser = false
|
||||
|
||||
for parser in declaration_parsers {
|
||||
switch parser.Compile(node: specific_declaration_node, withContext: compilation_context) {
|
||||
case .Ok(.none): {}()
|
||||
case .Ok(.some((_, let updated_context))):
|
||||
found_parser = true
|
||||
compilation_context = updated_context
|
||||
break
|
||||
if let parser = declaration_parsers[declaration_node.nodeType!] {
|
||||
let r = parser.CompileStatement(node: declaration_node, withContext: compilation_context)
|
||||
switch r {
|
||||
case .Ok(let compiled):
|
||||
compilation_context = compiled.effect(context: compilation_context)
|
||||
case .Error(let e):
|
||||
found_parser = true
|
||||
errors =
|
||||
if let errors = errors {
|
||||
errors.append(error: e)
|
||||
} else {
|
||||
e
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// If none of the declaration parsers chose to parse, that's an error, too!
|
||||
if !found_parser {
|
||||
let no_parser_error = ErrorWithLocation(
|
||||
sourceLocation: specific_declaration_node.toSourceLocation(),
|
||||
withError: "Could not find parser for declaration node"
|
||||
)
|
||||
}
|
||||
} else {
|
||||
let e = ErrorWithLocation(
|
||||
sourceLocation: declaration_node.toSourceLocation(),
|
||||
withError:
|
||||
"\(declaration_node.nodeType!) cannot be at a P4 program top level")
|
||||
errors =
|
||||
if let errors = errors {
|
||||
errors.append(error: no_parser_error)
|
||||
errors.append(error: e)
|
||||
} else {
|
||||
no_parser_error
|
||||
e
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -313,4 +319,5 @@ public struct SpecialCompilers {
|
||||
return Result.Ok(program)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,11 +22,12 @@ import SwiftTreeSitter
|
||||
import TreeSitterExtensions
|
||||
import TreeSitterP4
|
||||
|
||||
extension BlockStatement: CompilableStatement {
|
||||
extension BlockStatement: Compilable {
|
||||
public typealias C = BlockStatement
|
||||
public static func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<(EvaluatableStatement, CompilerContext)> {
|
||||
#RequireNodeType<Node, (EvaluatableStatement, CompilerContext)>(
|
||||
) -> Result<BlockStatement> {
|
||||
#RequireNodeType<Node, (P4Statement)>(
|
||||
node: node, type: "blockStatement", nice_type_name: "block statement")
|
||||
|
||||
var walker = Walker(node: node)
|
||||
@@ -34,7 +35,7 @@ extension BlockStatement: CompilableStatement {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(EvaluatableStatement, CompilerContext)>.Error(
|
||||
or: Result<BlockStatement>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Malformed block statement")))
|
||||
|
||||
@@ -45,23 +46,21 @@ extension BlockStatement: CompilableStatement {
|
||||
withError: "Missing { on block statement"))
|
||||
}
|
||||
|
||||
var statements: [EvaluatableStatement] = Array()
|
||||
var statements: [P4Statement] = Array()
|
||||
var parse_err: (any Errorable)? = .none
|
||||
var current_context = context
|
||||
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(EvaluatableStatement, CompilerContext)>.Error(
|
||||
or: Result<BlockStatement>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Malformed block statement")))
|
||||
|
||||
if current_node!.nodeType == "statements" {
|
||||
switch SpecialCompilers.Statements.Compile(
|
||||
node: current_node!, withContext: current_context)
|
||||
node: current_node!, withContext: context)
|
||||
{
|
||||
case .Ok(let (parsed_statements, updated_context)):
|
||||
current_context = updated_context
|
||||
case .Ok(let parsed_statements):
|
||||
statements = parsed_statements
|
||||
case .Error(let error):
|
||||
parse_err = error
|
||||
@@ -76,7 +75,7 @@ extension BlockStatement: CompilableStatement {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<(EvaluatableStatement, CompilerContext)>.Error(
|
||||
or: Result<BlockStatement>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Malformed block statement")))
|
||||
|
||||
@@ -87,16 +86,28 @@ extension BlockStatement: CompilableStatement {
|
||||
withError: "Missing } on block statement"))
|
||||
}
|
||||
|
||||
return .Ok((BlockStatement(statements), current_context))
|
||||
return .Ok(BlockStatement(statements))
|
||||
}
|
||||
}
|
||||
|
||||
extension ConditionalStatement: CompilableStatement {
|
||||
extension BlockStatement: CompilableStatement {
|
||||
public static func CompileStatement(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<P4Statement> {
|
||||
return switch Compile(node: node, withContext: context) {
|
||||
case .Ok(let res): .Ok(res)
|
||||
case .Error(let e): .Error(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension ConditionalStatement: Compilable {
|
||||
public typealias C = ConditionalStatement
|
||||
public static func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<(EvaluatableStatement, CompilerContext)> {
|
||||
) -> Result<ConditionalStatement> {
|
||||
|
||||
#RequireNodeType<Node, (EvaluatableStatement, CompilerContext)>(
|
||||
#RequireNodeType<Node, (P4Statement)>(
|
||||
node: node, type: "conditionalStatement", nice_type_name: "conditional statement")
|
||||
|
||||
let maybe_condition_expression = node.child(at: 2)
|
||||
@@ -128,7 +139,7 @@ extension ConditionalStatement: CompilableStatement {
|
||||
}
|
||||
|
||||
guard
|
||||
case .Ok((let thenns, _)) = Statement.Compile(
|
||||
case .Ok(let thenns) = Statement.Compile(
|
||||
node: thens, withContext: context)
|
||||
else {
|
||||
return Result.Error(
|
||||
@@ -137,7 +148,7 @@ extension ConditionalStatement: CompilableStatement {
|
||||
"Could not parse the then block in a conditional statement"))
|
||||
}
|
||||
|
||||
let optional_elss: Result<(any EvaluatableStatement, CompilerContext)>? =
|
||||
let optional_elss: Result<any P4Statement>? =
|
||||
if let elss = node.child(at: 6) {
|
||||
.some(
|
||||
Statement.Compile(
|
||||
@@ -148,7 +159,7 @@ extension ConditionalStatement: CompilableStatement {
|
||||
|
||||
if let parsed_elss = optional_elss {
|
||||
guard
|
||||
case .Ok((let elss, _)) = parsed_elss
|
||||
case .Ok(let elss) = parsed_elss
|
||||
else {
|
||||
return Result.Error(
|
||||
Error(
|
||||
@@ -156,18 +167,30 @@ extension ConditionalStatement: CompilableStatement {
|
||||
"Could not parse the else block in a conditional statement"))
|
||||
}
|
||||
return .Ok(
|
||||
(ConditionalStatement(condition: condition, withThen: thenns, andElse: elss), context))
|
||||
ConditionalStatement(condition: condition, withThen: thenns, andElse: elss))
|
||||
}
|
||||
return .Ok((ConditionalStatement(condition: condition, withThen: thenns), context))
|
||||
return .Ok(ConditionalStatement(condition: condition, withThen: thenns))
|
||||
}
|
||||
}
|
||||
|
||||
extension VariableDeclarationStatement: CompilableStatement {
|
||||
extension ConditionalStatement: CompilableStatement {
|
||||
public static func CompileStatement(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<P4Statement> {
|
||||
return switch Compile(node: node, withContext: context) {
|
||||
case .Ok(let res): .Ok(res)
|
||||
case .Error(let e): .Error(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension VariableDeclarationStatement: Compilable {
|
||||
public typealias C = VariableDeclarationStatement
|
||||
public static func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<(EvaluatableStatement, CompilerContext)> {
|
||||
) -> Result<VariableDeclarationStatement> {
|
||||
|
||||
#RequireNodeType<Node, (EvaluatableStatement, CompilerContext)>(
|
||||
#RequireNodeType<Node, (P4Statement)>(
|
||||
node: node, type: "variableDeclaration", nice_type_name: "variable declaration statement")
|
||||
|
||||
let maybe_typeref = node.child(at: 0)
|
||||
@@ -206,7 +229,7 @@ extension VariableDeclarationStatement: CompilableStatement {
|
||||
Error(withMessage: "Could not parse a P4 type from \(typeref.text!)"))
|
||||
}
|
||||
|
||||
var initializer: EvaluatableExpression? = .none
|
||||
var initializer: P4Expression? = .none
|
||||
|
||||
// If there is an initializer, it must be an expression.
|
||||
if let initializer_expression = maybe_rvalue {
|
||||
@@ -249,40 +272,59 @@ extension VariableDeclarationStatement: CompilableStatement {
|
||||
}
|
||||
|
||||
return Result.Ok(
|
||||
(
|
||||
VariableDeclarationStatement(
|
||||
identifier: parsed_variablename, withInitializer: initializer),
|
||||
// Context with updated names to include the newly declared name.
|
||||
context.update(
|
||||
newInstances: context.instances.declare(
|
||||
identifier: parsed_variablename, withValue: (declaration_p4_type, .none)))
|
||||
)
|
||||
identifier: TypedIdentifier(id: parsed_variablename, withType: declaration_p4_type),
|
||||
withInitializer: initializer),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
extension ExpressionStatement: CompilableStatement {
|
||||
public static func Compile(
|
||||
extension VariableDeclarationStatement: CompilableStatement {
|
||||
public static func CompileStatement(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<(EvaluatableStatement, CompilerContext)> {
|
||||
#RequireNodeType<Node, (EvaluatableStatement, CompilerContext)>(
|
||||
node: node, type: "expressionStatement", nice_type_name: "expression statement")
|
||||
|
||||
let expression_node = node.child(at: 0)!
|
||||
|
||||
return switch Expression.Compile(node: expression_node, withContext: context) {
|
||||
case .Ok(let expression): .Ok((ExpressionStatement(expression), context))
|
||||
) -> Result<P4Statement> {
|
||||
return switch Compile(node: node, withContext: context) {
|
||||
case .Ok(let res): .Ok(res)
|
||||
case .Error(let e): .Error(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension ParserAssignmentStatement: CompilableStatement {
|
||||
extension ExpressionStatement: Compilable {
|
||||
public typealias C = ExpressionStatement
|
||||
public static func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<(EvaluatableStatement, CompilerContext)> {
|
||||
) -> Result<ExpressionStatement> {
|
||||
#RequireNodeType<Node, (P4Statement)>(
|
||||
node: node, type: "expressionStatement", nice_type_name: "expression statement")
|
||||
|
||||
#RequireNodeType<Node, (EvaluatableStatement, CompilerContext)>(
|
||||
let expression_node = node.child(at: 0)!
|
||||
|
||||
return switch Expression.Compile(node: expression_node, withContext: context) {
|
||||
case .Ok(let expression): .Ok(ExpressionStatement(expression))
|
||||
case .Error(let e): .Error(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension ExpressionStatement: CompilableStatement {
|
||||
public static func CompileStatement(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<P4Statement> {
|
||||
return switch Compile(node: node, withContext: context) {
|
||||
case .Ok(let res): .Ok(res)
|
||||
case .Error(let e): .Error(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension ParserAssignmentStatement: Compilable {
|
||||
public typealias C = ParserAssignmentStatement
|
||||
public static func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<ParserAssignmentStatement> {
|
||||
|
||||
#RequireNodeType<Node, (P4Statement)>(
|
||||
node: node, type: "assignmentStatement", nice_type_name: "assignment statement")
|
||||
|
||||
guard let lvalue_node = node.child(at: 0),
|
||||
@@ -323,20 +365,30 @@ extension ParserAssignmentStatement: CompilableStatement {
|
||||
}
|
||||
|
||||
return Result.Ok(
|
||||
(
|
||||
ParserAssignmentStatement(
|
||||
withLValue: lvalue_identifier,
|
||||
withValue: rvalue
|
||||
), context
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
extension ReturnStatement: CompilableStatement {
|
||||
extension ParserAssignmentStatement: CompilableStatement {
|
||||
public static func CompileStatement(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<P4Statement> {
|
||||
return switch Compile(node: node, withContext: context) {
|
||||
case .Ok(let res): .Ok(res)
|
||||
case .Error(let e): .Error(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension ReturnStatement: Compilable {
|
||||
public typealias C = ReturnStatement
|
||||
public static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(any Common.EvaluatableStatement, CompilerContext)> {
|
||||
#RequireNodeType<Node, (EvaluatableStatement, CompilerContext)>(
|
||||
) -> Result<ReturnStatement> {
|
||||
#RequireNodeType<Node, (P4Statement)>(
|
||||
node: node, type: "return_statement", nice_type_name: "return statement")
|
||||
|
||||
let expression_node = node.child(at: 1)!
|
||||
@@ -344,7 +396,7 @@ extension ReturnStatement: CompilableStatement {
|
||||
return switch Expression.Compile(node: expression_node, withContext: context) {
|
||||
case .Ok(let result):
|
||||
if result.type().baseType().eq(rhs: context.expected_type!.baseType()) {
|
||||
.Ok((ReturnStatement(result), context))
|
||||
.Ok(ReturnStatement(result))
|
||||
} else {
|
||||
.Error(
|
||||
ErrorWithLocation(
|
||||
@@ -358,18 +410,184 @@ extension ReturnStatement: CompilableStatement {
|
||||
}
|
||||
}
|
||||
|
||||
extension ApplyStatement: CompilableStatement {
|
||||
extension ReturnStatement: CompilableStatement {
|
||||
public static func CompileStatement(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<P4Statement> {
|
||||
return switch Compile(node: node, withContext: context) {
|
||||
case .Ok(let res): .Ok(res)
|
||||
case .Error(let e): .Error(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension ApplyStatement: Compilable {
|
||||
public typealias C = ApplyStatement
|
||||
public static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Common.Result<(any Common.EvaluatableStatement, CompilerContext)> {
|
||||
#RequireNodeType<Node, (EvaluatableStatement, CompilerContext)>(
|
||||
) -> Result<ApplyStatement> {
|
||||
#RequireNodeType<Node, (P4Statement)>(
|
||||
node: node, type: "apply_statement", nice_type_name: "apply statement")
|
||||
|
||||
let expression_node = node.child(at: 1)!
|
||||
|
||||
return switch BlockStatement.Compile(node: expression_node, withContext: context) {
|
||||
case .Ok((let statement, let updated_context)):
|
||||
.Ok((ApplyStatement(statement as! BlockStatement), updated_context))
|
||||
case .Ok(let statement):
|
||||
.Ok(ApplyStatement(statement as! BlockStatement))
|
||||
case .Error(let e): .Error(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension ApplyStatement: CompilableStatement {
|
||||
public static func CompileStatement(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<P4Statement> {
|
||||
return switch Compile(node: node, withContext: context) {
|
||||
case .Ok(let res): .Ok(res)
|
||||
case .Error(let e): .Error(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Instantiation: Compilable {
|
||||
public typealias C = Instantiation
|
||||
public static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Result<Instantiation> {
|
||||
|
||||
let expression = node
|
||||
#RequireNodeType<Node, (Instantiation)>(
|
||||
node: expression, type: "instantiation", nice_type_name: "instantiation statement")
|
||||
|
||||
var walker = Walker(node: expression)
|
||||
var current_node: Node? = .none
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<Instantiation>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing function call component")))
|
||||
|
||||
let maybe_instantiated_type_name = Identifier.Compile(
|
||||
node: current_node!, withContext: context)
|
||||
guard case .Ok(let instantiated_type_name) = maybe_instantiated_type_name else {
|
||||
return Result.Error(maybe_instantiated_type_name.error()!)
|
||||
}
|
||||
|
||||
var maybe_instantiated_type: Result<(P4Lang.Parser?, Declaration?)> =
|
||||
switch context.types.lookup(identifier: instantiated_type_name) {
|
||||
case .Ok(let looked_up):
|
||||
switch looked_up {
|
||||
/// TODO: Further filter instantiable things.
|
||||
case let instantiated_parser as P4Lang.Parser:
|
||||
Result<(P4Lang.Parser?, Declaration?)>.Ok((instantiated_parser, .none)) // What we found is actually a parser declaration
|
||||
default:
|
||||
Result<(P4Lang.Parser?, Declaration?)>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: current_node!.toSourceLocation(),
|
||||
withError: "\(instantiated_type_name) cannot be instantiated"))
|
||||
}
|
||||
case .Error(let e): Result<(P4Lang.Parser?, Declaration?)>.Error(e)
|
||||
}
|
||||
|
||||
maybe_instantiated_type =
|
||||
if case .Error(let e) = maybe_instantiated_type {
|
||||
switch context.externs.lookup(identifier: instantiated_type_name) {
|
||||
case .Ok(let callee as Declaration):
|
||||
// Now, make sure that it is a function declaration!
|
||||
switch callee.identifier.type.baseType() {
|
||||
case is P4Lang.Parser: Result.Ok((.none, callee))
|
||||
default:
|
||||
.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: current_node!.toSourceLocation(),
|
||||
withError: "\(instantiated_type_name) cannot be instantiated"))
|
||||
}
|
||||
default: .Error(e)
|
||||
}
|
||||
} else {
|
||||
maybe_instantiated_type
|
||||
}
|
||||
|
||||
guard case .Ok(let callee) = maybe_instantiated_type else {
|
||||
return .Error(maybe_instantiated_type.error()!)
|
||||
}
|
||||
|
||||
walker.next()
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<Instantiation>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing instantiation component")))
|
||||
|
||||
let maybe_argument_list = ArgumentList.Compile(node: current_node!, withContext: context)
|
||||
|
||||
guard case .Ok(let arguments) = maybe_argument_list else {
|
||||
return .Error(maybe_argument_list.error()!)
|
||||
}
|
||||
|
||||
// Now, compare the arguments with the parameters:
|
||||
|
||||
let params =
|
||||
switch callee {
|
||||
case (.some(let callee), .none): Optional<ParameterList>.some(callee.parameters)
|
||||
case (.none, .some(let callee)):
|
||||
Optional<ParameterList>.some((callee.ffi!.type().baseType() as! P4Lang.Parser).parameters)
|
||||
default: Optional<ParameterList>.none
|
||||
}
|
||||
|
||||
guard case .some(let params) = params else {
|
||||
return Result.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError:
|
||||
"Could not lookup the parameters for the instantiated parser (\(instantiated_type_name))"
|
||||
))
|
||||
}
|
||||
|
||||
if case .Error(let e) = arguments.compatible(params) {
|
||||
return .Error(e)
|
||||
}
|
||||
|
||||
walker.next()
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<Instantiation>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing instantiation name")))
|
||||
|
||||
let name = Identifier.Compile(node: current_node!, withContext: context)
|
||||
guard case .Ok(let name) = name else {
|
||||
return .Error(name.error()!)
|
||||
}
|
||||
|
||||
let inst: Result<Instantiation> =
|
||||
switch callee {
|
||||
case (.some(let callee), .none):
|
||||
.Ok(Instantiation(named: name, ofType: callee, withArguments: arguments))
|
||||
case (.none, .some(let callee)):
|
||||
.Ok(Instantiation(named: name, ofType: callee, withArguments: arguments))
|
||||
default:
|
||||
Result.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError:
|
||||
"Unexpected error occurred calling function named (\(instantiated_type_name))"
|
||||
))
|
||||
}
|
||||
return inst
|
||||
}
|
||||
}
|
||||
|
||||
extension Instantiation: CompilableStatement {
|
||||
public static func CompileStatement(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<P4Statement> {
|
||||
return switch Compile(node: node, withContext: context) {
|
||||
case .Ok(let res): .Ok(res)
|
||||
case .Error(let e): .Error(e)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,95 +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
|
||||
|
||||
public protocol Visitable {
|
||||
|
||||
}
|
||||
|
||||
public protocol LanguageVisitor<Context> {
|
||||
associatedtype Context
|
||||
|
||||
// Program
|
||||
func visit(_ program: Program, _ c: VisitorContext<Context>) -> Result<VisitorContext<Context>>
|
||||
|
||||
// Parser
|
||||
func visit(_ parser: Parser, _ c: VisitorContext<Context>) -> Result<VisitorContext<Context>>
|
||||
func visit(
|
||||
_ parser_state: InstantiatedParserState, _ c: VisitorContext<Context>
|
||||
) -> Result<VisitorContext<Context>>
|
||||
|
||||
// Statements
|
||||
func visit(
|
||||
_ variable_declaration: VariableDeclarationStatement, _ c: VisitorContext<Context>
|
||||
) -> Result<VisitorContext<Context>>
|
||||
func visit(
|
||||
_ conditional: ConditionalStatement, _ c: VisitorContext<Context>
|
||||
) -> Result<VisitorContext<Context>>
|
||||
func visit(
|
||||
_ block: BlockStatement, _ c: VisitorContext<Context>
|
||||
) -> Result<VisitorContext<Context>>
|
||||
func visit(
|
||||
_ rtn: ReturnStatement, _ c: VisitorContext<Context>
|
||||
) -> Result<VisitorContext<Context>>
|
||||
func visit(
|
||||
_ apply: ApplyStatement, _ c: VisitorContext<Context>
|
||||
) -> Result<VisitorContext<Context>>
|
||||
|
||||
// Expressions
|
||||
func visit(
|
||||
_ keyset: KeysetExpression, _ c: VisitorContext<Context>
|
||||
) -> Result<VisitorContext<Context>>
|
||||
func visit(
|
||||
_ select_case: SelectCaseExpression, _ c: VisitorContext<Context>
|
||||
) -> Result<VisitorContext<Context>>
|
||||
func visit(
|
||||
_ select: SelectExpression, _ c: VisitorContext<Context>
|
||||
) -> Result<VisitorContext<Context>>
|
||||
func visit(
|
||||
_ array_access: ArrayAccessExpression, _ c: VisitorContext<Context>
|
||||
) -> Result<VisitorContext<Context>>
|
||||
func visit(
|
||||
_ field_access: FieldAccessExpression, _ c: VisitorContext<Context>
|
||||
) -> Result<VisitorContext<Context>>
|
||||
func visit(
|
||||
_ function_call: FunctionCall, _ c: VisitorContext<Context>
|
||||
) -> Result<VisitorContext<Context>>
|
||||
func visit(
|
||||
_ binary_operator: BinaryOperatorExpression, _ c: VisitorContext<Context>
|
||||
) -> Result<VisitorContext<Context>>
|
||||
|
||||
// Declarations
|
||||
func visit(_ decl: Declaration, _ c: VisitorContext<Context>) -> Result<VisitorContext<Context>>
|
||||
func visit(
|
||||
_ extern_decl: ExternDeclaration, _ c: VisitorContext<Context>
|
||||
) -> Result<VisitorContext<Context>>
|
||||
func visit(
|
||||
_ func_decl: FunctionDeclaration, _ c: VisitorContext<Context>
|
||||
) -> Result<VisitorContext<Context>>
|
||||
|
||||
// Control
|
||||
func visit(_ action: Action, _ c: VisitorContext<Context>) -> Result<VisitorContext<Context>>
|
||||
func visit(
|
||||
_ table_key_entry: TableKeyEntry, _ c: VisitorContext<Context>
|
||||
) -> Result<VisitorContext<Context>>
|
||||
func visit(
|
||||
_ table_property_list: TablePropertyList, _ c: VisitorContext<Context>
|
||||
) -> Result<VisitorContext<Context>>
|
||||
func visit(_ table: Table, _ c: VisitorContext<Context>) -> Result<VisitorContext<Context>>
|
||||
func visit(_ control: Control, _ c: VisitorContext<Context>) -> Result<VisitorContext<Context>>
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ public struct Declaration: P4Type {
|
||||
return self
|
||||
}
|
||||
public var description: String {
|
||||
return "Extern \(self.identifier)"
|
||||
return self.extern ? "Extern " : "" + "\(self.identifier)"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,3 +130,15 @@ public struct FunctionDeclaration: P4Type, P4DataValue {
|
||||
self.body = body
|
||||
}
|
||||
}
|
||||
|
||||
public struct Instantiation {
|
||||
public let name: Identifier
|
||||
public let tipe: P4Type
|
||||
public let arguments: ArgumentList
|
||||
|
||||
public init(named name: Identifier, ofType tipe: P4Type, withArguments arguments: ArgumentList) {
|
||||
self.name = name
|
||||
self.tipe = tipe
|
||||
self.arguments = arguments
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
import Common
|
||||
|
||||
public struct KeysetExpression {
|
||||
public let key: EvaluatableExpression
|
||||
public let key: P4Expression
|
||||
|
||||
public init(_ key: EvaluatableExpression) {
|
||||
public init(_ key: P4Expression) {
|
||||
self.key = key
|
||||
}
|
||||
|
||||
@@ -65,11 +65,11 @@ public struct SelectCaseExpression {
|
||||
}
|
||||
|
||||
public struct SelectExpression {
|
||||
public let selector: EvaluatableExpression
|
||||
public let selector: P4Expression
|
||||
public let case_expressions: [SelectCaseExpression]
|
||||
|
||||
public init(
|
||||
withSelector selector: EvaluatableExpression,
|
||||
withSelector selector: P4Expression,
|
||||
withSelectCaseExpressions sces: [SelectCaseExpression]
|
||||
) {
|
||||
self.selector = selector
|
||||
@@ -105,13 +105,13 @@ public struct BinaryOperatorExpression {
|
||||
}
|
||||
|
||||
public struct ArrayAccessExpression {
|
||||
public let indexor: EvaluatableExpression
|
||||
public let name: EvaluatableExpression
|
||||
public let indexor: P4Expression
|
||||
public let name: P4Expression
|
||||
public let type: P4Array
|
||||
|
||||
public init(
|
||||
withName name: EvaluatableExpression, withType type: P4Array,
|
||||
withIndexor indexor: EvaluatableExpression
|
||||
withName name: P4Expression, withType type: P4Array,
|
||||
withIndexor indexor: P4Expression
|
||||
) {
|
||||
self.name = name
|
||||
self.type = type
|
||||
@@ -121,9 +121,9 @@ public struct ArrayAccessExpression {
|
||||
|
||||
public struct FieldAccessExpression {
|
||||
public let field: P4StructFieldIdentifier
|
||||
public let strct: EvaluatableExpression
|
||||
public let strct: P4Expression
|
||||
|
||||
public init(withStruct strct: EvaluatableExpression, withField field: P4StructFieldIdentifier) {
|
||||
public init(withStruct strct: P4Expression, withField field: P4StructFieldIdentifier) {
|
||||
self.strct = strct
|
||||
self.field = field
|
||||
}
|
||||
|
||||
+10
-13
@@ -22,11 +22,11 @@ public struct LocalElements {}
|
||||
public struct LocalElement {}
|
||||
|
||||
public struct ParserAssignmentStatement {
|
||||
public let lvalue: EvaluatableLValueExpression
|
||||
public let value: EvaluatableExpression
|
||||
public let lvalue: P4LValueExpression
|
||||
public let value: P4Expression
|
||||
|
||||
public init(
|
||||
withLValue lvalue: EvaluatableLValueExpression, withValue value: EvaluatableExpression
|
||||
withLValue lvalue: P4LValueExpression, withValue value: P4Expression
|
||||
) {
|
||||
self.lvalue = lvalue
|
||||
self.value = value
|
||||
@@ -34,12 +34,9 @@ public struct ParserAssignmentStatement {
|
||||
}
|
||||
|
||||
/// A P4 Parser State
|
||||
///
|
||||
/// Note: A P4 Parser State is both a type and a value.
|
||||
/// This "bare" parser state represents the state more as a type than a value.
|
||||
public class ParserState: P4Type, Equatable, CustomStringConvertible {
|
||||
let name: Identifier
|
||||
public let statements: [EvaluatableStatement]
|
||||
public let statements: [P4Statement]
|
||||
|
||||
public static func == (lhs: ParserState, rhs: ParserState) -> Bool {
|
||||
return lhs.eq(rhs: rhs)
|
||||
@@ -60,12 +57,12 @@ public class ParserState: P4Type, Equatable, CustomStringConvertible {
|
||||
return self.name
|
||||
}
|
||||
|
||||
public func getStatements() -> [EvaluatableStatement] {
|
||||
public func getStatements() -> [P4Statement] {
|
||||
return self.statements
|
||||
}
|
||||
|
||||
/// Construct a ParserState
|
||||
public init(_ name: Identifier, _ statements: [EvaluatableStatement] = Array()) {
|
||||
public init(_ name: Identifier, _ statements: [P4Statement] = Array()) {
|
||||
self.name = name
|
||||
self.statements = statements
|
||||
}
|
||||
@@ -100,7 +97,7 @@ public class ParserStateDirectTransition: ParserState {
|
||||
/// Construct a ParserState
|
||||
public init(
|
||||
name: Identifier, withNextState next_state: InstantiatedParserState,
|
||||
withStatements stmts: [EvaluatableStatement] = Array(),
|
||||
withStatements stmts: [P4Statement] = Array(),
|
||||
) {
|
||||
self.next_state = next_state
|
||||
self.next_state_identifier = .none
|
||||
@@ -109,7 +106,7 @@ public class ParserStateDirectTransition: ParserState {
|
||||
|
||||
public init(
|
||||
name: Identifier, withNextStateIdentifier next_state_id: Identifier,
|
||||
withStatements stmts: [EvaluatableStatement] = Array(),
|
||||
withStatements stmts: [P4Statement] = Array(),
|
||||
) {
|
||||
self.next_state = .none
|
||||
self.next_state_identifier = next_state_id
|
||||
@@ -129,7 +126,7 @@ public class ParserStateDirectTransition: ParserState {
|
||||
public class ParserStateNoTransition: ParserState {
|
||||
/// Construct a ParserState
|
||||
public init(
|
||||
name: Identifier, withStatements stmts: [EvaluatableStatement] = Array(),
|
||||
name: Identifier, withStatements stmts: [P4Statement] = Array(),
|
||||
) {
|
||||
super.init(name, stmts)
|
||||
}
|
||||
@@ -145,7 +142,7 @@ public class ParserStateSelectTransition: ParserState {
|
||||
|
||||
public init(
|
||||
name: Identifier, withTransitionExpression te: SelectExpression,
|
||||
withStatements stmts: [EvaluatableStatement] = Array()
|
||||
withStatements stmts: [P4Statement] = Array()
|
||||
) {
|
||||
self.te = te
|
||||
super.init(name, stmts)
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
import Common
|
||||
|
||||
public struct ExpressionStatement {
|
||||
public let expression: EvaluatableExpression
|
||||
public let expression: P4Expression
|
||||
|
||||
public init(_ expr: EvaluatableExpression) {
|
||||
public init(_ expr: P4Expression) {
|
||||
self.expression = expr
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
// 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
|
||||
|
||||
public protocol Visitable {
|
||||
|
||||
}
|
||||
|
||||
public protocol LanguageVisitor<Context> {
|
||||
associatedtype Context
|
||||
|
||||
// Program
|
||||
func visit(_ program: Program, _ c: VisitorContext<Context>) -> Result<VisitorContext<Context>>
|
||||
|
||||
// Parser
|
||||
func visit(_ parser: Parser, _ c: VisitorContext<Context>) -> Result<VisitorContext<Context>>
|
||||
func visit(
|
||||
_ parser_state: InstantiatedParserState, _ c: VisitorContext<Context>
|
||||
) -> Result<VisitorContext<Context>>
|
||||
|
||||
// Statements
|
||||
func visit(
|
||||
_ variable_declaration: VariableDeclarationStatement, _ c: VisitorContext<Context>
|
||||
) -> Result<VisitorContext<Context>>
|
||||
func visit(
|
||||
_ conditional: ConditionalStatement, _ c: VisitorContext<Context>
|
||||
) -> Result<VisitorContext<Context>>
|
||||
func visit(
|
||||
_ block: BlockStatement, _ c: VisitorContext<Context>
|
||||
) -> Result<VisitorContext<Context>>
|
||||
func visit(
|
||||
_ rtn: ReturnStatement, _ c: VisitorContext<Context>
|
||||
) -> Result<VisitorContext<Context>>
|
||||
func visit(
|
||||
_ apply: ApplyStatement, _ c: VisitorContext<Context>
|
||||
) -> Result<VisitorContext<Context>>
|
||||
|
||||
// Expressions
|
||||
func visit(
|
||||
_ keyset: KeysetExpression, _ c: VisitorContext<Context>
|
||||
) -> Result<VisitorContext<Context>>
|
||||
func visit(
|
||||
_ select_case: SelectCaseExpression, _ c: VisitorContext<Context>
|
||||
) -> Result<VisitorContext<Context>>
|
||||
func visit(
|
||||
_ select: SelectExpression, _ c: VisitorContext<Context>
|
||||
) -> Result<VisitorContext<Context>>
|
||||
func visit(
|
||||
_ array_access: ArrayAccessExpression, _ c: VisitorContext<Context>
|
||||
) -> Result<VisitorContext<Context>>
|
||||
func visit(
|
||||
_ field_access: FieldAccessExpression, _ c: VisitorContext<Context>
|
||||
) -> Result<VisitorContext<Context>>
|
||||
func visit(
|
||||
_ function_call: FunctionCall, _ c: VisitorContext<Context>
|
||||
) -> Result<VisitorContext<Context>>
|
||||
func visit(
|
||||
_ binary_operator: BinaryOperatorExpression, _ c: VisitorContext<Context>
|
||||
) -> Result<VisitorContext<Context>>
|
||||
|
||||
// Declarations
|
||||
func visit(_ decl: Declaration, _ c: VisitorContext<Context>) -> Result<VisitorContext<Context>>
|
||||
func visit(
|
||||
_ extern_decl: ExternDeclaration, _ c: VisitorContext<Context>
|
||||
) -> Result<VisitorContext<Context>>
|
||||
func visit(
|
||||
_ func_decl: FunctionDeclaration, _ c: VisitorContext<Context>
|
||||
) -> Result<VisitorContext<Context>>
|
||||
|
||||
// Control
|
||||
func visit(_ action: Action, _ c: VisitorContext<Context>) -> Result<VisitorContext<Context>>
|
||||
func visit(
|
||||
_ table_key_entry: TableKeyEntry, _ c: VisitorContext<Context>
|
||||
) -> Result<VisitorContext<Context>>
|
||||
func visit(
|
||||
_ table_property_list: TablePropertyList, _ c: VisitorContext<Context>
|
||||
) -> Result<VisitorContext<Context>>
|
||||
func visit(_ table: Table, _ c: VisitorContext<Context>) -> Result<VisitorContext<Context>>
|
||||
func visit(_ control: Control, _ c: VisitorContext<Context>) -> Result<VisitorContext<Context>>
|
||||
}
|
||||
@@ -20,28 +20,28 @@ import Common
|
||||
public struct Statement {}
|
||||
|
||||
public struct VariableDeclarationStatement {
|
||||
public var initializer: EvaluatableExpression
|
||||
public var identifier: Identifier
|
||||
public init(identifier: Identifier, withInitializer initializer: EvaluatableExpression) {
|
||||
public var initializer: P4Expression
|
||||
public var identifier: TypedIdentifier
|
||||
public init(identifier: TypedIdentifier, withInitializer initializer: P4Expression) {
|
||||
self.identifier = identifier
|
||||
self.initializer = initializer
|
||||
}
|
||||
}
|
||||
|
||||
public struct ConditionalStatement {
|
||||
public var condition: EvaluatableExpression
|
||||
public var thenn: EvaluatableStatement
|
||||
public var elss: EvaluatableStatement?
|
||||
public var condition: P4Expression
|
||||
public var thenn: P4Statement
|
||||
public var elss: P4Statement?
|
||||
|
||||
public init(condition: EvaluatableExpression, withThen thenn: EvaluatableStatement) {
|
||||
public init(condition: P4Expression, withThen thenn: P4Statement) {
|
||||
self.condition = condition
|
||||
self.thenn = thenn
|
||||
self.elss = .none
|
||||
}
|
||||
|
||||
public init(
|
||||
condition: EvaluatableExpression, withThen thenn: EvaluatableStatement,
|
||||
andElse elss: EvaluatableStatement
|
||||
condition: P4Expression, withThen thenn: P4Statement,
|
||||
andElse elss: P4Statement
|
||||
) {
|
||||
self.condition = condition
|
||||
self.thenn = thenn
|
||||
@@ -50,18 +50,18 @@ public struct ConditionalStatement {
|
||||
}
|
||||
|
||||
public struct BlockStatement {
|
||||
public var statements: [EvaluatableStatement]
|
||||
public var statements: [P4Statement]
|
||||
|
||||
public init(_ statements: [EvaluatableStatement]) {
|
||||
public init(_ statements: [P4Statement]) {
|
||||
self.statements = statements
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public struct ReturnStatement {
|
||||
public let value: EvaluatableExpression
|
||||
public let value: P4Expression
|
||||
|
||||
public init(_ value: EvaluatableExpression) {
|
||||
public init(_ value: P4Expression) {
|
||||
self.value = value
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ public func Call<T>(
|
||||
param_direction == Direction.InOut || param_direction == Direction.Out
|
||||
{
|
||||
// Let's make sure that it is an evaluatable l value!
|
||||
guard let arg_lvalue = argument.argument as? EvaluatableLValueExpression else {
|
||||
guard let arg_lvalue = argument.argument as? P4LValueExpression else {
|
||||
return (
|
||||
.Error(Error(withMessage: "(in)out parameter argument is not lvalue")),
|
||||
updated_execution.exit_scope()
|
||||
|
||||
@@ -91,10 +91,14 @@ extension Control: LibraryCallable {
|
||||
}
|
||||
}
|
||||
|
||||
extension Action: EvaluatableStatement {
|
||||
extension Action: P4Statement {
|
||||
public func effect(context: Common.CompilerContext) -> Common.CompilerContext {
|
||||
return context
|
||||
}
|
||||
|
||||
public func evaluate(
|
||||
execution: Common.ProgramExecution
|
||||
) -> (Common.ControlFlow, Common.ProgramExecution) {
|
||||
) -> (ControlFlow, Common.ProgramExecution) {
|
||||
if let body = self.body {
|
||||
return body.evaluate(execution: execution)
|
||||
}
|
||||
|
||||
+134
-108
@@ -22,88 +22,11 @@ extension SelectCaseExpression: EvaluatableExpression {
|
||||
public func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution) {
|
||||
return (execution.scopes.lookup(identifier: next_state_identifier), execution)
|
||||
}
|
||||
|
||||
public func type() -> P4QualifiedType {
|
||||
return P4QualifiedType(AnyParserState)
|
||||
}
|
||||
}
|
||||
|
||||
extension SelectExpression: EvaluatableExpression {
|
||||
public func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution) {
|
||||
switch execution.evaluator.EvaluateExpression(self.selector, inExecution: execution) {
|
||||
case (.Ok(let selector_value), let updated_execution):
|
||||
for sce in self.case_expressions {
|
||||
if case (.Ok(let kse), let updated_execution) = updated_execution.evaluator
|
||||
.EvaluateExpression(
|
||||
sce.key, inExecution: updated_execution),
|
||||
kse.eq(selector_value)
|
||||
{
|
||||
//let result = sce.evaluate(execution: updated_execution)
|
||||
let result = updated_execution.evaluator.EvaluateExpression(
|
||||
sce, inExecution: updated_execution)
|
||||
return result
|
||||
}
|
||||
}
|
||||
return (.Error(Error(withMessage: "No key matched the selector")), updated_execution)
|
||||
case (.Error(let e), let updated_execution): return (.Error(e), updated_execution)
|
||||
}
|
||||
}
|
||||
|
||||
public func type() -> P4QualifiedType {
|
||||
return P4QualifiedType(AnyParserState)
|
||||
}
|
||||
}
|
||||
|
||||
// Variables are evaluatable because they can be looked up by identifiers.
|
||||
extension TypedIdentifier: EvaluatableExpression {
|
||||
public func type() -> P4QualifiedType {
|
||||
return self.type
|
||||
}
|
||||
|
||||
public func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution) {
|
||||
return (execution.scopes.lookup(identifier: self), execution)
|
||||
}
|
||||
}
|
||||
|
||||
// Variables are evaluatable because they can be looked up by identifiers.
|
||||
extension TypedIdentifier: EvaluatableLValueExpression {
|
||||
public func set(
|
||||
to: P4Value, inScopes scopes: Common.VarValueScopes,
|
||||
duringExecution execution: ProgramExecution
|
||||
) -> Common.Result<(Common.VarValueScopes, P4Value)> {
|
||||
if case .Error(let e) = scopes.lookup(identifier: self) {
|
||||
return .Error(e)
|
||||
}
|
||||
|
||||
return .Ok((scopes.set(identifier: self, withValue: to), to))
|
||||
}
|
||||
|
||||
public func check(
|
||||
to: any Common.EvaluatableExpression, inScopes scopes: Common.StaticVarValueScopes
|
||||
) -> Result<()> {
|
||||
guard case .Ok(let type) = scopes.lookup(identifier: self) else {
|
||||
return .Error(Error(withMessage: "Cannot assign to identifier not in scope"))
|
||||
}
|
||||
|
||||
return switch type.0.assignableFromType(to.type()) {
|
||||
case TypeCheckResults.IncompatibleTypes:
|
||||
.Error(
|
||||
Error(
|
||||
withMessage:
|
||||
"Cannot assign value with type \(to.type()) to identifier \(self) with type \(type.0)"))
|
||||
case TypeCheckResults.ReadOnly:
|
||||
.Error(
|
||||
Error(
|
||||
withMessage:
|
||||
"Cannot assign value with type \(to.type()) to identifier \(self) that is read only"))
|
||||
case TypeCheckResults.WrongDirection:
|
||||
.Error(
|
||||
Error(
|
||||
withMessage:
|
||||
"Cannot assign value with type \(to.type()) to identifier \(self) that is in parameter")
|
||||
)
|
||||
case TypeCheckResults.Ok: .Ok(())
|
||||
}
|
||||
public func effect(context: CompilerContext) -> CompilerContext {
|
||||
return context
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,7 +109,7 @@ public func binary_divide_operator_evaluator(left: P4Value, right: P4Value) -> P
|
||||
}
|
||||
|
||||
// swift-format-ignore
|
||||
public typealias BinaryOperatorChecker = (EvaluatableExpression, EvaluatableExpression) -> Result<()>
|
||||
public typealias BinaryOperatorChecker = (EvaluatableExpression, P4Expression) -> Result<()>
|
||||
|
||||
public func binary_and_or_operator_checker(
|
||||
left: EvaluatableExpression, right: EvaluatableExpression
|
||||
@@ -211,6 +134,10 @@ public func binary_int_math_operator_checker(
|
||||
}
|
||||
|
||||
extension BinaryOperatorExpression: EvaluatableExpression {
|
||||
public func effect(context: CompilerContext) -> CompilerContext {
|
||||
return context
|
||||
}
|
||||
|
||||
public func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution) {
|
||||
let updated_execution = execution
|
||||
//let maybe_evaluated_left = self.left.evaluate(execution: updated_execution)
|
||||
@@ -235,7 +162,11 @@ extension BinaryOperatorExpression: EvaluatableExpression {
|
||||
}
|
||||
}
|
||||
|
||||
extension ArrayAccessExpression: EvaluatableExpression {
|
||||
extension ArrayAccessExpression: EvaluatableExpression, EvaluatableLValueExpression {
|
||||
|
||||
public func effect(context: CompilerContext) -> CompilerContext {
|
||||
return context
|
||||
}
|
||||
public func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution) {
|
||||
let updated_execution = execution
|
||||
//let maybe_name = self.name.evaluate(execution: updated_execution)
|
||||
@@ -267,9 +198,7 @@ extension ArrayAccessExpression: EvaluatableExpression {
|
||||
public func type() -> P4QualifiedType {
|
||||
return self.type.value_type()
|
||||
}
|
||||
}
|
||||
|
||||
extension ArrayAccessExpression: EvaluatableLValueExpression {
|
||||
public func set(
|
||||
to: P4Value, inScopes scopes: Common.VarValueScopes,
|
||||
duringExecution execution: ProgramExecution
|
||||
@@ -352,35 +281,13 @@ extension ArrayAccessExpression: EvaluatableLValueExpression {
|
||||
}
|
||||
}
|
||||
|
||||
extension FieldAccessExpression: EvaluatableExpression {
|
||||
public func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution) {
|
||||
|
||||
let updated_execution = execution
|
||||
//let maybe_struct = self.strct.evaluate(execution: updated_execution)
|
||||
let maybe_struct = updated_execution.evaluator.EvaluateExpression(
|
||||
self.strct, inExecution: updated_execution)
|
||||
guard case (.Ok(let strct), let updated_execution) = maybe_struct else {
|
||||
return maybe_struct
|
||||
}
|
||||
|
||||
guard let struct_strct = strct.dataValue() as? P4StructValue else {
|
||||
return (.Error(Error(withMessage: "\(strct) does not identify a struct")), updated_execution)
|
||||
}
|
||||
|
||||
/// TODO: Create a default value?
|
||||
guard let value = struct_strct.get(field: self.field) else {
|
||||
return (.Error(Error(withMessage: "Missing value")), updated_execution)
|
||||
}
|
||||
|
||||
return (.Ok(value), updated_execution)
|
||||
}
|
||||
|
||||
extension FieldAccessExpression: EvaluatableExpression, EvaluatableLValueExpression {
|
||||
public func type() -> P4QualifiedType {
|
||||
return self.field.type
|
||||
}
|
||||
public func effect(context: CompilerContext) -> CompilerContext {
|
||||
return context
|
||||
}
|
||||
|
||||
extension FieldAccessExpression: EvaluatableLValueExpression {
|
||||
public func set(
|
||||
to: P4Value, inScopes scopes: Common.VarValueScopes,
|
||||
duringExecution execution: ProgramExecution
|
||||
@@ -459,9 +366,33 @@ extension FieldAccessExpression: EvaluatableLValueExpression {
|
||||
default: .Error(Error(withMessage: "Cannot assign to field \(self.field) of \(self.strct)"))
|
||||
}
|
||||
}
|
||||
public func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution) {
|
||||
|
||||
let updated_execution = execution
|
||||
//let maybe_struct = self.strct.evaluate(execution: updated_execution)
|
||||
let maybe_struct = updated_execution.evaluator.EvaluateExpression(
|
||||
self.strct, inExecution: updated_execution)
|
||||
guard case (.Ok(let strct), let updated_execution) = maybe_struct else {
|
||||
return maybe_struct
|
||||
}
|
||||
|
||||
guard let struct_strct = strct.dataValue() as? P4StructValue else {
|
||||
return (.Error(Error(withMessage: "\(strct) does not identify a struct")), updated_execution)
|
||||
}
|
||||
|
||||
/// TODO: Create a default value?
|
||||
guard let value = struct_strct.get(field: self.field) else {
|
||||
return (.Error(Error(withMessage: "Missing value")), updated_execution)
|
||||
}
|
||||
|
||||
return (.Ok(value), updated_execution)
|
||||
}
|
||||
}
|
||||
|
||||
extension KeysetExpression: EvaluatableExpression {
|
||||
public func effect(context: CompilerContext) -> CompilerContext {
|
||||
return context
|
||||
}
|
||||
public func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution) {
|
||||
//return self.key.evaluate(execution: execution)
|
||||
return execution.evaluator.EvaluateExpression(self.key, inExecution: execution)
|
||||
@@ -473,6 +404,10 @@ extension KeysetExpression: EvaluatableExpression {
|
||||
}
|
||||
|
||||
extension FunctionCall: EvaluatableExpression {
|
||||
|
||||
public func effect(context: CompilerContext) -> CompilerContext {
|
||||
return context
|
||||
}
|
||||
public func evaluate(
|
||||
execution: Common.ProgramExecution
|
||||
) -> (Common.Result<P4Value>, ProgramExecution) {
|
||||
@@ -533,4 +468,95 @@ extension P4Value: EvaluatableExpression {
|
||||
public func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution) {
|
||||
return (.Ok(self), execution)
|
||||
}
|
||||
|
||||
public func effect(context: CompilerContext) -> CompilerContext {
|
||||
return context
|
||||
}
|
||||
}
|
||||
|
||||
extension SelectExpression: EvaluatableExpression {
|
||||
public func evaluate(execution: ProgramExecution) -> (Result<P4Value>, ProgramExecution) {
|
||||
switch execution.evaluator.EvaluateExpression(self.selector, inExecution: execution) {
|
||||
case (.Ok(let selector_value), let updated_execution):
|
||||
for sce in self.case_expressions {
|
||||
if case (.Ok(let kse), let updated_execution) = updated_execution.evaluator
|
||||
.EvaluateExpression(
|
||||
sce.key, inExecution: updated_execution),
|
||||
kse.eq(selector_value)
|
||||
{
|
||||
//let result = sce.evaluate(execution: updated_execution)
|
||||
let result = updated_execution.evaluator.EvaluateExpression(
|
||||
sce, inExecution: updated_execution)
|
||||
return result
|
||||
}
|
||||
}
|
||||
return (.Error(Error(withMessage: "No key matched the selector")), updated_execution)
|
||||
case (.Error(let e), let updated_execution): return (.Error(e), updated_execution)
|
||||
}
|
||||
}
|
||||
|
||||
public func type() -> P4QualifiedType {
|
||||
return P4QualifiedType(AnyParserState)
|
||||
}
|
||||
|
||||
public func effect(context: CompilerContext) -> CompilerContext {
|
||||
return context
|
||||
}
|
||||
}
|
||||
|
||||
// Variables are evaluatable because they can be looked up by identifiers.
|
||||
extension TypedIdentifier: EvaluatableExpression, EvaluatableLValueExpression {
|
||||
public func evaluate(
|
||||
execution: Common.ProgramExecution
|
||||
) -> (Common.Result<Common.P4Value>, Common.ProgramExecution) {
|
||||
return (execution.scopes.lookup(identifier: self), execution)
|
||||
}
|
||||
|
||||
public func set(
|
||||
to: P4Value, inScopes scopes: Common.VarValueScopes,
|
||||
duringExecution execution: ProgramExecution
|
||||
) -> Common.Result<(Common.VarValueScopes, P4Value)> {
|
||||
if case .Error(let e) = scopes.lookup(identifier: self) {
|
||||
return .Error(e)
|
||||
}
|
||||
|
||||
return .Ok((scopes.set(identifier: self, withValue: to), to))
|
||||
}
|
||||
|
||||
public func type() -> P4QualifiedType {
|
||||
return self.type
|
||||
}
|
||||
|
||||
public func effect(context: CompilerContext) -> CompilerContext {
|
||||
return context
|
||||
}
|
||||
|
||||
// Variables are evaluatable because they can be looked up by identifiers.
|
||||
public func check(
|
||||
to: P4Expression, inScopes scopes: Common.StaticVarValueScopes
|
||||
) -> Result<()> {
|
||||
guard case .Ok(let type) = scopes.lookup(identifier: self) else {
|
||||
return .Error(Error(withMessage: "Cannot assign to identifier not in scope"))
|
||||
}
|
||||
|
||||
return switch type.0.assignableFromType(to.type()) {
|
||||
case TypeCheckResults.IncompatibleTypes:
|
||||
.Error(
|
||||
Error(
|
||||
withMessage:
|
||||
"Cannot assign value with type \(to.type()) to identifier \(self) with type \(type.0)"))
|
||||
case TypeCheckResults.ReadOnly:
|
||||
.Error(
|
||||
Error(
|
||||
withMessage:
|
||||
"Cannot assign value with type \(to.type()) to identifier \(self) that is read only"))
|
||||
case TypeCheckResults.WrongDirection:
|
||||
.Error(
|
||||
Error(
|
||||
withMessage:
|
||||
"Cannot assign value with type \(to.type()) to identifier \(self) that is in parameter")
|
||||
)
|
||||
case TypeCheckResults.Ok: .Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,11 @@
|
||||
import Common
|
||||
import P4Lang
|
||||
|
||||
extension ParserAssignmentStatement: EvaluatableStatement {
|
||||
extension ParserAssignmentStatement: P4Statement {
|
||||
public func effect(context: Common.CompilerContext) -> Common.CompilerContext {
|
||||
return context
|
||||
}
|
||||
|
||||
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
|
||||
let updated_execution = execution
|
||||
//let result = self.value.evaluate(execution: updated_execution)
|
||||
@@ -192,3 +196,19 @@ extension ParserValue: LibraryCallable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension ParserState: P4Statement {
|
||||
public func evaluate(
|
||||
execution: Common.ProgramExecution
|
||||
) -> (Common.ControlFlow, Common.ProgramExecution) {
|
||||
return (
|
||||
ControlFlow.Error,
|
||||
execution.setError(error: Error(withMessage: "Cannot evaluate unspecialized parser state"))
|
||||
)
|
||||
}
|
||||
|
||||
public func effect(context: Common.CompilerContext) -> Common.CompilerContext {
|
||||
return context.update(
|
||||
newTypes: context.types.declare(identifier: self.getName(), withValue: self))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,11 @@
|
||||
import Common
|
||||
import P4Lang
|
||||
|
||||
extension BlockStatement: EvaluatableStatement {
|
||||
extension BlockStatement: P4Statement {
|
||||
public func effect(context: Common.CompilerContext) -> Common.CompilerContext {
|
||||
return context
|
||||
}
|
||||
|
||||
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
|
||||
return execution.evaluator.ExecuteStatements(
|
||||
self.statements, inExecution: execution
|
||||
@@ -38,7 +42,14 @@ extension BlockStatement: EvaluatableStatement {
|
||||
}
|
||||
}
|
||||
|
||||
extension VariableDeclarationStatement: EvaluatableStatement {
|
||||
extension VariableDeclarationStatement: P4Statement {
|
||||
public func effect(context: Common.CompilerContext) -> Common.CompilerContext {
|
||||
return context.update(
|
||||
newInstances: context.instances.declare(
|
||||
identifier: self.identifier, withValue: (self.identifier.type(), .none)))
|
||||
|
||||
}
|
||||
|
||||
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
|
||||
guard
|
||||
//case (.Ok(let initial_value), let execution) = self.initializer.evaluate(execution: execution)
|
||||
@@ -56,7 +67,11 @@ extension VariableDeclarationStatement: EvaluatableStatement {
|
||||
}
|
||||
}
|
||||
|
||||
extension ConditionalStatement: EvaluatableStatement {
|
||||
extension ConditionalStatement: P4Statement {
|
||||
public func effect(context: Common.CompilerContext) -> Common.CompilerContext {
|
||||
return context
|
||||
}
|
||||
|
||||
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
|
||||
guard
|
||||
//case (.Ok(let evaluated_condition), let execution) = self.condition.evaluate(execution: execution)
|
||||
@@ -105,7 +120,11 @@ extension ConditionalStatement: EvaluatableStatement {
|
||||
}
|
||||
}
|
||||
|
||||
extension ExpressionStatement: EvaluatableStatement {
|
||||
extension ExpressionStatement: P4Statement {
|
||||
public func effect(context: Common.CompilerContext) -> Common.CompilerContext {
|
||||
return context
|
||||
}
|
||||
|
||||
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
|
||||
|
||||
// Evaluate, there might be side effects!
|
||||
@@ -118,7 +137,12 @@ extension ExpressionStatement: EvaluatableStatement {
|
||||
}
|
||||
}
|
||||
|
||||
extension ReturnStatement: EvaluatableStatement {
|
||||
extension ReturnStatement: P4Statement {
|
||||
public func effect(context: Common.CompilerContext) -> Common.CompilerContext {
|
||||
|
||||
return context
|
||||
}
|
||||
|
||||
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
|
||||
//return switch self.value.evaluate(execution: execution) {
|
||||
return switch execution.evaluator.EvaluateExpression(self.value, inExecution: execution) {
|
||||
@@ -128,8 +152,42 @@ extension ReturnStatement: EvaluatableStatement {
|
||||
}
|
||||
}
|
||||
|
||||
extension ApplyStatement: EvaluatableStatement {
|
||||
extension ApplyStatement: P4Statement {
|
||||
public func effect(context: Common.CompilerContext) -> Common.CompilerContext {
|
||||
|
||||
return context
|
||||
}
|
||||
|
||||
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
|
||||
return (ControlFlow.Next, execution)
|
||||
}
|
||||
}
|
||||
|
||||
extension Instantiation: P4Statement {
|
||||
public func effect(context: Common.CompilerContext) -> Common.CompilerContext {
|
||||
return context
|
||||
}
|
||||
|
||||
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
|
||||
return (ControlFlow.Next, execution)
|
||||
}
|
||||
}
|
||||
|
||||
extension Declaration: P4Statement {
|
||||
public func effect(context: Common.CompilerContext) -> Common.CompilerContext {
|
||||
if self.extern {
|
||||
return context.update(
|
||||
newExterns: context.externs.declare(
|
||||
identifier: self.identifier, withValue: self))
|
||||
}
|
||||
|
||||
return context.update(
|
||||
newTypes: context.types.declare(
|
||||
identifier: self.identifier, withValue: self.identifier.type().baseType()))
|
||||
}
|
||||
|
||||
public func evaluate(execution: ProgramExecution) -> (ControlFlow, ProgramExecution) {
|
||||
//// TODO
|
||||
return (ControlFlow.Next, execution)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ import P4Lang
|
||||
let result = try! #require(p.parse(simple))
|
||||
|
||||
#expect(
|
||||
#RequireErrorResult<(EvaluatableStatement, CompilerContext)>(
|
||||
#RequireErrorResult<ParserAssignmentStatement>(
|
||||
ErrorWithLocation(sourceLocation: SourceLocation(2, 154), withError: "Did not find assignment statement"),
|
||||
ParserAssignmentStatement.Compile( // Note: Calling ParserAssignmentStatement compilation directly.
|
||||
node: result.rootNode!, withContext: CompilerContext())))
|
||||
@@ -182,3 +182,16 @@ import P4Lang
|
||||
|
||||
#expect(#RequireOkResult(SpecialCompilers.ProgramCompiler.Compile(simple)))
|
||||
}
|
||||
|
||||
@Test func test_simple_compiler_with_instantiation() async throws {
|
||||
let simple_instantiation_program = """
|
||||
parser MainParser() {
|
||||
state start {
|
||||
transition accept;
|
||||
}
|
||||
};
|
||||
|
||||
MainParser() mp;
|
||||
"""
|
||||
#expect(#RequireOkResult(SpecialCompilers.ProgramCompiler.Compile(simple_instantiation_program)))
|
||||
}
|
||||
@@ -68,7 +68,7 @@ export default grammar({
|
||||
|
||||
|
||||
// Instantiation
|
||||
instantiation: $ => seq($.typeRef, '(', optional($.parameter_list), ')', $.identifier),
|
||||
instantiation: $ => seq($.typeRef, $.arguments, $.identifier),
|
||||
|
||||
// Declarations
|
||||
declaration: $ => seq(choice($.parserDeclaration, $.parserTypeDeclaration, $.type_declaration, $.function_declaration, $.control_declaration, $.extern_declaration)),
|
||||
|
||||
Reference in New Issue
Block a user