c-repl/src/errors.cpp

90 lines
4.3 KiB
C++

#include <vector>
#include <string>
#include <iomanip>
#include <iostream>
using namespace std;
#include "include/utils.h"
#include "include/errors.h"
#include "include/colors.h"
#include "include/tokenize.h"
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 '(";
case ErrorType::ExpectedRParen: return "Expected ')'";
case ErrorType::ExpectedLCurlyBracket: return "Expected '{'";
case ErrorType::ExpectedRCurlyBracket: return "Expected '}'";
case ErrorType::ExpectedSemicolon: return "Expected ';'";
case ErrorType::DependentDeclaration: return "A dependant statement may not be a declaration";
case ErrorType::NameOmitted: return "Omitting parameter name in a function definition";
// 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";
// Analysis
case ErrorType::UnknownType: return "Unknown type '"+get<string>(this->data)+"'";
case ErrorType::TypeNotCastable: return "Can't find an explicit cast to "+get<string>(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<string>(this->data)+"'";
case ErrorType::IncompatibleRedefinition: return "Redefinition of '"+get<string>(this->data)+"' as different kind of symbol";
case ErrorType::IncompatibleDefinition: return "Declaration of '"+get<string>(this->data)+"' is incompatible with previous prototype";
case ErrorType::UnexpectedArgumentCount: return "Expected "+to_string(get<int>(this->data))+" arguments to function call";
case ErrorType::IncompatibleReturnValue: return "Return value type does not match the function type";
case ErrorType::IncompleteType: return "Incomplete type is not allowed";
// Runtime
case ErrorType::UnknownIdentifier: return "Unknown identifier '"+get<string>(this->data)+"'";
case ErrorType::AlreadyDeclaredIdentifier: return "Already declared identifier '"+get<string>(this->data)+"'";
case ErrorType::UninitializedIdentifier: return "Accessing uninitialized identifier '"+get<string>(this->data)+"'";
case ErrorType::DivisionByZero: return "Division by 0";
case ErrorType::ModuloByZero: return "Modulo by 0";
default: return "Unknown error type";
}
}
void print_error_position(vector<string> history, CodePosition pos) {
if (pos.column == -1 || pos.line == -1)
return;
cout << endl << BOLD
<< setw(4) << setfill(' ')
<< pos.line+1 << " " RESET
<< history[pos.line] << endl;
for (int i=0; i < pos.column + 5; i++)
cout << " ";
cout << BOLD RED "^--" RESET << endl;
}
void print_error_stack_trace(vector<string> history, const RuntimeError& error) {
cout << "\n" BOLD "Traceback" RESET " (most recent call last)" << endl;
for (StackTraceEntry e : error.trace) {
cout << BOLD << setw(8) << setfill(' ')
<< to_string(get<1>(e).line+1) + ":" + to_string(get<1>(e).column+1)
<< RESET BLUE
<< setw(16) << setfill(' ')
<< get<0>(e) << RESET << " \t"
<< trim(history[get<1>(e).line]) << endl;
}
cout << BOLD RED "Runtime Error: " RESET << error.get_message() << endl;
}