diff --git a/Sources/Common/Execution.swift b/Sources/Common/Execution.swift index 80a49c7..a38b5f0 100644 --- a/Sources/Common/Execution.swift +++ b/Sources/Common/Execution.swift @@ -152,7 +152,7 @@ public typealias ExpressionInterloper = (EvaluatableExpression, Result, open class ProgramExecution: CustomStringConvertible { public var scopes: VarValueScopes = VarValueScopes() var globalValues: VarValueScopes? - var error: Error? + var error: (any Errorable)? var debug: DebugLevel = DebugLevel.Error public let evaluator: ProgramExecutionEvaluator @@ -182,11 +182,11 @@ open class ProgramExecution: CustomStringConvertible { return self.error != nil } - public func getError() -> Error? { + public func getError() -> (any Errorable)? { return self.error } - public func setError(error: Error) -> ProgramExecution { + public func setError(error: any Errorable) -> ProgramExecution { let npe = ProgramExecution(copy: self) npe.error = error return npe diff --git a/Sources/Common/Protocols.swift b/Sources/Common/Protocols.swift index d28b43c..e3fdbef 100644 --- a/Sources/Common/Protocols.swift +++ b/Sources/Common/Protocols.swift @@ -70,6 +70,19 @@ public protocol ProgramExecutionEvaluator { ) -> (Result, ProgramExecution) } +public protocol Errorable: CustomStringConvertible { + func format() -> String + func msg() -> String + func append(error: any Errorable) -> any Errorable + func eq(_ rhs: any Errorable) -> Bool +} + +extension Errorable { + public func eq(_ rhs: any Errorable) -> Bool { + return self.msg() == rhs.msg() + } +} + extension ProgramExecutionEvaluator { public func ExecuteStatements( _ statements: [EvaluatableStatement], inExecution execution: ProgramExecution diff --git a/Sources/Common/Result.swift b/Sources/Common/Result.swift new file mode 100644 index 0000000..f1ebbef --- /dev/null +++ b/Sources/Common/Result.swift @@ -0,0 +1,178 @@ +// 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 . + +public struct Error: Errorable, Equatable, CustomStringConvertible { + public func format() -> String { + return self.description + } + + public func msg() -> String { + return self._msg + } + + public func append(error: any Errorable) -> any Errorable { + return Errors(self, error) + } + + let _msg: String + + public init(withMessage msg: String) { + self._msg = msg + } + + public var description: String { + return self._msg + } +} + +public struct ErrorWithLocation: Errorable, Equatable, CustomStringConvertible { + + public func format() -> String { + return self.description + } + + public func msg() -> String { + return self.description + } + + public func append(error: any Errorable) -> any Errorable { + return Errors(self, error) + } + + let _msg: String + + let location: SourceLocation + + public init(sourceLocation location: SourceLocation, withError msg: String) { + self._msg = msg + self.location = location + } + + public var description: String { + return "\(self.location): \(self._msg)" + } +} + +public struct Errors: Errorable, CustomStringConvertible { + public func format() -> String { + return self.description + } + + public func msg() -> String { + return self.description + } + + public func append(error: any Errorable) -> any Errorable { + return Errors(self.errors + [error]) + } + + public var description: String { + return self.errors.map() { error in + return error.msg() + }.joined(separator: ";") + } + + public let errors: [any Errorable] + + init(_ errors: [any Errorable]) { + self.errors = errors + } + + public init(_ e1: any Errorable, _ e2: any Errorable) { + self.errors = [e1, e2] + } +} + +public struct ErrorWithLabel: Errorable { + let label: String + let error: any Errorable + + public init(_ label: String, _ error: any Errorable) { + self.label = label + self.error = error + } + + public func format() -> String { + return self.description + } + + public func msg() -> String { + return self.description + } + + public func append(error: any Errorable) -> any Errorable { + return Errors(self, error) + } + + public var description: String { + return "\(self.label): \(self.error.msg())" + } +} + +public enum Result: Equatable { + case Ok(OKT) + case Error(any Errorable) + + public static func == (lhs: Result, rhs: Result) -> Bool { + switch (lhs, rhs) { + case (Ok, Ok): + return true + case (Error(let le), Error(let re)): + return le.eq(re) + default: + return false + } + } + + public func ok() -> Bool { + switch self { + case .Ok(_): true + case .Error(_): false + } + } + public func error() -> (any Errorable)? { + if case Result.Error(let e) = self { + return e + } + return nil + } + + public func map(block: (OKT) -> Result) -> Result { + switch self { + case .Ok(let ok): return block(ok) + case .Error(let e): return .Error(e) + } + } + + public func map_err(block: (any Errorable) -> Result) -> Result { + switch self { + case .Ok(let ok): return .Ok(ok) + case .Error(let e): return block(e) + } + } +} + +extension Result: CustomStringConvertible where OKT: CustomStringConvertible { + public var description: String { + switch self { + case Result.Error(let e): + return e.format() + case Result.Ok(let o): + return "Ok: \(o)" + } + } +} diff --git a/Sources/Common/Support.swift b/Sources/Common/Support.swift index 10f3e2b..0232dea 100644 --- a/Sources/Common/Support.swift +++ b/Sources/Common/Support.swift @@ -15,6 +15,20 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +public struct SourceLocation: Equatable, CustomStringConvertible { + public let start: Int + public let extent: Int + + public init(_ start: Int, _ extent: Int) { + self.start = start + self.extent = extent + } + + public var description: String { + return "{\(self.start), \(self.extent)}" + } +} + public enum DebugLevel { case Trace case Verbose @@ -61,18 +75,6 @@ public enum DebugLevel { } } -public struct Error: Equatable, CustomStringConvertible { - public private(set) var msg: String - - public init(withMessage msg: String) { - self.msg = msg - } - - public var description: String { - return self.msg - } -} - public struct Nothing: CustomStringConvertible { public var description: String { return "Nothing" @@ -81,64 +83,17 @@ public struct Nothing: CustomStringConvertible { public init() {} } -public enum Result: Equatable { - case Ok(OKT) - case Error(Error) - - public static func == (lhs: Result, rhs: Result) -> Bool { - switch (lhs, rhs) { - case (Ok, Ok): - return true - case (Error(let le), Error(let re)): - return le.msg == re.msg - default: - return false - } - } - - public func ok() -> Bool { - switch self { - case .Ok(_): true - case .Error(_): false - } - } - public func error() -> Error? { - if case Result.Error(let e) = self { - return e - } - return nil - } - - public func map(block: (OKT) -> Result) -> Result { - switch self { - case .Ok(let ok): return block(ok) - case .Error(let e): return .Error(e) - } - } -} - -extension Result: CustomStringConvertible where OKT: CustomStringConvertible { - public var description: String { - switch self { - case Result.Error(let e): - return e.msg - case Result.Ok(let o): - return "Ok: \(o)" - } - } -} - public func Map(input: T, block: (T) -> U) -> U { return block(input) } @freestanding(expression) public macro RequireOkResult(_: Result) -> Bool = #externalMacro(module: "Macros", type: "RequireResult") -@freestanding(expression) public macro RequireErrorResult(_: Error, _: Result) -> Bool = +@freestanding(expression) public macro RequireErrorResult(_: any Errorable, _: Result) -> Bool = #externalMacro(module: "Macros", type: "RequireErrorResult") @freestanding(expression) public macro UseOkResult(_: Result) -> T = #externalMacro(module: "Macros", type: "UseOkResult") -@freestanding(expression) public macro UseErrorResult(_: Result) -> Error = +@freestanding(expression) public macro UseErrorResult(_: Result) -> any Errorable = #externalMacro(module: "Macros", type: "UseErrorResult") @freestanding(codeItem) public macro RequireNodeType( node: N, type: String, nice_type_name: String diff --git a/Sources/Macros/Macros.swift b/Sources/Macros/Macros.swift index 1b3709a..fcfa769 100644 --- a/Sources/Macros/Macros.swift +++ b/Sources/Macros/Macros.swift @@ -125,10 +125,14 @@ public struct RequireErrorResult: ExpressionMacro { { let __expected_error = \(expected_error) let __actual_error = \(error_producer) - if case Result.Error(__expected_error) = __actual_error { + if case Result.Error(let __found_error) = __actual_error { + if !__expected_error.eq(__found_error) { + print("Expected Error: \\(__expected_error) but got Error: \\(__found_error)") + return false + } return true } else { - print("Expected Error: \\(__expected_error) but got Error: \\(__actual_error)") + print("Expected error, but got Ok") return false } }() @@ -156,7 +160,7 @@ public struct RequireNodeType: CodeItemMacro { """ if \(node_to_check).nodeType != \(expected_type) { return Result.Error( - ErrorOnNode(node: \(node_to_check), withError: "\(raw: error_message)")) + ErrorWithLocation(sourceLocation: \(node_to_check).toSourceLocation(), withError: "\(raw: error_message)")) } """) ] @@ -198,7 +202,7 @@ public struct RequireNodesType: CodeItemMacro { """ if \(raw: ifs) { return Result.Error( - ErrorOnNode(node: \(node_to_check), withError: "\(raw: error_message)")) + ErrorWithLocation(sourceLocation: \(node_to_check).toSourceLocation(), withError: "\(raw: error_message)")) } """) ] diff --git a/Sources/P4Compiler/Common.swift b/Sources/P4Compiler/Common.swift index b6cc1c5..999bf90 100644 --- a/Sources/P4Compiler/Common.swift +++ b/Sources/P4Compiler/Common.swift @@ -42,8 +42,8 @@ func parameter_list_compiler( #MustOr( result: current_node, thing: walker.getNext(), or: Result<(ParameterList, CompilerContext)>.Error( - ErrorOnNode( - node: node, withError: "Missing parameter list component"))) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Missing parameter list component"))) if current_node?.nodeType == "parameter_list" { switch parameter_list_compiler(node: current_node!, withContext: context) { @@ -57,8 +57,8 @@ func parameter_list_compiler( #MustOr( result: current_node, thing: walker.getNext(), or: Result<(ParameterList, CompilerContext)>.Error( - ErrorOnNode( - node: node, withError: "Missing parameter list component"))) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Missing parameter list component"))) // If this is a ')', we are done. if current_node?.text == ")" { @@ -73,8 +73,8 @@ func parameter_list_compiler( #MustOr( result: current_node, thing: walker.getNext(), or: Result<(ParameterList, CompilerContext)>.Error( - ErrorOnNode( - node: node, withError: "Missing parameter list component"))) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Missing parameter list component"))) // Otherwise, there should be one parameter left! switch Parameter.Compile(node: current_node!, withContext: context) { @@ -101,15 +101,15 @@ extension ParameterList: Compilable { #MustOr( result: current_node, thing: walker.getNext(), or: Result<(ParameterList, CompilerContext)>.Error( - ErrorOnNode( - node: node, withError: "Missing '(' in parameter list component"))) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Missing '(' in parameter list component"))) walker.next() #MustOr( result: current_node, thing: walker.getNext(), or: Result<(ParameterList, CompilerContext)>.Error( - ErrorOnNode( - node: node, withError: "Missing parameter list component"))) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Missing parameter list component"))) return parameter_list_compiler(node: current_node!, withContext: context) } @@ -131,8 +131,8 @@ extension Direction: Compilable { guard let parsed_direction = directions[direction_node.text!] else { return .Error( - ErrorOnNode( - node: direction_node, withError: "\(direction_node.text!) is not a valid direction")) + ErrorWithLocation( + sourceLocation: direction_node.toSourceLocation(), withError: "\(direction_node.text!) is not a valid direction")) } return .Ok((parsed_direction, context)) @@ -154,14 +154,14 @@ extension Parameter: Compilable { #MustOr( result: current_node, thing: walker.getNext(), or: Result<(Parameter, CompilerContext)>.Error( - ErrorOnNode( - node: node, withError: "Missing parameter declaration component"))) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Missing parameter declaration component"))) // Annotation? if current_node!.nodeType == "annotations" { return .Error( - ErrorOnNode( - node: current_node!, + ErrorWithLocation( + sourceLocation: current_node!.toSourceLocation(), withError: "Annotations in parameter declarations are not yet handled")) // Will increment indexes here. } @@ -169,8 +169,8 @@ extension Parameter: Compilable { #MustOr( result: current_node, thing: walker.getNext(), or: Result<(Parameter, CompilerContext)>.Error( - ErrorOnNode( - node: node, withError: "Missing parameter declaration component"))) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Missing parameter declaration component"))) var direction: Direction? = .none // Direction? @@ -188,13 +188,13 @@ extension Parameter: Compilable { #MustOr( result: current_node, thing: walker.getNext(), or: Result<(Parameter, CompilerContext)>.Error( - ErrorOnNode( - node: node, withError: "Missing parameter declaration component"))) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Missing parameter declaration component"))) if current_node!.nodeType != "typeRef" { return Result.Error( - ErrorOnNode( - node: node, withError: "Did not find type name for parameter declaration")) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Did not find type name for parameter declaration")) } guard @@ -208,13 +208,13 @@ extension Parameter: Compilable { #MustOr( result: current_node, thing: walker.getNext(), or: Result<(Parameter, CompilerContext)>.Error( - ErrorOnNode( - node: node, withError: "Missing parameter declaration component"))) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Missing parameter declaration component"))) if current_node!.nodeType != "identifier" { return Result.Error( - ErrorOnNode( - node: node, withError: "Did not find identifier for parameter statement")) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Did not find identifier for parameter statement")) } guard @@ -256,8 +256,8 @@ func argument_list_compiler( #MustOr( result: current_node, thing: walker.getNext(), or: Result<(ArgumentList, CompilerContext)>.Error( - ErrorOnNode( - node: node, withError: "Missing argument list component"))) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Missing argument list component"))) if current_node?.nodeType == "argument_list" { switch argument_list_compiler(node: current_node!, withContext: context) { @@ -273,8 +273,8 @@ func argument_list_compiler( #MustOr( result: current_node, thing: walker.getNext(), or: Result<(ArgumentList, CompilerContext)>.Error( - ErrorOnNode( - node: node, withError: "Missing argument list component"))) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Missing argument list component"))) // If this is a ')', we are done. if current_node?.text == ")" { @@ -289,8 +289,8 @@ func argument_list_compiler( #MustOr( result: current_node, thing: walker.getNext(), or: Result<(ArgumentList, CompilerContext)>.Error( - ErrorOnNode( - node: node, withError: "Missing argument list component"))) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Missing argument list component"))) // Otherwise, there should be one argument left! switch Argument.Compile(node: current_node!, withContext: context) { @@ -317,16 +317,16 @@ extension ArgumentList: Compilable { #MustOr( result: current_node, thing: walker.getNext(), or: Result<(ArgumentList, CompilerContext)>.Error( - ErrorOnNode( - node: node, withError: "Missing '(' in argument list component"))) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Missing '(' in argument list component"))) walker.next() #MustOr( result: current_node, thing: walker.getNext(), or: Result<(ArgumentList, CompilerContext)>.Error( - ErrorOnNode( - node: node, withError: "Missing argument list component"))) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Missing argument list component"))) return argument_list_compiler(node: current_node!, withContext: context) } @@ -372,3 +372,9 @@ func ContainsInvalidStatements(block: BlockStatement, invalids: [EvaluatableStat return false } } + +extension Node { + public func toSourceLocation() -> SourceLocation { + return SourceLocation(self.range.location, self.range.length) + } +} \ No newline at end of file diff --git a/Sources/P4Compiler/Compiler.swift b/Sources/P4Compiler/Compiler.swift index 1321cf5..4378cc2 100644 --- a/Sources/P4Compiler/Compiler.swift +++ b/Sources/P4Compiler/Compiler.swift @@ -36,10 +36,6 @@ public func ConfigureP4Parser() -> Result { return .Ok(p) } -public func ErrorOnNode(node: Node, withError error: String) -> Error { - return Error(withMessage: "\(node.range): \(error)") -} - /// Context for compilation /// /// It contains (at least) three important pieces of information: diff --git a/Sources/P4Compiler/Declarations.swift b/Sources/P4Compiler/Declarations.swift index cb995c1..bccb794 100644 --- a/Sources/P4Compiler/Declarations.swift +++ b/Sources/P4Compiler/Declarations.swift @@ -60,8 +60,8 @@ extension FunctionDeclaration: CompilableDeclaration { #MustOr( result: current_node, thing: walker.getNext(), or: Result<(Declaration, CompilerContext)?>.Error( - ErrorOnNode( - node: function_declaration_node, withError: "Missing function declaration component"))) + ErrorWithLocation( + sourceLocation: function_declaration_node.toSourceLocation(), withError: "Missing function declaration component"))) let maybe_function_type = Types.CompileType(type: current_node!, withContext: context) guard case .Ok(let function_type) = maybe_function_type else { @@ -72,8 +72,8 @@ extension FunctionDeclaration: CompilableDeclaration { #MustOr( result: current_node, thing: walker.getNext(), or: Result<(Declaration, CompilerContext)?>.Error( - ErrorOnNode( - node: function_declaration_node, withError: "Missing function declaration component"))) + ErrorWithLocation( + sourceLocation: function_declaration_node.toSourceLocation(), withError: "Missing function declaration component"))) let maybe_function_name = Identifier.Compile(node: current_node!, withContext: context) guard case .Ok(let function_name) = maybe_function_name else { @@ -84,8 +84,8 @@ extension FunctionDeclaration: CompilableDeclaration { #MustOr( result: current_node, thing: walker.getNext(), or: Result<(Declaration, CompilerContext)?>.Error( - ErrorOnNode( - node: function_declaration_node, withError: "Missing function declaration component"))) + 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 @@ -120,8 +120,8 @@ extension FunctionDeclaration: CompilableDeclaration { if !context.extern_context { return Result.Error( - ErrorOnNode( - node: function_declaration_node, withError: "Missing function declaration component")) + ErrorWithLocation( + sourceLocation: function_declaration_node.toSourceLocation(), withError: "Missing function declaration component")) } } @@ -165,8 +165,8 @@ extension P4Struct: CompilableDeclaration { #MustOr( result: currentNode, thing: walker.getNext(), or: Result<(Declaration, CompilerContext)?>.Error( - ErrorOnNode( - node: struct_declaration_node, withError: "Missing function declaration component"))) + ErrorWithLocation( + sourceLocation: struct_declaration_node.toSourceLocation(), withError: "Missing function declaration component"))) // The name of the struct type. let maybe_struct_identifier = Identifier.Compile( @@ -181,8 +181,8 @@ extension P4Struct: CompilableDeclaration { #MustOr( result: currentNode, thing: walker.getNext(), or: Result<(Declaration, CompilerContext)?>.Error( - ErrorOnNode( - node: struct_declaration_node, withError: "Missing function declaration component"))) + ErrorWithLocation( + sourceLocation: struct_declaration_node.toSourceLocation(), withError: "Missing function declaration component"))) // If there are no fields, it will be a "}" if currentNode!.nodeType == "}" { @@ -201,7 +201,7 @@ extension P4Struct: CompilableDeclaration { )) } - var parse_errs: [Error] = Array() + var parse_errs: (any Errorable)? = .none var current_context = context var parsed_fields: [P4StructFieldIdentifier] = Array() @@ -217,18 +217,19 @@ extension P4Struct: CompilableDeclaration { id: variable_declaration.identifier, withType: variable_declaration.initializer.type() )) current_context = updated_context - case .Error(let e): parse_errs.append(e) + case .Error(let e): + parse_errs = + if let e = parse_errs { + parse_errs?.append(error: e) + } else { + e + } } } } - if !parse_errs.isEmpty { - return .Error( - Error( - withMessage: "Error(s) parsing select cases: " - + (parse_errs.map { error in - return "\(error.msg)" - }.joined(separator: ";")))) + if let parse_errs = parse_errs { + return .Error(ErrorWithLabel("Error(s) parsing select cases", parse_errs)) } let declared_struct = Declaration( @@ -263,12 +264,12 @@ extension P4Lang.Parser: CompilableDeclaration { #MustOr( result: current_node, thing: walker.getNext(), or: Result<(Declaration, CompilerContext)?>.Error( - ErrorOnNode( - node: parser_node, withError: "Missing elements of parser declaration"))) + ErrorWithLocation( + sourceLocation: parser_node.toSourceLocation(), withError: "Missing elements of parser declaration"))) if current_node!.nodeType != "parserType" { return .Error( - ErrorOnNode(node: current_node!, withError: "Missing type for parser declaration")) + ErrorWithLocation(sourceLocation: current_node!.toSourceLocation(), withError: "Missing type for parser declaration")) } let type_node = current_node @@ -284,13 +285,13 @@ extension P4Lang.Parser: CompilableDeclaration { #MustOr( result: type_node_child, thing: type_node_walker.getNext(), or: Result<(Declaration, CompilerContext)?>.Error( - ErrorOnNode( - node: parser_node, withError: "Missing elements of parser type in parser declaration"))) + ErrorWithLocation( + sourceLocation: parser_node.toSourceLocation(), withError: "Missing elements of parser type in parser declaration"))) if type_node_child!.nodeType == "annotations" { return .Error( - ErrorOnNode( - node: type_node_child!, withError: "Annotations in parser type are not yet handled.")) + ErrorWithLocation( + sourceLocation: type_node_child!.toSourceLocation(), withError: "Annotations in parser type are not yet handled.")) // Will increment indexes here. } @@ -298,8 +299,8 @@ extension P4Lang.Parser: CompilableDeclaration { #MustOr( result: type_node_child, thing: type_node_walker.getNext(), or: Result<(Declaration, CompilerContext)?>.Error( - ErrorOnNode( - node: type_node_child!, withError: "Missing name in parser type declaration"))) + ErrorWithLocation( + sourceLocation: type_node_child!.toSourceLocation(), withError: "Missing name in parser type declaration"))) switch Identifier.Compile(node: type_node_child!, withContext: current_context) { case .Ok(let id): parser_name = id @@ -311,8 +312,8 @@ extension P4Lang.Parser: CompilableDeclaration { #MustOr( result: type_node_child, thing: type_node_walker.getNext(), or: Result<(Declaration, CompilerContext)?>.Error( - ErrorOnNode( - node: type_node_child!, withError: "Missing parser parameters"))) + 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)): @@ -334,27 +335,27 @@ extension P4Lang.Parser: CompilableDeclaration { #MustOr( result: current_node, thing: walker.getNext(), or: Result<(Declaration, CompilerContext)?>.Error( - ErrorOnNode( - node: parser_node, withError: "Missing parser declaration component"))) + ErrorWithLocation( + sourceLocation: parser_node.toSourceLocation(), withError: "Missing parser declaration component"))) walker.next() #MustOr( result: current_node, thing: walker.getNext(), or: Result<(Declaration, CompilerContext)?>.Error( - ErrorOnNode( - node: parser_node, withError: "Missing elements of parser declaration"))) + ErrorWithLocation( + sourceLocation: parser_node.toSourceLocation(), withError: "Missing elements of parser declaration"))) if current_node!.nodeType == "parserLocalElements" { return .Error( - ErrorOnNode(node: current_node!, withError: "Parser Local Elements are not yet handled.")) + ErrorWithLocation(sourceLocation: current_node!.toSourceLocation(), withError: "Parser Local Elements are not yet handled.")) // Will increment indexes here. } #MustOr( result: current_node, thing: walker.getNext(), or: Result<(Declaration, CompilerContext)?>.Error( - ErrorOnNode( - node: parser_node, withError: "Missing body of parser declaration"))) + ErrorWithLocation( + sourceLocation: parser_node.toSourceLocation(), withError: "Missing body of parser declaration"))) if current_node!.nodeType != "parserStates" { return .Error(Error(withMessage: "Missing parser states in parser declaration")) @@ -398,8 +399,8 @@ extension Control: CompilableDeclaration { #MustOr( result: current_node, thing: walker.getNext(), or: Result<(Declaration, CompilerContext)?>.Error( - ErrorOnNode( - node: node, withError: "Missing control declaration component"))) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Missing control declaration component"))) guard case .Ok(let control_name) = Identifier.Compile( @@ -413,8 +414,8 @@ extension Control: CompilableDeclaration { #MustOr( result: current_node, thing: walker.getNext(), or: Result<(Declaration, CompilerContext)?>.Error( - ErrorOnNode( - node: node, withError: "Missing control declaration component"))) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Missing control declaration component"))) let maybe_control_parameters = ParameterList.Compile( node: current_node!, withContext: local_context) @@ -438,8 +439,8 @@ extension Control: CompilableDeclaration { #MustOr( result: current_node, thing: walker.getNext(), or: Result<(Declaration, CompilerContext)?>.Error( - ErrorOnNode( - node: node, withError: "Missing control declaration component"))) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Missing control declaration component"))) var actions: [Action] = Array() var tables: [Table] = Array() @@ -489,7 +490,7 @@ extension Control: CompilableDeclaration { // But, that is handled by the compiler. } else { return .Error( - ErrorOnNode(node: current_node, withError: "Uknown node type in control declaration")) + ErrorWithLocation(sourceLocation: current_node.toSourceLocation(), withError: "Uknown node type in control declaration")) } return .Ok(()) } @@ -505,13 +506,13 @@ extension Control: CompilableDeclaration { /// IDEA: Add a "compilation context" for the error message into the `CompilationContext` // that can be retrieved to make the error messages nicer. return .Error( - ErrorOnNode(node: node, withError: "More than one table in control declaration")) + ErrorWithLocation(sourceLocation: node.toSourceLocation(), withError: "More than one table in control declaration")) } // Check to make sure that there is an apply. guard let apply = apply else { return .Error( - ErrorOnNode(node: node, withError: "Missing apply in control declaration")) + ErrorWithLocation(sourceLocation: node.toSourceLocation(), withError: "Missing apply in control declaration")) } let declared_control = @@ -555,7 +556,7 @@ extension Action: Compilable { #MustOr( result: current_node, thing: walker.getNext(), or: Result<(P4Lang.Action, CompilerContext)>.Error( - ErrorOnNode(node: node, withError: "Missing action declaration component")) + ErrorWithLocation(sourceLocation: node.toSourceLocation(), withError: "Missing action declaration component")) ) guard @@ -570,7 +571,7 @@ extension Action: Compilable { #MustOr( result: current_node, thing: walker.getNext(), or: Result<(P4Lang.Action, CompilerContext)>.Error( - ErrorOnNode(node: node, withError: "Missing action declaration component")) + ErrorWithLocation(sourceLocation: node.toSourceLocation(), withError: "Missing action declaration component")) ) let maybe_action_parameters = ParameterList.Compile( @@ -585,7 +586,7 @@ extension Action: Compilable { #MustOr( result: current_node, thing: walker.getNext(), or: Result<(P4Lang.Action, CompilerContext)>.Error( - ErrorOnNode(node: node, withError: "Missing action declaration component")) + ErrorWithLocation(sourceLocation: node.toSourceLocation(), withError: "Missing action declaration component")) ) // Add the parameters into scope. @@ -631,8 +632,8 @@ extension TableKeyEntry: Compilable { #MustOr( result: current_node, thing: walker.getNext(), or: Result<(P4Lang.TableKeyEntry, CompilerContext)>.Error( - ErrorOnNode( - node: node, withError: "Missing table key entry declaration component"))) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Missing table key entry declaration component"))) let maybe_keyset_expression = KeysetExpression.compile( node: current_node!, withContext: current_context) @@ -646,8 +647,8 @@ extension TableKeyEntry: Compilable { #MustOr( result: current_node, thing: walker.getNext(), or: Result<(P4Lang.TableKeyEntry, CompilerContext)>.Error( - ErrorOnNode( - node: node, withError: "Missing table key entry declaration component"))) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Missing table key entry declaration component"))) let maybe_match_type = TableKeyMatchType.Compile( node: current_node!, withContext: current_context) @@ -670,7 +671,7 @@ extension TableKeyMatchType: Compilable { if node.text! == "exact" { return .Ok((TableKeyMatchType.Exact, context)) } - return .Error(ErrorOnNode(node: node, withError: "\(node.text!) is not a valid match type)")) + return .Error(ErrorWithLocation(sourceLocation: node.toSourceLocation(), withError: "\(node.text!) is not a valid match type)")) } } @@ -695,8 +696,8 @@ extension TableKeys: Compilable { #MustOr( result: current_node, thing: walker.getNext(), or: Result<(P4Lang.TableKeys, CompilerContext)>.Error( - ErrorOnNode( - node: node, withError: "Missing table keys declaration component in control declaration")) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Missing table keys declaration component in control declaration")) ) let (keys, errors) = walker.try_map(n: node.childCount - 1, onlyNamed: true) { current_node in @@ -708,11 +709,11 @@ extension TableKeys: Compilable { if !errors.isEmpty { return .Error( - ErrorOnNode( - node: node, + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Error(s) parsing table key: " + (errors.map { error in - return "\(error.msg)" + return "\(error.msg())" }.joined(separator: ";")))) } @@ -741,8 +742,8 @@ extension TableActionsProperty: Compilable { #MustOr( result: current_node, thing: walker.getNext(), or: Result<(TableActionsProperty, CompilerContext)>.Error( - ErrorOnNode( - node: node, + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Missing table actions declaration component in control declaration")) ) @@ -756,7 +757,7 @@ extension TableActionsProperty: Compilable { return .Ok(TypedIdentifier(id: listed_action, withType: P4QualifiedType(maybe_action))) } return .Error( - ErrorOnNode(node: node, withError: "\(listed_action) does not name an action")) + ErrorWithLocation(sourceLocation: node.toSourceLocation(), withError: "\(listed_action) does not name an action")) case .Error(let e): return .Error(e) } case .Error(let e): return .Error(e) @@ -765,11 +766,11 @@ extension TableActionsProperty: Compilable { if !errors.isEmpty { return .Error( - ErrorOnNode( - node: node, + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Error(s) parsing table actions: " + (errors.map { error in - return "\(error.msg)" + return "\(error.msg())" }.joined(separator: ";")))) } @@ -789,7 +790,7 @@ extension TablePropertyList: Compilable { var keys: [TableKeys] = Array() var actions: [TableActionsProperty] = Array() - var errors: [Error] = Array() + var errors: [any Errorable] = Array() node.enumerateNamedChildren { child in if child.nodeType == "table_keys" { @@ -808,17 +809,17 @@ extension TablePropertyList: Compilable { } } else { errors.append( - ErrorOnNode(node: child, withError: "Uknown node type in control declaration")) + ErrorWithLocation(sourceLocation: child.toSourceLocation(), withError: "Uknown node type in control declaration")) } } if !errors.isEmpty { return .Error( - ErrorOnNode( - node: node, + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Error(s) parsing property list: " + (errors.map { error in - return "\(error.msg)" + return "\(error.msg())" }.joined(separator: ";")))) } @@ -826,14 +827,14 @@ extension TablePropertyList: Compilable { if keys.count > 1 { // Todo: Make this error message better. return .Error( - ErrorOnNode(node: node, withError: "More than one key set in table property list")) + ErrorWithLocation(sourceLocation: node.toSourceLocation(), withError: "More than one key set in table property list")) } // There should be only one table actions! if actions.count > 1 { // Todo: Make this error message better. return .Error( - ErrorOnNode(node: node, withError: "More than one actions in table property list")) + ErrorWithLocation(sourceLocation: node.toSourceLocation(), withError: "More than one actions in table property list")) } if actions.isEmpty { actions.append(TableActionsProperty()) @@ -864,8 +865,8 @@ extension Table: Compilable { #MustOr( result: current_node, thing: walker.getNext(), or: Result<(P4Lang.Table, CompilerContext)>.Error( - ErrorOnNode( - node: node, withError: "Missing table declaration component"))) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Missing table declaration component"))) guard case .Ok(let table_name) = Identifier.Compile( @@ -881,8 +882,8 @@ extension Table: Compilable { #MustOr( result: current_node, thing: walker.getNext(), or: Result<(P4Lang.Table, CompilerContext)>.Error( - ErrorOnNode( - node: node, withError: "Missing table declaration component"))) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Missing table declaration component"))) let maybe_table_property_list = TablePropertyList.Compile( node: current_node!, withContext: current_context) @@ -928,8 +929,8 @@ extension ExternDeclaration: CompilableDeclaration { guard let found_ffi = found_ffi else { return .Error( - ErrorOnNode( - node: declarationed_node, + ErrorWithLocation( + sourceLocation: declarationed_node.toSourceLocation(), withError: "Could not find a foreign function that matches the extern declaration (\(declared))")) } diff --git a/Sources/P4Compiler/Expression.swift b/Sources/P4Compiler/Expression.swift index 625a8f9..01fb3ee 100644 --- a/Sources/P4Compiler/Expression.swift +++ b/Sources/P4Compiler/Expression.swift @@ -46,7 +46,7 @@ extension TypedIdentifier: CompilableExpression { case Result.Ok(let type) = context.instances.lookup( identifier: Common.Identifier(name: node.text!)) else { - return .Error(ErrorOnNode(node: node, withError: "Cannot find \(node.text!) in scope")) + return .Error(ErrorWithLocation(sourceLocation: node.toSourceLocation(), withError: "Cannot find \(node.text!) in scope")) } return .Ok(TypedIdentifier(name: node.text!, withType: type)) @@ -88,7 +88,7 @@ extension P4BooleanValue: CompilableExpression { } return .Error( - ErrorOnNode(node: node, withError: "Failed to parse boolean literal: \(node.text!)")) + ErrorWithLocation(sourceLocation: node.toSourceLocation(), withError: "Failed to parse boolean literal: \(node.text!)")) } } @@ -101,7 +101,7 @@ extension P4IntValue: CompilableExpression { if let parsed_int = Int(node.text!) { return .Ok(P4Value(P4IntValue(withValue: parsed_int))) } else { - return .Error(ErrorOnNode(node: node, withError: "Failed to parse integer: \(node.text!)")) + return .Error(ErrorWithLocation(sourceLocation: node.toSourceLocation(), withError: "Failed to parse integer: \(node.text!)")) } } } @@ -237,46 +237,45 @@ extension SelectExpression: CompilableExpression { guard let selector_node = node.child(at: 2), selector_node.nodeType == "expression" else { - return .Error(ErrorOnNode(node: node, withError: "Could not find selector expression")) + return .Error(ErrorWithLocation(sourceLocation: node.toSourceLocation(), withError: "Could not find selector expression")) } guard let select_body_node = node.child(at: 5), select_body_node.nodeType == "selectBody" else { - return .Error(ErrorOnNode(node: node, withError: "Could not find select expression body")) + return .Error(ErrorWithLocation(sourceLocation: node.toSourceLocation(), withError: "Could not find select expression body")) } let maybe_selector = Expression.Compile(node: selector_node, withContext: context) guard case .Ok(let selector) = maybe_selector else { return .Error( - ErrorOnNode( - node: selector_node, + ErrorWithLocation( + sourceLocation: selector_node.toSourceLocation(), withError: "Could not parse transition select expression selector expression: \(maybe_selector.error()!)" )) } var sces: [SelectCaseExpression] = Array() - var sces_errors: [Error] = Array() + var sces_errors: (any Errorable)? = .none select_body_node.enumerateNamedChildren { current_node in let maybe_parsed_cse = SelectCaseExpression.compile( node: current_node, withContext: context.update(newExpectation: selector.type())) - if case .Ok(let parsed_cse) = maybe_parsed_cse { - sces.append(parsed_cse as! SelectCaseExpression) - } else { - sces_errors.append(Error(withMessage: "\(maybe_parsed_cse.error()!)")) + switch maybe_parsed_cse { + case .Ok(let parsed_cse): sces.append(parsed_cse as! SelectCaseExpression) + case .Error(let e): sces_errors = if let sces_errors = sces_errors { + sces_errors.append(error: Error(withMessage: "\(maybe_parsed_cse.error()!)")) + } else { + e + } } } - if !sces_errors.isEmpty { - return .Error( - Error( - withMessage: "Error(s) parsing select cases: " - + (sces_errors.map { error in - return "\(error.msg)" - }.joined(separator: ";")))) + if let sces_errors = sces_errors { + return .Error(ErrorWithLabel("Error(s) parsing select cases", sces_errors)) } + return .Ok( SelectExpression(withSelector: selector, withSelectCaseExpressions: sces), ) @@ -311,13 +310,13 @@ extension SelectCaseExpression: CompilableExpression { guard let maybe_keysetexpression = maybe_keysetexpression else { return Result.Error( - ErrorOnNode(node: keysetexpression_node, withError: "Missing expected keyset expression")) + ErrorWithLocation(sourceLocation: keysetexpression_node.toSourceLocation(), withError: "Missing expected keyset expression")) } let keysetexpression = maybe_keysetexpression as! KeysetExpression if case .Error(let e) = keysetexpression.compatible(type: context.expected_type!) { - return .Error(ErrorOnNode(node: keysetexpression_node, withError: e.msg)) + return .Error(ErrorWithLocation(sourceLocation: keysetexpression_node.toSourceLocation(), withError: e.msg())) } let maybe_parsed_targetstate = Identifier.Compile( @@ -349,8 +348,8 @@ extension BinaryOperatorExpression: CompilableExpression { #MustOr( result: current_node, thing: walker.getNext(), or: Result.Error( - ErrorOnNode( - node: node, withError: "Malformed binary operator expression"))) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Malformed binary operator expression"))) /// TODO: This macro cannot handle new lines in the arrays // swift-format-ignore @@ -361,8 +360,8 @@ extension BinaryOperatorExpression: CompilableExpression { #MustOr( result: current_node, thing: walker.getNext(), or: Result.Error( - ErrorOnNode( - node: node, withError: "Missing LHS for binary operator expression"))) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Missing LHS for binary operator expression"))) let left_hand_side_raw = current_node! @@ -370,15 +369,15 @@ extension BinaryOperatorExpression: CompilableExpression { #MustOr( result: current_node, thing: walker.getNext(), or: Result.Error( - ErrorOnNode( - node: node, withError: "Missing binary operator for binary operator expression"))) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Missing binary operator for binary operator expression"))) walker.next() #MustOr( result: current_node, thing: walker.getNext(), or: Result.Error( - ErrorOnNode( - node: node, withError: "Missing RHS for binary operator expression"))) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Missing RHS for binary operator expression"))) let right_hand_side_raw = current_node! @@ -474,8 +473,8 @@ extension ArrayAccessExpression: CompilableExpression { #MustOr( result: current_node, thing: walker.getNext(), or: Result.Error( - ErrorOnNode( - node: node, withError: "Malformed array access expression"))) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Malformed array access expression"))) #RequireNodeType( node: current_node!, type: "expression", @@ -486,16 +485,16 @@ extension ArrayAccessExpression: CompilableExpression { #MustOr( result: current_node, thing: walker.getNext(), or: Result.Error( - ErrorOnNode( - node: node, withError: "Missing [ for array access expression"))) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Missing [ for array access expression"))) walker.next() #MustOr( result: current_node, thing: walker.getNext(), or: Result.Error( - ErrorOnNode( - node: node, withError: "Missing indexor expression for array access expression"))) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Missing indexor expression for array access expression"))) #RequireNodeType( node: current_node!, type: "expression", @@ -512,8 +511,8 @@ extension ArrayAccessExpression: CompilableExpression { let maybe_array_type = array_identifier.type() guard let array_type = maybe_array_type.baseType() as? P4Array else { return Result.Error( - ErrorOnNode( - node: array_access_identifier_node, + ErrorWithLocation( + sourceLocation: array_access_identifier_node.toSourceLocation(), withError: "\(array_identifier) does not name an array type") ) } @@ -547,8 +546,8 @@ extension FieldAccessExpression: CompilableExpression { #MustOr( result: current_node, thing: walker.getNext(), or: Result.Error( - ErrorOnNode( - node: node, withError: "Malformed field access expression"))) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Malformed field access expression"))) #RequireNodeType( node: current_node!, type: "expression", @@ -559,15 +558,15 @@ extension FieldAccessExpression: CompilableExpression { #MustOr( result: current_node, thing: walker.getNext(), or: Result.Error( - ErrorOnNode( - node: node, withError: "Missing . for field access expression"))) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Missing . for field access expression"))) walker.next() #MustOr( result: current_node, thing: walker.getNext(), or: Result.Error( - ErrorOnNode( - node: node, withError: "Missing field name for field access expression"))) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Missing field name for field access expression"))) #RequireNodeType( node: current_node!, type: "identifier", @@ -583,8 +582,8 @@ extension FieldAccessExpression: CompilableExpression { } guard let struct_type = struct_identifier.type().baseType() as? P4Struct else { return .Error( - ErrorOnNode( - node: struct_identifier_node, + ErrorWithLocation( + sourceLocation: struct_identifier_node.toSourceLocation(), withError: "\(struct_identifier_node.text!) does not have struct type")) } @@ -598,8 +597,8 @@ extension FieldAccessExpression: CompilableExpression { let maybe_field_type = struct_type.fields.get_field_type(field_name) guard let field_type = maybe_field_type else { return .Error( - ErrorOnNode( - node: field_name_node, + ErrorWithLocation( + sourceLocation: field_name_node.toSourceLocation(), withError: "\(field_name) is not a valid field for struct with type \(struct_type)")) } @@ -663,8 +662,8 @@ extension FunctionCall: CompilableExpression { #MustOr( result: current_node, thing: walker.getNext(), or: Result.Error( - ErrorOnNode( - node: node, withError: "Missing function call component"))) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Missing function call component"))) let maybe_callee_name = Identifier.Compile( node: current_node!, withContext: context) @@ -680,7 +679,7 @@ extension FunctionCall: CompilableExpression { Result<(FunctionDeclaration?, Declaration?)>.Ok((callee, .none)) // What we found is actually a function declaration default: Result<(FunctionDeclaration?, Declaration?)>.Error( - ErrorOnNode(node: current_node!, withError: "\(callee_name) is not a function")) + ErrorWithLocation(sourceLocation: current_node!.toSourceLocation(), withError: "\(callee_name) is not a function")) } case .Error(let e): Result<(FunctionDeclaration?, Declaration?)>.Error(e) } @@ -693,7 +692,7 @@ extension FunctionCall: CompilableExpression { switch callee.identifier.type.baseType() { case is FunctionDeclaration: Result.Ok((.none, callee)) default: - .Error(ErrorOnNode(node: current_node!, withError: "\(callee_name) is not a function")) + .Error(ErrorWithLocation(sourceLocation: current_node!.toSourceLocation(), withError: "\(callee_name) is not a function")) } default: .Error(e) } @@ -710,8 +709,8 @@ extension FunctionCall: CompilableExpression { #MustOr( result: current_node, thing: walker.getNext(), or: Result.Error( - ErrorOnNode( - node: node, withError: "Missing function call component"))) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Missing function call component"))) let maybe_argument_list = ArgumentList.Compile(node: current_node!, withContext: context) @@ -731,8 +730,8 @@ extension FunctionCall: CompilableExpression { guard case .some(let params) = params else { return Result.Error( - ErrorOnNode( - node: node, + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Could not lookup the parameters for the called function (\(callee_name))")) } @@ -747,8 +746,8 @@ extension FunctionCall: CompilableExpression { case (.none, .some(let callee)): .Ok(FunctionCall(callee.ffi!, withArguments: arguments)) default: Result.Error( - ErrorOnNode( - node: node, withError: "Unexpected error occurred calling function named (\(callee_name))" + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Unexpected error occurred calling function named (\(callee_name))" )) } } diff --git a/Sources/P4Compiler/Parser.swift b/Sources/P4Compiler/Parser.swift index f62e187..03cdf14 100644 --- a/Sources/P4Compiler/Parser.swift +++ b/Sources/P4Compiler/Parser.swift @@ -33,8 +33,8 @@ public struct Parser { guard let parser = localElementsParsers[node.nodeType ?? ""] else { return Result.Error( - ErrorOnNode( - node: node, + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Unparseable statement type (\(node.nodeType ?? "Unknown Statement Type"))")) } @@ -52,7 +52,7 @@ public struct Parser { node: Node, withContext context: CompilerContext ) -> Result<(EvaluatableStatement, CompilerContext)> { if node.nodeType != "parserStatement" && node.nodeType != "statement" { - return Result.Error(ErrorOnNode(node: node, withError: "Missing expected parser statement")) + return Result.Error(ErrorWithLocation(sourceLocation: node.toSourceLocation(), withError: "Missing expected parser statement")) } let statement = node.child(at: 0)! @@ -66,8 +66,8 @@ public struct Parser { ] guard let parser = statementParsers[statement.nodeType ?? ""] else { return Result.Error( - ErrorOnNode( - node: statement, + ErrorWithLocation( + sourceLocation: statement.toSourceLocation(), withError: "Unparseable statement type (\(statement.nodeType ?? "Unknown Statement Type"))")) } @@ -76,7 +76,7 @@ public struct Parser { return .Ok((parsed, updated_context)) case Result.Error(let e): return .Error( - ErrorOnNode(node: node, withError: "Failed to parse a statement element: \(e)")) + ErrorWithLocation(sourceLocation: node.toSourceLocation(), withError: "Failed to parse a statement element: \(e)")) } } } @@ -95,13 +95,13 @@ public struct Parser { tse_node.nodeType! == "transitionSelectionExpression" else { return .Error( - ErrorOnNode(node: node, withError: "Could not find transition select expression")) + ErrorWithLocation(sourceLocation: node.toSourceLocation(), withError: "Could not find transition select expression")) } guard let next_node = tse_node.child(at: 0) else { return .Error( - ErrorOnNode( - node: node, + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Could not find the next token in a transition selection expression")) } @@ -145,10 +145,10 @@ public struct Parser { node: Node, withContext context: CompilerContext ) -> Result<([EvaluatableStatement], CompilerContext)> { if node.nodeType != "statements" && node.nodeType != "parserStatements" { - return Result.Error(ErrorOnNode(node: node, withError: "Did not find expected statements")) + return Result.Error(ErrorWithLocation(sourceLocation: node.toSourceLocation(), withError: "Did not find expected statements")) } - var parse_errs: [Error] = Array() + var parse_errs: [any Errorable] = Array() var current_context = context var parsed_s: [EvaluatableStatement] = Array() @@ -168,7 +168,7 @@ public struct Parser { return Result.Error( Error( withMessage: parse_errs.map { err in - return String(err.msg) + return String(err.format()) }.joined(separator: ";"))) } return Result.Ok((parsed_s, current_context)) @@ -187,19 +187,19 @@ public struct Parser { node_type == "parserState" else { return Result.Error( - ErrorOnNode(node: node, withError: "Did not find a parser state declaration")) + ErrorWithLocation(sourceLocation: node.toSourceLocation(), withError: "Did not find a parser state declaration")) } #MustOr( result: current_node, thing: walker.getNext(), or: Result<(InstantiatedParserState, CompilerContext)>.Error( - ErrorOnNode( - node: node, withError: "Missing elements in parser state declaration"))) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Missing elements in parser state declaration"))) if current_node!.nodeType == "annotations" { return Result.Error( - ErrorOnNode( - node: current_node!, withError: "Annotations in parser state are not yet handled.")) + ErrorWithLocation( + sourceLocation: current_node!.toSourceLocation(), withError: "Annotations in parser state are not yet handled.")) // Would increment here. } @@ -209,8 +209,8 @@ public struct Parser { #MustOr( result: current_node, thing: walker.getNext(), or: Result<(InstantiatedParserState, CompilerContext)>.Error( - ErrorOnNode( - node: node, withError: "Missing elements in parser state declaration"))) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Missing elements in parser state declaration"))) let maybe_state_identifier = Identifier.Compile( node: current_node!, withContext: context) @@ -224,10 +224,10 @@ public struct Parser { #MustOr( result: current_node, thing: walker.getNext(), or: Result<(InstantiatedParserState, CompilerContext)>.Error( - ErrorOnNode( - node: node, withError: "Missing body of state declaration"))) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Missing body of state declaration"))) - var parse_errs: [Error] = Array() + var parse_errs: [any Errorable] = Array() var current_context = context var parsed_s: [EvaluatableStatement] = Array() @@ -248,15 +248,15 @@ public struct Parser { return Result.Error( Error( withMessage: parse_errs.map { err in - return String(err.msg) + return String(err.format()) }.joined(separator: ";"))) } #MustOr( result: current_node, thing: walker.getNext(), or: Result<(InstantiatedParserState, CompilerContext)>.Error( - ErrorOnNode( - node: node, withError: "Missing transition statement of state declaration"))) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Missing transition statement of state declaration"))) return TransitionStatement.Compile( node: current_node!, forState: state_identifier, withStatements: parsed_s, @@ -272,7 +272,7 @@ public struct Parser { var parser = P4Lang.Parser(withName: name, withParameters: parameters) // Build a state from each one listed. - var error: Error? = .none + var error: (any Errorable)? = .none var current_context = context /// TODO: Assert that there is only one. diff --git a/Sources/P4Compiler/Program.swift b/Sources/P4Compiler/Program.swift index be34b95..1da4424 100644 --- a/Sources/P4Compiler/Program.swift +++ b/Sources/P4Compiler/Program.swift @@ -60,7 +60,7 @@ public struct Program { // Add our FFIs compilation_context = compilation_context.update(newFFIs: ffis) - var errors: [Error] = Array() + var errors: [any Errorable] = Array() // If the caller gave any global instances, add them here. if let globalInstances = globalInstances { @@ -98,8 +98,8 @@ public struct Program { // If none of the declaration parsers chose to parse, that's an error, too! if !found_parser { errors.append( - ErrorOnNode( - node: specific_declaration_node, withError: "Could not find parser for declaration node" + ErrorWithLocation( + sourceLocation: specific_declaration_node.toSourceLocation(), withError: "Could not find parser for declaration node" )) } } @@ -108,7 +108,7 @@ public struct Program { return Result.Error( Error( withMessage: errors.map { error in - return error.msg + return error.format() }.joined(separator: ";"))) } diff --git a/Sources/P4Compiler/Statement.swift b/Sources/P4Compiler/Statement.swift index 7e1d386..1f96f99 100644 --- a/Sources/P4Compiler/Statement.swift +++ b/Sources/P4Compiler/Statement.swift @@ -35,22 +35,22 @@ extension BlockStatement: CompilableStatement { #MustOr( result: current_node, thing: walker.getNext(), or: Result<(EvaluatableStatement, CompilerContext)>.Error( - ErrorOnNode(node: node, withError: "Malformed block statement"))) + ErrorWithLocation(sourceLocation: node.toSourceLocation(), withError: "Malformed block statement"))) if current_node!.nodeType != "{" { return Result.Error( - ErrorOnNode(node: current_node!, withError: "Missing { on block statement")) + ErrorWithLocation(sourceLocation: current_node!.toSourceLocation(), withError: "Missing { on block statement")) } var statements: [EvaluatableStatement] = Array() - var parse_err: Error? = .none + var parse_err: (any Errorable)? = .none var current_context = context walker.next() #MustOr( result: current_node, thing: walker.getNext(), or: Result<(EvaluatableStatement, CompilerContext)>.Error( - ErrorOnNode(node: node, withError: "Malformed block statement"))) + ErrorWithLocation(sourceLocation: node.toSourceLocation(), withError: "Malformed block statement"))) if current_node!.nodeType == "statements" { switch Parser.Statements.Compile( @@ -73,11 +73,11 @@ extension BlockStatement: CompilableStatement { #MustOr( result: current_node, thing: walker.getNext(), or: Result<(EvaluatableStatement, CompilerContext)>.Error( - ErrorOnNode(node: node, withError: "Malformed block statement"))) + ErrorWithLocation(sourceLocation: node.toSourceLocation(), withError: "Malformed block statement"))) if current_node!.nodeType != "}" { return Result.Error( - ErrorOnNode(node: current_node!, withError: "Missing } on block statement")) + ErrorWithLocation(sourceLocation: current_node!.toSourceLocation(), withError: "Missing } on block statement")) } return .Ok((BlockStatement(statements), current_context)) @@ -97,7 +97,7 @@ extension ConditionalStatement: CompilableStatement { condition_expression.nodeType == "expression" else { return Result.Error( - ErrorOnNode(node: node, withError: "Did not find condition for conditional statement")) + ErrorWithLocation(sourceLocation: node.toSourceLocation(), withError: "Did not find condition for conditional statement")) } let maybe_thens = node.child(at: 4) @@ -105,8 +105,8 @@ extension ConditionalStatement: CompilableStatement { thens.nodeType == "statement" else { return Result.Error( - ErrorOnNode( - node: node, withError: "Did not find then statement block for conditional statement")) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Did not find then statement block for conditional statement")) } guard @@ -165,8 +165,8 @@ extension VariableDeclarationStatement: CompilableStatement { typeref.nodeType == "typeRef" else { return Result.Error( - ErrorOnNode( - node: node, withError: "Did not find type name for variable declaration statement")) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Did not find type name for variable declaration statement")) } let maybe_variablename = node.child(at: 1) @@ -174,8 +174,8 @@ extension VariableDeclarationStatement: CompilableStatement { variablename.nodeType == "identifier" else { return Result.Error( - ErrorOnNode( - node: node, withError: "Did not find identifier name for variable declaration statement")) + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Did not find identifier name for variable declaration statement")) } let maybe_rvalue = node.childCount > 3 ? node.child(at: 3) : .none @@ -200,8 +200,8 @@ extension VariableDeclarationStatement: CompilableStatement { if let initializer_expression = maybe_rvalue { guard initializer_expression.nodeType == "expression" else { return Result.Error( - ErrorOnNode( - node: node, + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "initial value for declaration statement is not an expression")) } @@ -231,7 +231,7 @@ extension VariableDeclarationStatement: CompilableStatement { guard let initializer = initializer else { return Result.Error( - ErrorOnNode(node: node, withError: "No initializer for declaration")) + ErrorWithLocation(sourceLocation: node.toSourceLocation(), withError: "No initializer for declaration")) } return Result.Ok( @@ -275,14 +275,14 @@ extension ParserAssignmentStatement: CompilableStatement { lvalue_node.nodeType == "expression" else { return Result.Error( - ErrorOnNode(node: node, withError: "Missing lvalue in assignment statement")) + ErrorWithLocation(sourceLocation: node.toSourceLocation(), withError: "Missing lvalue in assignment statement")) } guard let rvalue_node = node.child(at: 2), rvalue_node.nodeType == "expression" else { return Result.Error( - ErrorOnNode(node: node, withError: "Missing rvalue in assignment statement")) + ErrorWithLocation(sourceLocation: node.toSourceLocation(), withError: "Missing rvalue in assignment statement")) } let maybe_parsed_rvalue = Expression.Compile( @@ -299,8 +299,8 @@ extension ParserAssignmentStatement: CompilableStatement { let check_result = lvalue_identifier.check(to: rvalue, inScopes: context.instances) guard case .Ok(_) = check_result else { return Result.Error( - ErrorOnNode( - node: lvalue_node, + ErrorWithLocation( + sourceLocation: lvalue_node.toSourceLocation(), withError: "\(check_result.error()!)")) } @@ -329,8 +329,8 @@ extension ReturnStatement: CompilableStatement { .Ok((ReturnStatement(result), context)) } else { .Error( - ErrorOnNode( - node: node, + ErrorWithLocation( + sourceLocation: node.toSourceLocation(), withError: "Type of expression in return statement (\(result.type())) is not compatible with function return type (\(context.expected_type!))" )) diff --git a/Sources/P4Compiler/Walker.swift b/Sources/P4Compiler/Walker.swift index 97c5a87..a899d45 100644 --- a/Sources/P4Compiler/Walker.swift +++ b/Sources/P4Compiler/Walker.swift @@ -54,8 +54,8 @@ public struct Walker { public func try_map( n: Int, onlyNamed: Bool = false, todo: (Node) -> Result - ) -> ([T], [Error]) { - var errors: [Error] = Array() + ) -> ([T], [any Errorable]) { + var errors: [any Errorable] = Array() var results: [T] = Array() for currentChildIdx in currentChildIdx..( - Error(withMessage: "{2, 154}: Did not find assignment statement"), + ErrorWithLocation(sourceLocation: SourceLocation(2, 154), withError: "Did not find assignment statement"), ParserAssignmentStatement.Compile( // Note: Calling ParserAssignmentStatement compilation directly. node: result.rootNode!, withContext: CompilerContext()))) } diff --git a/Tests/p4rseTests/ValueTypeParserTests.swift b/Tests/p4rseTests/ValueTypeParserTests.swift index fd99d36..b0b892e 100644 --- a/Tests/p4rseTests/ValueTypeParserTests.swift +++ b/Tests/p4rseTests/ValueTypeParserTests.swift @@ -42,7 +42,7 @@ import TreeSitterP4 guard case Result.Error(let e) = err else { assert(false, "Expected an error, but had success") } - #expect(e.msg.contains("Failed to parse a statement element: Could not parse a P4 type from \(invalid_type_name)")) + #expect(e.format().contains("Failed to parse a statement element: Could not parse a P4 type from \(invalid_type_name)")) } }