error.h 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. #pragma once
  2. #include "namedict.h"
  3. #include "str.h"
  4. #include "tuplelist.h"
  5. namespace pkpy{
  6. struct NeedMoreLines {
  7. NeedMoreLines(bool is_compiling_class) : is_compiling_class(is_compiling_class) {}
  8. bool is_compiling_class;
  9. };
  10. struct HandledException {};
  11. struct UnhandledException {};
  12. struct ToBeRaisedException {};
  13. enum CompileMode {
  14. EXEC_MODE,
  15. EVAL_MODE,
  16. REPL_MODE,
  17. JSON_MODE,
  18. CELL_MODE
  19. };
  20. struct SourceData {
  21. std::string source;
  22. Str filename;
  23. std::vector<const char*> line_starts;
  24. CompileMode mode;
  25. std::pair<const char*,const char*> get_line(int lineno) const {
  26. if(lineno == -1) return {nullptr, nullptr};
  27. lineno -= 1;
  28. if(lineno < 0) lineno = 0;
  29. const char* _start = line_starts.at(lineno);
  30. const char* i = _start;
  31. while(*i != '\n' && *i != '\0') i++;
  32. return {_start, i};
  33. }
  34. SourceData(const Str& source, const Str& filename, CompileMode mode) {
  35. int index = 0;
  36. // Skip utf8 BOM if there is any.
  37. if (strncmp(source.begin(), "\xEF\xBB\xBF", 3) == 0) index += 3;
  38. // Replace all '\r' with ' '
  39. std::stringstream ss;
  40. while(index < source.length()){
  41. if(source[index] == '\r') ss << ' ';
  42. else ss << source[index];
  43. index++;
  44. }
  45. this->filename = filename;
  46. this->source = ss.str();
  47. line_starts.push_back(this->source.c_str());
  48. this->mode = mode;
  49. }
  50. Str snapshot(int lineno, const char* cursor=nullptr){
  51. std::stringstream ss;
  52. ss << " " << "File \"" << filename << "\", line " << lineno << '\n';
  53. std::pair<const char*,const char*> pair = get_line(lineno);
  54. Str line = "<?>";
  55. int removed_spaces = 0;
  56. if(pair.first && pair.second){
  57. line = Str(pair.first, pair.second-pair.first).lstrip();
  58. removed_spaces = pair.second - pair.first - line.length();
  59. if(line.empty()) line = "<?>";
  60. }
  61. ss << " " << line;
  62. if(cursor && line != "<?>" && cursor >= pair.first && cursor <= pair.second){
  63. auto column = cursor - pair.first - removed_spaces;
  64. if(column >= 0) ss << "\n " << std::string(column, ' ') << "^";
  65. }
  66. return ss.str();
  67. }
  68. };
  69. class Exception {
  70. using StackTrace = stack<Str>;
  71. StrName type;
  72. Str msg;
  73. StackTrace stacktrace;
  74. public:
  75. Exception(StrName type, Str msg): type(type), msg(msg) {}
  76. bool match_type(StrName type) const { return this->type == type;}
  77. bool is_re = true;
  78. void st_push(Str snapshot){
  79. if(stacktrace.size() >= 8) return;
  80. stacktrace.push(snapshot);
  81. }
  82. Str summary() const {
  83. StackTrace st(stacktrace);
  84. std::stringstream ss;
  85. if(is_re) ss << "Traceback (most recent call last):\n";
  86. while(!st.empty()) { ss << st.top() << '\n'; st.pop(); }
  87. if (!msg.empty()) ss << type.sv() << ": " << msg;
  88. else ss << type.sv();
  89. return ss.str();
  90. }
  91. };
  92. } // namespace pkpy