Refactor Compilation Interface
Compilation interface(s) now contain a compilation context. The change will make it easier to expand on what each step of the compilation process needs to know to complete its task without having to make major changes to the interface. Signed-off-by: Will Hawkins <hawkinsw@obs.cr>
This commit is contained in:
@@ -39,3 +39,11 @@ public func ConfigureP4Parser() -> Result<SwiftTreeSitter.Parser> {
|
|||||||
public func ErrorOnNode(node: Node, withError error: String) -> Error {
|
public func ErrorOnNode(node: Node, withError error: String) -> Error {
|
||||||
return Error(withMessage: "\(node.range): \(error)")
|
return Error(withMessage: "\(node.range): \(error)")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct CompilerContext {
|
||||||
|
public let names: LexicalScopes
|
||||||
|
|
||||||
|
public init(withNames _names: LexicalScopes) {
|
||||||
|
names = _names
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,13 +22,13 @@ import TreeSitterP4
|
|||||||
|
|
||||||
protocol CompilableExpression {
|
protocol CompilableExpression {
|
||||||
static func compile(
|
static func compile(
|
||||||
node: Node, withTypesInScope scopes: LexicalScopes
|
node: Node, withContext context: CompilerContext
|
||||||
) -> Result<EvaluatableExpression?>
|
) -> Result<EvaluatableExpression?>
|
||||||
}
|
}
|
||||||
|
|
||||||
extension TypedIdentifier: CompilableExpression {
|
extension TypedIdentifier: CompilableExpression {
|
||||||
static func compile(
|
static func compile(
|
||||||
node: SwiftTreeSitter.Node, withTypesInScope scopes: LexicalScopes
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Result<EvaluatableExpression?> {
|
) -> Result<EvaluatableExpression?> {
|
||||||
|
|
||||||
let node = node.child(at: 0)!
|
let node = node.child(at: 0)!
|
||||||
@@ -36,7 +36,7 @@ extension TypedIdentifier: CompilableExpression {
|
|||||||
node: node, type: "identifier")
|
node: node, type: "identifier")
|
||||||
|
|
||||||
guard
|
guard
|
||||||
case Result.Ok(let type) = scopes.lookup(
|
case Result.Ok(let type) = context.names.lookup(
|
||||||
identifier: Common.Identifier(name: node.text!))
|
identifier: Common.Identifier(name: node.text!))
|
||||||
else {
|
else {
|
||||||
return .Error(ErrorOnNode(node: node, withError: "Cannot find \(node.text!) in scope"))
|
return .Error(ErrorOnNode(node: node, withError: "Cannot find \(node.text!) in scope"))
|
||||||
@@ -48,7 +48,7 @@ extension TypedIdentifier: CompilableExpression {
|
|||||||
|
|
||||||
extension P4BooleanValue: CompilableExpression {
|
extension P4BooleanValue: CompilableExpression {
|
||||||
static func compile(
|
static func compile(
|
||||||
node: SwiftTreeSitter.Node, withTypesInScope scopes: LexicalScopes
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Result<EvaluatableExpression?> {
|
) -> Result<EvaluatableExpression?> {
|
||||||
let node = node.child(at: 0)!
|
let node = node.child(at: 0)!
|
||||||
#SkipUnlessNodeType<SwiftTreeSitter.Node, EvaluatableExpression?>(
|
#SkipUnlessNodeType<SwiftTreeSitter.Node, EvaluatableExpression?>(
|
||||||
@@ -67,7 +67,7 @@ extension P4BooleanValue: CompilableExpression {
|
|||||||
|
|
||||||
extension P4IntValue: CompilableExpression {
|
extension P4IntValue: CompilableExpression {
|
||||||
static func compile(
|
static func compile(
|
||||||
node: SwiftTreeSitter.Node, withTypesInScope scopes: LexicalScopes
|
node: SwiftTreeSitter.Node, withContext context: CompilerContext
|
||||||
) -> Result<EvaluatableExpression?> {
|
) -> Result<EvaluatableExpression?> {
|
||||||
let node = node.child(at: 0)!
|
let node = node.child(at: 0)!
|
||||||
#SkipUnlessNodeType<SwiftTreeSitter.Node, EvaluatableExpression?>(node: node, type: "integer")
|
#SkipUnlessNodeType<SwiftTreeSitter.Node, EvaluatableExpression?>(node: node, type: "integer")
|
||||||
@@ -81,7 +81,7 @@ extension P4IntValue: CompilableExpression {
|
|||||||
|
|
||||||
extension P4StringValue: CompilableExpression {
|
extension P4StringValue: CompilableExpression {
|
||||||
static func compile(
|
static func compile(
|
||||||
node: SwiftTreeSitter.Node, withTypesInScope scopes: LexicalScopes
|
node: SwiftTreeSitter.Node, withContext scopes: CompilerContext
|
||||||
) -> Result<EvaluatableExpression?> {
|
) -> Result<EvaluatableExpression?> {
|
||||||
let node = node.child(at: 0)!
|
let node = node.child(at: 0)!
|
||||||
#SkipUnlessNodeType<SwiftTreeSitter.Node, EvaluatableExpression?>(
|
#SkipUnlessNodeType<SwiftTreeSitter.Node, EvaluatableExpression?>(
|
||||||
@@ -92,7 +92,7 @@ extension P4StringValue: CompilableExpression {
|
|||||||
|
|
||||||
struct Expression {
|
struct Expression {
|
||||||
public static func Compile(
|
public static func Compile(
|
||||||
node: Node, withTypesInScope: LexicalScopes
|
node: Node, withContext: CompilerContext
|
||||||
) -> Result<EvaluatableExpression> {
|
) -> Result<EvaluatableExpression> {
|
||||||
|
|
||||||
#RequireNodesType<Node, EvaluatableExpression>(
|
#RequireNodesType<Node, EvaluatableExpression>(
|
||||||
@@ -113,7 +113,7 @@ struct Expression {
|
|||||||
|
|
||||||
for le_parser in localElementsParsers {
|
for le_parser in localElementsParsers {
|
||||||
switch le_parser.compile(
|
switch le_parser.compile(
|
||||||
node: node, withTypesInScope: withTypesInScope)
|
node: node, withContext: withContext)
|
||||||
{
|
{
|
||||||
case .Ok(.some(let parsed)): return .Ok(parsed)
|
case .Ok(.some(let parsed)): return .Ok(parsed)
|
||||||
case .Error(let e): return .Error(e)
|
case .Error(let e): return .Error(e)
|
||||||
@@ -127,7 +127,7 @@ struct Expression {
|
|||||||
|
|
||||||
struct LValue {
|
struct LValue {
|
||||||
public static func Compile(
|
public static func Compile(
|
||||||
node: Node, withTypesInScope: LexicalScopes
|
node: Node, withContext: CompilerContext
|
||||||
) -> Result<Common.Identifier> {
|
) -> Result<Common.Identifier> {
|
||||||
return if let node_text_value = node.text {
|
return if let node_text_value = node.text {
|
||||||
.Ok(Common.Identifier(name: node_text_value))
|
.Ok(Common.Identifier(name: node_text_value))
|
||||||
@@ -139,7 +139,7 @@ struct LValue {
|
|||||||
|
|
||||||
struct Identifier {
|
struct Identifier {
|
||||||
public static func Compile(
|
public static func Compile(
|
||||||
node: Node, withTypesInScopes scopes: LexicalScopes
|
node: Node, withContext context: CompilerContext
|
||||||
) -> Result<Common.Identifier> {
|
) -> Result<Common.Identifier> {
|
||||||
return if let node_text_value = node.text {
|
return if let node_text_value = node.text {
|
||||||
.Ok(Common.Identifier(name: node_text_value))
|
.Ok(Common.Identifier(name: node_text_value))
|
||||||
@@ -151,9 +151,9 @@ struct Identifier {
|
|||||||
|
|
||||||
extension SelectExpression: CompilableExpression {
|
extension SelectExpression: CompilableExpression {
|
||||||
static func compile(
|
static func compile(
|
||||||
node: Node, withTypesInScope scopes: LexicalScopes
|
node: Node, withContext context: CompilerContext
|
||||||
) -> Result<EvaluatableExpression?> {
|
) -> Result<EvaluatableExpression?> {
|
||||||
#RequireNodeType<Node, (SelectExpression, LexicalScopes)>(
|
#RequireNodeType<Node, (SelectExpression, CompilerContext)>(
|
||||||
node: node, type: "selectExpression", nice_type_name: "parser select expression")
|
node: node, type: "selectExpression", nice_type_name: "parser select expression")
|
||||||
|
|
||||||
guard let selector_node = node.child(at: 2),
|
guard let selector_node = node.child(at: 2),
|
||||||
@@ -168,7 +168,7 @@ extension SelectExpression: CompilableExpression {
|
|||||||
return .Error(ErrorOnNode(node: node, withError: "Could not find select expression body"))
|
return .Error(ErrorOnNode(node: node, withError: "Could not find select expression body"))
|
||||||
}
|
}
|
||||||
|
|
||||||
let maybe_selector = Expression.Compile(node: selector_node, withTypesInScope: scopes)
|
let maybe_selector = Expression.Compile(node: selector_node, withContext: context)
|
||||||
guard case .Ok(let selector) = maybe_selector else {
|
guard case .Ok(let selector) = maybe_selector else {
|
||||||
return .Error(
|
return .Error(
|
||||||
Error(
|
Error(
|
||||||
@@ -182,7 +182,7 @@ extension SelectExpression: CompilableExpression {
|
|||||||
|
|
||||||
select_body_node.enumerateNamedChildren { current_node in
|
select_body_node.enumerateNamedChildren { current_node in
|
||||||
let maybe_parsed_kse = KeysetExpression.compile(
|
let maybe_parsed_kse = KeysetExpression.compile(
|
||||||
node: current_node, withTypesInScope: scopes)
|
node: current_node, withContext: context)
|
||||||
if case .Ok(let parsed_kse) = maybe_parsed_kse {
|
if case .Ok(let parsed_kse) = maybe_parsed_kse {
|
||||||
kses.append(parsed_kse as! KeysetExpression)
|
kses.append(parsed_kse as! KeysetExpression)
|
||||||
} else {
|
} else {
|
||||||
@@ -206,7 +206,7 @@ extension SelectExpression: CompilableExpression {
|
|||||||
|
|
||||||
extension KeysetExpression: CompilableExpression {
|
extension KeysetExpression: CompilableExpression {
|
||||||
static func compile(
|
static func compile(
|
||||||
node: Node, withTypesInScope scopes: LexicalScopes
|
node: Node, withContext context: CompilerContext
|
||||||
) -> Result<EvaluatableExpression?> {
|
) -> Result<EvaluatableExpression?> {
|
||||||
if node.nodeType != "selectCase" {
|
if node.nodeType != "selectCase" {
|
||||||
return Result.Error(Error(withMessage: "Expected select case not found"))
|
return Result.Error(Error(withMessage: "Expected select case not found"))
|
||||||
@@ -225,13 +225,13 @@ extension KeysetExpression: CompilableExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let maybe_parsed_keysetexpression = Expression.Compile(
|
let maybe_parsed_keysetexpression = Expression.Compile(
|
||||||
node: keysetexpression_node, withTypesInScope: scopes)
|
node: keysetexpression_node, withContext: context)
|
||||||
guard case Result.Ok(let keysetexpression) = maybe_parsed_keysetexpression else {
|
guard case Result.Ok(let keysetexpression) = maybe_parsed_keysetexpression else {
|
||||||
return Result.Error(maybe_parsed_keysetexpression.error()!)
|
return Result.Error(maybe_parsed_keysetexpression.error()!)
|
||||||
}
|
}
|
||||||
|
|
||||||
let maybe_parsed_targetstate = Identifier.Compile(
|
let maybe_parsed_targetstate = Identifier.Compile(
|
||||||
node: targetstate_node, withTypesInScopes: scopes)
|
node: targetstate_node, withContext: context)
|
||||||
guard case .Ok(let targetstate) = maybe_parsed_targetstate else {
|
guard case .Ok(let targetstate) = maybe_parsed_targetstate else {
|
||||||
return Result.Error(maybe_parsed_targetstate.error()!)
|
return Result.Error(maybe_parsed_targetstate.error()!)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,10 +24,10 @@ import TreeSitterP4
|
|||||||
|
|
||||||
extension ParserAssignmentStatement: CompilableStatement {
|
extension ParserAssignmentStatement: CompilableStatement {
|
||||||
public static func Compile(
|
public static func Compile(
|
||||||
node: Node, withTypesInScope scopes: LexicalScopes
|
node: Node, withContext context: CompilerContext
|
||||||
) -> Result<(EvaluatableStatement, LexicalScopes)> {
|
) -> Result<(EvaluatableStatement, CompilerContext)> {
|
||||||
|
|
||||||
#RequireNodeType<Node, (EvaluatableStatement, LexicalScopes)>(
|
#RequireNodeType<Node, (EvaluatableStatement, CompilerContext)>(
|
||||||
node: node, type: "assignmentStatement", nice_type_name: "assignment statement")
|
node: node, type: "assignmentStatement", nice_type_name: "assignment statement")
|
||||||
|
|
||||||
guard let lvalue_node = node.child(at: 0),
|
guard let lvalue_node = node.child(at: 0),
|
||||||
@@ -45,16 +45,16 @@ extension ParserAssignmentStatement: CompilableStatement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let maybe_parsed_rvalue = Expression.Compile(
|
let maybe_parsed_rvalue = Expression.Compile(
|
||||||
node: rvalue_node, withTypesInScope: scopes)
|
node: rvalue_node, withContext: context)
|
||||||
guard case Result.Ok(let rvalue) = maybe_parsed_rvalue else {
|
guard case Result.Ok(let rvalue) = maybe_parsed_rvalue else {
|
||||||
return Result.Error(maybe_parsed_rvalue.error()!)
|
return Result.Error(maybe_parsed_rvalue.error()!)
|
||||||
}
|
}
|
||||||
|
|
||||||
let maybe_parsed_lvalue = LValue.Compile(node: lvalue_node, withTypesInScope: scopes)
|
let maybe_parsed_lvalue = LValue.Compile(node: lvalue_node, withContext: context)
|
||||||
guard case .Ok(let lvalue_identifier) = maybe_parsed_lvalue else {
|
guard case .Ok(let lvalue_identifier) = maybe_parsed_lvalue else {
|
||||||
return Result.Error(maybe_parsed_lvalue.error()!)
|
return Result.Error(maybe_parsed_lvalue.error()!)
|
||||||
}
|
}
|
||||||
guard case Result.Ok(let lvalue_type) = scopes.lookup(identifier: lvalue_identifier) else {
|
guard case Result.Ok(let lvalue_type) = context.names.lookup(identifier: lvalue_identifier) else {
|
||||||
return Result.Error(
|
return Result.Error(
|
||||||
ErrorOnNode(
|
ErrorOnNode(
|
||||||
node: lvalue_node,
|
node: lvalue_node,
|
||||||
@@ -67,7 +67,7 @@ extension ParserAssignmentStatement: CompilableStatement {
|
|||||||
ParserAssignmentStatement(
|
ParserAssignmentStatement(
|
||||||
withLValue: TypedIdentifier(name: lvalue_node.text!, withType: lvalue_type),
|
withLValue: TypedIdentifier(name: lvalue_node.text!, withType: lvalue_type),
|
||||||
withValue: rvalue
|
withValue: rvalue
|
||||||
), scopes
|
), context
|
||||||
))
|
))
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -84,8 +84,8 @@ extension ParserAssignmentStatement: CompilableStatement {
|
|||||||
public struct Parser {
|
public struct Parser {
|
||||||
public struct LocalElements {
|
public struct LocalElements {
|
||||||
static func Compile(
|
static func Compile(
|
||||||
node: Node, withTypesInScope scopes: LexicalScopes
|
node: Node, withContext context: CompilerContext
|
||||||
) -> Result<(EvaluatableStatement, LexicalScopes)> {
|
) -> Result<(EvaluatableStatement, CompilerContext)> {
|
||||||
let localElementsParsers: [String: CompilableStatement.Type] = [
|
let localElementsParsers: [String: CompilableStatement.Type] = [
|
||||||
"variableDeclaration": VariableDeclarationStatement.self
|
"variableDeclaration": VariableDeclarationStatement.self
|
||||||
]
|
]
|
||||||
@@ -97,7 +97,7 @@ public struct Parser {
|
|||||||
withError: "Unparseable statement type (\(node.nodeType ?? "Unknown Statement Type"))"))
|
withError: "Unparseable statement type (\(node.nodeType ?? "Unknown Statement Type"))"))
|
||||||
}
|
}
|
||||||
|
|
||||||
switch parser.Compile(node: node, withTypesInScope: scopes) {
|
switch parser.Compile(node: node, withContext: context) {
|
||||||
case Result.Ok(let (parsed, parsed_updated_scopes)):
|
case Result.Ok(let (parsed, parsed_updated_scopes)):
|
||||||
return Result.Ok((parsed, parsed_updated_scopes))
|
return Result.Ok((parsed, parsed_updated_scopes))
|
||||||
case Result.Error(let e):
|
case Result.Error(let e):
|
||||||
@@ -108,8 +108,8 @@ public struct Parser {
|
|||||||
|
|
||||||
public struct Statement {
|
public struct Statement {
|
||||||
static func Compile(
|
static func Compile(
|
||||||
node: Node, withTypesInScope scopes: LexicalScopes
|
node: Node, withContext context: CompilerContext
|
||||||
) -> Result<(EvaluatableStatement, LexicalScopes)> {
|
) -> Result<(EvaluatableStatement, CompilerContext)> {
|
||||||
if node.nodeType != "parserStatement" && node.nodeType != "statement" {
|
if node.nodeType != "parserStatement" && node.nodeType != "statement" {
|
||||||
return Result.Error(ErrorOnNode(node: node, withError: "Missing expected parser statement"))
|
return Result.Error(ErrorOnNode(node: node, withError: "Missing expected parser statement"))
|
||||||
}
|
}
|
||||||
@@ -132,9 +132,9 @@ public struct Parser {
|
|||||||
withError:
|
withError:
|
||||||
"Unparseable statement type (\(statement.nodeType ?? "Unknown Statement Type"))"))
|
"Unparseable statement type (\(statement.nodeType ?? "Unknown Statement Type"))"))
|
||||||
}
|
}
|
||||||
switch parser.Compile(node: statement, withTypesInScope: scopes) {
|
switch parser.Compile(node: statement, withContext: context) {
|
||||||
case Result.Ok(let (parsed, updatedLexicalScopes)):
|
case Result.Ok(let (parsed, updated_context)):
|
||||||
return .Ok((parsed, updatedLexicalScopes))
|
return .Ok((parsed, updated_context))
|
||||||
case Result.Error(let e):
|
case Result.Error(let e):
|
||||||
return .Error(
|
return .Error(
|
||||||
ErrorOnNode(node: node, withError: "Failed to parse a statement element: \(e)"))
|
ErrorOnNode(node: node, withError: "Failed to parse a statement element: \(e)"))
|
||||||
@@ -145,10 +145,10 @@ public struct Parser {
|
|||||||
public struct TransitionStatement {
|
public struct TransitionStatement {
|
||||||
static func Compile(
|
static func Compile(
|
||||||
node: Node, forState state_identifier: Common.Identifier,
|
node: Node, forState state_identifier: Common.Identifier,
|
||||||
withStatements stmts: [EvaluatableStatement], withTypesInScope scopes: LexicalScopes
|
withStatements stmts: [EvaluatableStatement], withContext context: CompilerContext
|
||||||
) -> Result<(ParserState, LexicalScopes)> {
|
) -> Result<(ParserState, CompilerContext)> {
|
||||||
|
|
||||||
#RequireNodeType<Node, (EvaluatableStatement, LexicalScopes)>(
|
#RequireNodeType<Node, (EvaluatableStatement, CompilerContext)>(
|
||||||
node: node, type: "parserTransitionStatement", nice_type_name: "parser transition statement"
|
node: node, type: "parserTransitionStatement", nice_type_name: "parser transition statement"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -169,12 +169,12 @@ public struct Parser {
|
|||||||
// If the next node is an identifier, we have the simple form ...
|
// If the next node is an identifier, we have the simple form ...
|
||||||
if next_node.nodeType == "identifier" {
|
if next_node.nodeType == "identifier" {
|
||||||
let maybe_parsed_next_state = Identifier.Compile(
|
let maybe_parsed_next_state = Identifier.Compile(
|
||||||
node: next_node, withTypesInScopes: scopes)
|
node: next_node, withContext: context)
|
||||||
if case .Ok(let next_state) = maybe_parsed_next_state {
|
if case .Ok(let next_state) = maybe_parsed_next_state {
|
||||||
return .Ok(
|
return .Ok(
|
||||||
(
|
(
|
||||||
ParserStateDirectTransition(
|
ParserStateDirectTransition(
|
||||||
name: state_identifier, withStatements: stmts, withNextState: next_state), scopes
|
name: state_identifier, withStatements: stmts, withNextState: next_state), context
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
return .Error(
|
return .Error(
|
||||||
@@ -187,14 +187,14 @@ public struct Parser {
|
|||||||
|
|
||||||
// We know that the next node is a select expression.
|
// We know that the next node is a select expression.
|
||||||
return
|
return
|
||||||
switch SelectExpression.compile(node: next_node, withTypesInScope: scopes)
|
switch SelectExpression.compile(node: next_node, withContext: context)
|
||||||
{
|
{
|
||||||
case .Ok(let tse):
|
case .Ok(let tse):
|
||||||
.Ok(
|
.Ok(
|
||||||
(
|
(
|
||||||
ParserStateSelectTransition(
|
ParserStateSelectTransition(
|
||||||
name: state_identifier, withStatements: stmts,
|
name: state_identifier, withStatements: stmts,
|
||||||
withTransitioniExpression: tse as! SelectExpression), scopes
|
withTransitioniExpression: tse as! SelectExpression), context
|
||||||
))
|
))
|
||||||
case .Error(let e): .Error(e)
|
case .Error(let e): .Error(e)
|
||||||
}
|
}
|
||||||
@@ -203,22 +203,22 @@ public struct Parser {
|
|||||||
|
|
||||||
public struct Statements {
|
public struct Statements {
|
||||||
static func Compile(
|
static func Compile(
|
||||||
node: Node, withTypesInScope scopes: LexicalScopes
|
node: Node, withContext context: CompilerContext
|
||||||
) -> Result<([EvaluatableStatement], LexicalScopes)> {
|
) -> Result<([EvaluatableStatement], CompilerContext)> {
|
||||||
if node.nodeType != "statements" && node.nodeType != "parserStatements" {
|
if node.nodeType != "statements" && node.nodeType != "parserStatements" {
|
||||||
return Result.Error(ErrorOnNode(node: node, withError: "Did not find expected statements"))
|
return Result.Error(ErrorOnNode(node: node, withError: "Did not find expected statements"))
|
||||||
}
|
}
|
||||||
|
|
||||||
var parse_err: Error? = .none
|
var parse_err: Error? = .none
|
||||||
var current_scopes = scopes
|
var current_context = context
|
||||||
var parsed_s: [EvaluatableStatement] = Array()
|
var parsed_s: [EvaluatableStatement] = Array()
|
||||||
|
|
||||||
node.enumerateNamedChildren { node in
|
node.enumerateNamedChildren { node in
|
||||||
switch Statement.Compile(
|
switch Statement.Compile(
|
||||||
node: node, withTypesInScope: current_scopes)
|
node: node, withContext: current_context)
|
||||||
{
|
{
|
||||||
case .Ok((let parsed_statement, let updated_scopes)):
|
case .Ok((let parsed_statement, let updated_context)):
|
||||||
current_scopes = updated_scopes
|
current_context = updated_context
|
||||||
parsed_s.append(parsed_statement)
|
parsed_s.append(parsed_statement)
|
||||||
case .Error(let e):
|
case .Error(let e):
|
||||||
parse_err = e
|
parse_err = e
|
||||||
@@ -228,14 +228,14 @@ public struct Parser {
|
|||||||
if let parse_err = parse_err {
|
if let parse_err = parse_err {
|
||||||
return Result.Error(parse_err)
|
return Result.Error(parse_err)
|
||||||
}
|
}
|
||||||
return Result.Ok((parsed_s, current_scopes))
|
return Result.Ok((parsed_s, current_context))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct State {
|
public struct State {
|
||||||
static func Compile(
|
static func Compile(
|
||||||
node: Node, withTypesInScope scopes: LexicalScopes
|
node: Node, withContext context: CompilerContext
|
||||||
) -> Result<(ParserState, LexicalScopes)> {
|
) -> Result<(ParserState, CompilerContext)> {
|
||||||
|
|
||||||
var currentChildIdx = 0
|
var currentChildIdx = 0
|
||||||
var currentChildIdxSafe = 1
|
var currentChildIdxSafe = 1
|
||||||
@@ -273,7 +273,7 @@ public struct Parser {
|
|||||||
|
|
||||||
currentChild = node.child(at: currentChildIdx)
|
currentChild = node.child(at: currentChildIdx)
|
||||||
let maybe_state_identifier = Identifier.Compile(
|
let maybe_state_identifier = Identifier.Compile(
|
||||||
node: currentChild!, withTypesInScopes: scopes)
|
node: currentChild!, withContext: context)
|
||||||
guard case Result.Ok(let state_identifier) = maybe_state_identifier else {
|
guard case Result.Ok(let state_identifier) = maybe_state_identifier else {
|
||||||
return Result.Error(maybe_state_identifier.error()!)
|
return Result.Error(maybe_state_identifier.error()!)
|
||||||
}
|
}
|
||||||
@@ -283,7 +283,7 @@ public struct Parser {
|
|||||||
currentChildIdxSafe += 2
|
currentChildIdxSafe += 2
|
||||||
|
|
||||||
var parse_err: Error? = .none
|
var parse_err: Error? = .none
|
||||||
var current_scopes: LexicalScopes = LexicalScopes()
|
var current_context = context
|
||||||
var parsed_s: [EvaluatableStatement] = Array()
|
var parsed_s: [EvaluatableStatement] = Array()
|
||||||
|
|
||||||
if node.childCount < currentChildIdxSafe {
|
if node.childCount < currentChildIdxSafe {
|
||||||
@@ -292,11 +292,11 @@ public struct Parser {
|
|||||||
currentChild = node.child(at: currentChildIdx)
|
currentChild = node.child(at: currentChildIdx)
|
||||||
if currentChild!.nodeType == "parserStatements" {
|
if currentChild!.nodeType == "parserStatements" {
|
||||||
switch Statements.Compile(
|
switch Statements.Compile(
|
||||||
node: currentChild!, withTypesInScope: scopes.enter())
|
node: currentChild!, withContext: current_context)
|
||||||
{
|
{
|
||||||
case .Ok(let (state_statements, updated_scopes)):
|
case .Ok(let (state_statements, updated_context)):
|
||||||
parsed_s = state_statements
|
parsed_s = state_statements
|
||||||
current_scopes = updated_scopes
|
current_context = updated_context
|
||||||
case .Error(let error):
|
case .Error(let error):
|
||||||
parse_err = error
|
parse_err = error
|
||||||
}
|
}
|
||||||
@@ -315,31 +315,34 @@ public struct Parser {
|
|||||||
currentChild = node.child(at: currentChildIdx)
|
currentChild = node.child(at: currentChildIdx)
|
||||||
return TransitionStatement.Compile(
|
return TransitionStatement.Compile(
|
||||||
node: currentChild!, forState: state_identifier, withStatements: parsed_s,
|
node: currentChild!, forState: state_identifier, withStatements: parsed_s,
|
||||||
withTypesInScope: current_scopes)
|
withContext: current_context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static func Compile(
|
static func Compile(
|
||||||
withName name: Common.Identifier, node: Node,
|
withName name: Common.Identifier, node: Node,
|
||||||
withTypesInScope scopes: LexicalScopes
|
withContext context: CompilerContext
|
||||||
) -> Result<(P4Lang.Parser, LexicalScopes)> {
|
) -> Result<(P4Lang.Parser, CompilerContext)> {
|
||||||
|
|
||||||
var parser = P4Lang.Parser(withName: name)
|
var parser = P4Lang.Parser(withName: name)
|
||||||
|
|
||||||
// Build a state from each one listed.
|
// Build a state from each one listed.
|
||||||
var error: Error? = .none
|
var error: Error? = .none
|
||||||
|
|
||||||
|
var current_context = context
|
||||||
// TODO: Assert that there is only one.
|
// TODO: Assert that there is only one.
|
||||||
node.enumerateNamedChildren { parser_state in
|
node.enumerateNamedChildren { parser_state in
|
||||||
if parser_state.nodeType != "parserState" {
|
if parser_state.nodeType != "parserState" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse a state in a nested scope.
|
||||||
switch Parser.State.Compile(
|
switch Parser.State.Compile(
|
||||||
node: parser_state, withTypesInScope: scopes.enter())
|
node: parser_state, withContext: CompilerContext(withNames: current_context.names.enter()))
|
||||||
{
|
{
|
||||||
case Result.Ok(let (state, _)):
|
case Result.Ok(let (state, updated_context)):
|
||||||
parser.states = parser.states.append(state: state)
|
parser.states = parser.states.append(state: state)
|
||||||
|
current_context = updated_context
|
||||||
case Result.Error(let e): error = e
|
case Result.Error(let e): error = e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -348,6 +351,6 @@ public struct Parser {
|
|||||||
return .Error(error)
|
return .Error(error)
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result.Ok((parser, scopes))
|
return Result.Ok((parser, current_context))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,8 +40,8 @@ public struct Program {
|
|||||||
|
|
||||||
var program = P4Lang.Program()
|
var program = P4Lang.Program()
|
||||||
|
|
||||||
// Set up a lexical scope for parsing.
|
// Set up a context for parsing.
|
||||||
var program_scope = LexicalScopes().enter()
|
var compilation_context = CompilerContext(withNames: LexicalScopes().enter())
|
||||||
|
|
||||||
var errors: [Error] = Array()
|
var errors: [Error] = Array()
|
||||||
|
|
||||||
@@ -107,7 +107,7 @@ public struct Program {
|
|||||||
}
|
}
|
||||||
currentChild = type_node?.child(at: currentChildIdx)
|
currentChild = type_node?.child(at: currentChildIdx)
|
||||||
|
|
||||||
switch Identifier.Compile(node: currentChild!, withTypesInScopes: program_scope) {
|
switch Identifier.Compile(node: currentChild!, withContext: compilation_context) {
|
||||||
case .Ok(let id): parser_name = id
|
case .Ok(let id): parser_name = id
|
||||||
case .Error(let e):
|
case .Error(let e):
|
||||||
errors.append(e)
|
errors.append(e)
|
||||||
@@ -164,10 +164,11 @@ public struct Program {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch Parser.Compile(
|
switch Parser.Compile(
|
||||||
withName: parser_name!, node: currentChild!, withTypesInScope: program_scope)
|
withName: parser_name!, node: currentChild!, withContext: compilation_context)
|
||||||
{
|
{
|
||||||
case Result.Ok((let parser, let new_program_scope)):
|
case Result.Ok((let parser, let updated_context)):
|
||||||
program_scope = new_program_scope.declare(identifier: parser.name, withValue: parser)
|
// Create a new context with the name of the parser that was just compiled in scope.
|
||||||
|
compilation_context = CompilerContext(withNames: updated_context.names.declare(identifier: parser.name, withValue: parser))
|
||||||
case Result.Error(let error): errors.append(error)
|
case Result.Error(let error): errors.append(error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,7 +184,7 @@ public struct Program {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Any of the types that are in the top-level scope should go into the program!
|
// Any of the types that are in the top-level scope should go into the program!
|
||||||
program.types = Array(program_scope)
|
program.types = Array(compilation_context.names)
|
||||||
return Result.Ok(program)
|
return Result.Ok(program)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ import TreeSitterP4
|
|||||||
|
|
||||||
public protocol CompilableStatement {
|
public protocol CompilableStatement {
|
||||||
static func Compile(
|
static func Compile(
|
||||||
node: Node, withTypesInScope scopes: LexicalScopes
|
node: Node, withContext context: CompilerContext
|
||||||
) -> Result<(EvaluatableStatement, LexicalScopes)>
|
) -> Result<(EvaluatableStatement, CompilerContext)>
|
||||||
}
|
}
|
||||||
|
|
||||||
public protocol CompilableValue {
|
public protocol CompilableValue {
|
||||||
|
|||||||
@@ -24,9 +24,9 @@ import TreeSitterP4
|
|||||||
|
|
||||||
extension BlockStatement: CompilableStatement {
|
extension BlockStatement: CompilableStatement {
|
||||||
public static func Compile(
|
public static func Compile(
|
||||||
node: Node, withTypesInScope scopes: LexicalScopes
|
node: Node, withContext context: CompilerContext
|
||||||
) -> Result<(EvaluatableStatement, LexicalScopes)> {
|
) -> Result<(EvaluatableStatement, CompilerContext)> {
|
||||||
#RequireNodeType<Node, (EvaluatableStatement, LexicalScopes)>(
|
#RequireNodeType<Node, (EvaluatableStatement, CompilerContext)>(
|
||||||
node: node, type: "blockStatement", nice_type_name: "block statement")
|
node: node, type: "blockStatement", nice_type_name: "block statement")
|
||||||
|
|
||||||
var currentChildIdx = 0
|
var currentChildIdx = 0
|
||||||
@@ -47,7 +47,7 @@ extension BlockStatement: CompilableStatement {
|
|||||||
|
|
||||||
var statements: [EvaluatableStatement] = Array()
|
var statements: [EvaluatableStatement] = Array()
|
||||||
var parse_err: Error? = .none
|
var parse_err: Error? = .none
|
||||||
var new_scopes: LexicalScopes = LexicalScopes()
|
var current_context = context
|
||||||
|
|
||||||
if node.childCount < currentChildIdxSafe {
|
if node.childCount < currentChildIdxSafe {
|
||||||
return Result.Error(
|
return Result.Error(
|
||||||
@@ -56,10 +56,10 @@ extension BlockStatement: CompilableStatement {
|
|||||||
currentChild = node.child(at: currentChildIdx)
|
currentChild = node.child(at: currentChildIdx)
|
||||||
if currentChild!.nodeType == "statements" {
|
if currentChild!.nodeType == "statements" {
|
||||||
switch Parser.Statements.Compile(
|
switch Parser.Statements.Compile(
|
||||||
node: currentChild!, withTypesInScope: scopes.enter())
|
node: currentChild!, withContext: current_context)
|
||||||
{
|
{
|
||||||
case .Ok(let (parsed_statements, parsed_scopes)):
|
case .Ok(let (parsed_statements, updated_context)):
|
||||||
new_scopes = parsed_scopes
|
current_context = updated_context
|
||||||
statements = parsed_statements
|
statements = parsed_statements
|
||||||
case .Error(let error):
|
case .Error(let error):
|
||||||
parse_err = error
|
parse_err = error
|
||||||
@@ -83,16 +83,16 @@ extension BlockStatement: CompilableStatement {
|
|||||||
ErrorOnNode(node: currentChild!, withError: "Missing } on block statement"))
|
ErrorOnNode(node: currentChild!, withError: "Missing } on block statement"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return .Ok((BlockStatement(statements), new_scopes))
|
return .Ok((BlockStatement(statements), current_context))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ConditionalStatement: CompilableStatement {
|
extension ConditionalStatement: CompilableStatement {
|
||||||
public static func Compile(
|
public static func Compile(
|
||||||
node: Node, withTypesInScope scopes: LexicalScopes
|
node: Node, withContext context: CompilerContext
|
||||||
) -> Result<(EvaluatableStatement, LexicalScopes)> {
|
) -> Result<(EvaluatableStatement, CompilerContext)> {
|
||||||
|
|
||||||
#RequireNodeType<Node, (EvaluatableStatement, LexicalScopes)>(
|
#RequireNodeType<Node, (EvaluatableStatement, CompilerContext)>(
|
||||||
node: node, type: "conditionalStatement", nice_type_name: "conditional statement")
|
node: node, type: "conditionalStatement", nice_type_name: "conditional statement")
|
||||||
|
|
||||||
let maybe_condition_expression = node.child(at: 2)
|
let maybe_condition_expression = node.child(at: 2)
|
||||||
@@ -114,7 +114,7 @@ extension ConditionalStatement: CompilableStatement {
|
|||||||
|
|
||||||
guard
|
guard
|
||||||
case .Ok(let condition) = Expression.Compile(
|
case .Ok(let condition) = Expression.Compile(
|
||||||
node: condition_expression, withTypesInScope: scopes)
|
node: condition_expression, withContext: context)
|
||||||
else {
|
else {
|
||||||
return Result.Error(
|
return Result.Error(
|
||||||
Error(withMessage: "Could not parse a conditional expression in a conditional statement"))
|
Error(withMessage: "Could not parse a conditional expression in a conditional statement"))
|
||||||
@@ -122,7 +122,7 @@ extension ConditionalStatement: CompilableStatement {
|
|||||||
|
|
||||||
guard
|
guard
|
||||||
case .Ok((let thenns, _)) = Parser.Statement.Compile(
|
case .Ok((let thenns, _)) = Parser.Statement.Compile(
|
||||||
node: thens, withTypesInScope: scopes)
|
node: thens, withContext: context)
|
||||||
else {
|
else {
|
||||||
return Result.Error(
|
return Result.Error(
|
||||||
Error(
|
Error(
|
||||||
@@ -130,11 +130,11 @@ extension ConditionalStatement: CompilableStatement {
|
|||||||
"Could not parse the then block in a conditional statement"))
|
"Could not parse the then block in a conditional statement"))
|
||||||
}
|
}
|
||||||
|
|
||||||
let optional_elss: Result<(any EvaluatableStatement, LexicalScopes)>? =
|
let optional_elss: Result<(any EvaluatableStatement, CompilerContext)>? =
|
||||||
if let elss = node.child(at: 6) {
|
if let elss = node.child(at: 6) {
|
||||||
.some(
|
.some(
|
||||||
Parser.Statement.Compile(
|
Parser.Statement.Compile(
|
||||||
node: elss, withTypesInScope: scopes))
|
node: elss, withContext: context))
|
||||||
} else {
|
} else {
|
||||||
.none
|
.none
|
||||||
}
|
}
|
||||||
@@ -149,18 +149,18 @@ extension ConditionalStatement: CompilableStatement {
|
|||||||
"Could not parse the else block in a conditional statement"))
|
"Could not parse the else block in a conditional statement"))
|
||||||
}
|
}
|
||||||
return .Ok(
|
return .Ok(
|
||||||
(ConditionalStatement(condition: condition, withThen: thenns, andElse: elss), scopes))
|
(ConditionalStatement(condition: condition, withThen: thenns, andElse: elss), context))
|
||||||
}
|
}
|
||||||
return .Ok((ConditionalStatement(condition: condition, withThen: thenns), scopes))
|
return .Ok((ConditionalStatement(condition: condition, withThen: thenns), context))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension VariableDeclarationStatement: CompilableStatement {
|
extension VariableDeclarationStatement: CompilableStatement {
|
||||||
public static func Compile(
|
public static func Compile(
|
||||||
node: Node, withTypesInScope scopes: LexicalScopes
|
node: Node, withContext context: CompilerContext
|
||||||
) -> Result<(EvaluatableStatement, LexicalScopes)> {
|
) -> Result<(EvaluatableStatement, CompilerContext)> {
|
||||||
|
|
||||||
#RequireNodeType<Node, (EvaluatableStatement, LexicalScopes)>(
|
#RequireNodeType<Node, (EvaluatableStatement, CompilerContext)>(
|
||||||
node: node, type: "variableDeclaration", nice_type_name: "variable declaration statement")
|
node: node, type: "variableDeclaration", nice_type_name: "variable declaration statement")
|
||||||
|
|
||||||
let maybe_typeref = node.child(at: 0)
|
let maybe_typeref = node.child(at: 0)
|
||||||
@@ -193,7 +193,7 @@ extension VariableDeclarationStatement: CompilableStatement {
|
|||||||
|
|
||||||
guard
|
guard
|
||||||
case .Ok(let parsed_variablename) = Identifier.Compile(
|
case .Ok(let parsed_variablename) = Identifier.Compile(
|
||||||
node: variablename, withTypesInScopes: scopes.enter())
|
node: variablename, withContext: context)
|
||||||
else {
|
else {
|
||||||
return Result.Error(
|
return Result.Error(
|
||||||
Error(withMessage: "Could not parse variable name"))
|
Error(withMessage: "Could not parse variable name"))
|
||||||
@@ -201,7 +201,7 @@ extension VariableDeclarationStatement: CompilableStatement {
|
|||||||
|
|
||||||
guard
|
guard
|
||||||
case .Ok(let parsed_rvalue) = Expression.Compile(
|
case .Ok(let parsed_rvalue) = Expression.Compile(
|
||||||
node: rvalue, withTypesInScope: scopes.enter())
|
node: rvalue, withContext: context)
|
||||||
else {
|
else {
|
||||||
return Result.Error(
|
return Result.Error(
|
||||||
Error(
|
Error(
|
||||||
@@ -219,8 +219,9 @@ extension VariableDeclarationStatement: CompilableStatement {
|
|||||||
(
|
(
|
||||||
VariableDeclarationStatement(
|
VariableDeclarationStatement(
|
||||||
identifier: parsed_variablename, withInitializer: parsed_rvalue),
|
identifier: parsed_variablename, withInitializer: parsed_rvalue),
|
||||||
scopes.declare(
|
// Context with updated names to include the newly declared name.
|
||||||
identifier: parsed_variablename, withValue: declaration_p4_type)
|
CompilerContext(withNames: context.names.declare(
|
||||||
|
identifier: parsed_variablename, withValue: declaration_p4_type))
|
||||||
))
|
))
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -236,13 +237,13 @@ extension VariableDeclarationStatement: CompilableStatement {
|
|||||||
|
|
||||||
extension ExpressionStatement: CompilableStatement {
|
extension ExpressionStatement: CompilableStatement {
|
||||||
public static func Compile(
|
public static func Compile(
|
||||||
node: Node, withTypesInScope scopes: LexicalScopes
|
node: Node, withContext context: CompilerContext
|
||||||
) -> Result<(EvaluatableStatement, LexicalScopes)> {
|
) -> Result<(EvaluatableStatement, CompilerContext)> {
|
||||||
#RequireNodeType<Node, (EvaluatableStatement, LexicalScopes)>(
|
#RequireNodeType<Node, (EvaluatableStatement, CompilerContext)>(
|
||||||
node: node, type: "expressionStatement", nice_type_name: "expression statement")
|
node: node, type: "expressionStatement", nice_type_name: "expression statement")
|
||||||
|
|
||||||
let _ = node.child(at: 0)
|
let _ = node.child(at: 0)
|
||||||
|
|
||||||
return Result.Ok((ExpressionStatement(), scopes))
|
return Result.Ok((ExpressionStatement(), context))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,8 +111,8 @@ import P4Lang
|
|||||||
let result = try! #require(p.parse(simple))
|
let result = try! #require(p.parse(simple))
|
||||||
|
|
||||||
#expect(
|
#expect(
|
||||||
#RequireErrorResult<(EvaluatableStatement, LexicalScopes)>(
|
#RequireErrorResult<(EvaluatableStatement, CompilerContext)>(
|
||||||
Error(withMessage: "{2, 154}: Did not find assignment statement"),
|
Error(withMessage: "{2, 154}: Did not find assignment statement"),
|
||||||
ParserAssignmentStatement.Compile(
|
ParserAssignmentStatement.Compile(
|
||||||
node: result.rootNode!, withTypesInScope: LexicalScopes())))
|
node: result.rootNode!, withContext: CompilerContext(withNames: LexicalScopes()))))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user