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