diff --git a/src/analysis.cpp b/src/analysis.cpp index bb81956..59df4fb 100644 --- a/src/analysis.cpp +++ b/src/analysis.cpp @@ -373,7 +373,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) { try { memory.get_function_scope(); } catch (const InternalError& _) { - throw RuntimeError(ErrorType::UnexpectedReturn, node.pos, {}); + throw ControlError(ErrorType::UnexpectedReturn, node.pos, {}); } return {}; } diff --git a/src/errors.cpp b/src/errors.cpp index 4b9af77..a201615 100644 --- a/src/errors.cpp +++ b/src/errors.cpp @@ -9,9 +9,14 @@ using namespace std; string UserError::get_message(void) const { switch (this->type) { + // Generic case ErrorType::NotImplemented: return "Not implemented"; + + // Lexing case ErrorType::UnknownToken: return "Unknown token"; case ErrorType::IntegerTooLarge: return "Integer constant is too large"; + + // Parsing case ErrorType::EmptyInput: return "Input must not be empty"; case ErrorType::InvalidSyntax: return "Invalid syntax"; case ErrorType::ExceptedLParen: return "Expected '("; @@ -20,25 +25,31 @@ string UserError::get_message(void) const { case ErrorType::ExpectedRCurlyBracket: return "Expected '}'"; case ErrorType::ExpectedSemicolon: return "Expected ';'"; case ErrorType::DependentDeclaration: return "A dependant statement may not be a declaration"; + + // Flow control + case ErrorType::BreakNotWithinLoop: return "Break statement not within loop"; + case ErrorType::ContinueNotWithinLoop: return "Continue statement not within loop"; + case ErrorType::ControlReachesEndOfNonVoidFn: return "Control reaches end of non-void function"; + case ErrorType::UnexpectedReturn: return "Return not within a function"; + + // Analysus case ErrorType::UnknownType: return "Unknown type '"+get(this->data)+"'"; case ErrorType::TypeNotCastable: return "Can't find an explicit cast to "+get(this->data)+"'"; case ErrorType::TypesNotComparable: return "Types not comparable"; case ErrorType::ExpectedIntegralType: return "Expression must have integral type"; + case ErrorType::ExpectedArithmeticType: return "Expression must have arithmetic type"; case ErrorType::NestedFunction: return "Function definition is not allowed here"; case ErrorType::FunctionRedefinition: return "Redefinition of '"+get(this->data)+"'"; case ErrorType::IncompatibleRedefinition: return "Redefinition of '"+get(this->data)+"' as different kind of symbol"; case ErrorType::IncompatibleDefinition: return "Declaration of '"+get(this->data)+"' is incompatible with previous prototype"; case ErrorType::UnexpectedArgumentCount: return "Expected "+to_string(get(this->data))+" arguments to function call"; - case ErrorType::UnexpectedReturn: return "Return not within a function"; - case ErrorType::ExpectedArithmeticType: return "Expression must have arithmetic type"; + + // Runtime case ErrorType::UnknownIdentifier: return "Unknown identifier '"+get(this->data)+"'"; case ErrorType::AlreadyDeclaredIdentifier: return "Already declared identifier '"+get(this->data)+"'"; case ErrorType::UninitializedIdentifier: return "Accessing uninitialized identifier '"+get(this->data)+"'"; case ErrorType::DivisionByZero: return "Division by 0"; case ErrorType::ModuloByZero: return "Modulo by 0"; - case ErrorType::BreakNotWithinLoop: return "Break statement not within loop"; - case ErrorType::ContinueNotWithinLoop: return "Continue statement not within loop"; - case ErrorType::ControlReachesEndOfNonVoidFn: return "Control reaches end of non-void function"; default: return "Unknown error type"; } } diff --git a/src/execute.cpp b/src/execute.cpp index 8f44793..96d596b 100644 --- a/src/execute.cpp +++ b/src/execute.cpp @@ -37,8 +37,8 @@ EvalResult execute(vector input, Memory& memory, int initial_line, ExecA return res; } catch (const BreakException& except) { - throw RuntimeError(ErrorType::BreakNotWithinLoop, except.pos); + throw ControlError(ErrorType::BreakNotWithinLoop, except.pos); } catch (const ContinueException& except) { - throw RuntimeError(ErrorType::ContinueNotWithinLoop, except.pos); + throw ControlError(ErrorType::ContinueNotWithinLoop, except.pos); } } \ No newline at end of file diff --git a/src/include/errors.h b/src/include/errors.h index 62e0a59..22e8b6f 100644 --- a/src/include/errors.h +++ b/src/include/errors.h @@ -27,6 +27,12 @@ enum class ErrorType { ExpectedSemicolon, DependentDeclaration, + // Flow control + BreakNotWithinLoop, + ContinueNotWithinLoop, + ControlReachesEndOfNonVoidFn, + UnexpectedReturn, + // Analysis UnknownType, TypeNotCastable, @@ -38,17 +44,13 @@ enum class ErrorType { IncompatibleRedefinition, // redefinition of a variable as a function IncompatibleDefinition, // function declaration incompatible with prototype UnexpectedArgumentCount, - UnexpectedReturn, // Runtime UnknownIdentifier, AlreadyDeclaredIdentifier, UninitializedIdentifier, DivisionByZero, - ModuloByZero, - BreakNotWithinLoop, - ContinueNotWithinLoop, - ControlReachesEndOfNonVoidFn + ModuloByZero }; using ErrorData = variant; @@ -75,6 +77,12 @@ public: : UserError(type, pos, data) {} }; +class ControlError : public UserError { +public: + explicit ControlError(ErrorType type, CodePosition pos, ErrorData data = {}) + : UserError(type, pos, data) {} +}; + class TypeError : public UserError { public: explicit TypeError(ErrorType type, CodePosition pos, ErrorData data = {}) diff --git a/src/interpreter.cpp b/src/interpreter.cpp index 5c30bb4..88ddf5f 100644 --- a/src/interpreter.cpp +++ b/src/interpreter.cpp @@ -212,7 +212,7 @@ EvalResult eval(Node &ast, Memory &memory) { // Tmp: no flow control if (get<0>(prototype[0]).type != TypeType::Void) { - throw RuntimeError(ErrorType::ControlReachesEndOfNonVoidFn, identifierTok.pos); + throw ControlError(ErrorType::ControlReachesEndOfNonVoidFn, identifierTok.pos); } } catch (const ReturnException& e) { diff --git a/src/main.cpp b/src/main.cpp index 2a165c3..8355dad 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -110,6 +110,10 @@ int main(int argc, char* argv[]) { print_error_position(input, e.pos); cout << BOLD RED "Syntax Error: " RESET << e.get_message() << endl; + } catch (const ControlError& e) { + print_error_position(input, e.pos); + cout << BOLD RED "Control Error: " RESET << e.get_message() << endl; + } catch (const TypeError& e) { print_error_position(input, e.pos); cout << BOLD RED "Type Error: " RESET << e.get_message() << endl;