Browse Source

in place variables can reference records

Vladislav Folts 11 years ago
parent
commit
e3c564eb02
8 changed files with 51 additions and 22 deletions
  1. BIN
      bin/compiled.zip
  2. 2 2
      src/context.js
  3. 4 0
      src/eberon/EberonString.ob
  4. 15 5
      src/eberon/eberon_context.js
  5. 4 2
      src/ob/Code.ob
  6. 3 2
      src/ob/Operator.ob
  7. 11 9
      src/ob/Types.ob
  8. 12 2
      test/test_unit_eberon.js

BIN
bin/compiled.zip


+ 2 - 2
src/context.js

@@ -97,7 +97,7 @@ function checkTypeCast(fromInfo, fromType, toType, msg){
             + fromType.description() + "'");
 
     if (fromType instanceof Type.Record){
-        if (!(fromInfo instanceof Type.VariableRef))
+        if (!fromInfo.isReference())
             throw new Errors.Error(
                 prefix + ": a value variable cannot be used");
         if (!(toType instanceof Type.Record))
@@ -449,7 +449,7 @@ exports.Designator = ChainedContext.extend({
     __makeRefCode: function(code){
         if (   this.__currentType instanceof Type.Array
             || this.__currentType instanceof Type.Record
-            || this.__info instanceof Type.VariableRef)
+            || this.__info.isReference())
             return code;
         if (this.__derefCode)
             return this.language().rtl.makeRef(this.__derefCode, this.__propCode);

+ 4 - 0
src/eberon/EberonString.ob

@@ -18,6 +18,10 @@ PROCEDURE ElementVariable.type(): Types.PType;
     RETURN Types.basic.ch
 END ElementVariable.type;
 
+PROCEDURE ElementVariable.isReference(): BOOLEAN;
+    RETURN FALSE
+END ElementVariable.isReference;
+
 PROCEDURE makeElementVariable*(): Types.PVariable;
 VAR
     result: POINTER TO ElementVariable;

+ 15 - 5
src/eberon/eberon_context.js

@@ -18,7 +18,6 @@ function log(s){
     console.info(s);
 }
 */
-
 function methodCallGenerator(context, id, type){
     return new Procedure.makeProcCallGenerator(context, id, type);
 }
@@ -127,13 +126,24 @@ var ResultVariable = Type.Variable.extend({
 });
 
 var TempVariable = Type.Variable.extend({
-    init: function TempVariable(type){
-        this.__type = type;
-        this.__invertedType = type;
+    init: function TempVariable(e){
+        this.__type = e.type();
+        this.__invertedType = this.__type;
+
+        this.__isRef = false;
+        var d = e.designator();
+        if (d) {
+            var v = d.info();
+            if (v instanceof Type.Variable)
+                this.__isRef = v.isReference();
+        }
     },
     type: function(){
         return this.__type;
     },
+    isReference: function(){
+        return this.__isRef;
+    },
     //idType: function(){return "temporary variable";},
     promoteType: function(t){
         var result = this.__type;
@@ -246,7 +256,7 @@ var TemplValueInit = Context.Chained.extend({
         gen.write("var " + this.__id + " = ");
     },
     handleExpression: function(e){
-        var v = new TempVariable(e.type());
+        var v = new TempVariable(e);
         this.__symbol = Symbol.makeSymbol(this.__id, v);
     },
     endParse: function(){

+ 4 - 2
src/ob/Code.ob

@@ -324,7 +324,8 @@ VAR
 BEGIN
     IF     (e.mDesignator = NIL)
         OR ((e.mType IS Types.PArray) OR (e.mType IS Types.PRecord)) 
-        OR ~(e.mDesignator.mInfo IS Types.PVariableRef) THEN
+        OR ~((e.mDesignator.mInfo IS Types.PVariable) 
+                & e.mDesignator.mInfo(Types.PVariable).isReference()) THEN
         result := e;
     ELSE
         result := makeSimpleExpression(e.mCode + ".get()", e.mType);
@@ -337,7 +338,8 @@ VAR
     result: PExpression;
 BEGIN
     IF     (e.mDesignator = NIL) 
-        OR (e.mDesignator.mInfo IS Types.PVariableRef) THEN
+        OR ((e.mDesignator.mInfo IS Types.PVariable) 
+            & e.mDesignator.mInfo(Types.PVariable).isReference()) THEN
         result := e;
     ELSE
         result := makeSimpleExpression(e.mDesignator.mRefCode(e.mDesignator.mCode),

+ 3 - 2
src/ob/Operator.ob

@@ -528,7 +528,7 @@ BEGIN
                 castExp := Code.derefExpression(right);
             END;
             rightCode := castExp.code();
-            IF info IS Types.PVariableRef THEN
+            IF (info IS Types.PVariable) & info(Types.PVariable).isReference() THEN
                 rightCode := ".set(" + rightCode + ")";
             ELSE
                 rightCode := " = " + rightCode;
@@ -546,7 +546,8 @@ VAR
     result: STRING;
 BEGIN
     designator := left.designator();
-    IF designator.info() IS Types.PVariableRef THEN
+    info <- designator.info();
+    IF (info IS Types.PVariable) & info.isReference() THEN
         result := assign(left, altOp(left, right, cx.rtl), cx);
     ELSE
         rightExp := Code.derefExpression(right);

+ 11 - 9
src/ob/Types.ob

@@ -51,24 +51,21 @@ TYPE
 
     Variable* = RECORD(Id)
         PROCEDURE type*(): PType;
-        PROCEDURE isReadOnly*(): BOOLEAN
+        PROCEDURE isReadOnly*(): BOOLEAN;
+        PROCEDURE isReference*(): BOOLEAN
     END;
 
     PVariable* = POINTER TO Variable;
 
     VariableImpl = RECORD(Variable)
-        mType: PType
+        mType: PType;
+        mRef: BOOLEAN
     END;
     PVariableImpl = POINTER TO VariableImpl;
 
     ReadOnlyVariable = RECORD(VariableImpl)
     END;
 
-    VariableRef* = RECORD(VariableImpl)
-    END;
-
-    PVariableRef* = POINTER TO VariableRef;
-
     ExportedVariable = RECORD(ReadOnlyVariable)
     END;
 
@@ -316,6 +313,10 @@ PROCEDURE VariableImpl.type(): PType;
     RETURN SELF.mType
 END VariableImpl.type;
 
+PROCEDURE VariableImpl.isReference(): BOOLEAN;
+    RETURN SELF.mRef
+END VariableImpl.isReference;
+
 PROCEDURE procedureType*(p: ProcedureId): PType;
     RETURN p.type
 END procedureType;
@@ -637,12 +638,13 @@ BEGIN
     RETURN result
 END makeVariable;
 
-PROCEDURE makeVariableRef*(type: PType): PVariableRef;
+PROCEDURE makeVariableRef*(type: PType): PVariable;
 VAR
-    result: PVariableRef;
+    result: PVariableImpl;
 BEGIN
     NEW(result);
     result.mType := type;
+    result.mRef := TRUE;
     RETURN result
 END makeVariableRef;
 

+ 12 - 2
test/test_unit_eberon.js

@@ -382,7 +382,7 @@ exports.suite = {
          ["returnProc()", "procedure returning a result cannot be used as a statement"] // call is not applied implicitly to result
         )
     ),
-"temporary values": {
+"in place variables": {
     "initialization": testWithContext(
         context(grammar.statement,
                 "VAR i: INTEGER;"
@@ -538,6 +538,16 @@ exports.suite = {
         fail(["PROCEDURE p(); PROCEDURE procBaseAsVar(VAR p: PBase); END procBaseAsVar;  BEGIN b <- pBase; IF b IS PDerived THEN procBaseAsVar(b); b.flag := FALSE; END; END p;",
               "type mismatch for argument 1: cannot pass 'PDerived' as VAR parameter of type 'PBase'"]
             )
-        )
+        ),
+    "as references": testWithContext(
+          context(grammar.declarationSequence,
+                "TYPE Base = RECORD pBase: POINTER TO Base END; Derived = RECORD (Base) END;"
+                + "VAR base: Base;"
+               ),
+          pass("PROCEDURE p(); BEGIN baseRef <- base.pBase^; ASSERT(baseRef IS Derived); END p;",
+               "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"])
+      )
     }
 };