Fix the bug of assignment conversion: 'short s = 12' should be allowed. And for such...
authorjzhou <jzhou>
Fri, 28 Jan 2011 01:58:29 +0000 (01:58 +0000)
committerjzhou <jzhou>
Fri, 28 Jan 2011 01:58:29 +0000 (01:58 +0000)
19 files changed:
Robust/src/IR/FieldDescriptor.java
Robust/src/IR/Flat/BuildFlat.java
Robust/src/IR/Tree/ArrayAccessNode.java
Robust/src/IR/Tree/ArrayInitializerNode.java
Robust/src/IR/Tree/AssignmentNode.java
Robust/src/IR/Tree/CastNode.java
Robust/src/IR/Tree/ClassTypeNode.java
Robust/src/IR/Tree/CreateObjectNode.java
Robust/src/IR/Tree/ExpressionNode.java
Robust/src/IR/Tree/FieldAccessNode.java
Robust/src/IR/Tree/InstanceOfNode.java
Robust/src/IR/Tree/LiteralNode.java
Robust/src/IR/Tree/MethodInvokeNode.java
Robust/src/IR/Tree/NameNode.java
Robust/src/IR/Tree/OffsetNode.java
Robust/src/IR/Tree/OpNode.java
Robust/src/IR/Tree/SemanticCheck.java
Robust/src/IR/Tree/TertiaryNode.java
Robust/src/Tests/AssignmentConversionTest.java [new file with mode: 0644]

index a60a65d3234559efc82c70c87b68711c76385dab..ce515321a3d5e80eedfe9984feae037bf92b8d1a 100644 (file)
@@ -52,6 +52,10 @@ public class FieldDescriptor extends Descriptor {
       return en;
   }
 
+  public boolean isFinal() {
+    return modifier.isFinal();
+  }
+  
   public boolean isStatic() {
     return modifier.isStatic();
   }
