error.h 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. #pragma once
  2. #include "safestl.h"
  3. class NeedMoreLines {
  4. public:
  5. NeedMoreLines(bool isClassDef) : isClassDef(isClassDef) {}
  6. bool isClassDef;
  7. };
  8. enum CompileMode {
  9. EXEC_MODE,
  10. EVAL_MODE,
  11. SINGLE_MODE, // for REPL
  12. JSON_MODE,
  13. };
  14. struct SourceMetadata {
  15. const char* source;
  16. _Str filename;
  17. std::vector<const char*> lineStarts;
  18. CompileMode mode;
  19. std::pair<const char*,const char*> getLine(int lineno) const {
  20. if(lineno == -1) return {nullptr, nullptr};
  21. lineno -= 1;
  22. if(lineno < 0) lineno = 0;
  23. const char* _start = lineStarts.at(lineno);
  24. const char* i = _start;
  25. while(*i != '\n' && *i != '\0') i++;
  26. return {_start, i};
  27. }
  28. SourceMetadata(const char* source, _Str filename, CompileMode mode) {
  29. source = strdup(source);
  30. // Skip utf8 BOM if there is any.
  31. if (strncmp(source, "\xEF\xBB\xBF", 3) == 0) source += 3;
  32. this->filename = filename;
  33. this->source = source;
  34. lineStarts.push_back(source);
  35. this->mode = mode;
  36. }
  37. _Str snapshot(int lineno, const char* cursor=nullptr){
  38. _StrStream ss;
  39. ss << " " << "File \"" << filename << "\", line " << lineno << '\n';
  40. std::pair<const char*,const char*> pair = getLine(lineno);
  41. _Str line = "<?>";
  42. int removedSpaces = 0;
  43. if(pair.first && pair.second){
  44. line = _Str(pair.first, pair.second-pair.first).__lstrip();
  45. removedSpaces = pair.second - pair.first - line.size();
  46. if(line.empty()) line = "<?>";
  47. }
  48. ss << " " << line << '\n';
  49. if(cursor && line != "<?>" && cursor >= pair.first && cursor <= pair.second){
  50. auto column = cursor - pair.first - removedSpaces;
  51. if(column >= 0){
  52. ss << " " << std::string(column, ' ') << "^\n";
  53. }
  54. }
  55. return ss.str();
  56. }
  57. ~SourceMetadata(){
  58. free((void*)source);
  59. }
  60. };
  61. typedef pkpy::shared_ptr<SourceMetadata> _Source;
  62. class _Error : public std::exception {
  63. private:
  64. _Str _what;
  65. public:
  66. _Error(_Str type, _Str msg, _Str desc){
  67. _what = desc + type + ": " + msg;
  68. }
  69. const char* what() const noexcept override {
  70. return _what.c_str();
  71. }
  72. };
  73. class CompileError : public _Error {
  74. public:
  75. CompileError(_Str type, _Str msg, _Str snapshot)
  76. : _Error(type, msg, snapshot) {}
  77. };
  78. class RuntimeError : public _Error {
  79. private:
  80. static _Str __concat(std::stack<_Str> snapshots){
  81. _StrStream ss;
  82. ss << "Traceback (most recent call last):" << '\n';
  83. while(!snapshots.empty()){
  84. ss << snapshots.top();
  85. snapshots.pop();
  86. }
  87. return ss.str();
  88. }
  89. public:
  90. RuntimeError(_Str type, _Str msg, const std::stack<_Str>& snapshots)
  91. : _Error(type, msg, __concat(snapshots)) {}
  92. };