As static blocks is compiled as a method without returntype, previous isConstructor...
[IRC.git] / Robust / src / IR / Tree / SemanticCheck.java
index 9bb7d55baefe3bed79967d37a193916d952b42be..692054232d7fc48e7d03db38bf90d2e3d9393737 100644 (file)
 package IR.Tree;
 
 import java.util.*;
+
 import IR.*;
 
 public class SemanticCheck {
   State state;
   TypeUtil typeutil;
+  Stack loopstack;
+  HashSet toanalyze;
+  HashSet completed;
+
 
   public SemanticCheck(State state, TypeUtil tu) {
     this.state=state;
     this.typeutil=tu;
+    this.loopstack=new Stack();
+    this.toanalyze=new HashSet();
+    this.completed=new HashSet();
   }
 
-  public void semanticCheck() {
-    SymbolTable classtable=state.getClassSymbolTable();
-    Iterator it=classtable.getDescriptorsIterator();
-    // Do descriptors first
-    while(it.hasNext()) {
-      ClassDescriptor cd=(ClassDescriptor)it.next();
-      //System.out.println("Checking class: "+cd);
+  public ClassDescriptor getClass(String classname) {
+    ClassDescriptor cd=typeutil.getClass(classname, toanalyze);
+    checkClass(cd);
+    return cd;
+  }
+
+  private void checkClass(ClassDescriptor cd) {
+    if (!completed.contains(cd)) {
+      completed.add(cd);
+      
       //Set superclass link up
       if (cd.getSuper()!=null) {
-       cd.setSuper(typeutil.getClass(cd.getSuper()));
+       cd.setSuper(getClass(cd.getSuper()));
        // Link together Field, Method, and Flag tables so classes
        // inherit these from their superclasses
        cd.getFieldTable().setParent(cd.getSuperDesc().getFieldTable());
        cd.getMethodTable().setParent(cd.getSuperDesc().getMethodTable());
        cd.getFlagTable().setParent(cd.getSuperDesc().getFlagTable());
+    if(state.MGC) {
+      // TODO add version for normal Java later
+      // Link together Field, Method tables do classes inherit these from 
+      // their ancestor interfaces
+      Vector<String> sifv = cd.getSuperInterface();
+      for(int i = 0; i < sifv.size(); i++) {
+        ClassDescriptor superif = getClass(sifv.elementAt(i));
+        cd.addSuperInterfaces(superif);
+        cd.getFieldTable().addParentIF(superif.getFieldTable());
+        cd.getMethodTable().addParentIF(superif.getMethodTable());
       }
-
+    }
+      }
+      
       /* Check to see that fields are well typed */
       for(Iterator field_it=cd.getFields(); field_it.hasNext();) {
        FieldDescriptor fd=(FieldDescriptor)field_it.next();
-       //System.out.println("Checking field: "+fd);
        checkField(cd,fd);
       }
-
+      
+      boolean hasConstructor = false;
       for(Iterator method_it=cd.getMethods(); method_it.hasNext();) {
        MethodDescriptor md=(MethodDescriptor)method_it.next();
        checkMethod(cd,md);
+    hasConstructor |= md.isConstructor();
       }
-    }
-
-    it=classtable.getDescriptorsIterator();
-    // Do descriptors first
-    while(it.hasNext()) {
-      ClassDescriptor cd=(ClassDescriptor)it.next();
-      for(Iterator method_it=cd.getMethods(); method_it.hasNext();) {
-       MethodDescriptor md=(MethodDescriptor)method_it.next();
-       checkMethodBody(cd,md);
+      if(!hasConstructor) {
+        // add a default constructor for this class
+        MethodDescriptor md = new MethodDescriptor(new Modifiers(Modifiers.PUBLIC),
+            cd.getSymbol(), false);
+        BlockNode bn=new BlockNode();
+        state.addTreeCode(md,bn);
+        cd.addMethod(md);
+        checkMethod(cd,md);
       }
     }
+  }
 
-    for(Iterator task_it=state.getTaskSymbolTable().getDescriptorsIterator(); task_it.hasNext();) {
-      TaskDescriptor td=(TaskDescriptor)task_it.next();
-      checkTask(td);
-
+  public void semanticCheck() {
+    SymbolTable classtable=state.getClassSymbolTable();
+    toanalyze.addAll(classtable.getValueSet());
+    toanalyze.addAll(state.getTaskSymbolTable().getValueSet());
+
+    // Do methods next
+    while(!toanalyze.isEmpty()) {
+      Object obj=toanalyze.iterator().next();
+      if (obj instanceof TaskDescriptor) {
+       toanalyze.remove(obj);
+       TaskDescriptor td=(TaskDescriptor)obj;
+       try {
+         checkTask(td);
+       } catch( Error e ) {
+           System.out.println( "Error in "+td );
+           throw e;
+       }
+      } else {
+       ClassDescriptor cd=(ClassDescriptor)obj;
+       toanalyze.remove(cd);
+       //need to initialize typeutil object here...only place we can
+       //get class descriptors without first calling getclass
+       getClass(cd.getSymbol());
+       for(Iterator method_it=cd.getMethods(); method_it.hasNext();) {
+         MethodDescriptor md=(MethodDescriptor)method_it.next();
+         try {
+           checkMethodBody(cd,md);
+         } catch( Error e ) {
+           System.out.println( "Error in "+md );
+           throw e;
+         }
+       }
+      }
     }
   }
 
@@ -64,7 +117,7 @@ public class SemanticCheck {
       return;       /* Done */
     else if (td.isClass()) {
       String name=td.toString();
-      ClassDescriptor field_cd=(ClassDescriptor)state.getClassSymbolTable().get(name);
+      ClassDescriptor field_cd=getClass(name);
       if (field_cd==null)
        throw new Error("Undefined class "+name);
       td.setClassDescriptor(field_cd);
@@ -184,8 +237,17 @@ public class SemanticCheck {
   }
 
   public void checkMethod(ClassDescriptor cd, MethodDescriptor md) {
+    if(state.MGC) {
+      // TODO add version for normal Java later
+      /* Check for abstract methods */
+      if(md.isAbstract()) {
+        if(!cd.isAbstract() && !cd.isInterface()) {
+          throw new Error("Error! The non-abstract Class " + cd.getSymbol() + " contains an abstract method " + md.getSymbol());
+        }
+      }
+    }
     /* Check return type */
-    if (!md.isConstructor())
+    if (!md.isConstructor() && !md.isStaticBlock())
       if (!md.getReturnType().isVoid())
        checkTypeDescriptor(md.getReturnType());
 
@@ -246,6 +308,10 @@ public class SemanticCheck {
     case Kind.IfStatementNode:
       checkIfStatementNode(md, nametable, (IfStatementNode)bsn);
       return;
+      
+    case Kind.SwitchStatementNode:
+      checkSwitchStatementNode(md, nametable, (SwitchStatementNode)bsn);
+      return;
 
     case Kind.LoopNode:
       checkLoopNode(md, nametable, (LoopNode)bsn);
@@ -266,7 +332,21 @@ public class SemanticCheck {
     case Kind.AtomicNode:
       checkAtomicNode(md, nametable, (AtomicNode)bsn);
       return;
+
+    case Kind.SynchronizedNode:
+      checkSynchronizedNode(md, nametable, (SynchronizedNode)bsn);
+      return;
+
+    case Kind.ContinueBreakNode:
+       checkContinueBreakNode(md, nametable, (ContinueBreakNode) bsn);
+       return;
+
+    case Kind.SESENode:
+    case Kind.GenReachNode:
+      // do nothing, no semantic check for SESEs
+      return;
     }
+
     throw new Error();
   }
 
@@ -305,6 +385,19 @@ public class SemanticCheck {
     checkBlockNode(md, nametable, sbn.getBlockNode());
   }
 
+  void checkSynchronizedNode(Descriptor md, SymbolTable nametable, SynchronizedNode sbn) {
+    checkBlockNode(md, nametable, sbn.getBlockNode());
+    //todo this could be Object
+    checkExpressionNode(md, nametable, sbn.getExpr(), null);
+  }
+
+  void checkContinueBreakNode(Descriptor md, SymbolTable nametable, ContinueBreakNode cbn) {
+      if (loopstack.empty())
+         throw new Error("continue/break outside of loop");
+      LoopNode ln=(LoopNode)loopstack.peek();
+      cbn.setLoop(ln);
+  }
+
   void checkReturnNode(Descriptor d, SymbolTable nametable, ReturnNode rn) {
     if (d instanceof TaskDescriptor)
       throw new Error("Illegal return appears in Task: "+d.getSymbol());
@@ -334,6 +427,51 @@ public class SemanticCheck {
     if (isn.getFalseBlock()!=null)
       checkBlockNode(md, nametable, isn.getFalseBlock());
   }
+  
+  void checkSwitchStatementNode(Descriptor md, SymbolTable nametable, SwitchStatementNode ssn) {
+    checkExpressionNode(md, nametable, ssn.getCondition(), new TypeDescriptor(TypeDescriptor.INT));
+    
+    BlockNode sbn = ssn.getSwitchBody();
+    boolean hasdefault = false;
+    for(int i = 0; i < sbn.size(); i++) {
+      boolean containdefault = checkSwitchBlockNode(md, nametable, (SwitchBlockNode)sbn.get(i));
+      if(hasdefault && containdefault) {
+        throw new Error("Error: duplicate default branch in switch-case statement in Method: " + md.getSymbol());
+      }
+      hasdefault = containdefault;
+    }
+  }
+  
+  boolean checkSwitchBlockNode(Descriptor md, SymbolTable nametable, SwitchBlockNode sbn) {
+    Vector<SwitchLabelNode> slnv = sbn.getSwitchConditions();
+    int defaultb = 0;
+    for(int i = 0; i < slnv.size(); i++) {
+      if(slnv.elementAt(i).isdefault) {
+        defaultb++;
+      } else {
+        checkConstantExpressionNode(md, nametable, slnv.elementAt(i).getCondition(), new TypeDescriptor(TypeDescriptor.INT));
+      }
+    }
+    if(defaultb > 1) {
+      throw new Error("Error: duplicate default branch in switch-case statement in Method: " + md.getSymbol());
+    } else {
+      checkBlockNode(md, nametable, sbn.getSwitchBlockStatement());
+      return (defaultb > 0);
+    }
+  }
+  
+  void checkConstantExpressionNode(Descriptor md, SymbolTable nametable, ExpressionNode en, TypeDescriptor td) {
+    switch(en.kind()) {
+    case Kind.FieldAccessNode:
+      checkFieldAccessNode(md,nametable,(FieldAccessNode)en,td);
+      return;
+     
+    case Kind.LiteralNode:
+      checkLiteralNode(md,nametable,(LiteralNode)en,td);
+      return;
+    }
+    throw new Error();
+  }
 
   void checkExpressionNode(Descriptor md, SymbolTable nametable, ExpressionNode en, TypeDescriptor td) {
     switch(en.kind()) {
@@ -372,16 +510,40 @@ public class SemanticCheck {
     case Kind.OpNode:
       checkOpNode(md,nametable,(OpNode)en,td);
       return;
+
+    case Kind.OffsetNode:
+      checkOffsetNode(md, nametable, (OffsetNode)en, td);
+      return;
+
+    case Kind.TertiaryNode:
+      checkTertiaryNode(md, nametable, (TertiaryNode)en, td);
+      return;
+      
+    case Kind.InstanceOfNode:
+      checkInstanceOfNode(md, nametable, (InstanceOfNode) en, td);
+      return;
+
+    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) {
       NameDescriptor typenamed=cn.getTypeName().getName();
       String typename=typenamed.toString();
-      TypeDescriptor ntd=new TypeDescriptor(typeutil.getClass(typename));
+      TypeDescriptor ntd=new TypeDescriptor(getClass(typename));
       cn.setType(ntd);
     }
 
@@ -422,12 +584,51 @@ public class SemanticCheck {
       fd=FieldDescriptor.arrayLength;
     else
       fd=(FieldDescriptor) ltd.getClassDesc().getFieldTable().get(fieldname);
+    if(state.MGC) {
+      // TODO add version for normal Java later
+    if(ltd.isStatic()) {
+      if(ltd.getClassDesc().isEnum()) {
+        int value = ltd.getClassDesc().getEnumConstant(fieldname);
+        if(-1 == value) {
+          // check if this field is an enum constant
+          throw new Error(fieldname + " is not an enum constant in "+fan.printNode(0)+" in "+md);
+        }
+        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()) {
+        // 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);
+      }
+    } 
+    }
     if (fd==null)
       throw new Error("Unknown field "+fieldname + " in "+fan.printNode(0)+" in "+md);
-    fan.setField(fd);
-    if (td!=null)
+
+    if (fd.getType().iswrapper()) {
+      FieldAccessNode fan2=new FieldAccessNode(left, fieldname);
+      fan2.setField(fd);
+      fan.left=fan2;
+      fan.fieldname="value";
+
+      ExpressionNode leftwr=fan.getExpression();
+      TypeDescriptor ltdwr=leftwr.getType();
+      String fieldnamewr=fan.getFieldName();
+      FieldDescriptor fdwr=(FieldDescriptor) ltdwr.getClassDesc().getFieldTable().get(fieldnamewr);
+      fan.setField(fdwr);
+      if (fdwr==null)
+         throw new Error("Unknown field "+fieldnamewr + " in "+fan.printNode(0)+" in "+md);
+    } else {
+      fan.setField(fd);
+    }
+    if (td!=null) {
       if (!typeutil.isSuperorType(td,fan.getType()))
        throw new Error("Field node returns "+fan.getType()+", but need "+td);
+    }
   }
 
   void checkArrayAccessNode(Descriptor md, SymbolTable nametable, ArrayAccessNode aan, TypeDescriptor td) {
@@ -436,6 +637,9 @@ public class SemanticCheck {
 
     checkExpressionNode(md,nametable,aan.getIndex(),new TypeDescriptor(TypeDescriptor.INT));
     TypeDescriptor ltd=left.getType();
+    if (ltd.dereference().iswrapper()) {
+      aan.wrappertype=((FieldDescriptor)ltd.dereference().getClassDesc().getFieldTable().get("value")).getType();
+    }
 
     if (td!=null)
       if (!typeutil.isSuperorType(td,aan.getType()))
@@ -460,12 +664,29 @@ public class SemanticCheck {
     } else if (o instanceof Character) {
       ln.setType(new TypeDescriptor(TypeDescriptor.CHAR));
     } else if (o instanceof String) {
-      ln.setType(new TypeDescriptor(typeutil.getClass(TypeUtil.StringClass)));
+      ln.setType(new TypeDescriptor(getClass(TypeUtil.StringClass)));
     }
 
     if (td!=null)
-      if (!typeutil.isSuperorType(td,ln.getType()))
-       throw new Error("Field node returns "+ln.getType()+", but need "+td);
+      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) {
@@ -480,13 +701,65 @@ public class SemanticCheck {
       String varname=nd.toString();
       Descriptor d=(Descriptor)nametable.get(varname);
       if (d==null) {
-       throw new Error("Name "+varname+" undefined in: "+md);
+        if(state.MGC) {
+          // TODO add version for normal Java later
+        ClassDescriptor cd = null;
+        if(((MethodDescriptor)md).isStaticBlock()) {
+          // this is a static block, all the accessed fields should be static field
+          cd = ((MethodDescriptor)md).getClassDesc();
+          SymbolTable fieldtbl = cd.getFieldTable();
+          FieldDescriptor fd=(FieldDescriptor)fieldtbl.get(varname);
+          if((fd == null) || (!fd.isStatic())){
+            // 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);
+            nn.setClassDesc(cd);
+            return;
+          }
+        } else {
+          cd=getClass(varname);
+          if(cd != null) {
+            // this is a class name
+            nn.setClassDesc(cd);
+            return;
+          } else {
+            throw new Error("Name "+varname+" undefined in: "+md);
+          }
+        }
+        } else {
+          throw new Error("Name "+varname+" undefined in: "+md);
+        }
       }
       if (d instanceof VarDescriptor) {
        nn.setVar(d);
       } else if (d instanceof FieldDescriptor) {
-       nn.setField((FieldDescriptor)d);
-       nn.setVar((VarDescriptor)nametable.get("this"));        /* Need a pointer to this */
+       FieldDescriptor fd=(FieldDescriptor)d;
+       if (fd.getType().iswrapper()) {
+         String id=nd.getIdentifier();
+         NameDescriptor base=nd.getBase();
+         NameNode n=new NameNode(nn.getName());
+         n.setField(fd);
+         n.setVar((VarDescriptor)nametable.get("this"));        /* Need a pointer to this */
+         FieldAccessNode fan=new FieldAccessNode(n,"value");
+         FieldDescriptor fdval=(FieldDescriptor) fd.getType().getClassDesc().getFieldTable().get("value");
+         fan.setField(fdval);
+         nn.setExpression(fan);
+       } else {
+         nn.setField(fd);
+         nn.setVar((VarDescriptor)nametable.get("this"));        /* Need a pointer to this */
+       }
       } else if (d instanceof TagVarDescriptor) {
        nn.setVar(d);
       } else throw new Error("Wrong type of descriptor");
@@ -496,14 +769,101 @@ public class SemanticCheck {
     }
   }
 
+  void checkOffsetNode(Descriptor md, SymbolTable nameTable, OffsetNode ofn, TypeDescriptor td) {
+    TypeDescriptor ltd=ofn.td;
+    checkTypeDescriptor(ltd);
+    
+    String fieldname = ofn.fieldname;
+    FieldDescriptor fd=null;
+    if (ltd.isArray()&&fieldname.equals("length")) {
+      fd=FieldDescriptor.arrayLength;
+    } else {
+      fd=(FieldDescriptor) ltd.getClassDesc().getFieldTable().get(fieldname);
+    }
+
+    ofn.setField(fd);
+    checkField(ltd.getClassDesc(), fd);
+
+    if (fd==null)
+      throw new Error("Unknown field "+fieldname + " in "+ofn.printNode(1)+" in "+md);
+
+    if (td!=null) {
+      if (!typeutil.isSuperorType(td, ofn.getType())) {
+       System.out.println(td);
+       System.out.println(ofn.getType());
+       throw new Error("Type of rside not compatible with type of lside"+ofn.printNode(0));
+      }
+    }
+  }
+
+
+  void checkTertiaryNode(Descriptor md, SymbolTable nametable, TertiaryNode tn, TypeDescriptor td) {
+    checkExpressionNode(md, nametable, tn.getCond(), new TypeDescriptor(TypeDescriptor.BOOLEAN));
+    checkExpressionNode(md, nametable, tn.getTrueExpr(), td );
+    checkExpressionNode(md, nametable, tn.getFalseExpr(), td );
+  }
+
+  void checkInstanceOfNode(Descriptor md, SymbolTable nametable, InstanceOfNode tn, TypeDescriptor td) {
+    if (td!=null&&!td.isBoolean())
+      throw new Error("Expecting type "+td+"for instanceof expression");
+    
+    checkTypeDescriptor(tn.getExprType());
+    checkExpressionNode(md, nametable, tn.getExpr(), null);
+  }
+
+  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==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) {
     boolean postinc=true;
     if (an.getOperation().getBaseOp()==null||
         (an.getOperation().getBaseOp().getOp()!=Operation.POSTINC&&
          an.getOperation().getBaseOp().getOp()!=Operation.POSTDEC))
       postinc=false;
-
-    if (!postinc)
+    if (!postinc)      
       checkExpressionNode(md, nametable, an.getSrc(),td);
     //TODO: Need check on validity of operation here
     if (!((an.getDest() instanceof FieldAccessNode)||
@@ -525,7 +885,7 @@ public class SemanticCheck {
 
     if (an.getDest().getType().isString()&&an.getOperation().getOp()==AssignOperation.PLUSEQ) {
       //String add
-      ClassDescriptor stringcl=typeutil.getClass(TypeUtil.StringClass);
+      ClassDescriptor stringcl=getClass(TypeUtil.StringClass);
       TypeDescriptor stringtd=new TypeDescriptor(stringcl);
       NameDescriptor nd=new NameDescriptor("String");
       NameDescriptor valuend=new NameDescriptor(nd, "valueOf");
@@ -539,11 +899,28 @@ public class SemanticCheck {
     }
 
     if (!postinc&&!typeutil.isSuperorType(an.getDest().getType(),an.getSrc().getType())) {
-      throw new Error("Type of rside ("+an.getSrc().getType()+") not compatible with type of lside ("+an.getDest().getType()+")"+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));
+      }
     }
   }
 
   void checkLoopNode(Descriptor md, SymbolTable nametable, LoopNode ln) {
+      loopstack.push(ln);
     if (ln.getType()==LoopNode.WHILELOOP||ln.getType()==LoopNode.DOWHILELOOP) {
       checkExpressionNode(md, nametable, ln.getCondition(), new TypeDescriptor(TypeDescriptor.BOOLEAN));
       checkBlockNode(md, nametable, ln.getBody());
@@ -561,6 +938,7 @@ public class SemanticCheck {
       checkBlockNode(md, bn.getVarTable(), ln.getBody());
       checkBlockNode(md, bn.getVarTable(), ln.getUpdate());
     }
+    loopstack.pop();
   }
 
 
@@ -577,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) {
@@ -695,11 +1078,17 @@ NextMethod:
       ExpressionNode en=min.getArg(i);
       checkExpressionNode(md,nametable,en,null);
       tdarray[i]=en.getType();
+      if(state.MGC && en.getType().isClass() && en.getType().getClassDesc().isEnum()) {
+        tdarray[i] = new TypeDescriptor(TypeDescriptor.INT);
+      }
     }
     TypeDescriptor typetolookin=null;
     if (min.getExpression()!=null) {
       checkExpressionNode(md,nametable,min.getExpression(),null);
       typetolookin=min.getExpression().getType();
+      //if (typetolookin==null)
+      //throw new Error(md+" has null return type");
+
     } else if (min.getBaseName()!=null) {
       String rootname=min.getBaseName().getRoot();
       if (rootname.equals("super")) {
@@ -712,7 +1101,11 @@ NextMethod:
        typetolookin=min.getExpression().getType();
       } else {
        //we have a type
-       ClassDescriptor cd=typeutil.getClass(min.getBaseName().getSymbol());
+       ClassDescriptor cd;
+       if (min.getBaseName().getSymbol().equals("System.out"))
+         cd=getClass("System");
+       else
+         cd=getClass(min.getBaseName().getSymbol());
        if (cd==null)
          throw new Error("md = "+ md.toString()+ "  "+min.getBaseName()+" undefined");
        typetolookin=new TypeDescriptor(cd);
@@ -825,6 +1218,9 @@ NextMethod:
        throw new Error();
       else if (ltd.isLong()||rtd.isLong())
        lefttype=new TypeDescriptor(TypeDescriptor.LONG);
+      // 090205 hack for boolean
+      else if (ltd.isBoolean()||rtd.isBoolean())
+       lefttype=new TypeDescriptor(TypeDescriptor.BOOLEAN);
       else
        lefttype=new TypeDescriptor(TypeDescriptor.INT);
       righttype=lefttype;
@@ -878,8 +1274,12 @@ NextMethod:
     case Operation.GTE:
       // 5.6.2 Binary Numeric Promotion
       //TODO unboxing of reference objects
-      if (!ltd.isNumber()||!rtd.isNumber())
-       throw new Error();
+      if (!ltd.isNumber()||!rtd.isNumber()) {
+       if (!ltd.isNumber())
+         throw new Error("Leftside is not number"+on.printNode(0)+"type="+ltd.toPrettyString());
+       if (!rtd.isNumber())
+         throw new Error("Rightside is not number"+on.printNode(0));
+      }
 
       if (ltd.isDouble()||rtd.isDouble())
        lefttype=new TypeDescriptor(TypeDescriptor.DOUBLE);
@@ -897,7 +1297,7 @@ NextMethod:
 
     case Operation.ADD:
       if (ltd.isString()||rtd.isString()) {
-       ClassDescriptor stringcl=typeutil.getClass(TypeUtil.StringClass);
+       ClassDescriptor stringcl=getClass(TypeUtil.StringClass);
        TypeDescriptor stringtd=new TypeDescriptor(stringcl);
        NameDescriptor nd=new NameDescriptor("String");
        NameDescriptor valuend=new NameDescriptor(nd, "valueOf");