소스 검색

Make type narrowing work even if testing was done for dereferenced (^) in-place variable.

Vladislav Folts 10 년 전
부모
커밋
ba49a9b8df
4개의 변경된 파일40개의 추가작업 그리고 4개의 파일을 삭제
  1. BIN
      bin/compiled.zip
  2. 4 1
      src/context.js
  3. 31 3
      src/eberon/eberon_context.js
  4. 5 0
      test/test_unit_eberon.js

BIN
bin/compiled.zip


+ 4 - 1
src/context.js

@@ -347,6 +347,9 @@ exports.Designator = ChainedContext.extend({
     _makeDenoteVar: function(field, isReadOnly){
         return Type.makeVariable(field.type(), isReadOnly);
     },
+    _makeDerefVar: function(){
+        return Type.makeVariableRef(this.__currentType, false);
+    },
     handleExpression: function(e){this.__indexExpression = e;},
     __handleIndexExpression: function(){
         var e = this.__indexExpression;
@@ -410,7 +413,7 @@ exports.Designator = ChainedContext.extend({
         }
         else if (s == "^"){
             this.__handleDeref();
-            this.__info = Type.makeVariableRef(this.__currentType, false);
+            this.__info = this._makeDerefVar(this.__info);
         }
     },
     __handleDeref: function(){

+ 31 - 3
src/eberon/eberon_context.js

@@ -119,7 +119,12 @@ var ResultVariable = Type.Variable.extend({
     idType: function(){return "procedure call " + (this.type() ? "result" : "statement");}
 });
 
-var TypeNarrowVariable = Type.Variable.extend({
+var TypeNarrowVariableBase = Type.Variable.extend({
+    init: function TypeNarrowVariableBase(){
+    }    
+});
+
+var TypeNarrowVariable = TypeNarrowVariableBase.extend({
     init: function TypeNarrowVariable(type, isRef, isReadOnly){
         this.__type = type;
         this.__isRef = isRef;
@@ -136,13 +141,31 @@ var TypeNarrowVariable = Type.Variable.extend({
     },
     idType: function(){
         return this.__isReadOnly ? "non-VAR formal parameter"
-                                 : Type.Variable.prototype.idType.call(this);
+                                 : TypeNarrowVariableBase.prototype.idType.call(this);
     },
     setType: function(type){
         this.__type = type;
     }
 });
 
+var DereferencedTypeNarrowVariable = TypeNarrowVariableBase.extend({
+    init: function DereferencedTypeNarrowVariable(v){
+        this.__v = v;
+    },
+    type: function(){
+        return this.__v.type();
+    },
+    isReference: function(){
+        return true;
+    },
+    isReadOnly: function(){
+        return false;
+    },
+    setType: function(type){
+        this.__v.setType(type);
+    }
+});
+
 var InPlaceStringLiteral = TypeNarrowVariable.extend({
     init: function(type){
         TypeNarrowVariable.prototype.init.call(this, type, false, true);
@@ -196,6 +219,11 @@ var Designator = Context.Designator.extend({
             isReadOnly = field.identdef().isReadOnly();
         return Context.Designator.prototype._makeDenoteVar(field, isReadOnly);
     },
+    _makeDerefVar: function(info){
+        if (info instanceof TypeNarrowVariable)
+            return new DereferencedTypeNarrowVariable(info);
+        return Context.Designator.prototype._makeDerefVar(info);
+    },
     handleMessage: function(msg){
         if (msg == Context.beginCallMsg)
             return this.__beginCall();
@@ -781,7 +809,7 @@ var RelationOps = Context.RelationOps.extend({
             var d = left.designator();
             if (d){
                 var v = d.info();
-                if (v instanceof TypeNarrowVariable)
+                if (v instanceof TypeNarrowVariableBase)
                     context.handleMessage(new PromoteTypeMsg(v, type));
             }
             return impl(left, right);

+ 5 - 0
test/test_unit_eberon.js

@@ -766,6 +766,11 @@ exports.suite = {
               "type mismatch for argument 1: cannot pass 'PDerived' as VAR parameter of type 'PBase'"]
             )
         ),
+    "type promotion after dereferencing": testWithContext(
+        temporaryValues.context,
+        temporaryValues.passExpressions(
+            "(b^ IS Derived) & b.flag")
+        ),
     "IS expression after type promotion": testWithContext(
         temporaryValues.context,
         pass(),