Pārlūkot izejas kodu

in place record variables are cloned from initializers

Vladislav Folts 11 gadi atpakaļ
vecāks
revīzija
a0f60594fa

BIN
bin/compiled.zip


+ 11 - 3
src/eberon/eberon_context.js

@@ -130,6 +130,7 @@ var TempVariable = Type.Variable.extend({
         this.__type = e.type();
         this.__invertedType = this.__type;
 
+        /*
         this.__isRef = false;
         var d = e.designator();
         if (d) {
@@ -137,12 +138,13 @@ var TempVariable = Type.Variable.extend({
             if (v instanceof Type.Variable)
                 this.__isRef = v.isReference();
         }
+        */
     },
     type: function(){
         return this.__type;
     },
     isReference: function(){
-        return this.__isRef;
+        return false;
     },
     //idType: function(){return "temporary variable";},
     promoteType: function(t){
@@ -247,23 +249,29 @@ var TemplValueInit = Context.Chained.extend({
         Context.Chained.prototype.init.call(this, context);
         this.__id = undefined;
         this.__symbol = undefined;
+        this.__code = undefined;
     },
+    codeGenerator: function(){return Code.nullGenerator();},
     handleIdent: function(id){
         this.__id = id;
     },
     handleLiteral: function(){
-        var gen = this.codeGenerator();
-        gen.write("var " + this.__id + " = ");
+        this.__code = "var " + this.__id + " = ";
     },
     handleExpression: function(e){
         var v = new TempVariable(e);
         this.__symbol = Symbol.makeSymbol(this.__id, v);
+        if (e.type() instanceof Type.Record)
+            this.__code += this.language().rtl.clone(e.code());
+        else
+            this.__code += Code.derefExpression(e).code();
     },
     endParse: function(){
         if (!this.__symbol)
             return false;
 
         this.currentScope().addSymbol(this.__symbol);
+        this.parent().codeGenerator().write(this.__code);
         return true;
     }
 });

+ 7 - 0
src/rtl.js

@@ -160,6 +160,11 @@ var impl = {
             }
         }
     },
+    clone: function(from){
+        var to = new from.constructor();
+        this.copy(from, to);
+        return to;
+    },
     assert: function(condition){
         if (!condition)
             throw new Error("assertion failed");
@@ -167,5 +172,7 @@ var impl = {
 };
 
 exports.Class = Class;
+exports.dependencies = { "clone": ["copy"] };
+
 for(var e in impl)
     exports[e] = impl[e];

+ 9 - 0
src/rtl_code.js

@@ -55,6 +55,15 @@ exports.RTL = Rtl.Class.extend({
                 this.__demandedCallback();
             if (!this.__entries[name])
                 this.__entries[name] = Rtl[name];
+            
+            var dependencies = Rtl.dependencies[name];
+            if (dependencies)
+                for(var i = 0; i < dependencies.length; ++i){
+                    var d = dependencies[i];
+                    if (!this.__entries[d])
+                        this.__entries[d] = Rtl[d];
+                }
+
             return this.name() + "." + name;
         };
     },

+ 20 - 4
test/expected/eberon/temporary_value.js → test/expected/eberon/in_place_variables.js

@@ -12,6 +12,22 @@ var RTL$ = {
         
         result.extend = extend;
         return result;
+    },
+    clone: function (from){
+        var to = new from.constructor();
+        this.copy(from, to);
+        return to;
+    },
+    copy: function (from, to){
+        for(var prop in to){
+            if (to.hasOwnProperty(prop)){
+                var v = from[prop];
+                if (v !== null && typeof v == "object")
+                    this.copy(v, to[prop]);
+                else
+                    to[prop] = v;
+            }
+        }
     }
 };
 var m = function (){
@@ -30,13 +46,13 @@ function void$(){
 }
 
 function valueArgs(r/*T*/, i/*INTEGER*/){
-	var v1 = r;
+	var v1 = RTL$.clone(r);
 	var v2 = i;
 }
 
 function varArgs(r/*VAR T*/, i/*VAR INTEGER*/){
-	var v1 = r;
-	var v2 = i;
+	var v1 = RTL$.clone(r);
+	var v2 = i.get();
 }
 var v1 = 0;
 var v2 = 1.23;
@@ -47,5 +63,5 @@ var v6 = i + i | 0;
 var v7 = p();
 var v8 = void$;
 var do$ = 0;
-var tempRecord = r;
+var tempRecord = RTL$.clone(r);
 }();

+ 0 - 0
test/input/eberon/temporary_value.ob → test/input/eberon/in_place_variables.ob


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

@@ -0,0 +1,14 @@
+MODULE m;
+TYPE
+    T = RECORD 
+    	b: BOOLEAN
+    END;
+
+VAR
+    r: T;
+
+BEGIN
+    r.b := TRUE;
+    temp <- r;
+	ASSERT(temp.b);
+END m.

+ 16 - 1
test/test_unit_eberon.js

@@ -547,6 +547,21 @@ exports.suite = {
               "invalid type test: 'Derived' is not an extension of 'Derived'"]
             )
         ),
+    "record types as values": testWithContext(
+          context(grammar.declarationSequence,
+                "TYPE Base = RECORD pBase: POINTER TO Base END; Derived = RECORD (Base) END;"
+                + "VAR base: Base;"
+                + "PROCEDURE procBaseVar(VAR b: Base); END procBaseVar;"
+               ),
+          pass("PROCEDURE p(b: Base); BEGIN base <- b; procBaseVar(base); base := b; END p;"),
+          fail(["PROCEDURE p(); BEGIN baseVar <- base.pBase^; ASSERT(base IS Derived); END p;",
+                "invalid type test: a value variable cannot be used"],
+               ["PROCEDURE p(VAR b: Base); BEGIN base <- b; ASSERT(base IS Derived); END p;",
+                "invalid type test: a value variable cannot be used"],
+               ["PROCEDURE p(b: Base); BEGIN base <- b; ASSERT(base IS Derived); END p;",
+                "invalid type test: a value variable cannot be used"]
+              )
+      )/*
     "as references": testWithContext(
           context(grammar.declarationSequence,
                 "TYPE Base = RECORD pBase: POINTER TO Base END; Derived = RECORD (Base) END;"
@@ -556,6 +571,6 @@ exports.suite = {
                "PROCEDURE p(VAR b: Base); BEGIN baseRef <- b; ASSERT(baseRef IS Derived); END p;"),
           fail(["PROCEDURE p(b: Base); BEGIN baseRef <- b; ASSERT(baseRef IS Derived); END p;",
                 "invalid type test: a value variable cannot be used"])
-      )
+      )*/
     }
 };