소스 검색

get from MAP

Vladislav Folts 10 년 전
부모
커밋
991c58245e
11개의 변경된 파일143개의 추가작업 그리고 25개의 파일을 삭제
  1. BIN
      bin/compiled.zip
  2. 26 18
      src/context.js
  3. 7 4
      src/eberon/eberon_context.js
  4. 8 0
      src/rtl.js
  5. 3 0
      test/expected/blur.js
  6. 42 1
      test/expected/eberon/map.js
  7. 3 0
      test/expected/len.js
  8. 3 0
      test/expected/string.js
  9. 27 2
      test/input/eberon/map.ob
  10. 14 0
      test/input/eberon/run/map.ob
  11. 10 0
      test/test_unit_eberon.js

BIN
bin/compiled.zip


+ 26 - 18
src/context.js

@@ -335,14 +335,13 @@ exports.Designator = ChainedContext.extend({
             isReadOnly = false;
         }
         var field = t.denote(id);
-        this.__currentType = field.type();
+        var currentType = field.type();
         this.__derefCode = this.__code;
-        var codeId = this.__currentType instanceof Type.Procedure 
-                 ? this.__currentType.designatorCode(id)
-                 : Type.mangleField(id, this.__currentType);
+        var codeId = currentType instanceof Type.Procedure 
+                 ? currentType.designatorCode(id)
+                 : Type.mangleField(id, currentType);
         this.__propCode = "\"" + codeId + "\"";
-        this.__info = field.asVar(isReadOnly, this);
-        this.__code += "." + codeId;
+        this._advance(currentType, field.asVar(isReadOnly, this), "." + codeId);
         this.__scope = undefined;
     },
     _currentType: function(){return this.__currentType;},
