blueloveTH 3 лет назад
Родитель
Сommit
24f3628b8d
5 измененных файлов с 74 добавлено и 71 удалено
  1. 14 7
      src/codeobject.h
  2. 16 28
      src/compiler.h
  3. 36 20
      src/error.h
  4. 6 11
      src/parser.h
  5. 2 5
      src/vm.h

+ 14 - 7
src/codeobject.h

@@ -2,6 +2,7 @@
 
 #include "obj.h"
 #include "pointer.h"
+#include "error.h"
 
 enum Opcode {
     #define OPCODE(name) OP_##name,
@@ -32,12 +33,17 @@ enum CompileMode {
 };
 
 struct CodeObject {
-    CompileMode mode = EXEC_MODE;
-
-    std::vector<ByteCode> co_code;
-    _Str co_filename;
+    _Source src;
     _Str co_name;
+    CompileMode mode;
 
+    CodeObject(_Source src, _Str co_name, CompileMode mode=EXEC_MODE) {
+        this->src = src;
+        this->co_name = co_name;
+        this->mode = mode;
+    }
+
+    std::vector<ByteCode> co_code;
     PyVarList co_consts;
     std::vector<std::shared_ptr<NamePointer>> co_names;
 
@@ -118,9 +124,10 @@ public:
         return code->co_code[ip++];
     }
 
-    int currentLine(){
-        if(isEnd()) return -1;
-        return code->co_code[ip].line;
+    _Str errorSnapshot(){
+        int line = -1;
+        if(!isEnd()) line = code->co_code[ip].line;
+        return code->src->snapshot(line);
     }
 
     int stackSize() const {

+ 16 - 28
src/compiler.h

@@ -61,12 +61,10 @@ public:
         return loops.top();
     }
 
-    Compiler(VM* vm, const char* source, _Code code){
+    Compiler(VM* vm, const char* source, _Str filename, CompileMode mode){
         this->vm = vm;
-        this->codes.push(code);
-        this->mode = code->mode;
-        if (!code->co_filename.empty()) path = code->co_filename;
-        this->parser = std::make_unique<Parser>(source);
+        this->mode = mode;
+        this->parser = std::make_unique<Parser>(filename, source);
 
 // http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/
 #define METHOD(name) &Compiler::name
@@ -340,9 +338,7 @@ public:
         func.name = "<lambda>";
         __compileFunctionArgs(func);
         consume(TK(":"));
-        func.code = std::make_shared<CodeObject>();
-        func.code->co_name = func.name;
-        func.code->co_filename = path;
+        func.code = std::make_shared<CodeObject>(parser->src, func.name);
         this->codes.push(func.code);
         EXPR_TUPLE();
         emitCode(OP_RETURN_VALUE);
@@ -820,9 +816,7 @@ __LISTCOMP:
             consume(TK(")"));
         }
 
-        func.code = std::make_shared<CodeObject>();
-        func.code->co_name = func.name;
-        func.code->co_filename = path;
+        func.code = std::make_shared<CodeObject>(parser->src, func.name);
         this->codes.push(func.code);
         compileBlockBody();
         this->codes.pop();
@@ -853,7 +847,10 @@ __LITERAL_EXIT:
         }
     }
 
-    void __fillCode(){
+    _Code __fillCode(){
+        _Code code = std::make_shared<CodeObject>(parser->src, _Str("<module>"), mode);
+        codes.push(code);
+
         // Lex initial tokens. current <-- next.
         lexToken();
         lexToken();
@@ -862,21 +859,20 @@ __LITERAL_EXIT:
         if(mode == EVAL_MODE) {
             EXPR_TUPLE();
             consume(TK("@eof"));
-            return;
+            return code;
         }
 
         while (!match(TK("@eof"))) {
             compileTopLevelStatement();
             matchNewLines();
         }
+        return code;
     }
 
     /***** Error Reporter *****/
-    LineSnapshot getLineSnapshot(){
-        const char* line_start = parser->line_starts.at(parser->previous.line-1);
-        const char* i = line_start;
-        while(*i != '\n' && *i != '\0') i++;
-        return LineSnapshot(path, parser->previous.line, _Str(line_start, i-line_start));
+    _Str getLineSnapshot(){
+        int lineno = parser->previous.line;
+        return parser->src->snapshot(lineno);
     }
 
     void syntaxError(_Str msg){
@@ -889,14 +885,6 @@ __LITERAL_EXIT:
 };
 
 _Code compile(VM* vm, const char* source, _Str filename, CompileMode mode=EXEC_MODE) {
-    // Skip utf8 BOM if there is any.
-    if (strncmp(source, "\xEF\xBB\xBF", 3) == 0) source += 3;
-
-    _Code code = std::make_shared<CodeObject>();
-    code->co_filename = filename;
-    code->mode = mode;
-
-    Compiler compiler(vm, source, code);
-    compiler.__fillCode();
-    return code;
+    Compiler compiler(vm, source, filename, mode);
+    return compiler.__fillCode();
 }

+ 36 - 20
src/error.h

@@ -12,6 +12,37 @@ public:
     bool isClassDef;
 };
 
+struct SourceMetadata {
+    _Str filename;
+    const char* source;
+    std::vector<const char*> lineStarts;
+
+    _Str getLine(int lineno) const {
+        if(lineno == -1) return "<?>";
+        const char* _start = lineStarts.at(lineno-1);
+        const char* i = _start;
+        while(*i != '\n' && *i != '\0') i++;
+        return _Str(_start, i-_start);
+    }
+
+    SourceMetadata(_Str filename, const char* source) {
+        // Skip utf8 BOM if there is any.
+        if (strncmp(source, "\xEF\xBB\xBF", 3) == 0) source += 3;
+        this->filename = filename;
+        this->source = source;
+        lineStarts.push_back(source);
+    }
+
+    _Str snapshot(int lineno){
+        _StrStream ss;
+        ss << "  " << "File \"" << filename << "\", line " << lineno << '\n';
+        ss << "    " << getLine(lineno) << '\n';
+        return ss.str();
+    }
+};
+
+typedef std::shared_ptr<SourceMetadata> _Source;
+
 class _Error : public std::exception {
 private:
     _Str _what;
@@ -25,40 +56,25 @@ public:
     }
 };
 
-class LineSnapshot {
-    _Str filename;
-    int lineno;
-    _Str source;
-public:
-    LineSnapshot(_Str filename, int lineno, _Str source="<?>") : filename(filename), lineno(lineno), source(source) {}
-
-    _Str str() const {
-        _StrStream ss;
-        ss << "  " << "File \"" << filename << "\", line " << lineno << '\n';
-        ss << "    " << source << '\n';
-        return ss.str();
-    }
-};
-
 class CompileError : public _Error {
 public:
-    CompileError(_Str type, _Str msg, const LineSnapshot& snapshot)
-        : _Error(type, msg, snapshot.str()) {}
+    CompileError(_Str type, _Str msg, _Str snapshot)
+        : _Error(type, msg, snapshot) {}
 };
 
 class RuntimeError : public _Error {
 private:
-    static _Str __concat(std::stack<LineSnapshot> snapshots){
+    static _Str __concat(std::stack<_Str> snapshots){
         _StrStream ss;
         ss << "Traceback (most recent call last):" << '\n';
         while(!snapshots.empty()){
-            ss << snapshots.top().str();
+            ss << snapshots.top();
             snapshots.pop();
         }
         return ss.str();
     }
 public:
-    RuntimeError(_Str type, _Str msg, std::stack<LineSnapshot> snapshots)
+    RuntimeError(_Str type, _Str msg, std::stack<_Str> snapshots)
         : _Error(type, msg, __concat(snapshots)) {}
 };
 

+ 6 - 11
src/parser.h

@@ -84,17 +84,13 @@ enum Precedence {
 
 // The context of the parsing phase for the compiler.
 struct Parser {
-    const char* source;         //< Currently compiled source.
-    const char* token_start;    //< Start of the currently parsed token.
-    const char* current_char;   //< Current char position in the source.
+    _Source src;
 
+    const char* token_start;
+    const char* current_char;
     int current_line = 1;
-
-    std::vector<const char*> line_starts;
-
     Token previous, current;
     std::queue<Token> nexts;
-
     std::stack<int> indents;
 
     Token nextToken(){
@@ -160,7 +156,7 @@ struct Parser {
         current_char++;
         if (c == '\n'){
             current_line++;
-            line_starts.push_back(current_char);
+            src->lineStarts.push_back(current_char);
         }
         return c;
     }
@@ -232,11 +228,10 @@ struct Parser {
         else setNextToken(one);
     }
 
-    Parser(const char* source) {
-        this->source = source;
+    Parser(_Str filename, const char* source) {
+        this->src = std::make_shared<SourceMetadata>(filename, source);
         this->token_start = source;
         this->current_char = source;
-        this->line_starts.push_back(source);
         this->nexts.push(Token{TK("@sof"), token_start, 0, current_line});
         this->indents.push(0);
     }

+ 2 - 5
src/vm.h

@@ -634,13 +634,10 @@ public:
     /***** Error Reporter *****/
 private:
     void _error(const _Str& name, const _Str& msg){
-        std::stack<LineSnapshot> snapshots;
+        std::stack<_Str> snapshots;
         while (!callstack.empty()){
             auto frame = callstack.top();
-            snapshots.push(LineSnapshot(
-                frame->code->co_filename,
-                frame->currentLine()
-            ));
+            snapshots.push(frame->errorSnapshot());
             callstack.pop();
         }
         throw RuntimeError(name, msg, snapshots);