index 48b07b78329250c63dfdb439a91b0f5917c295be..c9f4b783de711176f69ab93eff5c4840b864add2 100644 (file)
@@ -542,9 +542,13 @@ public class BuildFlat {
 
     //Get src value
     if (an.getSrc()!=null) {
-      NodePair np_src=flattenExpressionNode(an.getSrc(),src_tmp);
-      first=np_src.getBegin();
-      last=np_src.getEnd();
+      if(an.getSrc().getEval() != null) {
+        first = last = new FlatLiteralNode(an.getSrc().getType(), an.getSrc().getEval().longValue(), src_tmp);
+      } else {
+        NodePair np_src=flattenExpressionNode(an.getSrc(),src_tmp);
+        first=np_src.getBegin();
+        last=np_src.getEnd();
+      }
     } else if (!pre) {
       FlatLiteralNode fln=new FlatLiteralNode(new TypeDescriptor(TypeDescriptor.INT),new Integer(1),src_tmp);
       first=fln;
index 46ca561249ea268da58f3e009ca0d80db72e09aa..a88004fdfedab2e3a4cad07a325009ae9e829249 100644 (file)
@@ -38,4 +38,9 @@ public class ArrayAccessNode extends ExpressionNode {
     else
       return left.getType().dereference();
   }
+  
+  public Long evaluate() {
+    eval = null;
+    return eval; //null;
+  }
 }
index e6bc7b335e99b42419a2a9df63965cf2783c2800..5c12ffe331eb19490c3586a93c3e2b126d7875e5 100644 (file)
@@ -43,4 +43,9 @@ public class ArrayInitializerNode extends ExpressionNode {
   public int kind() {
     return Kind.ArrayInitializerNode;
   }
+  
+  public Long evaluate() {
+    eval = null;
+    return eval; //null;
+  }
 }
index 9d6b8ab97baeb2a517ad850bbd160f9adf68d5f9..abe6d41f76c7b138f58cae74dab32c0ec4af921f 100644 (file)
@@ -39,4 +39,9 @@ public class AssignmentNode extends ExpressionNode {
   public int kind() {
     return Kind.AssignmentNode;
   }
+  
+  public Long evaluate() {
+    eval = left.evaluate();
+    return eval;
+  }
 }
index e7e41c5f29094a0beb209be51c503e9866dc736c..d3267ebd8adb10793da76a370bea7acff82cadca 100644 (file)
@@ -44,4 +44,9 @@ public class CastNode extends ExpressionNode  {
   public int kind() {
     return Kind.CastNode;
   }
+  
+  public Long evaluate() {
+    eval = exp.evaluate();
+    return eval;
+  }
 }
index 18a7b0009204191bd24d1e60317f15180d339329..b07e0ef8d8089529fe79be05ecba7dd9a429e8f4 100644 (file)
@@ -28,4 +28,9 @@ public class ClassTypeNode extends ExpressionNode {
   public int kind() {
     return Kind.ClassTypeNode;
   }
+  
+  public Long evaluate() {
+    eval = null;
+    return eval; //null;
+  }
 }
index ccc5f3a2c415dc962d68200474bfe3fc26714d85..ebe23e7a63370b808b850d4ae91ea513a5446c32 100644 (file)
@@ -100,4 +100,9 @@ public class CreateObjectNode extends ExpressionNode {
   public int kind() {
     return Kind.CreateObjectNode;
   }
+  
+  public Long evaluate() {
+    eval = null;
+    return eval; //null;
+  }
 }
index b6e4a476e71cf9ca8bf5cf816f8a918f097eb825..1b80cc354cf79e616ed9a83902998abe3a0d819d 100644 (file)
@@ -2,6 +2,8 @@ package IR.Tree;
 import IR.TypeDescriptor;
 
 public class ExpressionNode extends TreeNode {
+  Long eval = null;
+  
   public TypeDescriptor getType() {
     throw new Error();
   }
@@ -9,4 +11,12 @@ public class ExpressionNode extends TreeNode {
   public String printNode(int indentlevel) {
     return null;
   }
+  
+  public Long evaluate() {
+    throw new Error();
+  }
+  
+  public Long getEval() {
+    return this.eval;
+  }
 }
index 9a06ee4485b7f0ea6d6766ae9d5787e2710e51db..151478cdafaf0ef658cdb2b997845f7ecfbc0ba0 100644 (file)
@@ -38,4 +38,14 @@ public class FieldAccessNode extends ExpressionNode {
     return getField().getType();
   }
 
+  public Long evaluate() {
+    // if the field is a constant value then OK
+    eval = null;
+    if(field.isStatic() && field.isFinal()) {
+      eval = field.getExpressionNode().evaluate();
+    } else if (field.isEnum()) {
+      eval = Long.valueOf((long)field.enumValue());
+    }
+    return eval;
+  }
 }
index 95d55ddb71b53f8472feb087c5c8603f092911ff..bf015614f8cc3ce3db7eeafe9053050f3e7c5b80 100644 (file)
@@ -30,4 +30,9 @@ public class InstanceOfNode extends ExpressionNode {
   public int kind() {
     return Kind.InstanceOfNode;
   }
+  
+  public Long evaluate() {
+    eval = null;
+    return eval; //null;
+  }
 }
index 9c64184cbe5b671792e233fe48212dfe60a7bff5..e975c19ed865f16c41b7b94decf2821b2c245172 100644 (file)
@@ -60,4 +60,12 @@ public class LiteralNode extends ExpressionNode {
   public int kind() {
     return Kind.LiteralNode;
   }
+  
+  public Long evaluate() {
+    eval = null;
+    if(this.type.isChar() || this.type.isInt()) { 
+      eval = Long.parseLong(this.value.toString());
+    }
+    return eval;
+  }
 }
index 6925b5e4beca811f6210dd43aef289c3bac1e56f..0ace6405728b4a9191c3f4100dc649d81d9b2085 100644 (file)
@@ -87,4 +87,9 @@ public class MethodInvokeNode extends ExpressionNode {
   public int kind() {
     return Kind.MethodInvokeNode;
   }
+  
+  public Long evaluate() {
+    eval = null;
+    return eval; //null;
+  }
 }
index e2634647c804fdb10b02f34c02684c070614f317..1785b23a6ea213ab3c59dac28fdbe5366672fd38 100644 (file)
@@ -97,4 +97,18 @@ public class NameNode extends ExpressionNode {
   public int kind() {
     return Kind.NameNode;
   }
+  
+  public Long evaluate() {
+    eval = null;
+    if(fd != null ) {
+      if(fd.isFinal() && fd.isStatic()) {
+        eval = fd.getExpressionNode().evaluate();
+      } else if(fd.isEnum()) {
+        eval = Long.valueOf((long)fd.enumValue());
+      } 
+    } else if(en!= null) {
+      eval = en.evaluate();
+    }
+    return eval; //null;
+  }
 }
index 74ba651d5730f9541096057ee2b179b19ad917a1..c293b86979035bdeb23ab709b8d41cd5cad72d46 100644 (file)
@@ -41,4 +41,9 @@ public class OffsetNode extends ExpressionNode {
   public int kind() {
     return Kind.OffsetNode;
   }
+  
+  public Long evaluate() {
+    eval = null;
+    return eval; //null;
+  }
 }
index 815f4894674cd3ba69537973ce78e5193ccbcb3f..d2a9dc81d9d7504bf42dad271aaef5cc5d53b8d3 100644 (file)
@@ -68,4 +68,65 @@ public class OpNode extends ExpressionNode {
   public int kind() {
     return Kind.OpNode;
   }
+  
+  public Long evaluate() {
+    eval = null;
+    Long l = this.left.evaluate();
+    if(l != null) {
+      if (this.op.getOp() == Operation.LOGIC_NOT)
+        eval = Long.valueOf(l.longValue() > 0 ? 0 : 1);
+      else if (this.op.getOp() == Operation.COMP)
+        eval = Long.valueOf((long)(~l.longValue()));
+      else {
+        Long r = this.right.evaluate();
+        if(r != null) {
+          //if (this.op.getOp() == Operation.LOGIC_OR)
+          //  return Long.valueOf((long)(l.longValue() || r.longValue()));
+          //else if (this.op.getOp() == Operation.LOGIC_AND)
+          //  return Long.valueOf((long)(l.longValue() && r.longValue()));
+          /*else */if (this.op.getOp() == Operation.BIT_OR)
+            eval = Long.valueOf(l.longValue() | r.longValue());
+          else if (this.op.getOp() == Operation.BIT_XOR)
+            eval = Long.valueOf(l.longValue() ^ r.longValue());
+          else if (this.op.getOp() == Operation.BIT_AND)
+            eval = Long.valueOf(l.longValue() & r.longValue());
+          else if (this.op.getOp() == Operation.EQUAL)
+            eval = Long.valueOf((l.longValue() == r.longValue())?1:0);
+          else if (this.op.getOp() == Operation.NOTEQUAL)
+            eval = Long.valueOf((l.longValue() != r.longValue())?1:0);
+          else if (this.op.getOp() == Operation.LT)
+            eval = Long.valueOf((l.longValue() < r.longValue())?1:0);
+          else if (this.op.getOp() == Operation.GT)
+            eval = Long.valueOf((l.longValue() > r.longValue())?1:0);
+          else if (this.op.getOp() == Operation.LTE)
+            eval = Long.valueOf((l.longValue() <= r.longValue())?1:0);
+          else if (this.op.getOp() == Operation.GTE)
+            eval = Long.valueOf((l.longValue() >= r.longValue())?1:0);
+          else if (this.op.getOp() == Operation.LEFTSHIFT)
+            eval = Long.valueOf(l.longValue() << r.longValue());
+          else if (this.op.getOp() == Operation.RIGHTSHIFT)
+            eval = Long.valueOf(l.longValue() >> r.longValue());
+          else if (this.op.getOp() == Operation.URIGHTSHIFT)
+            eval = Long.valueOf(l.longValue() >>> r.longValue());
+          else if (this.op.getOp() == Operation.SUB)
+            eval = Long.valueOf(l.longValue() - r.longValue());
+          else if (this.op.getOp() == Operation.ADD)
+            eval = Long.valueOf(l.longValue() + r.longValue());
+          else if (this.op.getOp() == Operation.MULT)
+            eval = Long.valueOf(l.longValue() * r.longValue());
+          else if (this.op.getOp() == Operation.DIV)
+            eval = Long.valueOf(l.longValue() / r.longValue());
+          else if (this.op.getOp() == Operation.MOD)
+            eval = Long.valueOf(l.longValue() % r.longValue());
+          else if (this.op.getOp() == Operation.UNARYPLUS)
+            eval = Long.valueOf(+l.longValue());
+          else if (this.op.getOp() == Operation.UNARYMINUS)
+            eval = Long.valueOf(-l.longValue() );
+          else if (this.op.getOp() == Operation.ASSIGN)
+            eval = Long.valueOf(r.longValue());
+        }
+      }
+    }
+    return eval;
+  }
 }
index be2e490a3f9faa20bb5ddd1c626d561fffca88e4..6b057ed56fc31cb3e42e11e5e412a852175f148b 100644 (file)
@@ -588,8 +588,12 @@ public class SemanticCheck {
         fd = new FieldDescriptor(new Modifiers(Modifiers.PUBLIC|Modifiers.FINAL), new TypeDescriptor(TypeDescriptor.INT), fieldname, null, false);
         fd.setAsEnum();
         fd.setEnumValue(value);
-      } else if(!fd.isStatic()) {
+      } else if(fd.isStatic()) {
         // check if this field is a static field
+        if(fd.getExpressionNode() != null) {
+          checkExpressionNode(md,nametable,fd.getExpressionNode(),null);
+        }
+      } else {
         throw new Error("Dereference of the non-static field "+ fieldname + " in "+fan.printNode(0)+" in "+md);
       }
     } 
