diff --git a/include/pocketpy/error.h b/include/pocketpy/error.h index 950bb742..f46e538b 100644 --- a/include/pocketpy/error.h +++ b/include/pocketpy/error.h @@ -34,21 +34,41 @@ struct SourceData { SourceData(const Str& source, const Str& filename, CompileMode mode); std::pair get_line(int lineno) const; - Str snapshot(int lineno, const char* cursor=nullptr, std::string_view name=""); + Str snapshot(int lineno, const char* cursor, std::string_view name) const; +}; + +struct ExceptionLine{ + std::shared_ptr src; + int lineno; + const char* cursor; + std::string name; + + Str snapshot() const { return src->snapshot(lineno, cursor, name); } + + ExceptionLine(std::shared_ptr src, int lineno, const char* cursor, std::string_view name): + src(src), lineno(lineno), cursor(cursor), name(name) {} }; struct Exception { StrName type; Str msg; bool is_re; - stack stacktrace; int _ip_on_error; void* _code_on_error; + + stack stacktrace; - Exception(StrName type, Str msg): type(type), msg(msg), is_re(true), _ip_on_error(-1), _code_on_error(nullptr) {} + Exception(StrName type, Str msg): + type(type), msg(msg), is_re(true), _ip_on_error(-1), _code_on_error(nullptr) {} bool match_type(StrName t) const { return this->type == t;} - void st_push(Str&& snapshot); + + template + void st_push(Args&&... args){ + if(stacktrace.size() >= 8) return; + stacktrace.emplace(std::forward(args)...); + } + Str summary() const; }; diff --git a/src/error.cpp b/src/error.cpp index ed8844ef..4d56caf9 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -29,7 +29,7 @@ namespace pkpy{ return {_start, i}; } - Str SourceData::snapshot(int lineno, const char* cursor, std::string_view name){ + Str SourceData::snapshot(int lineno, const char* cursor, std::string_view name) const{ std::stringstream ss; ss << " " << "File \"" << filename << "\", line " << lineno; if(!name.empty()) ss << ", in " << name; @@ -50,16 +50,14 @@ namespace pkpy{ return ss.str(); } - void Exception::st_push(Str&& snapshot){ - if(stacktrace.size() >= 8) return; - stacktrace.push(std::move(snapshot)); - } - Str Exception::summary() const { - stack st(stacktrace); + stack st(stacktrace); std::stringstream ss; if(is_re) ss << "Traceback (most recent call last):\n"; - while(!st.empty()) { ss << st.top() << '\n'; st.pop(); } + while(!st.empty()) { + ss << st.top().snapshot() << '\n'; + st.pop(); + } if (!msg.empty()) ss << type.sv() << ": " << msg; else ss << type.sv(); return ss.str(); diff --git a/src/lexer.cpp b/src/lexer.cpp index 60807907..de8a33dd 100644 --- a/src/lexer.cpp +++ b/src/lexer.cpp @@ -454,8 +454,8 @@ static bool is_unicode_Lo_char(uint32_t c) { } void Lexer::throw_err(Str type, Str msg, int lineno, const char* cursor){ - auto e = Exception(type, msg); - e.st_push(src->snapshot(lineno, cursor)); + Exception e(type, msg); + e.st_push(src, lineno, cursor, ""); throw e; } diff --git a/src/vm.cpp b/src/vm.cpp index 5ee9913d..e884dc8a 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -1095,7 +1095,7 @@ void VM::_raise(bool re_raise){ int current_line = frame->co->lines[actual_ip]; // current line auto current_f_name = frame->co->name.sv(); // current function name if(frame->_callable == nullptr) current_f_name = ""; // not in a function - e.st_push(frame->co->src->snapshot(current_line, nullptr, current_f_name)); + e.st_push(frame->co->src, current_line, nullptr, current_f_name); if(ok) throw HandledException(); else throw UnhandledException();