2
0
Эх сурвалжийг харах

fix in place variables initialized with array

Vladislav Folts 11 жил өмнө
parent
commit
8d6aae0579

BIN
bin/compiled.zip


+ 1 - 1
doc/wiki/eberon-in-place-variables.md

@@ -16,7 +16,7 @@ variable will have type INTEGER. In the following example the variable will have
 
 Although the type is not specified explicitly a variable is still statically typed (its type cannot be changed) with deduced type in the same way as a regular variable (declared in VAR section).
 
-*In place* variable behaves in the same way as a regular variable (declared in VAR section). It can be reassigned or passed as a VAR parameter to procedure. When variable is initialized with a record type - it will be copied as if variable of this record type was declared in VAR section and then assigned to another variable of record type.
+*In place* variable behaves in the same way as a regular variable (declared in VAR section). It can be reassigned or passed as a VAR parameter to procedure. When variable is initialized with a record type - it will be copied as if variable of this record type was declared in VAR section and then assigned to another variable of record type. When variable is initialized with an array type - array will be copied. *In place* variable cannot be initialized with open array because its full type (including size) is unknown.
 
     PROCEDURE p(a1: SomeRecord; VAR a2: SomeRecord);
     BEGIN

+ 7 - 1
src/eberon/eberon_context.js

