Rework stacktrace

This commit is contained in:
ala89 2024-01-04 13:50:03 +01:00
parent dda04d8859
commit a0c1724b2e
8 changed files with 59 additions and 56 deletions

View File

@ -75,7 +75,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
string identifier = get<string>(token.data);
if (!memory.contains(identifier))
throw RuntimeError(ErrorType::UnknownIdentifier, token.pos, identifier);
throw TypeError(ErrorType::UnknownIdentifier, token.pos, identifier);
return memory.get(identifier).type;
throw exception();
@ -211,7 +211,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
string identifier = get<string>(token.data);
if (memory.contains_top(identifier))
throw RuntimeError(ErrorType::AlreadyDeclaredIdentifier, token.pos, identifier);
throw TypeError(ErrorType::AlreadyDeclaredIdentifier, token.pos, identifier);
Type type = try_string_to_type(type_string, type_token.pos);
memory.declare(identifier, type);
@ -226,7 +226,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
string identifier = get<string>(token.data);
if (memory.contains_top(identifier))
throw RuntimeError(ErrorType::AlreadyDeclaredIdentifier, token.pos, identifier);
throw TypeError(ErrorType::AlreadyDeclaredIdentifier, token.pos, identifier);
Type type = try_string_to_type(type_string, type_token.pos);
memory.declare(identifier, type);
@ -239,7 +239,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
Token identifierTok = get<Token>(node.children[0]);
string identifier = get<string>(identifierTok.data);
if (!memory.contains(identifier))
throw RuntimeError(ErrorType::UnknownIdentifier, identifierTok.pos, identifier);
throw TypeError(ErrorType::UnknownIdentifier, identifierTok.pos, identifier);
Type type = memory.get(identifier).type;
AnalysisResult res = analyze(node.children[1], memory);
@ -256,7 +256,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
string identifier = get<string>(identifierTok.data);
if (!memory.contains(identifier))
throw RuntimeError(ErrorType::UnknownIdentifier, identifierTok.pos, identifier);
throw TypeError(ErrorType::UnknownIdentifier, identifierTok.pos, identifier);
return memory.get(identifier).type;
}
@ -274,7 +274,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
try {
memory.get_function_scope();
throw RuntimeError(ErrorType::NestedFunction, token.pos, {});
throw TypeError(ErrorType::NestedFunction, token.pos, {});
} catch (const InternalError& _) {}
FunctionPrototype prototype = make_fn_prototype(node);
@ -310,12 +310,12 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
// Déclarée dans une fonction
try {
memory.get_function_scope();
throw RuntimeError(ErrorType::NestedFunction, token.pos, {});
throw TypeError(ErrorType::NestedFunction, token.pos, {});
} catch (const InternalError& _) {}
// Corps de la fonction déjà déclaré
if (memory.contains(function_name) && memory.get(function_name).initialized)
throw RuntimeError(ErrorType::FunctionRedefinition, token.pos, function_name);
throw TypeError(ErrorType::FunctionRedefinition, token.pos, function_name);
FunctionPrototype prototype = make_fn_prototype(node);
Type type = {
@ -356,7 +356,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
string function_name = get<string>(token.data);
if (!memory.contains(function_name))
throw RuntimeError(ErrorType::UnknownIdentifier, token.pos, function_name);
throw TypeError(ErrorType::UnknownIdentifier, token.pos, function_name);
MemoryVar function = memory.get(function_name);

View File

@ -56,18 +56,6 @@ string UserError::get_message(void) const {
}
}
StackTrace& RuntimeError::get_trace(void) {
StackTraceEntry top = { "<repl>", lastPos };
trace.push_back(top);
return trace;
}
void RuntimeError::add_call(string callName, CodePosition callPos) {
StackTraceEntry entry = { callName, lastPos };
trace.push_back(entry);
lastPos = callPos;
}
void print_error_position(vector<string> history, CodePosition pos) {
if (pos.column == -1 || pos.line == -1)
return;

View File

@ -56,9 +56,6 @@ enum class ErrorType {
using ErrorData = variant<monostate, string, int>;
using StackTraceEntry = tuple<string, CodePosition>;
using StackTrace = vector<StackTraceEntry>;
class UserError : public exception {
public:
explicit UserError(ErrorType type, CodePosition pos, ErrorData data = {})
@ -94,17 +91,11 @@ public:
};
class RuntimeError : public UserError {
private:
StackTrace trace;
CodePosition lastPos;
public:
explicit RuntimeError(ErrorType type, CodePosition pos, ErrorData data = {})
: UserError(type, pos, data), trace(), lastPos() {}
explicit RuntimeError(ErrorType type, CodePosition pos, StackTrace trace, ErrorData data = {})
: UserError(type, pos, data), trace(trace) {}
StackTrace& get_trace(void);
void add_call(string name, CodePosition pos);
const StackTrace trace;
};
class InternalError : public exception {

View File

@ -13,7 +13,7 @@ class Memory {
public:
bool contains(string identifier);
bool contains_top(string identifier);
void add_scope(ScopeType type, MemoryVar* fn = NULL);
void add_scope(ScopeType type, MemoryVar* fn = NULL, CodePosition entry_pos = { });
void remove_scope(void);
MemoryVar& get(string identifier);
@ -21,6 +21,8 @@ class Memory {
void declare(string identifier, Type type);
void update(string identifier, EvalResult value);
StackTrace get_trace(CodePosition pos);
Scope& _debug_top(void);
void _debug_print(void);

View File

@ -50,6 +50,9 @@ struct Token {
CodePosition pos;
};
using StackTraceEntry = tuple<string, CodePosition>;
using StackTrace = vector<StackTraceEntry>;
/** Grammar:
Prog -> Instruction Prog | Instruction
@ -206,6 +209,7 @@ struct MemoryVar {
EvalResult value;
Type type;
bool initialized;
string identifier;
};
struct Scope {
@ -213,6 +217,7 @@ struct Scope {
int depth;
ScopeType type;
MemoryVar* fn;
CodePosition entry_pos;
};
#endif

View File

@ -185,7 +185,7 @@ EvalResult eval(Node &ast, Memory &memory) {
MemoryVar& var = memory.get(identifier);
if (!var.initialized)
throw RuntimeError(ErrorType::UninitializedIdentifier, identifierTok.pos, identifier);
throw RuntimeError(ErrorType::UninitializedIdentifier, identifierTok.pos, memory.get_trace(identifierTok.pos), identifier);
vector<EvalResult> argValues = {};
for (Node arg : args) {
@ -196,7 +196,7 @@ EvalResult eval(Node &ast, Memory &memory) {
EvalResult res = {};
memory.add_scope(ScopeType::Function, &var);
memory.add_scope(ScopeType::Function, &var, identifierTok.pos);
try {
for (size_t i = 1; i < prototype.size(); i++) {
@ -221,11 +221,6 @@ EvalResult eval(Node &ast, Memory &memory) {
memory.remove_scope();
}
catch (RuntimeError& e) {
e.add_call(identifier, identifierTok.pos);
throw;
}
catch (...) {
memory.remove_scope();
@ -373,13 +368,13 @@ EvalResult eval(Node &ast, Memory &memory) {
if (holds_alternative<double>(e1) || holds_alternative<double>(e2)) {
double d1 = double_cast(e1);
double d2 = double_cast(e2);
if (d2 == 0) throw RuntimeError(ErrorType::DivisionByZero, node.pos);
if (d2 == 0) throw RuntimeError(ErrorType::DivisionByZero, node.pos, memory.get_trace(node.pos));
return d1 / d2;
}
else {
int i1 = get<int>(e1);
int i2 = get<int>(e2);
if (i2 == 0) throw RuntimeError(ErrorType::DivisionByZero, node.pos);
if (i2 == 0) throw RuntimeError(ErrorType::DivisionByZero, node.pos, memory.get_trace(node.pos));
return i1 / i2;
}
} break;
@ -389,7 +384,7 @@ EvalResult eval(Node &ast, Memory &memory) {
int i1 = get<int>(e1);
int i2 = get<int>(e2);
if (i2 == 0) throw RuntimeError(ErrorType::ModuloByZero, node.pos);
if (i2 == 0) throw RuntimeError(ErrorType::ModuloByZero, node.pos, memory.get_trace(node.pos));
return i1 % i2;
} break;
case NodeType::UnaryPlus: {
@ -468,7 +463,7 @@ EvalResult eval(Node &ast, Memory &memory) {
MemoryVar& var = memory.get(identifier);
if (!var.initialized) {
throw RuntimeError(ErrorType::UninitializedIdentifier, identifierTok.pos, identifier);
throw RuntimeError(ErrorType::UninitializedIdentifier, identifierTok.pos, memory.get_trace(identifierTok.pos), identifier);
}
else if (var.type.type == TypeType::Int) {
memory.update(identifier, get<int>(var.value) + 1);
@ -485,7 +480,7 @@ EvalResult eval(Node &ast, Memory &memory) {
MemoryVar& var = memory.get(identifier);
if (!var.initialized) {
throw RuntimeError(ErrorType::UninitializedIdentifier, identifierTok.pos, identifier);
throw RuntimeError(ErrorType::UninitializedIdentifier, identifierTok.pos, memory.get_trace(identifierTok.pos), identifier);
}
else if (var.type.type == TypeType::Int) {
int oldVal = get<int>(var.value);
@ -503,7 +498,7 @@ EvalResult eval(Node &ast, Memory &memory) {
MemoryVar& var = memory.get(identifier);
if (!var.initialized) {
throw RuntimeError(ErrorType::UninitializedIdentifier, identifierTok.pos, identifier);
throw RuntimeError(ErrorType::UninitializedIdentifier, identifierTok.pos, memory.get_trace(identifierTok.pos), identifier);
}
else if (var.type.type == TypeType::Int) {
memory.update(identifier, get<int>(var.value) - 1);
@ -520,7 +515,7 @@ EvalResult eval(Node &ast, Memory &memory) {
MemoryVar& var = memory.get(identifier);
if (!var.initialized) {
throw RuntimeError(ErrorType::UninitializedIdentifier, identifierTok.pos, identifier);
throw RuntimeError(ErrorType::UninitializedIdentifier, identifierTok.pos, memory.get_trace(identifierTok.pos), identifier);
}
else if (var.type.type == TypeType::Int) {
int oldVal = get<int>(var.value);
@ -555,7 +550,7 @@ EvalResult eval(Node &ast, Memory &memory) {
MemoryVar& var = memory.get(identifier);
if (!var.initialized)
throw RuntimeError(ErrorType::UninitializedIdentifier, token.pos, identifier);
throw RuntimeError(ErrorType::UninitializedIdentifier, token.pos, memory.get_trace(token.pos), identifier);
return var.value;
} break;

View File

@ -118,10 +118,11 @@ int main(int argc, char* argv[]) {
print_error_position(input, e.pos);
cout << BOLD RED "Type Error: " RESET << e.get_message() << endl;
} catch (RuntimeError& e) {
} catch (const RuntimeError& e) {
print_error_position(input, e.pos);
cout << BOLD RED "Runtime Error: " RESET << e.get_message() << endl;
for (auto e : e.get_trace()) {
for (StackTraceEntry e : e.trace) {
cout << get<0>(e) << " " << (get<1>(e).line + 1) << endl;
}
}

View File

@ -22,12 +22,13 @@ bool Memory::contains_top(string identifier) {
return top.vars.contains(identifier);
}
void Memory::add_scope(ScopeType type, MemoryVar* fn) {
void Memory::add_scope(ScopeType type, MemoryVar* fn, CodePosition entry_pos) {
Scope& top = scopes.back();
scopes.emplace_back();
scopes.back().depth = top.depth + 1;
scopes.back().type = type;
scopes.back().fn = fn;
Scope& newScope = scopes.emplace_back();
newScope.depth = top.depth + 1;
newScope.type = type;
newScope.fn = fn;
newScope.entry_pos = entry_pos;
}
void Memory::remove_scope(void) {
@ -56,6 +57,7 @@ Scope& Memory::get_function_scope(void) {
void Memory::declare(string identifier, Type type) {
Scope& top = scopes.back();
top.vars[identifier].type = type;
top.vars[identifier].identifier = identifier;
}
void Memory::update(string identifier, EvalResult value) {
@ -71,6 +73,25 @@ void Memory::update(string identifier, EvalResult value) {
throw exception();
}
StackTrace Memory::get_trace(CodePosition pos) {
StackTrace trace = {};
for (auto rit = scopes.rbegin(); rit != scopes.rend(); ++rit) {
Scope& scope = *rit;
if (scope.type == ScopeType::Function) {
MemoryVar fn = *(scope.fn);
StackTraceEntry entry = { fn.identifier, pos };
trace.push_back(entry);
pos = scope.entry_pos;
}
}
StackTraceEntry top = { "<repl>", pos };
trace.push_back(top);
return trace;
}
Scope& Memory::_debug_top(void) {
Scope& top = scopes.back();
return top;