Prechádzať zdrojové kódy

Let the compiler itself to report current module location on error

Vladislav Folts 4 rokov pred
rodič
commit
8d2ae00f42

BIN
bin/compiled.zip


+ 3 - 2
browser/oberonjs.html

@@ -94,8 +94,9 @@ END test.
                     ? "eberon/eberon_grammar.js"
                     : "oberon/oberon_grammar.js").language;
             var options = {checkIndexes: document.getElementById("checkIndexesOption").checked};
-            result = require("oc.js").compile(
-                    src, 
+            oc = require("oc.js")
+            result = oc.compile(
+                    new oc.ReadModule(src), 
                     language, 
                     function(e){errors += e;},
                     options

+ 4 - 15
src/nodejs.js

@@ -63,8 +63,6 @@ function compile(sources, language, handleErrors, includeDirs, outDir, importDir
     var moduleCode = function(name, imports){
         return new ModuleGenerator(name, imports, importDir);};
 
-    var compiledFilesStack = [];
-    var failToCompile = {};
     return oc.compileModules(
             sources,
             function(name){
@@ -72,12 +70,6 @@ function compile(sources, language, handleErrors, includeDirs, outDir, importDir
                 if (!path.extname(fileName).length)
                     fileName += ".ob";
                 
-                var alreadyFail = failToCompile[fileName];
-                if (alreadyFail)
-                    throw new Errors.Error("'" + fileName + "': error " + alreadyFail);
-
-                compiledFilesStack.push(fileName);
-
                 var readPath = fileName;
                 var i = 0;
                 while (!fs.existsSync(readPath) && i < includeDirs.length){
@@ -86,7 +78,9 @@ function compile(sources, language, handleErrors, includeDirs, outDir, importDir
                 }
                 if (!fs.existsSync(readPath))
                     throw new Error("cannot find file: '" + fileName + "' in " + includeDirs);
-                return fs.readFileSync(readPath, "utf8");
+                return new oc.ReadModule(
+                    fs.readFileSync(readPath, "utf8"),
+                    "File \"" + readPath + "\"");
             },
             language.grammar,
             function(moduleResolver){
@@ -98,18 +92,13 @@ function compile(sources, language, handleErrors, includeDirs, outDir, importDir
                   stdSymbols: language.stdSymbols,
                   moduleResolver: moduleResolver
                 });},
-            function(e){
-                var fileName = compiledFilesStack[compiledFilesStack.length - 1];
-                failToCompile[fileName] = e;
-                handleErrors("File \"" + fileName + "\", " + e);
-            },
+            handleErrors,
             function(name, code){
                 if (rtlCodeWatcher.used()){
                     code = "var " + rtl.name() + " = require(\"" + rtl.module() + "\");\n" + code;
                     rtlCodeWatcher.reset();
                 }
                 writeCompiledModule(name, code, outDir);
-                compiledFilesStack.pop();
             });
 }
 

+ 27 - 15
src/oc.js

@@ -57,14 +57,20 @@ function compileModulesFromText(
         var context = contextFactory(resolveModule);
         var module = compileModule(grammar, stream, context, handleErrors);
         if (!module)
-            return false;
+            return;
         handleCompiledModule(module);
         Lexer.skipSpaces(stream, context);
     }
     while (!Stream.eof(stream));
-    return true;
 }
 
+var ReadModule = Class.extend({
+    init: function Oc$Module(content, location){
+        this.content = content
+        this.location = location
+    }
+});
+
 var ModuleResolver = Class.extend({
     init: function Oc$ModuleResolver(compile, handleCompiledModule, moduleReader, handleErrors){
         this.__modules = {};
@@ -74,23 +80,33 @@ var ModuleResolver = Class.extend({
         this.__handleErrors = handleErrors;
         this.__detectRecursion = [];
     },
-    compile: function(text){
-        return this.__compile(text, this.__resolveModule.bind(this), this.__handleModule.bind(this));
+    compile: function(module){
+        var handleErrors = module.location 
+            ? function(e){
+                this.__handleErrors(module.location + ", " + e)
+              }.bind(this)
+            : this.__handleErrors;
+        this.__compile(module.content,
+                       this.__resolveModule.bind(this),
+                       this.__handleModule.bind(this),
+                       handleErrors);
     },
     __resolveModule: function(name){
-        if (this.__moduleReader && !this.__modules[name]){
+        if (this.__moduleReader && !(name in this.__modules)){
             if (this.__detectRecursion.indexOf(name) != -1){
                 this.__handleErrors("recursive import: " + this.__detectRecursion.join(" -> "));
                 return undefined;
             }
             this.__detectRecursion.push(name);
-
             try {
                 this.compile(this.__moduleReader(name));
             }
             finally {
                 this.__detectRecursion.pop();
             }
+            if (!(name in this.__modules))
+                // failed to compile, do not compile it again
+                this.__modules[name] = undefined;
         }
         return this.__modules[name];
     },
@@ -104,8 +120,8 @@ var ModuleResolver = Class.extend({
 
 function makeResolver(grammar, contextFactory, handleCompiledModule, handleErrors, moduleReader){
     return new ModuleResolver(
-        function(text, resolveModule, handleModule){
-            return compileModulesFromText(
+        function(text, resolveModule, handleModule, handleErrors){
+            compileModulesFromText(
                 text,
                 grammar,
                 contextFactory,
@@ -121,13 +137,8 @@ function makeResolver(grammar, contextFactory, handleCompiledModule, handleError
 
 function compileModules(names, moduleReader, grammar, contextFactory, handleErrors, handleCompiledModule){
     var resolver = makeResolver(grammar, contextFactory, handleCompiledModule, handleErrors, moduleReader);
-    var i = 0;
-    var success = true;
-    while (i < names.length && success){
-        success = resolver.compile(moduleReader(names[i]));
-        ++i;
-    }
-    return success;
+    for(var i in names)
+        resolver.compile(moduleReader(names[i]));
 }
 
 function compile(text, language, handleErrors, options, moduleReader){
@@ -158,6 +169,7 @@ function compile(text, language, handleErrors, options, moduleReader){
     return result;
 }
 
+exports.ReadModule = ReadModule;
 exports.compileModule = compileModule;
 exports.compile = compile;
 exports.compileModules = compileModules;

+ 1 - 1
test/expected/eberon/errors/in_place_variable_has_the_same_scope_as_module_variable.txt

@@ -1 +1 @@
-line 4: 'i' already declared in module scope
+input/eberon/errors/in_place_variable_has_the_same_scope_as_module_variable.ob, line 4: 'i' already declared in module scope

+ 1 - 1
test/expected/errors/compile.txt

@@ -1 +1 @@
-line 2: original module name 'm1' expected, got 'm2'
+input/errors/compile.ob, line 2: original module name 'm1' expected, got 'm2'

+ 1 - 1
test/expected/errors/syntax.txt

@@ -1 +1 @@
-line 5: END expected (MODULE)
+input/errors/syntax.ob, line 5: END expected (MODULE)

+ 10 - 4
test/test_compile.js

@@ -44,10 +44,17 @@ function extractOptions(text){
     return match ? JSON.parse(match[1]) : null;
 }
 
+function readModule(src){
+    var same_path_on_linux_and_win = src.replace(/\\/g, "/");
+    return new oc.ReadModule(fs.readFileSync(src, "utf8"),
+                             same_path_on_linux_and_win);
+}
+
 function compile(src, language){
-    var text = fs.readFileSync(src, "utf8");
+    var module = readModule(src);
     var errors = "";
-    var result = oc.compile(text, language, function(e){errors += e;}, extractOptions(text));
+    var result = oc.compile(module, language, function(e){errors += e;},
+                            extractOptions(module.content));
     if (errors)
         throw new Test.TestError(errors);
     return result;
@@ -77,10 +84,9 @@ function expectOk(src, dirs, grammar){
 }
 
 function expectError(src, dirs, language){
-    var text = fs.readFileSync(src, "utf8");
     var errors = "";
     try {
-        oc.compile(text, language, function(e){errors += e + "\n";});
+        oc.compile(readModule(src), language, function(e){errors += e + "\n";});
     }
     catch (e){
         errors += e;