As static blocks is compiled as a method without returntype, previous isConstructor...
[IRC.git] / Robust / src / IR / Tree / SemanticCheck.java
index 4feeb962ab0306c394fb6442e69220f2526965a0..692054232d7fc48e7d03db38bf90d2e3d9393737 100644 (file)
@@ -247,7 +247,7 @@ public class SemanticCheck {
       }
     }
     /* Check return type */
-    if (!md.isConstructor())
+    if (!md.isConstructor() && !md.isStaticBlock())
       if (!md.getReturnType().isVoid())
        checkTypeDescriptor(md.getReturnType());
 
@@ -526,10 +526,18 @@ public class SemanticCheck {
     case Kind.ArrayInitializerNode:
       checkArrayInitializerNode(md, nametable, (ArrayInitializerNode) en, td);
       return;
+     
+    case Kind.ClassTypeNode:
+      checkClassTypeNode(md, nametable, (ClassTypeNode) en, td);
+      return;
     }
     throw new Error();
   }
 
+  void checkClassTypeNode(Descriptor md, SymbolTable nametable, ClassTypeNode tn, TypeDescriptor td) {
+    checkTypeDescriptor(tn.getType());
+  }
+  
   void checkCastNode(Descriptor md, SymbolTable nametable, CastNode cn, TypeDescriptor td) {
     /* Get type descriptor */
     if (cn.getType()==null) {
@@ -588,8 +596,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 +668,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) {
@@ -681,8 +710,18 @@ public class SemanticCheck {
           SymbolTable fieldtbl = cd.getFieldTable();
           FieldDescriptor fd=(FieldDescriptor)fieldtbl.get(varname);
           if((fd == null) || (!fd.isStatic())){
-            // no such field in the class or it is not a static field
-            throw new Error("Name "+varname+" should not be used in static block: "+md);
+            // no such field in the class, check if this is a class
+            if(varname.equals("this")) {
+              throw new Error("Error: access this obj in a static block");
+            }
+            cd=getClass(varname);
+            if(cd != null) {
+              // this is a class name
+              nn.setClassDesc(cd);
+              return;
+            } else {
+              throw new Error("Name "+varname+" should not be used in static block: "+md);
+            }
           } else {
             // this is a static field
             nn.setField(fd);
@@ -773,9 +812,49 @@ public class SemanticCheck {
   }
 
   void checkArrayInitializerNode(Descriptor md, SymbolTable nametable, ArrayInitializerNode ain, TypeDescriptor td) {
+    Vector<TypeDescriptor> vec_type = new Vector<TypeDescriptor>();
     for( int i = 0; i < ain.numVarInitializers(); ++i ) {
-      checkExpressionNode(md, nametable, ain.getVarInitializer(i), td.dereference()); 
+      checkExpressionNode(md, nametable, ain.getVarInitializer(i), td==null?td:td.dereference());
+      vec_type.add(ain.getVarInitializer(i).getType());
+    }
+    // descide the type of this variableInitializerNode
+    TypeDescriptor out_type = vec_type.elementAt(0);
+    for(int i = 1; i < vec_type.size(); i++) {
+      TypeDescriptor tmp_type = vec_type.elementAt(i);
+      if(out_type == null) {
+        if(tmp_type != null) {
+          out_type = tmp_type;
+        }
+      } else if(out_type.isNull()) {
+        if(!tmp_type.isNull() ) {
+          if(!tmp_type.isArray()) {
+            throw new Error("Error: mixed type in var initializer list");
+          } else {
+            out_type = tmp_type;
+          }
+        }
+      } else if(out_type.isArray()) {
+        if(tmp_type.isArray()) {
+          if(tmp_type.getArrayCount() > out_type.getArrayCount()) {
+            out_type = tmp_type;
+          }
+        } else if((tmp_type != null) && (!tmp_type.isNull())) {
+          throw new Error("Error: mixed type in var initializer list");
+        }
+      } else if(out_type.isInt()) {
+        if(!tmp_type.isInt()) {
+          throw new Error("Error: mixed type in var initializer list");
+        }
+      } else if(out_type.isString()) {
+        if(!tmp_type.isString()) {
+          throw new Error("Error: mixed type in var initializer list");
+        }
+      }
     }
+    if(out_type != null) {
+      out_type = out_type.makeArray(state);
+    }
+    ain.setType(out_type);
   }
 
   void checkAssignmentNode(Descriptor md, SymbolTable nametable, AssignmentNode an, TypeDescriptor td) {
@@ -820,7 +899,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));
+      }
     }
   }
 
@@ -860,6 +955,11 @@ public class SemanticCheck {
 
     if (td!=null&&!typeutil.isSuperorType(td, typetolookin))
       throw new Error(typetolookin + " isn't a "+td);
+    
+    /* Check Array Initializers */
+    if(state.MGC && (con.getArrayInitializer() != null)) {
+      checkArrayInitializerNode(md, nametable, con.getArrayInitializer(), td);
+    }
 
     /* Check flag effects */
     if (con.getFlagEffects()!=null) {