@@ -355,7 +354,7 @@ exports.Designator = ChainedContext.extend({
     __handleIndexExpression: function(){
         var e = this.__indexExpression;
         this._checkIndexType(e.type());
-        var index = this._indexSequence(this.__info);
+        var index = this._indexSequence(this.__info, this.__derefCode, Code.derefExpression(e).code());
         this._checkIndexValue(index, e.constValue());  
         return index;
     },
@@ -378,12 +377,13 @@ exports.Designator = ChainedContext.extend({
                                  + (length - 1)
                                  + ", got " + value );
     },
-    _advance: function(type, info, code){
+    _advance: function(type, info, code, lval){
         this.__currentType = type;
         this.__info = info;
         this.__code += code;
+        this.__lval = lval;
     },
-    _indexSequence: function(info){
+    _indexSequence: function(info, code, indexCode){
         var type = this._currentType();
         var isArray = type instanceof Type.Array;
         if (!isArray && !(type instanceof Type.String))
@@ -395,22 +395,30 @@ exports.Designator = ChainedContext.extend({
         if (!isArray && !length)
             throw new Errors.Error("cannot index empty string" );
         var indexType = isArray ? Type.arrayElementsType(type) : basicTypes.ch;
+
+        code = code + "[" + indexCode + "]";
+        var lval;
+        if (indexType == basicTypes.ch){
+            lval = code;
+            code = this._stringIndexCode();
+        }
+
         return { length: length,
                  type: indexType,
-                 info: Type.makeVariable(indexType, info instanceof Type.Const || info.isReadOnly())
+                 info: Type.makeVariable(indexType, info instanceof Type.Const || info.isReadOnly()),
+                 code: code,
+                 lval: lval,
+                 asProperty: indexCode
                };
     },
+    _stringIndexCode: function(){
+        return this.__derefCode + ".charCodeAt(" + Code.derefExpression(this.__indexExpression).code() + ")";
+    },
     handleLiteral: function(s){
         if (s == "]" || s == ","){
             var index = this.__handleIndexExpression();
-            var indexCode = Code.derefExpression(this.__indexExpression).code();
-            this.__propCode = indexCode;
-            var code = this.__derefCode + "[" + indexCode + "]";
-            if (index.type == basicTypes.ch){
-                this.__lval = code;
-                code = this.__derefCode + ".charCodeAt(" + indexCode + ")";
-            }
-            this._advance(index.type, index.info, this.__code + code);
+            this.__propCode = index.asProperty;
+            this._advance(index.type, index.info, this.__code + index.code, index.lval);
         }
         if (s == "[" || s == ","){
             this.__derefCode = this.__code;

+ 7 - 4
src/eberon/eberon_context.js

@@ -201,23 +201,26 @@ var Designator = Context.Designator.extend({
         }
         return Context.Designator.prototype._checkIndexType.call(this, type);
     },
-    _indexSequence: function(info){
+    _indexSequence: function(info, code, indexCode){
         var currentType = this._currentType();
         if (currentType == EberonString.string())
             return { length: undefined, 
                      type: Type.basic().ch,
-                     info: EberonString.makeElementVariable()
+                     info: EberonString.makeElementVariable(),
+                     code: this._stringIndexCode()
                    };
 
         if (currentType instanceof EberonMap.Type){
             var indexType = currentType.valueType;
             return { length: undefined, 
                      type: indexType,
-                     info: Type.makeVariable(indexType, info.isReadOnly())
+                     info: Type.makeVariable(indexType, info.isReadOnly()),
+                     code: this.language().rtl.getMappedValue(code, indexCode),
+                     lval: code + "[" + indexCode + "]"
                    };
         }
         
-        return Context.Designator.prototype._indexSequence.call(this, info);
+        return Context.Designator.prototype._indexSequence.call(this, info, code, indexCode);
     },
     _makeDerefVar: function(info){
         if (info instanceof TypeNarrowVariable)

+ 8 - 0
src/rtl.js

@@ -55,6 +55,11 @@ var impl = {
         }
         return from;
     },
+    getMappedValue: function(map, key){
+        if (!map.hasOwnProperty(key))
+            throw new Error("invalid key: " + key);
+        return map[key];
+    },
     makeArray: function(/*dimensions, initializer*/){
         var forward = Array.prototype.slice.call(arguments);
         var result = new Array(forward.shift());
@@ -81,6 +86,9 @@ var impl = {
             rtl.__setupCharArrayMethods(result);
             return result;
         };
+        a.toString = function(){
+            return String.fromCharCode.apply(this, this);
+        };
     },
     __makeCharArray: function(length){
         var result = new Uint16Array(length);

+ 3 - 0
test/expected/blur.js

@@ -37,6 +37,9 @@ var RTL$ = {
             rtl.__setupCharArrayMethods(result);
             return result;
         };
+        a.toString = function(){
+            return String.fromCharCode.apply(this, this);
+        };
     }
 };
 var Blur = function (){

+ 42 - 1
test/expected/eberon/map.js

@@ -41,12 +41,33 @@ var RTL$ = {
             rtl.__setupCharArrayMethods(result);
             return result;
         };
+        a.toString = function(){
+            return String.fromCharCode.apply(this, this);
+        };
+    },
+    getMappedValue: function (map, key){
+        if (!map.hasOwnProperty(key))
+            throw new Error("invalid key: " + key);
+        return map[key];
+    },
+    copyRecord: function (from, to){
+        for(var prop in to){
+            if (to.hasOwnProperty(prop)){
+                var v = from[prop];
+                var isScalar = prop[0] != "$";
+                if (isScalar)
+                    to[prop] = v;
+                else
+                    to[prop] = v instanceof Array ? this.cloneArrayOfRecords(v)
+                                                  : this.cloneRecord(v);
+            }
+        }
     }
 };
 var test = function (){
-var m = {};
 
 function ForEach(){
+	var m = {};
 	for(var k in m){
 		var v = m[k];
 		RTL$.assert(v == 0);
@@ -55,11 +76,31 @@ function ForEach(){
 }
 
 function put(){
+	function T(){
+		this.field = 0;
+	}
+	var m = {};
 	var s = '';
 	var a = RTL$.makeCharArray(3);
+	var mapOfMap = {};
+	var mapOfRecord = {};
+	var mapOfPointer = {};
 	m["a"] = 1;
 	m["abc"] = 2;
 	m[s] = 3;
 	m[a] = 4;
+	RTL$.getMappedValue(mapOfMap, "abc")["cde"] = 5;
+	RTL$.getMappedValue(mapOfRecord, "abc").field = 6;
+	RTL$.copyRecord(new T(), RTL$.getMappedValue(mapOfPointer, "abc"));
+}
+
+function get(){
+	var m = {};
+	var s = '';
+	var a = RTL$.makeCharArray(3);
+	RTL$.assert(RTL$.getMappedValue(m, "a") == 1);
+	RTL$.assert(RTL$.getMappedValue(m, "abc") == 2);
+	RTL$.assert(RTL$.getMappedValue(m, s) == 3);
+	RTL$.assert(RTL$.getMappedValue(m, a) == 4);
 }
 }();

+ 3 - 0
test/expected/len.js

@@ -55,6 +55,9 @@ var RTL$ = {
             rtl.__setupCharArrayMethods(result);
             return result;
         };
+        a.toString = function(){
+            return String.fromCharCode.apply(this, this);
+        };
     },
     assert: function (condition){
         if (!condition)

+ 3 - 0
test/expected/string.js

@@ -37,6 +37,9 @@ var RTL$ = {
             rtl.__setupCharArrayMethods(result);
             return result;
         };
+        a.toString = function(){
+            return String.fromCharCode.apply(this, this);
+        };
     },
     assignArrayFromString: function (a, s){
         var i;

+ 27 - 2
test/input/eberon/map.ob

@@ -1,8 +1,10 @@
 MODULE test;
-VAR
-    m: MAP OF INTEGER;
+TYPE
+    MapOfInteger = MAP OF INTEGER;
 
 PROCEDURE ForEach();
+VAR
+    m: MapOfInteger;
 BEGIN
     FOREACH v, k IN m DO
         ASSERT(v = 0);
@@ -11,14 +13,37 @@ BEGIN
 END;
 
 PROCEDURE put();
+TYPE
+    T = RECORD 
+        field: INTEGER;
+    END;
 VAR
+    m: MapOfInteger;
     s: STRING;
     a: ARRAY 3 OF CHAR;
+    mapOfMap: MAP OF MapOfInteger;
+    mapOfRecord: MAP OF T;
+    mapOfPointer: MAP OF POINTER TO T;
 BEGIN
     m["a"] := 1;
     m["abc"] := 2;
     m[s] := 3;
     m[a] := 4;
+    mapOfMap["abc"]["cde"] := 5;
+    mapOfRecord["abc"].field := 6;
+    mapOfPointer["abc"]^ := T();
+END;
+
+PROCEDURE get();
+VAR
+    m: MapOfInteger;
+    s: STRING;
+    a: ARRAY 3 OF CHAR;
+BEGIN
+    ASSERT(m["a"] = 1);
+    ASSERT(m["abc"] = 2);
+    ASSERT(m[s] = 3);
+    ASSERT(m[a] = 4);
 END;
 
 END test.

+ 14 - 0
test/input/eberon/run/map.ob

@@ -9,6 +9,20 @@ BEGIN
     END;
 END;
 
+PROCEDURE testPutGet();
+VAR
+    m: MAP OF INTEGER;
+    a: ARRAY 3 OF CHAR;
+BEGIN
+    m["abc"] := 1;
+    m["cde"] := 2;
+    ASSERT(m["abc"] = 1);
+    ASSERT(m["cde"] = 2);
+    a := "abc";
+    ASSERT(m[a] = 1);
+END;
+
 BEGIN
     testEmptyForEach();
+    testPutGet();
 END test.

+ 10 - 0
test/test_unit_eberon.js

@@ -1353,6 +1353,16 @@ exports.suite = {
             ),
         fail(["m[123] := 123", "invalid MAP index: STRING or string literal or ARRAY OF CHAR expected, got 'INTEGER'"])
         ),
+    "get": testWithContext(
+        context(grammar.expression,
+                "VAR m: MAP OF INTEGER;"
+                + "sIndex: STRING; aIndex: ARRAY 3 OF CHAR;"),
+        pass("m[\"abc\"]",
+             "m[sIndex]",
+             "m[aIndex]"
+            ),
+        fail(["m[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;"),