start of new file
[IRC.git] / Robust / src / IR / Tree / SemanticCheck.java
index 12e5223c5a6d68345c1e19d9ff6fb4183c94fe2a..816ee712eae68d6d8fd7d74353d1903575c13b93 100644 (file)
@@ -57,7 +57,6 @@ public class SemanticCheck {
            checkTask(td);
            
        }
-
     }
 
     public void checkTypeDescriptor(TypeDescriptor td) {
@@ -102,7 +101,7 @@ public class SemanticCheck {
            //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");
+               throw new Error("Parameter "+varname+" in Flag Effects not declared in "+td);
            fe.setVar(vd);
 
            //Make sure it correspods to a class
@@ -203,7 +202,18 @@ public class SemanticCheck {
     }
 
     public void checkMethodBody(ClassDescriptor cd, MethodDescriptor md) {
-       //System.out.println("Processing method:"+md);
+       ClassDescriptor superdesc=cd.getSuperDesc();
+       if (superdesc!=null) {
+           Set possiblematches=superdesc.getMethodTable().getSet(md.getSymbol());
+           for(Iterator methodit=possiblematches.iterator();methodit.hasNext();) {
+               MethodDescriptor matchmd=(MethodDescriptor)methodit.next();
+               if (md.matches(matchmd)) {
+                   if (matchmd.getModifiers().isFinal()) {
+                       throw new Error("Try to override final method in method:"+md+" declared in  "+cd);
+                   }
+               }
+           }
+       }
        BlockNode bn=state.getMethodBody(md);
        checkBlockNode(md, md.getParameterTable(),bn);
     }
@@ -270,7 +280,7 @@ public class SemanticCheck {
            (d instanceof FieldDescriptor)) {
            nametable.add(vd);
        } else
-           throw new Error(vd.getSymbol()+" defined a second time");
+           throw new Error(vd.getSymbol()+" in "+md+" defined a second time");
        if (dn.getExpression()!=null)
            checkExpressionNode(md, nametable, dn.getExpression(), vd.getType());
     }
@@ -403,7 +413,7 @@ public class SemanticCheck {
        else
            fd=(FieldDescriptor) ltd.getClassDesc().getFieldTable().get(fieldname);
        if (fd==null)
-           throw new Error("Unknown field "+fieldname + " in "+fan.printNode(0));
+           throw new Error("Unknown field "+fieldname + " in "+fan.printNode(0)+" in "+md);
        fan.setField(fd);
        if (td!=null)
            if (!typeutil.isSuperorType(td,fan.getType()))
@@ -460,7 +470,7 @@ public class SemanticCheck {
            String varname=nd.toString();
            Descriptor d=(Descriptor)nametable.get(varname);
            if (d==null) {
-               throw new Error("Name "+varname+" undefined");
+               throw new Error("Name "+varname+" undefined in: "+md);
            }
            if (d instanceof VarDescriptor) {
                nn.setVar(d);
@@ -492,6 +502,7 @@ public class SemanticCheck {
            throw new Error("Bad lside in "+an.printNode(0));
        checkExpressionNode(md, nametable, an.getDest(), null);
 
+
        /* We want parameter variables to tasks to be immutable */
        if (md instanceof TaskDescriptor) {
            if (an.getDest() instanceof NameNode) {
@@ -503,6 +514,22 @@ public class SemanticCheck {
            }
        }
        
+       if (an.getDest().getType().isString()&&an.getOperation().getOp()==AssignOperation.PLUSEQ) {
+           //String add
+           ClassDescriptor stringcl=typeutil.getClass(TypeUtil.StringClass);
+           TypeDescriptor stringtd=new TypeDescriptor(stringcl);
+           NameDescriptor nd=new NameDescriptor("String");
+           NameDescriptor valuend=new NameDescriptor(nd, "valueOf");
+           
+           if (!(an.getSrc().getType().isString()&&(an.getSrc() instanceof OpNode))) {
+               MethodInvokeNode rightmin=new MethodInvokeNode(valuend);
+               rightmin.addArgument(an.getSrc());
+               an.right=rightmin;
+               checkExpressionNode(md, nametable, an.getSrc(), null);
+           }
+       }
+
+       
        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));
        }
@@ -599,14 +626,14 @@ public class SemanticCheck {
                if (bestmd==null)
                    bestmd=currmd;
                else {
-                   if (isMoreSpecific(currmd,bestmd)) {
+                   if (typeutil.isMoreSpecific(currmd,bestmd)) {
                        bestmd=currmd;
                    } else if (con.isGlobal()&&match(currmd, bestmd)) {
                        if (currmd.isGlobal()&&!bestmd.isGlobal())
                            bestmd=currmd;
                        else if (currmd.isGlobal()&&bestmd.isGlobal())
                            throw new Error();
-                   } else if (!isMoreSpecific(bestmd, currmd)) {
+                   } else if (!typeutil.isMoreSpecific(bestmd, currmd)) {
                        throw new Error("No method is most specific");
                    }
                    
@@ -614,33 +641,12 @@ public class SemanticCheck {
                }
            }
            if (bestmd==null)
-               throw new Error("No method found for "+con.printNode(0));
+               throw new Error("No method found for "+con.printNode(0)+" in "+md);
            con.setConstructor(bestmd);
        }
     }
 
 
-    /** Check to see if md1 is more specific than md2...  Informally
-       if md2 could always be called given the arguments passed into
-       md1 */
-
-    boolean isMoreSpecific(MethodDescriptor md1, MethodDescriptor md2) {
-       /* Checks if md1 is more specific than md2 */
-       if (md1.numParameters()!=md2.numParameters())
-           throw new Error();
-       for(int i=0;i<md1.numParameters();i++) {
-           if (!typeutil.isSuperorType(md2.getParamType(i), md1.getParamType(i)))
-               return false;
-       }
-       if (!typeutil.isSuperorType(md2.getReturnType(), md1.getReturnType()))
-               return false;
-
-       if (!typeutil.isSuperorType(md2.getClassDesc(), md1.getClassDesc()))
-               return false;
-
-       return true;
-    }
-
     /** Check to see if md1 is the same specificity as md2.*/
 
     boolean match(MethodDescriptor md1, MethodDescriptor md2) {
@@ -688,7 +694,10 @@ public class SemanticCheck {
            typetolookin=min.getExpression().getType();
        } else if (min.getBaseName()!=null) {
            String rootname=min.getBaseName().getRoot();
-           if (nametable.get(rootname)!=null) {
+           if (rootname.equals("super")) {
+               ClassDescriptor supercd=((MethodDescriptor)md).getClassDesc().getSuperDesc();
+               typetolookin=new TypeDescriptor(supercd);
+           } else if (nametable.get(rootname)!=null) {
                //we have an expression
                min.setExpression(translateNameDescriptorintoExpression(min.getBaseName()));
                checkExpressionNode(md, nametable, min.getExpression(), null);
@@ -700,6 +709,10 @@ public class SemanticCheck {
                    throw new Error(min.getBaseName()+" undefined");
                typetolookin=new TypeDescriptor(cd);
            }
+       } else if ((md instanceof MethodDescriptor)&&min.getMethodName().equals("super")) {
+           ClassDescriptor supercd=((MethodDescriptor)md).getClassDesc().getSuperDesc();
+           min.methodid=supercd.getSymbol();
+           typetolookin=new TypeDescriptor(supercd);
        } else if (md instanceof MethodDescriptor) {
            typetolookin=new TypeDescriptor(((MethodDescriptor)md).getClassDesc());
        } else {
@@ -727,16 +740,16 @@ public class SemanticCheck {
            if (bestmd==null)
                bestmd=currmd;
            else {
-               if (isMoreSpecific(currmd,bestmd)) {
+               if (typeutil.isMoreSpecific(currmd,bestmd)) {
                    bestmd=currmd;
-               } else if (!isMoreSpecific(bestmd, currmd))
+               } else if (!typeutil.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 :"+min.printNode(0));
+           throw new Error("No method found for :"+min.printNode(0)+" in class: " + classtolookin+" in "+md);
        min.setMethod(bestmd);
 
        if ((td!=null)&&(min.getType()!=null)&&!typeutil.isSuperorType(td,  min.getType()))
@@ -777,6 +790,21 @@ public class SemanticCheck {
            on.setType(new TypeDescriptor(TypeDescriptor.BOOLEAN));
            break;
 
+       case Operation.COMP:
+           // 5.6.2 Binary Numeric Promotion
+           //TODO unboxing of reference objects
+           if (ltd.isDouble())
+               throw new Error();
+           else if (ltd.isFloat())
+               throw new Error();
+           else if (ltd.isLong())
+               lefttype=new TypeDescriptor(TypeDescriptor.LONG);
+           else 
+               lefttype=new TypeDescriptor(TypeDescriptor.INT);
+           on.setLeftType(lefttype);
+           on.setType(lefttype);
+           break;
+
        case Operation.BIT_OR:
        case Operation.BIT_XOR:
        case Operation.BIT_AND:
@@ -797,6 +825,14 @@ public class SemanticCheck {
            on.setType(lefttype);
            break;
 
+       case Operation.ISAVAILABLE:
+           if (!(ltd.isPtr())) {
+               throw new Error("Can't use isavailable on non-pointers/non-parameters.");
+           }
+           lefttype=ltd;
+           on.setLeftType(lefttype);
+           on.setType(new TypeDescriptor(TypeDescriptor.BOOLEAN));
+           break;
        case Operation.EQUAL:
        case Operation.NOTEQUAL:
            // 5.6.2 Binary Numeric Promotion
@@ -805,8 +841,8 @@ public class SemanticCheck {
                if (!(ltd.isBoolean()&&rtd.isBoolean()))
                    throw new Error();
                righttype=lefttype=new TypeDescriptor(TypeDescriptor.BOOLEAN);
-           } else if (ltd.isPtr()||ltd.isArray()||rtd.isPtr()||rtd.isArray()) {
-               if (!((ltd.isPtr()||ltd.isArray())&&(rtd.isPtr()||rtd.isArray())))
+           } else if (ltd.isPtr()||rtd.isPtr()) {
+               if (!(ltd.isPtr()&&rtd.isPtr()))
                    throw new Error();
                righttype=rtd;
                lefttype=ltd;
@@ -850,8 +886,30 @@ public class SemanticCheck {
            break;
 
        case Operation.ADD:
-           //TODO: Need special case for strings eventually
-           
+           if (ltd.isString()||rtd.isString()) {
+               ClassDescriptor stringcl=typeutil.getClass(TypeUtil.StringClass);
+               TypeDescriptor stringtd=new TypeDescriptor(stringcl);
+               NameDescriptor nd=new NameDescriptor("String");
+               NameDescriptor valuend=new NameDescriptor(nd, "valueOf");
+               if (!(ltd.isString()&&(on.getLeft() instanceof OpNode))) {
+                   MethodInvokeNode leftmin=new MethodInvokeNode(valuend);
+                   leftmin.addArgument(on.getLeft());
+                   on.left=leftmin;
+                   checkExpressionNode(md, nametable, on.getLeft(), null);
+               }
+
+               if (!(rtd.isString()&&(on.getRight() instanceof OpNode))) {
+                   MethodInvokeNode rightmin=new MethodInvokeNode(valuend);
+                   rightmin.addArgument(on.getRight());
+                   on.right=rightmin;
+                   checkExpressionNode(md, nametable, on.getRight(), null);
+               }
+
+               on.setLeftType(stringtd);
+               on.setRightType(stringtd);
+               on.setType(stringtd);
+               break;
+           }
            
        case Operation.SUB:
        case Operation.MULT:
@@ -878,6 +936,7 @@ public class SemanticCheck {
 
        case Operation.LEFTSHIFT:
        case Operation.RIGHTSHIFT:
+       case Operation.URIGHTSHIFT:
            if (!rtd.isIntegerType())
                throw new Error();
            //5.6.1 Unary Numeric Promotion