@@ -261,8 +261,14 @@ var TemplValueInit = Context.Chained.extend({
     handleExpression: function(e){
         var v = new TempVariable(e);
         this.__symbol = Symbol.makeSymbol(this.__id, v);
-        if (e.type() instanceof Type.Record)
+        var type = e.type();
+        if (type instanceof Type.Record)
             this.__code += this.language().rtl.clone(e.code());
+        else if (type instanceof Type.Array){
+            if (Type.arrayLength(type) == Type.openArrayLength)
+                throw new Errors.Error("cannot initialize variable '" + this.__id + "' with open array");
+            this.__code += this.language().rtl.clone(e.code());
+        }
         else
             this.__code += Code.derefExpression(e).code();
     },

+ 39 - 11
src/rtl.js

@@ -68,18 +68,17 @@ var impl = {
                 result[i] = this.makeArray.apply(this, forward);
         return result;
     },
+    __makeCharArray: function(length){
+        var result = new Uint16Array(length);
+        result.charCodeAt = function(i){return this[i];};
+        return result;
+    },
     makeCharArray: function(/*dimensions*/){
         var forward = Array.prototype.slice.call(arguments);
         var length = forward.pop();
 
         if (!forward.length)
-            return makeCharArray(length);
-
-        function makeCharArray(length){
-            var result = new Uint16Array(length);
-            result.charCodeAt = function(i){return this[i];};
-            return result;
-        }
+            return this.__makeCharArray(length);
 
         function makeArray(){
             var forward = Array.prototype.slice.call(arguments);
@@ -96,7 +95,7 @@ var impl = {
             return result;
         }
 
-        forward.push(makeCharArray.bind(undefined, length));
+        forward.push(this.__makeCharArray.bind(undefined, length));
         return makeArray.apply(undefined, forward);
     },
     makeSet: function(/*...*/){
@@ -161,8 +160,34 @@ var impl = {
         }
     },
     clone: function(from){
-        var to = new from.constructor();
-        this.copy(from, to);
+        var to;
+        var len;
+        var i;
+        var Ctr = from.constructor;
+        if (Ctr == Uint16Array){
+            len = from.length;
+            to = this.__makeCharArray(len);
+            for(i = 0; i < len; ++i)
+                to[i] = from[i];
+        }
+        else {
+            to = new Ctr();
+            if (Ctr == Array)
+                len = from.length;
+                if (len){
+                    if (typeof from[0] != "object")
+                        for(i = 0; i < len; ++i)
+                            to[i] = from[i];
+                    else
+                        for(i = 0; i < len; ++i){
+                            var o = from[i];
+                            if (o !== null)
+                                to[i] = this.clone(o);
+                        }
+                }
+            else
+                this.copy(from, to);
+        }
         return to;
     },
     assert: function(condition){
@@ -172,7 +197,10 @@ var impl = {
 };
 
 exports.Class = Class;
-exports.dependencies = { "clone": ["copy"] };
+exports.dependencies = { 
+    "clone": ["copy", "__makeCharArray"] ,
+    "makeCharArray": ["__makeCharArray"]
+};
 
 for(var e in impl)
     exports[e] = impl[e];

+ 7 - 8
test/expected/blur.js

@@ -4,13 +4,7 @@ var RTL$ = {
         var length = forward.pop();
 
         if (!forward.length)
-            return makeCharArray(length);
-
-        function makeCharArray(length){
-            var result = new Uint16Array(length);
-            result.charCodeAt = function(i){return this[i];};
-            return result;
-        }
+            return this.__makeCharArray(length);
 
         function makeArray(){
             var forward = Array.prototype.slice.call(arguments);
@@ -27,8 +21,13 @@ var RTL$ = {
             return result;
         }
 
-        forward.push(makeCharArray.bind(undefined, length));
+        forward.push(this.__makeCharArray.bind(undefined, length));
         return makeArray.apply(undefined, forward);
+    },
+    __makeCharArray: function (length){
+        var result = new Uint16Array(length);
+        result.charCodeAt = function(i){return this[i];};
+        return result;
     }
 };
 var Blur = function (){

+ 57 - 4
test/expected/eberon/in_place_variables.js

@@ -13,9 +13,53 @@ var RTL$ = {
         result.extend = extend;
         return result;
     },
+    makeArray: function (/*dimensions, initializer*/){
+        var forward = Array.prototype.slice.call(arguments);
+        var result = new Array(forward.shift());
+        var i;
+        if (forward.length == 1){
+            var init = forward[0];
+            if (typeof init == "function")
+                for(i = 0; i < result.length; ++i)
+                    result[i] = init();
+            else
+                for(i = 0; i < result.length; ++i)
+                    result[i] = init;
+        }
+        else
+            for(i = 0; i < result.length; ++i)
+                result[i] = this.makeArray.apply(this, forward);
+        return result;
+    },
     clone: function (from){
-        var to = new from.constructor();
-        this.copy(from, to);
+        var to;
+        var len;
+        var i;
+        var Ctr = from.constructor;
+        if (Ctr == Uint16Array){
+            len = from.length;
+            to = this.__makeCharArray(len);
+            for(i = 0; i < len; ++i)
+                to[i] = from[i];
+        }
+        else {
+            to = new Ctr();
+            if (Ctr == Array)
+                len = from.length;
+                if (len){
+                    if (typeof from[0] != "object")
+                        for(i = 0; i < len; ++i)
+                            to[i] = from[i];
+                    else
+                        for(i = 0; i < len; ++i){
+                            var o = from[i];
+                            if (o !== null)
+                                to[i] = this.clone(o);
+                        }
+                }
+            else
+                this.copy(from, to);
+        }
         return to;
     },
     copy: function (from, to){
@@ -28,6 +72,11 @@ var RTL$ = {
                     to[prop] = v;
             }
         }
+    },
+    __makeCharArray: function (length){
+        var result = new Uint16Array(length);
+        result.charCodeAt = function(i){return this[i];};
+        return result;
     }
 };
 var m = function (){
@@ -37,6 +86,7 @@ var T = RTL$.extend({
 });
 var r = new T();
 var i = 0;
+var a = RTL$.makeArray(10, 0);
 
 function p(){
 	return false;
@@ -45,14 +95,16 @@ function p(){
 function void$(){
 }
 
-function valueArgs(r/*T*/, i/*INTEGER*/){
+function valueArgs(r/*T*/, i/*INTEGER*/, a/*ARRAY 10 OF INTEGER*/){
 	var v1 = RTL$.clone(r);
 	var v2 = i;
+	var v3 = RTL$.clone(a);
 }
 
-function varArgs(r/*VAR T*/, i/*VAR INTEGER*/){
+function varArgs(r/*VAR T*/, i/*VAR INTEGER*/, a/*ARRAY 10 OF INTEGER*/){
 	var v1 = RTL$.clone(r);
 	var v2 = i.get();
+	var v3 = RTL$.clone(a);
 }
 var v1 = 0;
 var v2 = 1.23;
@@ -64,4 +116,5 @@ var v7 = p();
 var v8 = void$;
 var do$ = 0;
 var tempRecord = RTL$.clone(r);
+var tempArray = RTL$.clone(a);
 }();

+ 7 - 8
test/expected/len.js

@@ -22,13 +22,7 @@ var RTL$ = {
         var length = forward.pop();
 
         if (!forward.length)
-            return makeCharArray(length);
-
-        function makeCharArray(length){
-            var result = new Uint16Array(length);
-            result.charCodeAt = function(i){return this[i];};
-            return result;
-        }
+            return this.__makeCharArray(length);
 
         function makeArray(){
             var forward = Array.prototype.slice.call(arguments);
@@ -45,9 +39,14 @@ var RTL$ = {
             return result;
         }
 
-        forward.push(makeCharArray.bind(undefined, length));
+        forward.push(this.__makeCharArray.bind(undefined, length));
         return makeArray.apply(undefined, forward);
     },
+    __makeCharArray: function (length){
+        var result = new Uint16Array(length);
+        result.charCodeAt = function(i){return this[i];};
+        return result;
+    },
     assert: function (condition){
         if (!condition)
             throw new Error("assertion failed");

+ 7 - 8
test/expected/string.js

@@ -4,13 +4,7 @@ var RTL$ = {
         var length = forward.pop();
 
         if (!forward.length)
-            return makeCharArray(length);
-
-        function makeCharArray(length){
-            var result = new Uint16Array(length);
-            result.charCodeAt = function(i){return this[i];};
-            return result;
-        }
+            return this.__makeCharArray(length);
 
         function makeArray(){
             var forward = Array.prototype.slice.call(arguments);
@@ -27,9 +21,14 @@ var RTL$ = {
             return result;
         }
 
-        forward.push(makeCharArray.bind(undefined, length));
+        forward.push(this.__makeCharArray.bind(undefined, length));
         return makeArray.apply(undefined, forward);
     },
+    __makeCharArray: function (length){
+        var result = new Uint16Array(length);
+        result.charCodeAt = function(i){return this[i];};
+        return result;
+    },
     assignArrayFromString: function (a, s){
         var i;
         for(i = 0; i < s.length; ++i)

+ 7 - 2
test/input/eberon/in_place_variables.ob

@@ -3,10 +3,12 @@ MODULE m;
 TYPE
     T = RECORD
     END;
+    A = ARRAY 10 OF INTEGER;
 
 VAR 
     r: T;
     i: INTEGER;
+    a: A;
 
 PROCEDURE p(): BOOLEAN; 
     RETURN FALSE
@@ -15,16 +17,18 @@ END p;
 PROCEDURE void();
 END void;
 
-PROCEDURE valueArgs(r: T; i: INTEGER);
+PROCEDURE valueArgs(r: T; i: INTEGER; a: A);
 BEGIN
     v1 <- r;
     v2 <- i;
+    v3 <- a;
 END valueArgs;
 
-PROCEDURE varArgs(VAR r: T; VAR i: INTEGER);
+PROCEDURE varArgs(VAR r: T; VAR i: INTEGER; a: A);
 BEGIN
     v1 <- r;
     v2 <- i;
+    v3 <- a;
 END varArgs;
 
 BEGIN
@@ -39,4 +43,5 @@ BEGIN
     do <- {};
 
     tempRecord <- r;
+    tempArray <- a;
 END m.

+ 13 - 1
test/input/eberon/run/clone.ob

@@ -6,9 +6,21 @@ TYPE
 
 VAR
     r: T;
-
+    a: ARRAY 2 OF BOOLEAN;
+    charArray: ARRAY 2 OF CHAR;
 BEGIN
     r.b := TRUE;
     temp <- r;
 	ASSERT(temp.b);
+
+    a[0] := TRUE;
+    tempA <- a;
+    ASSERT(tempA[0]);
+    ASSERT(~tempA[1]);
+
+    charArray[0] := "a";
+    charArray[1] := "b";
+    tempCharArray <- charArray;
+    ASSERT(tempCharArray[0] = "a");
+    ASSERT(tempCharArray[1] = "b");
 END m.

+ 16 - 0
test/test_unit_eberon.js

@@ -561,7 +561,23 @@ exports.suite = {
                ["PROCEDURE p(b: Base); BEGIN base <- b; ASSERT(base IS Derived); END p;",
                 "invalid type test: a value variable cannot be used"]
               )
+      ),
+    "arrays as values": testWithContext(
+          context(grammar.declarationSequence,
+                "TYPE A = ARRAY 3 OF INTEGER; T = RECORD a: A END;"
+                + "VAR r: T;"
+                + "PROCEDURE procArrayVar(VAR a: A); END procArrayVar;"
+               ),
+          pass("PROCEDURE p(r: T); BEGIN a <- r.a; a[0] := 123; procArrayVar(a); END p;",
+               "PROCEDURE p(a: A); BEGIN tmp <- a; END p;",
+               "PROCEDURE p(); VAR a: A; BEGIN tmp <- a; END p;",
+               "PROCEDURE p(); VAR a: ARRAY 3 OF BOOLEAN; BEGIN tmp <- a; END p;"
+               ),
+          fail(["PROCEDURE p(a: ARRAY OF INTEGER); BEGIN v <- a; END p;",
+                "cannot initialize variable 'v' with open array"]
+              )
       )/*
+      /*
     "as references": testWithContext(
           context(grammar.declarationSequence,
                 "TYPE Base = RECORD pBase: POINTER TO Base END; Derived = RECORD (Base) END;"