@@ -656,8 +660,25 @@ public class SemanticCheck {
     }
 
     if (td!=null)
-      if (!typeutil.isSuperorType(td,ln.getType()))
-       throw new Error("Field node returns "+ln.getType()+", but need "+td+" in "+md);
+      if (!typeutil.isSuperorType(td,ln.getType())) {
+        Long l = ln.evaluate();
+        if((ln.getType().isByte() || ln.getType().isShort() 
+            || ln.getType().isChar() || ln.getType().isInt()) 
+            && (l != null) 
+            && (td.isByte() || td.isShort() || td.isChar() 
+                || td.isInt() || td.isLong())) {
+          long lnvalue = l.longValue();
+          if((td.isByte() && ((lnvalue > 127) || (lnvalue < -128))) 
+              || (td.isShort() && ((lnvalue > 32767) || (lnvalue < -32768)))
+              || (td.isChar() && ((lnvalue > 65535) || (lnvalue < 0)))
+              || (td.isInt() && ((lnvalue > 2147483647) || (lnvalue < -2147483648)))
+              || (td.isLong() && ((lnvalue > 9223372036854775807L) || (lnvalue < -9223372036854775808L)))) {
+            throw new Error("Field node returns "+ln.getType()+", but need "+td+" in "+md);
+          }
+        } else {
+          throw new Error("Field node returns "+ln.getType()+", but need "+td+" in "+md);
+        }
+      }
   }
 
   void checkNameNode(Descriptor md, SymbolTable nametable, NameNode nn, TypeDescriptor td) {
@@ -860,7 +881,23 @@ public class SemanticCheck {
     }
 
     if (!postinc&&!typeutil.isSuperorType(an.getDest().getType(),an.getSrc().getType())) {
-      throw new Error("Type of rside ("+an.getSrc().getType().toPrettyString()+") not compatible with type of lside ("+an.getDest().getType().toPrettyString()+")"+an.printNode(0));
+      TypeDescriptor dt = an.getDest().getType();
+      TypeDescriptor st = an.getSrc().getType();
+      Long l = an.getSrc().evaluate();
+      if((st.isByte() || st.isShort() || st.isChar() || st.isInt()) 
+          && (l != null) 
+          && (dt.isByte() || dt.isShort() || dt.isChar() || dt.isInt() || dt.isLong())) {
+        long lnvalue = l.longValue();
+        if((dt.isByte() && ((lnvalue > 127) || (lnvalue < -128))) 
+            || (dt.isShort() && ((lnvalue > 32767) || (lnvalue < -32768)))
+            || (dt.isChar() && ((lnvalue > 65535) || (lnvalue < 0)))
+            || (dt.isInt() && ((lnvalue > 2147483647) || (lnvalue < -2147483648)))
+            || (dt.isLong() && ((lnvalue > 9223372036854775807L) || (lnvalue < -9223372036854775808L)))) {
+          throw new Error("Field node returns "+st+", but need "+dt+" in "+md);
+        }
+      } else {
+        throw new Error("Type of rside ("+an.getSrc().getType().toPrettyString()+") not compatible with type of lside ("+an.getDest().getType().toPrettyString()+")"+an.printNode(0));
+      }
     }
   }
 
