2
0
Vladislav Folts 10 жил өмнө
parent
commit
b25576998b

BIN
bin/compiled.zip


+ 23 - 18
src/context.js

@@ -354,32 +354,37 @@ exports.Designator = ChainedContext.extend({
     handleExpression: function(e){this.__indexExpression = e;},
     __handleIndexExpression: function(){
         var e = this.__indexExpression;
-        var expType = e.type();
-        if (!Type.isInt(expType))
+        this._checkIndexType(e.type());
+        var index = this._indexSequence(this.__info);
+        this._checkIndexValue(index, e.constValue());  
+        return index;
+    },
+    _checkIndexType: function(type){
+        if (!Type.isInt(type))
             throw new Errors.Error(
-                Type.intsDescription() + " expression expected, got '" + expType.description() + "'");
+                Type.intsDescription() + " expression expected, got '" + type.description() + "'");
+    },        
+    _checkIndexValue: function(index, pValue){
+        if (!pValue)
+            return;
 
-        var index = this._indexSequence(this.__currentType, this.__info);
-        var pValue = e.constValue();
-        if (pValue){
-            var value = pValue.value;
-            Code.checkIndex(value);
-            
-            var length = index.length;
-            if ((this.__currentType instanceof Type.StaticArray || this.__currentType instanceof Type.String)
-             && value >= length)
-                throw new Errors.Error("index out of bounds: maximum possible index is "
-                                     + (length - 1)
-                                     + ", got " + value );
-        }
-        return index;
+        var value = pValue.value;
+        Code.checkIndex(value);
+        
+        var length = index.length;
+        if ((this.__currentType instanceof Type.StaticArray || this.__currentType instanceof Type.String)
+         && value >= length)
+            throw new Errors.Error("index out of bounds: maximum possible index is "
+                                 + (length - 1)
+                                 + ", got " + value );
     },
     _advance: function(type, info, code){
         this.__currentType = type;
         this.__info = info;
         this.__code += code;
     },
-    _indexSequence: function(type, info){
+    _indexSequence: function(info){
+        var type = this._currentType();
         var isArray = type instanceof Type.Array;
         if (!isArray && !(type instanceof Type.String))
             throw new Errors.Error("ARRAY or string expected, got '" + type.description() + "'");

+ 21 - 5
src/eberon/eberon_context.js

@@ -193,15 +193,31 @@ var Designator = Context.Designator.extend({
         Context.Designator.prototype.init.call(this, parent);
         this.__procCall = undefined;
     },
-    _indexSequence: function(type, info){
-        if (type == EberonString.string()){
-            var indexType = Type.basic().ch;
+    _checkIndexType: function(type){
+        if (this._currentType() instanceof EberonMap.Type){
+            if (type != EberonString.string() && !Type.isString(type))
+                throw new Errors.Error("invalid MAP index: STRING or string literal or ARRAY OF CHAR expected, got '" + type.description() + "'");            
+            return;
+        }
+        return Context.Designator.prototype._checkIndexType.call(this, type);
+    },
+    _indexSequence: function(info){
+        var currentType = this._currentType();
+        if (currentType == EberonString.string())
+            return { length: undefined, 
+                     type: Type.basic().ch,
+                     info: EberonString.makeElementVariable()
+                   };
+
+        if (currentType instanceof EberonMap.Type){
+            var indexType = currentType.valueType;
             return { length: undefined, 
                      type: indexType,
-                     info: EberonString.makeElementVariable(indexType)
+                     info: Type.makeVariable(indexType, info.isReadOnly())
                    };
         }
-        return Context.Designator.prototype._indexSequence.call(this, type, info);
+        
+        return Context.Designator.prototype._indexSequence.call(this, info);
     },
     _makeDerefVar: function(info){
         if (info instanceof TypeNarrowVariable)

+ 48 - 0
test/expected/eberon/map.js

@@ -2,6 +2,45 @@ var RTL$ = {
     assert: function (condition){
         if (!condition)
             throw new Error("assertion failed");
+    },
+    makeCharArray: function (/*dimensions*/){
+        var forward = Array.prototype.slice.call(arguments);
+        var length = forward.pop();
+
+        if (!forward.length)
+            return this.__makeCharArray(length);
+
+        function makeArray(){
+            var forward = Array.prototype.slice.call(arguments);
+            var result = new Array(forward.shift());
+            var i;
+            if (forward.length == 1){
+                var init = forward[0];
+                for(i = 0; i < result.length; ++i)
+                    result[i] = init();
+            }
+            else
+                for(i = 0; i < result.length; ++i)
+                    result[i] = makeArray.apply(undefined, forward);
+            return result;
+        }
+
+        forward.push(this.__makeCharArray.bind(this, length));
+        return makeArray.apply(undefined, forward);
+    },
+    __makeCharArray: function (length){
+        var result = new Uint16Array(length);
+        this.__setupCharArrayMethods(result);
+        return result;
+    },
+    __setupCharArrayMethods: function (a){
+        var rtl = this;
+        a.charCodeAt = function(i){return this[i];};
+        a.slice = function(){
+            var result = Array.prototype.slice.apply(this, arguments);
+            rtl.__setupCharArrayMethods(result);
+            return result;
+        };
     }
 };
 var test = function (){
@@ -14,4 +53,13 @@ function ForEach(){
 		RTL$.assert(k != "");
 	}
 }
+
+function put(){
+	var s = '';
+	var a = RTL$.makeCharArray(3);
+	m["a"] = 1;
+	m["abc"] = 2;
+	m[s] = 3;
+	m[a] = 4;
+}
 }();

+ 11 - 0
test/input/eberon/map.ob

@@ -10,4 +10,15 @@ BEGIN
     END;
 END;
 
+PROCEDURE put();
+VAR
+    s: STRING;
+    a: ARRAY 3 OF CHAR;
+BEGIN
+    m["a"] := 1;
+    m["abc"] := 2;
+    m[s] := 3;
+    m[a] := 4;
+END;
+
 END test.

+ 17 - 0
test/test_unit_eberon.js

@@ -1333,6 +1333,7 @@ exports.suite = {
              "TYPE M = MAP OF RECORD END;",
              "TYPE M = MAP OF POINTER TO RECORD END;",
              "TYPE M = MAP OF MAP OF INTEGER;",
+             "TYPE M = MAP OF ARRAY * OF INTEGER;",
              "TYPE M = MAP OF M;",
              "TYPE T = RECORD field: MAP OF T; END;",
              "VAR v: MAP OF SET;"
@@ -1342,6 +1343,22 @@ exports.suite = {
              ["VAR MAP: INTEGER;", "not parsed"]
             )
         ),
+    "put": testWithContext(
+        context(grammar.statement,
+                "VAR m: MAP OF INTEGER;"
+                + "sIndex: STRING; aIndex: ARRAY 3 OF CHAR;"),
+        pass("m[\"abc\"] := 123",
+             "m[sIndex] := 123",
+             "m[aIndex] := 123"
+            ),
+        fail(["m[123] := 123", "invalid MAP index: STRING or string literal or ARRAY OF CHAR expected, got 'INTEGER'"])
+        ),
+    "non-VAR parameter": testWithContext(
+        context(grammar.declarationSequence,
+                "TYPE M = MAP OF INTEGER;"),
+        pass(),
+        fail(["PROCEDURE p(m: M); BEGIN m[\"abc\"] := 123; END;", "cannot assign to read-only variable"])
+        ),
     "FOREACH": testWithContext(
         context(grammar.statement,
                 "TYPE T = RECORD END;"