@@ -16,18 +16,17 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import Common
|
||||
import P4Lang
|
||||
import P4Runtime
|
||||
import SwiftTreeSitter
|
||||
import TreeSitterExtensions
|
||||
import TreeSitterP4
|
||||
|
||||
extension BlockStatement: Compilable {
|
||||
public typealias C = BlockStatement
|
||||
extension AST.BlockStatement: Compilable {
|
||||
public typealias C = AST.BlockStatement
|
||||
public static func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<BlockStatement> {
|
||||
#RequireNodeType<Node, (P4Statement)>(
|
||||
node: Node, withContext context: ASTCompilerContext
|
||||
) -> Result<AST.BlockStatement> {
|
||||
/*
|
||||
#RequireNodeType<Node, AST.BlockStatement>(
|
||||
node: node, type: "blockStatement", nice_type_name: "block statement")
|
||||
|
||||
var walker = Walker(node: node)
|
||||
@@ -35,7 +34,7 @@ extension BlockStatement: Compilable {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<BlockStatement>.Error(
|
||||
or: Result<AST.BlockStatement>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Malformed block statement")))
|
||||
|
||||
@@ -46,13 +45,13 @@ extension BlockStatement: Compilable {
|
||||
withError: "Missing { on block statement"))
|
||||
}
|
||||
|
||||
var statements: [P4Statement] = Array()
|
||||
var statements: [AST.AnStatement] = Array()
|
||||
var parse_err: (any Errorable)? = .none
|
||||
|
||||
walker.next()
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<BlockStatement>.Error(
|
||||
or: Result<AST.BlockStatement>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Malformed block statement")))
|
||||
|
||||
@@ -75,7 +74,7 @@ extension BlockStatement: Compilable {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<BlockStatement>.Error(
|
||||
or: Result<AST.BlockStatement>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Malformed block statement")))
|
||||
|
||||
@@ -86,20 +85,22 @@ extension BlockStatement: Compilable {
|
||||
withError: "Missing } on block statement"))
|
||||
}
|
||||
|
||||
return .Ok(BlockStatement(statements))
|
||||
return .Ok(AST.BlockStatement(statements))
|
||||
*/
|
||||
return .Ok(AST.BlockStatement([]))
|
||||
}
|
||||
}
|
||||
|
||||
@deriveCompilableStatement
|
||||
extension BlockStatement: CompilableStatement {}
|
||||
extension AST.BlockStatement: CompilableStatement {}
|
||||
|
||||
extension ConditionalStatement: Compilable {
|
||||
public typealias C = ConditionalStatement
|
||||
extension AST.ConditionalStatement: Compilable {
|
||||
public typealias C = AST.ConditionalStatement
|
||||
public static func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<ConditionalStatement> {
|
||||
node: Node, withContext context: ASTCompilerContext
|
||||
) -> Result<AST.ConditionalStatement> {
|
||||
|
||||
#RequireNodeType<Node, (P4Statement)>(
|
||||
#RequireNodeType<Node, AST.ConditionalStatement>(
|
||||
node: node, type: "conditionalStatement", nice_type_name: "conditional statement")
|
||||
|
||||
let maybe_condition_expression = node.child(at: 2)
|
||||
@@ -123,7 +124,7 @@ extension ConditionalStatement: Compilable {
|
||||
}
|
||||
|
||||
guard
|
||||
case .Ok(let condition) = Expression.Compile(
|
||||
case .Ok(let condition) = AST.Expression.Compile(
|
||||
node: condition_expression, withContext: context)
|
||||
else {
|
||||
return Result.Error(
|
||||
@@ -131,7 +132,7 @@ extension ConditionalStatement: Compilable {
|
||||
}
|
||||
|
||||
guard
|
||||
case .Ok(let thenns) = Statement.Compile(
|
||||
case .Ok(let thenns) = AST.Statement.Compile(
|
||||
node: thens, withContext: context)
|
||||
else {
|
||||
return Result.Error(
|
||||
@@ -140,10 +141,10 @@ extension ConditionalStatement: Compilable {
|
||||
"Could not parse the then block in a conditional statement"))
|
||||
}
|
||||
|
||||
let optional_elss: Result<any P4Statement>? =
|
||||
let optional_elss: Result<AST.AnStatement>? =
|
||||
if let elss = node.child(at: 6) {
|
||||
.some(
|
||||
Statement.Compile(
|
||||
AST.Statement.Compile(
|
||||
node: elss, withContext: context))
|
||||
} else {
|
||||
.none
|
||||
@@ -159,22 +160,22 @@ extension ConditionalStatement: Compilable {
|
||||
"Could not parse the else block in a conditional statement"))
|
||||
}
|
||||
return .Ok(
|
||||
ConditionalStatement(condition: condition, withThen: thenns, andElse: elss))
|
||||
AST.ConditionalStatement(condition: condition, withThen: thenns, andElse: elss))
|
||||
}
|
||||
return .Ok(ConditionalStatement(condition: condition, withThen: thenns))
|
||||
return .Ok(AST.ConditionalStatement(condition: condition, withThen: thenns))
|
||||
}
|
||||
}
|
||||
|
||||
@deriveCompilableStatement
|
||||
extension ConditionalStatement: CompilableStatement {}
|
||||
extension AST.ConditionalStatement: CompilableStatement {}
|
||||
|
||||
extension VariableDeclarationStatement: Compilable {
|
||||
public typealias C = VariableDeclarationStatement
|
||||
extension AST.VariableDeclarationStatement: Compilable {
|
||||
public typealias C = AST.VariableDeclarationStatement
|
||||
public static func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<VariableDeclarationStatement> {
|
||||
node: Node, withContext context: ASTCompilerContext
|
||||
) -> Result<AST.VariableDeclarationStatement> {
|
||||
|
||||
#RequireNodeType<Node, (P4Statement)>(
|
||||
#RequireNodeType<Node, AST.VariableDeclarationStatement>(
|
||||
node: node, type: "variableDeclaration", nice_type_name: "variable declaration statement")
|
||||
|
||||
let maybe_typeref = node.child(at: 0)
|
||||
@@ -200,20 +201,21 @@ extension VariableDeclarationStatement: Compilable {
|
||||
let maybe_rvalue = node.childCount > 3 ? node.child(at: 3) : .none
|
||||
|
||||
guard
|
||||
case .Ok(let parsed_variablename) = Identifier.Compile(
|
||||
case .Ok(let parsed_variablename) = AST.Identifier.CompileExpression(
|
||||
node: variablename, withContext: context)
|
||||
else {
|
||||
return Result.Error(
|
||||
Error(withMessage: "Could not parse variable name"))
|
||||
}
|
||||
|
||||
guard case .Ok(let declaration_p4_type) = Types.CompileType(type: typeref, withContext: context)
|
||||
guard
|
||||
case .Ok(let declaration_p4_type) = AST.Types.CompileType(type: typeref, withContext: context)
|
||||
else {
|
||||
return Result.Error(
|
||||
Error(withMessage: "Could not parse a P4 type from \(typeref.text!)"))
|
||||
}
|
||||
|
||||
var initializer: P4Expression? = .none
|
||||
var initializer: AST.AnExpression? = .none
|
||||
|
||||
// If there is an initializer, it must be an expression.
|
||||
if let initializer_expression = maybe_rvalue {
|
||||
@@ -224,7 +226,7 @@ extension VariableDeclarationStatement: Compilable {
|
||||
withError: "initial value for declaration statement is not an expression"))
|
||||
}
|
||||
|
||||
let maybe_parsed_rvalue = Expression.Compile(
|
||||
let maybe_parsed_rvalue = AST.Expression.Compile(
|
||||
node: initializer_expression, withContext: context)
|
||||
guard
|
||||
case .Ok(let parsed_rvalue) = maybe_parsed_rvalue
|
||||
@@ -232,67 +234,47 @@ extension VariableDeclarationStatement: Compilable {
|
||||
return .Error(maybe_parsed_rvalue.error()!)
|
||||
}
|
||||
|
||||
if parsed_rvalue.type().eq(declaration_p4_type) {
|
||||
initializer = parsed_rvalue
|
||||
} else {
|
||||
return Result.Error(
|
||||
Error(
|
||||
withMessage:
|
||||
"Cannot initialize \(parsed_variablename) (with type \(declaration_p4_type)) from expression with type \(parsed_rvalue.type())"
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
// If there is no initializer, then it must be defaultable.
|
||||
|
||||
if initializer == nil {
|
||||
initializer = declaration_p4_type.def()
|
||||
}
|
||||
|
||||
guard let initializer = initializer else {
|
||||
return Result.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "No initializer for declaration"))
|
||||
initializer = parsed_rvalue
|
||||
}
|
||||
|
||||
return Result.Ok(
|
||||
VariableDeclarationStatement(
|
||||
identifier: TypedIdentifier(id: parsed_variablename, withType: declaration_p4_type),
|
||||
AST.VariableDeclarationStatement(
|
||||
identifier: parsed_variablename as! AST.Identifier, withType: declaration_p4_type,
|
||||
withInitializer: initializer),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@deriveCompilableStatement
|
||||
extension VariableDeclarationStatement: CompilableStatement {}
|
||||
extension AST.VariableDeclarationStatement: CompilableStatement {}
|
||||
|
||||
extension ExpressionStatement: Compilable {
|
||||
public typealias C = ExpressionStatement
|
||||
extension AST.ExpressionStatement: Compilable {
|
||||
public typealias C = AST.ExpressionStatement
|
||||
public static func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<ExpressionStatement> {
|
||||
node: Node, withContext context: ASTCompilerContext
|
||||
) -> Result<AST.ExpressionStatement> {
|
||||
#RequireNodeType<Node, (P4Statement)>(
|
||||
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))
|
||||
return switch AST.Expression.Compile(node: expression_node, withContext: context) {
|
||||
case .Ok(let expression): .Ok(AST.ExpressionStatement(expression))
|
||||
case .Error(let e): .Error(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@deriveCompilableStatement
|
||||
extension ExpressionStatement: CompilableStatement {}
|
||||
extension AST.ExpressionStatement: CompilableStatement {}
|
||||
|
||||
extension ParserAssignmentStatement: Compilable {
|
||||
public typealias C = ParserAssignmentStatement
|
||||
extension AST.ParserAssignmentStatement: Compilable {
|
||||
public typealias C = AST.ParserAssignmentStatement
|
||||
public static func Compile(
|
||||
node: Node, withContext context: CompilerContext
|
||||
) -> Result<ParserAssignmentStatement> {
|
||||
node: Node, withContext context: ASTCompilerContext
|
||||
) -> Result<AST.ParserAssignmentStatement> {
|
||||
|
||||
#RequireNodeType<Node, (P4Statement)>(
|
||||
#RequireNodeType<Node, AST.ParserAssignmentStatement>(
|
||||
node: node, type: "assignmentStatement", nice_type_name: "assignment statement")
|
||||
|
||||
guard let lvalue_node = node.child(at: 0),
|
||||
@@ -313,95 +295,77 @@ extension ParserAssignmentStatement: Compilable {
|
||||
withError: "Missing rvalue in assignment statement"))
|
||||
}
|
||||
|
||||
let maybe_parsed_rvalue = Expression.Compile(
|
||||
let maybe_parsed_rvalue = AST.Expression.Compile(
|
||||
node: rvalue_node, withContext: context)
|
||||
guard case Result.Ok(let rvalue) = maybe_parsed_rvalue else {
|
||||
return Result.Error(maybe_parsed_rvalue.error()!)
|
||||
}
|
||||
|
||||
let maybe_parsed_lvalue = LValue.Compile(node: lvalue_node, withContext: context)
|
||||
guard case .Ok(let lvalue_identifier) = maybe_parsed_lvalue else {
|
||||
let maybe_parsed_lvalue = AST.Expression.Compile(node: lvalue_node, withContext: context)
|
||||
guard case .Ok(let lvalue) = maybe_parsed_lvalue else {
|
||||
return Result.Error(maybe_parsed_lvalue.error()!)
|
||||
}
|
||||
|
||||
let check_result = lvalue_identifier.check(to: rvalue, inScopes: context.instances)
|
||||
guard case .Ok(_) = check_result else {
|
||||
return Result.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: lvalue_node.toSourceLocation(),
|
||||
withError: "\(check_result.error()!)"))
|
||||
}
|
||||
|
||||
return Result.Ok(
|
||||
ParserAssignmentStatement(
|
||||
withLValue: lvalue_identifier,
|
||||
AST.ParserAssignmentStatement(
|
||||
withLValue: lvalue,
|
||||
withValue: rvalue
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@deriveCompilableStatement
|
||||
extension ParserAssignmentStatement: CompilableStatement {}
|
||||
extension AST.ParserAssignmentStatement: CompilableStatement {}
|
||||
|
||||
extension ReturnStatement: Compilable {
|
||||
public typealias C = ReturnStatement
|
||||
extension AST.ReturnStatement: Compilable {
|
||||
public typealias C = AST.ReturnStatement
|
||||
public static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Result<ReturnStatement> {
|
||||
#RequireNodeType<Node, (P4Statement)>(
|
||||
node: SwiftTreeSitter.Node, withContext context: ASTCompilerContext
|
||||
) -> Result<AST.ReturnStatement> {
|
||||
#RequireNodeType<Node, AST.ReturnStatement>(
|
||||
node: node, type: "return_statement", nice_type_name: "return statement")
|
||||
|
||||
let expression_node = node.child(at: 1)!
|
||||
|
||||
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))
|
||||
} else {
|
||||
.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(),
|
||||
withError:
|
||||
"Type of expression in return statement (\(result.type())) is not compatible with function return type (\(context.expected_type!))"
|
||||
))
|
||||
}
|
||||
return switch AST.Expression.Compile(node: expression_node, withContext: context) {
|
||||
case .Ok(let result): .Ok(AST.ReturnStatement(result))
|
||||
case .Error(let e): .Error(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@deriveCompilableStatement
|
||||
extension ReturnStatement: CompilableStatement {}
|
||||
extension AST.ReturnStatement: CompilableStatement {}
|
||||
|
||||
extension ApplyStatement: Compilable {
|
||||
public typealias C = ApplyStatement
|
||||
extension AST.ApplyStatement: Compilable {
|
||||
public typealias C = AST.ApplyStatement
|
||||
public static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Result<ApplyStatement> {
|
||||
#RequireNodeType<Node, (P4Statement)>(
|
||||
node: SwiftTreeSitter.Node, withContext context: ASTCompilerContext
|
||||
) -> Result<AST.ApplyStatement> {
|
||||
#RequireNodeType<Node, AST.ApplyStatement>(
|
||||
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) {
|
||||
return switch AST.BlockStatement.Compile(node: expression_node, withContext: context) {
|
||||
case .Ok(let statement):
|
||||
.Ok(ApplyStatement(statement))
|
||||
.Ok(AST.ApplyStatement(statement))
|
||||
case .Error(let e): .Error(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@deriveCompilableStatement
|
||||
extension ApplyStatement: CompilableStatement {}
|
||||
extension AST.ApplyStatement: CompilableStatement {}
|
||||
|
||||
extension Instantiation: Compilable {
|
||||
public typealias C = Instantiation
|
||||
extension AST.Instantiation: Compilable {
|
||||
public typealias C = AST.Instantiation
|
||||
public static func Compile(
|
||||
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||
) -> Result<Instantiation> {
|
||||
node: SwiftTreeSitter.Node, withContext context: ASTCompilerContext
|
||||
) -> Result<AST.Instantiation> {
|
||||
|
||||
let expression = node
|
||||
#RequireNodeType<Node, (Instantiation)>(
|
||||
#RequireNodeType<Node, AST.Instantiation>(
|
||||
node: expression, type: "instantiation", nice_type_name: "instantiation statement")
|
||||
|
||||
var walker = Walker(node: expression)
|
||||
@@ -409,122 +373,48 @@ extension Instantiation: Compilable {
|
||||
|
||||
#MustOr(
|
||||
result: current_node, thing: walker.getNext(),
|
||||
or: Result<Instantiation>.Error(
|
||||
or: Result<AST.Instantiation>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing function call component")))
|
||||
|
||||
let maybe_instantiated_type_name = Identifier.Compile(
|
||||
let maybe_instantiated_type_name = AST.Identifier.CompileExpression(
|
||||
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(
|
||||
or: Result<AST.Instantiation>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing instantiation component")))
|
||||
|
||||
let maybe_argument_list = ArgumentList.Compile(node: current_node!, withContext: context)
|
||||
let maybe_argument_list = AST.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(
|
||||
or: Result<AST.Instantiation>.Error(
|
||||
ErrorWithLocation(
|
||||
sourceLocation: node.toSourceLocation(), withError: "Missing instantiation name")))
|
||||
|
||||
let name = Identifier.Compile(node: current_node!, withContext: context)
|
||||
let name = AST.Identifier.CompileExpression(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
|
||||
return .Ok(
|
||||
AST.Instantiation(
|
||||
named: name as! AST.Identifier, withType: instantiated_type_name as! AST.Identifier,
|
||||
withArguments: arguments))
|
||||
}
|
||||
}
|
||||
|
||||
@deriveCompilableStatement
|
||||
extension Instantiation: CompilableStatement {}
|
||||
extension AST.Instantiation: CompilableStatement {}
|
||||
|
||||
Reference in New Issue
Block a user