index 099828651eb6d6278f81d0b5af241d5f8285496e..4da59212db61c79f3d29a9af2245da314783d842 100644 (file)
@@ -37,4 +37,23 @@ public class TertiaryNode extends ExpressionNode {
   public int kind() {
     return Kind.TertiaryNode;
   }
+  
+  public Long evaluate() {
+    eval = null;
+    Long c = this.cond.evaluate();
+    if(c != null) {
+      Long t = this.trueExpr.evaluate();
+      if(t != null) {
+        Long f = this.falseExpr.evaluate();
+        if(f != null) {
+          if(c.intValue() > 0) {
+            eval = t;
+          } else {
+            eval = f;
+          }
+        }
+      }
+    }
+    return eval;
+  }
 }
\ No newline at end of file
diff --git a/Robust/src/Tests/AssignmentConversionTest.java b/Robust/src/Tests/AssignmentConversionTest.java
new file mode 100644 (file)
index 0000000..3e746f9
--- /dev/null
@@ -0,0 +1,61 @@
+class AssignmentConversionTest {
+    public static final int sfi = 100;
+  
+    public static void main(String[] args) {
+        short s = 12;           // narrow 12 to short
+        float f = s;            // widen short to float
+        System.out.println("f=12 : " + (int)f);
+
+        char c = '\u0009';
+        int l = c;         // widen char to int
+        System.out.println("l=0x9 : 0x" + Integer.toString(l));
+
+        f = 1.23f;
+        double d = f;           // widen float to double
+        System.out.println("d=123 : " + (int)(d*100));
+        
+        s = AssignmentConversionTest.sfi;
+        System.out.println("s=100 : " + s);
+        
+        s = 12+2;
+        System.out.println("s=12+2=" + (12+2) + ": "+ s);
+        
+        s = 12-2;
+        System.out.println("s=12-2=" + (12-2) + ": "+ s);
+        
+        s = 12*2;
+        System.out.println("s=12*2=" + (12*2) + ": "+ s);
+        
+        s = 12/2;
+        System.out.println("s=12/2=" + (12/2) + ": "+ s);
+        
+        s = 12%2;
+        System.out.println("s=12%2=" + (12%2) + ": "+ s);
+        
+        s = 12|2;
+        System.out.println("s=12|2=" + (12|2) + ": "+ s);
+        
+        s = 12^2;
+        System.out.println("s=12^2=" + (12^2) + ": "+ s);
+        
+        s = 12&2;
+        System.out.println("s=12&2=" + (12&2) + ": "+ s);
+        
+        s = 12>2?1:2;
+        System.out.println("s=12>2?1:2=" + (12>2?1:2) + ": "+ s);
+        
+        s = 12<2?1:2;
+        System.out.println("s=12<2?1:2=" + (12<2?1:2) + ": "+ s);
+        
+        /*       
+        byte a = 12<2;
+
+        s = 12%2?1:2;
+        System.out.println("s=12&2=" + (12%2?1:2) + ": "+ s);
+        
+        short se = 123;
+        char ce = se;         // error: would require cast
+        se = ce;              // error: would require cast
+        */
+    }
+}