Add beginning of support for dsm
[IRC.git] / Robust / src / IR / Tree / SemanticCheck.java
index 680603c034000ea1008cc9f3fe10a3858bd9aaff..af01c8861d89642ae9d29232572c2719d0a78cdc 100644 (file)
@@ -18,20 +18,24 @@ public class SemanticCheck {
        // Do descriptors first
        while(it.hasNext()) {
            ClassDescriptor cd=(ClassDescriptor)it.next();
-           System.out.println("Checking class: "+cd);
+           //System.out.println("Checking class: "+cd);
            //Set superclass link up
            if (cd.getSuper()!=null) {
                cd.setSuper(typeutil.getClass(cd.getSuper()));
-               // Link together Field and Method tables
+               // 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());
            }
            
+           /* 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);
+               //System.out.println("Checking field: "+fd);
                checkField(cd,fd);
            }
+
            for(Iterator method_it=cd.getMethods();method_it.hasNext();) {
                MethodDescriptor md=(MethodDescriptor)method_it.next();
                checkMethod(cd,md);
@@ -47,26 +51,137 @@ public class SemanticCheck {
                checkMethodBody(cd,md);
            }
        }
+
+       for(Iterator task_it=state.getTaskSymbolTable().getDescriptorsIterator();task_it.hasNext();) {
+           TaskDescriptor td=(TaskDescriptor)task_it.next();
+           checkTask(td);
+           
+       }
+
     }
 
     public void checkTypeDescriptor(TypeDescriptor td) {
        if (td.isPrimitive())
            return; /* Done */
-       if (td.isClass()) {
+       else if (td.isClass()) {
            String name=td.toString();
            ClassDescriptor field_cd=(ClassDescriptor)state.getClassSymbolTable().get(name);
            if (field_cd==null)
                throw new Error("Undefined class "+name);
            td.setClassDescriptor(field_cd);
            return;
-       }
-       throw new Error();
+       } else if (td.isTag())
+           return;
+       else
+           throw new Error();
     }
 
     public void checkField(ClassDescriptor cd, FieldDescriptor fd) {
        checkTypeDescriptor(fd.getType());
     }
 
+    public void checkConstraintCheck(TaskDescriptor td, SymbolTable nametable, Vector ccs) {
+       if (ccs==null)
+           return; /* No constraint checks to check */
+       for(int i=0;i<ccs.size();i++) {
+           ConstraintCheck cc=(ConstraintCheck) ccs.get(i);
+           
+           for(int j=0;j<cc.numArgs();j++) {
+               ExpressionNode en=cc.getArg(j);
+               checkExpressionNode(td,nametable,en,null);
+           }
+       }
+    }
+
+    public void checkFlagEffects(TaskDescriptor td, Vector vfe, SymbolTable nametable) {
+       if (vfe==null)
+           return; /* No flag effects to check */
+       for(int i=0;i<vfe.size();i++) {
+           FlagEffects fe=(FlagEffects) vfe.get(i);
+           String varname=fe.getName();
+           //Make sure the variable is declared as a parameter to the task
+           VarDescriptor vd=(VarDescriptor)td.getParameterTable().get(varname);
+           if (vd==null)
+               throw new Error("Parameter "+varname+" in Flag Effects not declared");
+           fe.setVar(vd);
+
+           //Make sure it correspods to a class
+           TypeDescriptor type_d=vd.getType();
+           if (!type_d.isClass())
+               throw new Error("Cannot have non-object argument for flag_effect");
+
+           ClassDescriptor cd=type_d.getClassDesc();
+           for(int j=0;j<fe.numEffects();j++) {
+               FlagEffect flag=fe.getEffect(j);
+               String name=flag.getName();
+               FlagDescriptor flag_d=(FlagDescriptor)cd.getFlagTable().get(name);
+               //Make sure the flag is declared
+               if (flag_d==null)
+                   throw new Error("Flag descriptor "+name+" undefined in class: "+cd.getSymbol());
+               if (flag_d.getExternal())
+                   throw new Error("Attempting to modify external flag: "+name);
+               flag.setFlag(flag_d);
+           }
+           for(int j=0;j<fe.numTagEffects();j++) {
+               TagEffect tag=fe.getTagEffect(j);
+               String name=tag.getName();
+               
+               Descriptor d=(Descriptor)nametable.get(name);
+               if (d==null)
+                   throw new Error("Tag descriptor "+name+" undeclared");
+               else if (!(d instanceof TagVarDescriptor))
+                   throw new Error(name+" is not a tag descriptor");
+               tag.setTag((TagVarDescriptor)d);
+           }
+       }
+    }
+
+    public void checkTask(TaskDescriptor td) {
+       for(int i=0;i<td.numParameters();i++) {
+           /* Check that parameter is well typed */
+           TypeDescriptor param_type=td.getParamType(i);
+           checkTypeDescriptor(param_type);
+
+           /* Check the parameter's flag expression is well formed */
+           FlagExpressionNode fen=td.getFlag(td.getParameter(i));
+           if (!param_type.isClass())
+               throw new Error("Cannot have non-object argument to a task");
+           ClassDescriptor cd=param_type.getClassDesc();
+           if (fen!=null)
+               checkFlagExpressionNode(cd, fen);
+       }
+
+       checkFlagEffects(td, td.getFlagEffects(),td.getParameterTable());
+       /* Check that the task code is valid */
+       BlockNode bn=state.getMethodBody(td);
+       checkBlockNode(td, td.getParameterTable(),bn);
+    }
+
+    public void checkFlagExpressionNode(ClassDescriptor cd, FlagExpressionNode fen) {
+       switch(fen.kind()) {
+       case Kind.FlagOpNode: 
+           {
+               FlagOpNode fon=(FlagOpNode)fen;
+               checkFlagExpressionNode(cd, fon.getLeft());
+               if (fon.getRight()!=null)
+                   checkFlagExpressionNode(cd, fon.getRight());
+               break;
+           }
+       case Kind.FlagNode:
+           {
+               FlagNode fn=(FlagNode)fen;
+               String name=fn.getFlagName();
+               FlagDescriptor fd=(FlagDescriptor)cd.getFlagTable().get(name);
+               if (fd==null)
+                   throw new Error("Undeclared flag: "+name);
+               fn.setFlag(fd);
+               break;
+           }
+       default:
+           throw new Error("Unrecognized FlagExpressionNode");
+       }
+    }
+
     public void checkMethod(ClassDescriptor cd, MethodDescriptor md) {
        /* Check return type */
        if (!md.isConstructor())
@@ -88,12 +203,12 @@ public class SemanticCheck {
     }
 
     public void checkMethodBody(ClassDescriptor cd, MethodDescriptor md) {
-       System.out.println("Processing method:"+md);
+       //System.out.println("Processing method:"+md);
        BlockNode bn=state.getMethodBody(md);
        checkBlockNode(md, md.getParameterTable(),bn);
     }
     
-    public void checkBlockNode(MethodDescriptor md, SymbolTable nametable, BlockNode bn) {
+    public void checkBlockNode(Descriptor md, SymbolTable nametable, BlockNode bn) {
        /* Link in the naming environment */
        bn.getVarTable().setParent(nametable);
        for(int i=0;i<bn.size();i++) {
@@ -102,7 +217,7 @@ public class SemanticCheck {
        }
     }
     
-    public void checkBlockStatementNode(MethodDescriptor md, SymbolTable nametable, BlockStatementNode bsn) {
+    public void checkBlockStatementNode(Descriptor md, SymbolTable nametable, BlockStatementNode bsn) {
        switch(bsn.kind()) {
        case Kind.BlockExpressionNode:
            checkBlockExpressionNode(md, nametable,(BlockExpressionNode)bsn);
@@ -111,6 +226,10 @@ public class SemanticCheck {
        case Kind.DeclarationNode:
            checkDeclarationNode(md, nametable, (DeclarationNode)bsn);
            return;
+
+       case Kind.TagDeclarationNode:
+           checkTagDeclarationNode(md, nametable, (TagDeclarationNode)bsn);
+           return;
            
        case Kind.IfStatementNode:
            checkIfStatementNode(md, nametable, (IfStatementNode)bsn);
@@ -124,18 +243,26 @@ public class SemanticCheck {
            checkReturnNode(md, nametable, (ReturnNode)bsn);
            return;
 
+       case Kind.TaskExitNode:
+           checkTaskExitNode(md, nametable, (TaskExitNode)bsn);
+           return;
+
        case Kind.SubBlockNode:
            checkSubBlockNode(md, nametable, (SubBlockNode)bsn);
            return;
+
+       case Kind.AtomicNode:
+           checkAtomicNode(md, nametable, (AtomicNode)bsn);
+           return;
        }
        throw new Error();
     }
 
-    void checkBlockExpressionNode(MethodDescriptor md, SymbolTable nametable, BlockExpressionNode ben) {
+    void checkBlockExpressionNode(Descriptor md, SymbolTable nametable, BlockExpressionNode ben) {
        checkExpressionNode(md, nametable, ben.getExpression(), null);
     }
 
-    void checkDeclarationNode(MethodDescriptor md, SymbolTable nametable,  DeclarationNode dn) {
+    void checkDeclarationNode(Descriptor md, SymbolTable nametable,  DeclarationNode dn) {
        VarDescriptor vd=dn.getVarDescriptor();
        checkTypeDescriptor(vd.getType());
        Descriptor d=nametable.get(vd.getSymbol());
@@ -147,27 +274,56 @@ public class SemanticCheck {
        if (dn.getExpression()!=null)
            checkExpressionNode(md, nametable, dn.getExpression(), vd.getType());
     }
+
+    void checkTagDeclarationNode(Descriptor md, SymbolTable nametable,  TagDeclarationNode dn) {
+       TagVarDescriptor vd=dn.getTagVarDescriptor();
+       Descriptor d=nametable.get(vd.getSymbol());
+       if ((d==null)||
+           (d instanceof FieldDescriptor)) {
+           nametable.add(vd);
+       } else
+           throw new Error(vd.getSymbol()+" defined a second time");
+    }
     
-    void checkSubBlockNode(MethodDescriptor md, SymbolTable nametable, SubBlockNode sbn) {
+    void checkSubBlockNode(Descriptor md, SymbolTable nametable, SubBlockNode sbn) {
+       checkBlockNode(md, nametable, sbn.getBlockNode());
+    }
+
+    void checkAtomicNode(Descriptor md, SymbolTable nametable, AtomicNode sbn) {
        checkBlockNode(md, nametable, sbn.getBlockNode());
     }
 
-    void checkReturnNode(MethodDescriptor md, SymbolTable nametable, ReturnNode rn) {
+    void checkReturnNode(Descriptor d, SymbolTable nametable, ReturnNode rn) {
+       if (d instanceof TaskDescriptor)
+           throw new Error("Illegal return appears in Task: "+d.getSymbol());
+       MethodDescriptor md=(MethodDescriptor)d;
        if (rn.getReturnExpression()!=null)
-           checkExpressionNode(md, nametable, rn.getReturnExpression(), md.getReturnType());
+           if (md.getReturnType()==null) 
+               throw new Error("Constructor can't return something.");
+           else if (md.getReturnType().isVoid())
+               throw new Error(md+" is void");
+           else
+               checkExpressionNode(md, nametable, rn.getReturnExpression(), md.getReturnType());
        else
            if (md.getReturnType()!=null&&!md.getReturnType().isVoid())
                throw new Error("Need to return something for "+md);
     }
 
-    void checkIfStatementNode(MethodDescriptor md, SymbolTable nametable, IfStatementNode isn) {
+    void checkTaskExitNode(Descriptor md, SymbolTable nametable, TaskExitNode ten) {
+       if (md instanceof MethodDescriptor)
+           throw new Error("Illegal taskexit appears in Method: "+md.getSymbol());
+       checkFlagEffects((TaskDescriptor)md, ten.getFlagEffects(),nametable);
+       checkConstraintCheck((TaskDescriptor) md, nametable, ten.getChecks());
+    }
+
+    void checkIfStatementNode(Descriptor md, SymbolTable nametable, IfStatementNode isn) {
        checkExpressionNode(md, nametable, isn.getCondition(), new TypeDescriptor(TypeDescriptor.BOOLEAN));
        checkBlockNode(md, nametable, isn.getTrueBlock());
        if (isn.getFalseBlock()!=null)
            checkBlockNode(md, nametable, isn.getFalseBlock());
     }
     
-    void checkExpressionNode(MethodDescriptor md, SymbolTable nametable, ExpressionNode en, TypeDescriptor td) {
+    void checkExpressionNode(Descriptor md, SymbolTable nametable, ExpressionNode en, TypeDescriptor td) {
        switch(en.kind()) {
         case Kind.AssignmentNode:
             checkAssignmentNode(md,nametable,(AssignmentNode)en,td);
@@ -181,6 +337,9 @@ public class SemanticCheck {
         case Kind.FieldAccessNode:
            checkFieldAccessNode(md,nametable,(FieldAccessNode)en,td);
            return;
+        case Kind.ArrayAccessNode:
+           checkArrayAccessNode(md,nametable,(ArrayAccessNode)en,td);
+           return;
         case Kind.LiteralNode:
            checkLiteralNode(md,nametable,(LiteralNode)en,td);
            return;
@@ -197,7 +356,7 @@ public class SemanticCheck {
        throw new Error();
     }
 
-    void checkCastNode(MethodDescriptor md, SymbolTable nametable, CastNode cn, TypeDescriptor td) {
+    void checkCastNode(Descriptor md, SymbolTable nametable, CastNode cn, TypeDescriptor td) {
        /* Get type descriptor */
        if (cn.getType()==null) {
            NameDescriptor typenamed=cn.getTypeName().getName();
@@ -224,27 +383,46 @@ public class SemanticCheck {
 
        if (typeutil.isSuperorType(etd,cast_type)) /* Cast may succeed */
            return;
-
+       if (typeutil.isCastable(etd, cast_type))
+           return;
+       
        /* Different branches */
        /* TODO: change if add interfaces */
        throw new Error("Cast will always fail\n"+cn.printNode(0));
     }
 
-    void checkFieldAccessNode(MethodDescriptor md, SymbolTable nametable, FieldAccessNode fan, TypeDescriptor td) {
+    void checkFieldAccessNode(Descriptor md, SymbolTable nametable, FieldAccessNode fan, TypeDescriptor td) {
        ExpressionNode left=fan.getExpression();
        checkExpressionNode(md,nametable,left,null);
        TypeDescriptor ltd=left.getType();
        String fieldname=fan.getFieldName();
-       FieldDescriptor fd=(FieldDescriptor) ltd.getClassDesc().getFieldTable().get(fieldname);
+
+       FieldDescriptor fd=null;
+       if (ltd.isArray()&&fieldname.equals("length"))
+           fd=FieldDescriptor.arrayLength;
+       else
+           fd=(FieldDescriptor) ltd.getClassDesc().getFieldTable().get(fieldname);
        if (fd==null)
-           throw new Error("Unknown field "+fieldname);
+           throw new Error("Unknown field "+fieldname + " in "+fan.printNode(0));
        fan.setField(fd);
        if (td!=null)
            if (!typeutil.isSuperorType(td,fan.getType()))
                throw new Error("Field node returns "+fan.getType()+", but need "+td);
     }
 
-    void checkLiteralNode(MethodDescriptor md, SymbolTable nametable, LiteralNode ln, TypeDescriptor td) {
+    void checkArrayAccessNode(Descriptor md, SymbolTable nametable, ArrayAccessNode aan, TypeDescriptor td) {
+       ExpressionNode left=aan.getExpression();
+       checkExpressionNode(md,nametable,left,null);
+
+       checkExpressionNode(md,nametable,aan.getIndex(),new TypeDescriptor(TypeDescriptor.INT));
+       TypeDescriptor ltd=left.getType();
+
+       if (td!=null)
+           if (!typeutil.isSuperorType(td,aan.getType()))
+               throw new Error("Field node returns "+aan.getType()+", but need "+td);
+    }
+
+    void checkLiteralNode(Descriptor md, SymbolTable nametable, LiteralNode ln, TypeDescriptor td) {
        /* Resolve the type */
        Object o=ln.getValue();
        if (ln.getTypeString().equals("null")) {
@@ -270,7 +448,7 @@ public class SemanticCheck {
                throw new Error("Field node returns "+ln.getType()+", but need "+td);
     }
 
-    void checkNameNode(MethodDescriptor md, SymbolTable nametable, NameNode nn, TypeDescriptor td) {
+    void checkNameNode(Descriptor md, SymbolTable nametable, NameNode nn, TypeDescriptor td) {
        NameDescriptor nd=nn.getName();
        if (nd.getBase()!=null) {
            /* Big hack */
@@ -285,30 +463,52 @@ public class SemanticCheck {
                throw new Error("Name "+varname+" undefined");
            }
            if (d instanceof VarDescriptor) {
-               nn.setVar((VarDescriptor)d);
+               nn.setVar(d);
            } else if (d instanceof FieldDescriptor) {
                nn.setField((FieldDescriptor)d);
                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");
            if (td!=null)
                if (!typeutil.isSuperorType(td,nn.getType()))
                    throw new Error("Field node returns "+nn.getType()+", but need "+td);
        }
     }
 
-    void checkAssignmentNode(MethodDescriptor md, SymbolTable nametable, AssignmentNode an, TypeDescriptor td) {
-       checkExpressionNode(md, nametable, an.getSrc() ,td);
+    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)
+           checkExpressionNode(md, nametable, an.getSrc() ,td);
        //TODO: Need check on validity of operation here
        if (!((an.getDest() instanceof FieldAccessNode)||
+             (an.getDest() instanceof ArrayAccessNode)||
              (an.getDest() instanceof NameNode)))
            throw new Error("Bad lside in "+an.printNode(0));
        checkExpressionNode(md, nametable, an.getDest(), null);
-       if (!typeutil.isSuperorType(an.getDest().getType(),an.getSrc().getType())) {
+
+       /* We want parameter variables to tasks to be immutable */
+       if (md instanceof TaskDescriptor) {
+           if (an.getDest() instanceof NameNode) {
+               NameNode nn=(NameNode)an.getDest();
+               if (nn.getVar()!=null) {
+                   if (((TaskDescriptor)md).getParameterTable().contains(nn.getVar().getSymbol()))
+                       throw new Error("Can't modify parameter "+nn.getVar()+ " to task "+td.getSymbol());
+               }
+           }
+       }
+       
+       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));
        }
     }
 
-    void checkLoopNode(MethodDescriptor md, SymbolTable nametable, LoopNode ln) {
+    void checkLoopNode(Descriptor md, SymbolTable nametable, LoopNode ln) {
        if (ln.getType()==LoopNode.WHILELOOP||ln.getType()==LoopNode.DOWHILELOOP) {
            checkExpressionNode(md, nametable, ln.getCondition(), new TypeDescriptor(TypeDescriptor.BOOLEAN));
            checkBlockNode(md, nametable, ln.getBody());
@@ -329,7 +529,7 @@ public class SemanticCheck {
     }
 
 
-    void checkCreateObjectNode(MethodDescriptor md, SymbolTable nametable, CreateObjectNode con, TypeDescriptor td) {
+    void checkCreateObjectNode(Descriptor md, SymbolTable nametable, CreateObjectNode con, TypeDescriptor td) {
        TypeDescriptor[] tdarray=new TypeDescriptor[con.numArgs()];
        for(int i=0;i<con.numArgs();i++) {
            ExpressionNode en=con.getArg(i);
@@ -339,43 +539,80 @@ public class SemanticCheck {
 
        TypeDescriptor typetolookin=con.getType();
        checkTypeDescriptor(typetolookin);
-       if (!typetolookin.isClass()) 
-           throw new Error();
 
-       ClassDescriptor classtolookin=typetolookin.getClassDesc();
-       System.out.println("Looking for "+typetolookin.getSymbol());
-       System.out.println(classtolookin.getMethodTable());
+       if (td!=null&&!typeutil.isSuperorType(td, typetolookin))
+           throw new Error(typetolookin + " isn't a "+td);
 
-       Set methoddescriptorset=classtolookin.getMethodTable().getSet(typetolookin.getSymbol());
-       MethodDescriptor bestmd=null;
-       NextMethod:
-       for(Iterator methodit=methoddescriptorset.iterator();methodit.hasNext();) {
-           MethodDescriptor currmd=(MethodDescriptor)methodit.next();
-           /* Need correct number of parameters */
-           System.out.println("Examining: "+currmd);
-           if (con.numArgs()!=currmd.numParameters())
-               continue;
-           for(int i=0;i<con.numArgs();i++) {
-               if (!typeutil.isSuperorType(currmd.getParamType(i),tdarray[i]))
-                   continue NextMethod;
+
+
+       /* Check flag effects */
+       if (con.getFlagEffects()!=null) {
+           FlagEffects fe=con.getFlagEffects();
+           ClassDescriptor cd=typetolookin.getClassDesc();
+           
+           for(int j=0;j<fe.numEffects();j++) {
+               FlagEffect flag=fe.getEffect(j);
+               String name=flag.getName();
+               FlagDescriptor flag_d=(FlagDescriptor)cd.getFlagTable().get(name);
+               //Make sure the flag is declared
+               if (flag_d==null)
+                   throw new Error("Flag descriptor "+name+" undefined in class: "+cd.getSymbol());
+               if (flag_d.getExternal())
+                   throw new Error("Attempting to modify external flag: "+name);
+               flag.setFlag(flag_d);
            }
-           /* Method okay so far */
-           if (bestmd==null)
-               bestmd=currmd;
-           else {
-               if (isMoreSpecific(currmd,bestmd)) {
-                   bestmd=currmd;
-               } else if (!isMoreSpecific(bestmd, currmd))
-                   throw new Error("No method is most specific");
+           for(int j=0;j<fe.numTagEffects();j++) {
+               TagEffect tag=fe.getTagEffect(j);
+               String name=tag.getName();
                
-               /* Is this more specific than bestmd */
+               Descriptor d=(Descriptor)nametable.get(name);
+               if (d==null)
+                   throw new Error("Tag descriptor "+name+" undeclared");
+               else if (!(d instanceof TagVarDescriptor))
+                   throw new Error(name+" is not a tag descriptor");
+               tag.setTag((TagVarDescriptor)d);
            }
        }
-       if (bestmd==null)
-           throw new Error("No method found for "+con.printNode(0));
-       con.setConstructor(bestmd);
 
-       
+
+       if ((!typetolookin.isClass())&&(!typetolookin.isArray())) 
+           throw new Error("Can't allocate primitive type:"+con.printNode(0));
+
+       if (!typetolookin.isArray()) {
+           //Array's don't need constructor calls
+           ClassDescriptor classtolookin=typetolookin.getClassDesc();
+           //System.out.println("Looking for "+typetolookin.getSymbol());
+           //System.out.println(classtolookin.getMethodTable());
+           
+           Set methoddescriptorset=classtolookin.getMethodTable().getSet(typetolookin.getSymbol());
+           MethodDescriptor bestmd=null;
+       NextMethod:
+           for(Iterator methodit=methoddescriptorset.iterator();methodit.hasNext();) {
+               MethodDescriptor currmd=(MethodDescriptor)methodit.next();
+               /* Need correct number of parameters */
+               //System.out.println("Examining: "+currmd);
+               if (con.numArgs()!=currmd.numParameters())
+                   continue;
+               for(int i=0;i<con.numArgs();i++) {
+                   if (!typeutil.isSuperorType(currmd.getParamType(i),tdarray[i]))
+                       continue NextMethod;
+               }
+               /* Method okay so far */
+               if (bestmd==null)
+                   bestmd=currmd;
+               else {
+                   if (isMoreSpecific(currmd,bestmd)) {
+                       bestmd=currmd;
+                   } else if (!isMoreSpecific(bestmd, currmd))
+                       throw new Error("No method is most specific");
+                   
+                   /* Is this more specific than bestmd */
+               }
+           }
+           if (bestmd==null)
+               throw new Error("No method found for "+con.printNode(0));
+           con.setConstructor(bestmd);
+       }
     }
 
 
@@ -393,6 +630,10 @@ public class SemanticCheck {
        }
        if (!typeutil.isSuperorType(md2.getReturnType(), md1.getReturnType()))
                return false;
+
+       if (!typeutil.isSuperorType(md2.getClassDesc(), md1.getClassDesc()))
+               return false;
+
        return true;
     }
 
@@ -406,7 +647,7 @@ public class SemanticCheck {
     }
 
 
-    void checkMethodInvokeNode(MethodDescriptor md, SymbolTable nametable, MethodInvokeNode min, TypeDescriptor td) {
+    void checkMethodInvokeNode(Descriptor md, SymbolTable nametable, MethodInvokeNode min, TypeDescriptor td) {
        /*Typecheck subexpressions
          and get types for expressions*/
 
@@ -434,13 +675,17 @@ public class SemanticCheck {
                    throw new Error(min.getBaseName()+" undefined");
                typetolookin=new TypeDescriptor(cd);
            }
+       } else if (md instanceof MethodDescriptor) {
+           typetolookin=new TypeDescriptor(((MethodDescriptor)md).getClassDesc());
        } else {
-           typetolookin=new TypeDescriptor(md.getClassDesc());
+           /* If this a task descriptor we throw an error at this point */
+           throw new Error("Unknown method call to "+min.getMethodName()+"in task"+md.getSymbol());
        }
        if (!typetolookin.isClass()) 
-           throw new Error();
+           throw new Error("Error with method call to "+min.getMethodName());
        ClassDescriptor classtolookin=typetolookin.getClassDesc();
-       System.out.println("Method name="+min.getMethodName());
+       //System.out.println("Method name="+min.getMethodName());
+
        Set methoddescriptorset=classtolookin.getMethodTable().getSet(min.getMethodName());
        MethodDescriptor bestmd=null;
        NextMethod:
@@ -468,6 +713,9 @@ public class SemanticCheck {
        if (bestmd==null)
            throw new Error("No method found for :"+min.printNode(0));
        min.setMethod(bestmd);
+
+       if ((td!=null)&&(min.getType()!=null)&&!typeutil.isSuperorType(td,  min.getType()))
+           throw new Error(min.getType()+ " is not equal to or a subclass of "+td);
        /* Check whether we need to set this parameter to implied this */
        if (!bestmd.isStatic()) {
            if (min.getExpression()==null) {
@@ -476,11 +724,10 @@ public class SemanticCheck {
                checkExpressionNode(md, nametable, min.getExpression(), null);
            }
        }
-
     }
 
 
-    void checkOpNode(MethodDescriptor md, SymbolTable nametable, OpNode on, TypeDescriptor td) {
+    void checkOpNode(Descriptor md, SymbolTable nametable, OpNode on, TypeDescriptor td) {
        checkExpressionNode(md, nametable, on.getLeft(), null);
        if (on.getRight()!=null)
            checkExpressionNode(md, nametable, on.getRight(), null);
@@ -493,11 +740,15 @@ public class SemanticCheck {
        switch(op.getOp()) {
        case Operation.LOGIC_OR:
        case Operation.LOGIC_AND:
-           if (!(ltd.isBoolean()&&rtd.isBoolean()))
+           if (!(rtd.isBoolean()))
+               throw new Error();
+           on.setRightType(rtd);
+       case Operation.LOGIC_NOT:
+           if (!(ltd.isBoolean()))
                throw new Error();
            //no promotion
            on.setLeftType(ltd);
-           on.setRightType(rtd);
+
            on.setType(new TypeDescriptor(TypeDescriptor.BOOLEAN));
            break;
 
@@ -529,8 +780,8 @@ public class SemanticCheck {
                if (!(ltd.isBoolean()&&rtd.isBoolean()))
                    throw new Error();
                righttype=lefttype=new TypeDescriptor(TypeDescriptor.BOOLEAN);
-           } else if (ltd.isPtr()||rtd.isPtr()) {
-               if (!(ltd.isPtr()&&rtd.isPtr()))
+           } else if (ltd.isPtr()||ltd.isArray()||rtd.isPtr()||rtd.isArray()) {
+               if (!((ltd.isPtr()||ltd.isArray())&&(rtd.isPtr()||rtd.isArray())))
                    throw new Error();
                righttype=rtd;
                lefttype=ltd;
@@ -583,7 +834,7 @@ public class SemanticCheck {
        case Operation.MOD:
            // 5.6.2 Binary Numeric Promotion
            //TODO unboxing of reference objects
-           if (!ltd.isNumber()||!rtd.isNumber())
+           if (ltd.isArray()||rtd.isArray()||!ltd.isNumber()||!rtd.isNumber())
                throw new Error("Error in "+on.printNode(0));
 
            if (ltd.isDouble()||rtd.isDouble())
@@ -615,10 +866,10 @@ public class SemanticCheck {
                throw new Error();
        case Operation.UNARYPLUS:
        case Operation.UNARYMINUS:
-       case Operation.POSTINC:
-       case Operation.POSTDEC:
-       case Operation.PREINC:
-       case Operation.PREDEC:
+           /*  case Operation.POSTINC:
+               case Operation.POSTDEC:
+               case Operation.PREINC:
+               case Operation.PREDEC:*/
            if (!ltd.isNumber())
                throw new Error();
            //5.6.1 Unary Numeric Promotion
@@ -630,11 +881,9 @@ public class SemanticCheck {
            on.setType(lefttype);
            break;
        default:
-           throw new Error();
+           throw new Error(op.toString());
        }
-
-     
-
+   
        if (td!=null)
            if (!typeutil.isSuperorType(td, on.getType())) {
                System.out.println(td);