Sfoglia il codice sorgente

Check array indexes (ARRAY OF CHAR for the start) as an option.

Vladislav Folts 9 anni fa
parent
commit
6ca53472db

BIN
bin/compiled.zip


+ 4 - 2
src/nodejs.js

@@ -3,6 +3,7 @@
 var Class = require("rtl.js").Class;
 var Code = require("js/Code.js");
 var ContextHierarchy = require("js/ContextHierarchy.js");
+var LanguageContext = require("js/LanguageContext.js");
 var oc = require("oc.js");
 var makeRTL = require("rtl_code.js").makeRTL;
 
@@ -80,8 +81,9 @@ function compile(sources, language, handleErrors, includeDirs, outDir, importDir
                 return fs.readFileSync(readPath, "utf8");
             },
             language.grammar,
-            function(moduleResolver){return new ContextHierarchy.Root(
-                { codeGenerator: language.codeGenerator.make(),
+            function(moduleResolver){
+                return new ContextHierarchy.Root(
+                { codeTraits: new LanguageContext.CodeTraits(language.codeGenerator.make()),
                   moduleGenerator: moduleCode,
                   rtl: rtl,
                   types: language.types,

+ 1 - 1
src/ob/ContextDesignator.ob

@@ -136,7 +136,7 @@ BEGIN
 END;
 
 PROCEDURE stringIndexCode*(d: Type): STRING;
-    RETURN d.derefCode + ".charCodeAt(" + Expression.deref(d.indexExpression).code() + ")";
+    RETURN d.root().language().codeTraits.stringIndex(d.derefCode, Expression.deref(d.indexExpression).code());
 END;
 
 PROCEDURE advance*(VAR d: Type; type: Types.PType; info: Types.PId; code, lval: STRING; replace: BOOLEAN);

+ 1 - 1
src/ob/ContextHierarchy.ob

@@ -161,7 +161,7 @@ BEGIN
 END;
 
 PROCEDURE Root.codeGenerator(): CodeGenerator.PIGenerator;
-    RETURN SELF.mLanguage.codeGenerator;
+    RETURN SELF.mLanguage.codeTraits.generator();
 END;
 
 PROCEDURE Root.root(): PRoot;

+ 32 - 1
src/ob/LanguageContext.ob

@@ -27,13 +27,23 @@ TYPE
     END;
     PModuleGenerator* = POINTER TO ModuleGenerator;
 
+    CodeTraits* = RECORD
+        PROCEDURE CodeTraits*(code: CodeGenerator.PIGenerator; rtl: OberonRtl.PType);
+
+        PROCEDURE generator*(): CodeGenerator.PIGenerator;
+        PROCEDURE stringIndex*(e, index: STRING): STRING;
+
+        code: CodeGenerator.PIGenerator;
+        rtl: OberonRtl.PType;
+    END;
+
     Imports = MAP OF STRING;
 
     Language* = RECORD
         moduleResolver-: PROCEDURE(name: STRING): T.PModule;
         PROCEDURE moduleGenerator*(name: STRING; imports: Imports): PModuleGenerator;
         rtl-: OberonRtl.PType;
-        codeGenerator-: CodeGenerator.PIGenerator;
+        codeTraits-: POINTER TO CodeTraits;
         types-: PTypes;
         stdSymbols-: Symbols.Map;
     END;
@@ -51,4 +61,25 @@ PROCEDURE Type.Type(language: PLanguage; cx: Context.PType)
       cx(cx);
 END;
 
+PROCEDURE CodeTraits.CodeTraits(code: CodeGenerator.PIGenerator; rtl: OberonRtl.PType)
+    | code(code),
+      rtl(rtl);
+END;
+
+PROCEDURE CodeTraits.generator(): CodeGenerator.PIGenerator;
+    RETURN SELF.code;
+END;
+
+PROCEDURE CodeTraits.stringIndex(e, index: STRING): STRING;
+VAR
+    r: STRING;
+BEGIN
+    IF SELF.rtl = NIL THEN
+        r := e + ".charCodeAt(" + index + ")";
+    ELSE
+        r := SELF.rtl.charAt(e, index);
+    END; 
+    RETURN r;
+END;
+
 END LanguageContext.

+ 1 - 0
src/ob/OberonRtl.ob

@@ -14,6 +14,7 @@ TYPE
         PROCEDURE makeArray*(dimensions: STRING): STRING;
         PROCEDURE makeCharArray*(dimensions: STRING): STRING;
         PROCEDURE typeGuard*(from, to: STRING): STRING;
+        PROCEDURE charAt*(s, index: STRING): STRING;
     END;
     PType* = POINTER TO Type;
 END OberonRtl.

+ 4 - 2
src/oc.js

@@ -4,6 +4,7 @@ var Class = require("rtl.js").Class;
 var Code = require("js/Code.js");
 var ContextHierarchy = require("js/ContextHierarchy.js");
 var Errors = require("js/Errors.js");
+var LanguageContext = require("js/LanguageContext.js");
 var Lexer = require("js/Lexer.js");
 var makeRTL = require("rtl_code.js").makeRTL;
 var Scope = require("js/Scope.js");
@@ -121,7 +122,7 @@ function compileModules(names, moduleReader, grammar, contextFactory, handleErro
     names.forEach(function(name){ resolver.compile(moduleReader(name)); });
 }
 
-function compile(text, language, handleErrors){
+function compile(text, language, handleErrors, options){
     var result = "";
     var rtl = new makeRTL(language.rtl);
     var moduleCode = function(name, imports){return new Code.ModuleGenerator(name, imports);};
@@ -129,7 +130,8 @@ function compile(text, language, handleErrors){
             language.grammar,
             function(moduleResolver){
                 return new ContextHierarchy.Root(
-                    { codeGenerator: language.codeGenerator.make(),
+                    { codeTraits: new LanguageContext.CodeTraits(language.codeGenerator.make(), 
+                                                                 options && options.checkIndexes ? rtl : null),
                       moduleGenerator: moduleCode,
                       rtl: rtl,
                       types: language.types,

+ 8 - 2
src/rtl.js

@@ -42,10 +42,11 @@ var methods = {
         if (!(from instanceof to)){
             var fromStr;
             var toStr;
+            var scope;
             
             if (from && from.constructor && from.constructor.name){
                 var name = from.constructor.name;
-                var scope = from.$scope;
+                scope = from.$scope;
                 fromStr = scope ? scope + "." + name : name;
             }
             else
@@ -53,7 +54,7 @@ var methods = {
             
             if (to.name){
                 toStr = "" + to.name;
-                var scope = to.prototype.$scope;
+                scope = to.prototype.$scope;
                 toStr = scope ? scope + "." + toStr : toStr;
             }
             else
@@ -66,6 +67,11 @@ var methods = {
         }
         return from;
     },
+    charAt: function(s, index){
+        if (index >= 0 && index < s.length)
+            return s[index];
+        throw new Error("index out of bounds: " + index);
+    },
     makeArray: function(/*dimensions, initializer*/){
         var forward = Array.prototype.slice.call(arguments);
         var result = new Array(forward.shift());

+ 9 - 0
test/expected/check_indexes.js

@@ -0,0 +1,9 @@
+<rtl code>
+var m = function (){
+
+function charArray(a/*ARRAY OF CHAR*/){
+	var c = 0;
+	c = RTL$.charAt(a, 1);
+	c = RTL$.charAt(a, RTL$.charAt(a, 1));
+}
+}();

+ 1 - 0
test/expected/errorsRT/check_indexes.txt

@@ -0,0 +1 @@
+Error: index out of bounds: 0

+ 12 - 0
test/input/check_indexes.ob

@@ -0,0 +1,12 @@
+(*options:{"checkIndexes": true}*)
+MODULE m;
+
+PROCEDURE charArray(a: ARRAY OF CHAR);
+VAR
+	c: CHAR;
+BEGIN
+	c := a[1];
+	c := a[ORD(a[1])]
+END charArray;
+
+END m.

+ 13 - 0
test/input/errorsRT/check_indexes.ob

@@ -0,0 +1,13 @@
+(*options:{"checkIndexes": true}*)
+MODULE m;
+
+PROCEDURE charArray(a: ARRAY OF CHAR);
+VAR
+	c: CHAR;
+BEGIN
+	c := a[0];
+END charArray;
+
+BEGIN
+	charArray("");
+END m.

+ 6 - 1
test/test_compile.js

@@ -39,10 +39,15 @@ function compareResults(result, name, dirs){
         throw new Test.TestError("Failed");
 }
 
+function extractOptions(text){
+    var match = text.match(/\(\*options:({.*})\*\)/);
+    return match ? JSON.parse(match[1]) : null;
+}
+
 function compile(src, language){
     var text = fs.readFileSync(src, "utf8");
     var errors = "";
-    var result = oc.compile(text, language, function(e){errors += e;});
+    var result = oc.compile(text, language, function(e){errors += e;}, extractOptions(text));
     if (errors)
         throw new Test.TestError(errors);
     return result;

+ 2 - 1
test/test_unit_common.js

@@ -6,6 +6,7 @@ var ContextExpression = require("js/ContextExpression.js");
 var ContextHierarchy = require("js/ContextHierarchy.js");
 var ContextType = require("js/ContextType.js");
 var Errors = require("js/Errors.js");
+var LanguageContext = require("js/LanguageContext.js");
 var oc = require("oc.js");
 var makeRTL = require("rtl_code.js").makeRTL;
 var Scope = require("js/Scope.js");
@@ -33,7 +34,7 @@ var TestContextRoot = Class.extend.call(ContextHierarchy.Root, {
         var rtl = new makeRTL(language.rtl);
         ContextHierarchy.Root.call(
                 this,
-                { codeGenerator: language.codeGenerator.nil,
+                { codeTraits: new LanguageContext.CodeTraits(language.codeGenerator.nil),
                   moduleGenerator: function(){return new TestModuleGenerator();},
                   rtl: rtl,
                   types: language.types,