Add the stracktrace to RuntimeError
This commit is contained in:
parent
2d8316d7ff
commit
dda04d8859
@ -214,7 +214,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
|
||||
throw RuntimeError(ErrorType::AlreadyDeclaredIdentifier, token.pos, identifier);
|
||||
|
||||
Type type = try_string_to_type(type_string, type_token.pos);
|
||||
memory.declare(identifier, type, type_token.pos);
|
||||
memory.declare(identifier, type);
|
||||
|
||||
return {};
|
||||
} break;
|
||||
@ -229,7 +229,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
|
||||
throw RuntimeError(ErrorType::AlreadyDeclaredIdentifier, token.pos, identifier);
|
||||
|
||||
Type type = try_string_to_type(type_string, type_token.pos);
|
||||
memory.declare(identifier, type, type_token.pos);
|
||||
memory.declare(identifier, type);
|
||||
|
||||
get_cast(type, analyze(node.children[2], memory), get_node_pos(node));
|
||||
|
||||
@ -295,7 +295,7 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
|
||||
}
|
||||
}
|
||||
|
||||
memory.declare(function_name, type, return_type_token.pos);
|
||||
memory.declare(function_name, type);
|
||||
|
||||
return {};
|
||||
} break;
|
||||
@ -335,16 +335,16 @@ AnalysisResult analyze(Node &ast, Memory &memory) {
|
||||
}
|
||||
}
|
||||
|
||||
memory.declare(function_name, type, return_type_token.pos);
|
||||
memory.declare(function_name, type);
|
||||
|
||||
memory.update(function_name, node.children[3]);
|
||||
|
||||
memory.add_scope(ScopeType::Function, token.pos, &memory.get(function_name));
|
||||
memory.add_scope(ScopeType::Function, &memory.get(function_name));
|
||||
for (tuple<Type, string> variable : prototype) {
|
||||
Type vtype = get<0>(variable);
|
||||
string vname = get<1>(variable);
|
||||
|
||||
memory.declare(vname, vtype, token.pos);
|
||||
memory.declare(vname, vtype);
|
||||
}
|
||||
analyze(node.children[3], memory);
|
||||
memory.remove_scope();
|
||||
|
@ -56,6 +56,18 @@ 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;
|
||||
|
@ -56,7 +56,8 @@ enum class ErrorType {
|
||||
|
||||
using ErrorData = variant<monostate, string, int>;
|
||||
|
||||
using StackTrace = vector<tuple<string, CodePosition>>;
|
||||
using StackTraceEntry = tuple<string, CodePosition>;
|
||||
using StackTrace = vector<StackTraceEntry>;
|
||||
|
||||
class UserError : public exception {
|
||||
public:
|
||||
@ -93,11 +94,17 @@ public:
|
||||
};
|
||||
|
||||
class RuntimeError : public UserError {
|
||||
private:
|
||||
StackTrace trace;
|
||||
CodePosition lastPos;
|
||||
|
||||
public:
|
||||
explicit RuntimeError(ErrorType type, CodePosition pos, ErrorData data = {})
|
||||
: UserError(type, pos, data), trace() {}
|
||||
: UserError(type, pos, data), trace(), lastPos() {}
|
||||
|
||||
const StackTrace trace;
|
||||
StackTrace& get_trace(void);
|
||||
|
||||
void add_call(string name, CodePosition pos);
|
||||
};
|
||||
|
||||
class InternalError : public exception {
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <optional>
|
||||
#include "types.h"
|
||||
#include "colors.h"
|
||||
using namespace std;
|
||||
@ -12,12 +13,12 @@ class Memory {
|
||||
public:
|
||||
bool contains(string identifier);
|
||||
bool contains_top(string identifier);
|
||||
void add_scope(ScopeType type, CodePosition entry_pos = { }, MemoryVar* fn = NULL);
|
||||
void add_scope(ScopeType type, MemoryVar* fn = NULL);
|
||||
void remove_scope(void);
|
||||
|
||||
MemoryVar& get(string identifier);
|
||||
Scope& get_function_scope(void);
|
||||
void declare(string identifier, Type type, CodePosition pos = { });
|
||||
void declare(string identifier, Type type);
|
||||
void update(string identifier, EvalResult value);
|
||||
|
||||
Scope& _debug_top(void);
|
||||
|
@ -206,14 +206,12 @@ struct MemoryVar {
|
||||
EvalResult value;
|
||||
Type type;
|
||||
bool initialized;
|
||||
CodePosition declarationPos;
|
||||
};
|
||||
|
||||
struct Scope {
|
||||
unordered_map<string, MemoryVar> vars;
|
||||
int depth;
|
||||
ScopeType type;
|
||||
CodePosition entry_pos;
|
||||
MemoryVar* fn;
|
||||
};
|
||||
|
||||
|
@ -157,7 +157,7 @@ EvalResult eval(Node &ast, Memory &memory) {
|
||||
memory.declare(identifier, {
|
||||
.type = TypeType::Function,
|
||||
.data = prototype
|
||||
}, retTypeTok.pos);
|
||||
});
|
||||
|
||||
return {};
|
||||
} break;
|
||||
@ -171,7 +171,7 @@ EvalResult eval(Node &ast, Memory &memory) {
|
||||
memory.declare(identifier, {
|
||||
.type = TypeType::Function,
|
||||
.data = prototype
|
||||
}, retTypeTok.pos);
|
||||
});
|
||||
|
||||
memory.update(identifier, node.children[3]);
|
||||
|
||||
@ -196,7 +196,7 @@ EvalResult eval(Node &ast, Memory &memory) {
|
||||
|
||||
EvalResult res = {};
|
||||
|
||||
memory.add_scope(ScopeType::Function, identifierTok.pos, &var);
|
||||
memory.add_scope(ScopeType::Function, &var);
|
||||
|
||||
try {
|
||||
for (size_t i = 1; i < prototype.size(); i++) {
|
||||
@ -221,6 +221,11 @@ EvalResult eval(Node &ast, Memory &memory) {
|
||||
|
||||
memory.remove_scope();
|
||||
}
|
||||
catch (RuntimeError& e) {
|
||||
e.add_call(identifier, identifierTok.pos);
|
||||
|
||||
throw;
|
||||
}
|
||||
catch (...) {
|
||||
memory.remove_scope();
|
||||
|
||||
@ -414,7 +419,7 @@ EvalResult eval(Node &ast, Memory &memory) {
|
||||
string identifier = get<string>(identifierTok.data);
|
||||
|
||||
Type type = string_to_type(typeName);
|
||||
memory.declare(identifier, type, typeTok.pos);
|
||||
memory.declare(identifier, type);
|
||||
|
||||
return {};
|
||||
} break;
|
||||
@ -426,7 +431,7 @@ EvalResult eval(Node &ast, Memory &memory) {
|
||||
EvalResult value = eval(node.children[2], memory);
|
||||
|
||||
Type type = string_to_type(typeName);
|
||||
memory.declare(identifier, type, typeTok.pos);
|
||||
memory.declare(identifier, type);
|
||||
|
||||
if (type.type == TypeType::Int) {
|
||||
memory.update(identifier, int_cast(value));
|
||||
|
@ -118,9 +118,12 @@ int main(int argc, char* argv[]) {
|
||||
print_error_position(input, e.pos);
|
||||
cout << BOLD RED "Type Error: " RESET << e.get_message() << endl;
|
||||
|
||||
} catch (const RuntimeError& e) {
|
||||
// print_error_position(input, e.pos);
|
||||
// cout << BOLD RED "Runtime Error: " RESET << e.get_message() << endl;
|
||||
} catch (RuntimeError& e) {
|
||||
print_error_position(input, e.pos);
|
||||
cout << BOLD RED "Runtime Error: " RESET << e.get_message() << endl;
|
||||
for (auto e : e.get_trace()) {
|
||||
cout << get<0>(e) << " " << (get<1>(e).line + 1) << endl;
|
||||
}
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
|
@ -22,12 +22,11 @@ bool Memory::contains_top(string identifier) {
|
||||
return top.vars.contains(identifier);
|
||||
}
|
||||
|
||||
void Memory::add_scope(ScopeType type, CodePosition entry_pos, MemoryVar* fn) {
|
||||
void Memory::add_scope(ScopeType type, MemoryVar* fn) {
|
||||
Scope& top = scopes.back();
|
||||
scopes.emplace_back();
|
||||
scopes.back().depth = top.depth + 1;
|
||||
scopes.back().type = type;
|
||||
scopes.back().entry_pos = entry_pos;
|
||||
scopes.back().fn = fn;
|
||||
}
|
||||
|
||||
@ -54,10 +53,9 @@ Scope& Memory::get_function_scope(void) {
|
||||
throw InternalError();
|
||||
}
|
||||
|
||||
void Memory::declare(string identifier, Type type, CodePosition pos) {
|
||||
void Memory::declare(string identifier, Type type) {
|
||||
Scope& top = scopes.back();
|
||||
top.vars[identifier].type = type;
|
||||
top.vars[identifier].declarationPos = pos;
|
||||
}
|
||||
|
||||
void Memory::update(string identifier, EvalResult value) {
|
||||
|
Loading…
Reference in New Issue
Block a user