X-Git-Url: http://plrg.eecs.uci.edu/git/?p=IRC.git;a=blobdiff_plain;f=Robust%2Fsrc%2FIR%2FTree%2FSemanticCheck.java;h=a90adc06f55e8afcff8088ab6b44790eb841e2c8;hp=82c732ed29b4d459b802f25d4838fa06dc9b6adf;hb=eb17be02c22191b3fc7bdc335d9434ada68278de;hpb=4709a7687d982a20f67a140a9dfd8f2e5431812a diff --git a/Robust/src/IR/Tree/SemanticCheck.java b/Robust/src/IR/Tree/SemanticCheck.java index 82c732ed..a90adc06 100644 --- a/Robust/src/IR/Tree/SemanticCheck.java +++ b/Robust/src/IR/Tree/SemanticCheck.java @@ -1,73 +1,156 @@ package IR.Tree; import java.util.*; + import IR.*; public class SemanticCheck { State state; TypeUtil typeutil; - Stack loopstack; + Stack loopstack; + HashSet toanalyze; + HashMap completed; + + //This is the class mappings for a particular file based + //on the import names. Maps class to canonical class name. + static Hashtable singleImportMap; + public static final int NOCHECK=0; + public static final int REFERENCE=1; + public static final int INIT=2; + boolean checkAll; + + public boolean hasLayout(ClassDescriptor cd) { + return completed.get(cd)!=null&&completed.get(cd)==INIT; + } public SemanticCheck(State state, TypeUtil tu) { + this(state, tu, true); + } + + public SemanticCheck(State state, TypeUtil tu, boolean checkAll) { this.state=state; this.typeutil=tu; this.loopstack=new Stack(); + this.toanalyze=new HashSet(); + this.completed=new HashMap(); + this.checkAll=checkAll; } - 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); - //Set superclass link up - if (cd.getSuper()!=null) { - cd.setSuper(typeutil.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()); - } + public ClassDescriptor getClass(ClassDescriptor context, String classname) { + return getClass(context, classname, INIT); + } + public ClassDescriptor getClass(ClassDescriptor context, String classname, int fullcheck) { + if (context!=null) { +// System.out.println(context.getSymbol() + " is looking for " + classname); + Hashtable remaptable=context.getSingleImportMappings(); + classname=remaptable.containsKey(classname)?((String)remaptable.get(classname)):classname; + } + ClassDescriptor cd=typeutil.getClass(classname, toanalyze); + checkClass(cd, fullcheck); - /* 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); - } + return cd; + } - for(Iterator method_it=cd.getMethods(); method_it.hasNext();) { - MethodDescriptor md=(MethodDescriptor)method_it.next(); - checkMethod(cd,md); - } - } + public void checkClass(ClassDescriptor cd) { + checkClass(cd, INIT); + } - 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); + public void checkClass(ClassDescriptor cd, int fullcheck) { + if (!completed.containsKey(cd)||completed.get(cd)=REFERENCE&&oldstatus sifv = cd.getSuperInterface(); + for(int i = 0; i < sifv.size(); i++) { + ClassDescriptor superif = getClass(cd, sifv.elementAt(i), fullcheck); + if(!superif.isInterface()) { + throw new Error("Error! Class " + cd.getSymbol() + " implements non-interface " + superif.getSymbol()); + } + if (oldstatus=INIT) { + /* Check to see that fields are well typed */ + for(Iterator field_it=cd.getFields(); field_it.hasNext(); ) { + FieldDescriptor fd=(FieldDescriptor)field_it.next(); + checkField(cd,fd); + } + for(Iterator method_it=cd.getMethods(); method_it.hasNext(); ) { + MethodDescriptor md=(MethodDescriptor)method_it.next(); + 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); + //set the class mappings based on imports. + singleImportMap = cd.getSingleImportMappings(); + + // need to initialize typeutil object here...only place we can + // get class descriptors without first calling getclass + getClass(cd, 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; + } + } + } } } - public void checkTypeDescriptor(TypeDescriptor td) { + private void checkTypeDescriptor(ClassDescriptor cd, TypeDescriptor td) { if (td.isPrimitive()) return; /* Done */ else if (td.isClass()) { String name=td.toString(); - ClassDescriptor field_cd=(ClassDescriptor)state.getClassSymbolTable().get(name); + ClassDescriptor field_cd=checkAll?getClass(cd, name):getClass(cd, name, REFERENCE); + if (field_cd==null) throw new Error("Undefined class "+name); td.setClassDescriptor(field_cd); @@ -79,7 +162,7 @@ public class SemanticCheck { } public void checkField(ClassDescriptor cd, FieldDescriptor fd) { - checkTypeDescriptor(fd.getType()); + checkTypeDescriptor(cd, fd.getType()); } public void checkConstraintCheck(TaskDescriptor td, SymbolTable nametable, Vector ccs) { @@ -142,7 +225,7 @@ public class SemanticCheck { for(int i=0; i 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 { + loopstack.push(sbn); + checkBlockNode(md, nametable, sbn.getSwitchBlockStatement()); + loopstack.pop(); + 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; + + case Kind.NameNode: + checkNameNode(md,nametable,(NameNode)en,td); + return; + + case Kind.OpNode: + checkOpNode(md, nametable, (OpNode)en, td); + return; + } + throw new Error(); + } + void checkExpressionNode(Descriptor md, SymbolTable nametable, ExpressionNode en, TypeDescriptor td) { switch(en.kind()) { case Kind.AssignmentNode: @@ -393,24 +564,43 @@ public class SemanticCheck { return; case Kind.OffsetNode: - checkOffsetNode(md, nametable, (OffsetNode)en, new TypeDescriptor(TypeDescriptor.OFFSET)); + 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(((md instanceof MethodDescriptor)?((MethodDescriptor)md).getClassDesc():null), 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(((md instanceof MethodDescriptor)?((MethodDescriptor)md).getClassDesc():null), typenamed.toString())); cn.setType(ntd); } /* Check the type descriptor */ TypeDescriptor cast_type=cn.getType(); - checkTypeDescriptor(cast_type); + checkTypeDescriptor(((md instanceof MethodDescriptor)?((MethodDescriptor)md).getClassDesc():null),cast_type); /* Type check */ if (td!=null) { @@ -445,12 +635,54 @@ public class SemanticCheck { fd=FieldDescriptor.arrayLength; else fd=(FieldDescriptor) ltd.getClassDesc().getFieldTable().get(fieldname); + + if(ltd.isClassNameRef()) { + // the field access is using a class name directly + 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 == null) { + throw new Error("Could not find field "+ fieldname + " in "+fan.printNode(0)+" in "+md + " (Line: "+fan.getNumLine()+")"); + } 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.setNumLine(left.getNumLine()); + 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) { @@ -459,6 +691,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())) @@ -483,12 +718,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(null, TypeUtil.StringClass))); } 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) { @@ -496,20 +748,89 @@ public class SemanticCheck { if (nd.getBase()!=null) { /* Big hack */ /* Rewrite NameNode */ - ExpressionNode en=translateNameDescriptorintoExpression(nd); + ExpressionNode en=translateNameDescriptorintoExpression(nd,nn.getNumLine()); nn.setExpression(en); checkExpressionNode(md,nametable,en,td); } else { String varname=nd.toString(); + if(varname.equals("this")) { + // "this" + nn.setVar((VarDescriptor)nametable.get("this")); + return; + } Descriptor d=(Descriptor)nametable.get(varname); if (d==null) { - throw new Error("Name "+varname+" undefined in: "+md); + ClassDescriptor cd = null; + if((md instanceof MethodDescriptor) && ((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(((md instanceof MethodDescriptor)?((MethodDescriptor)md).getClassDesc():null), 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 { + // check if the var is a static field of the class + if(md instanceof MethodDescriptor) { + cd = ((MethodDescriptor)md).getClassDesc(); + FieldDescriptor fd = (FieldDescriptor)cd.getFieldTable().get(varname); + if((fd != null) && (fd.isStatic())) { + nn.setField(fd); + nn.setClassDesc(cd); + if (td!=null) + if (!typeutil.isSuperorType(td,nn.getType())) + throw new Error("Field node returns "+nn.getType()+", but need "+td); + return; + } else if(fd != null) { + throw new Error("Name "+varname+" should not be used in " + md); + } + } + cd=getClass(((md instanceof MethodDescriptor)?((MethodDescriptor)md).getClassDesc():null), varname); + if(cd != null) { + // this is a class name + nn.setClassDesc(cd); + return; + } 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.setNumLine(nn.getNumLine()); + n.setField(fd); + n.setVar((VarDescriptor)nametable.get("this")); /* Need a pointer to this */ + FieldAccessNode fan=new FieldAccessNode(n,"value"); + fan.setNumLine(n.getNumLine()); + 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"); @@ -520,30 +841,92 @@ public class SemanticCheck { } void checkOffsetNode(Descriptor md, SymbolTable nameTable, OffsetNode ofn, TypeDescriptor td) { - TypeDescriptor ltd = ofn.td; - //System.out.println("Testing TypeDescriptor ltd = " + ofn.td); - String fieldname = ofn.fieldname; - //System.out.println("Testing String fieldname = " + ofn.fieldname); - Descriptor d = (Descriptor) nameTable.get(fieldname); - //System.out.println("Testing Descriptor d = " + d.toString()); - - ClassDescriptor cd = null; - checkTypeDescriptor(ltd); - cd = ltd.getClassDesc(); - ofn.setClassDesc(cd); - //System.out.println("Testing for ClassDescriptor cd = " + cd.toString()); + TypeDescriptor ltd=ofn.td; + checkTypeDescriptor(((md instanceof MethodDescriptor)?((MethodDescriptor)md).getClassDesc():null),ltd); + String fieldname = ofn.fieldname; FieldDescriptor fd=null; if (ltd.isArray()&&fieldname.equals("length")) { fd=FieldDescriptor.arrayLength; } else { - fd=(FieldDescriptor) cd.getFieldTable().get(fieldname); + fd=(FieldDescriptor) ltd.getClassDesc().getFieldTable().get(fieldname); } - //System.out.println("Testing for FieldDescriptor fd = " + fd.toString()); + ofn.setField(fd); + checkField(ltd.getClassDesc(), fd); + if (fd==null) throw new Error("Unknown field "+fieldname + " in "+ofn.printNode(1)+" in "+md); - ofn.setType(td); + + 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(((md instanceof MethodDescriptor)?((MethodDescriptor)md).getClassDesc():null), tn.getExprType()); + checkExpressionNode(md, nametable, tn.getExpr(), null); + } + + void checkArrayInitializerNode(Descriptor md, SymbolTable nametable, ArrayInitializerNode ain, TypeDescriptor td) { + Vector vec_type = new Vector(); + 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); + //out_type.setStatic(); + } + ain.setType(out_type); } void checkAssignmentNode(Descriptor md, SymbolTable nametable, AssignmentNode an, TypeDescriptor td) { @@ -552,7 +935,6 @@ public class SemanticCheck { (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 @@ -575,13 +957,14 @@ public class SemanticCheck { if (an.getDest().getType().isString()&&an.getOperation().getOp()==AssignOperation.PLUSEQ) { //String add - ClassDescriptor stringcl=typeutil.getClass(TypeUtil.StringClass); + ClassDescriptor stringcl=getClass(null, 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.setNumLine(an.getSrc().getNumLine()); rightmin.addArgument(an.getSrc()); an.right=rightmin; checkExpressionNode(md, nametable, an.getSrc(), null); @@ -589,12 +972,45 @@ 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(); + if(an.getSrc().kind() == Kind.ArrayInitializerNode) { + if(dt.getArrayCount() != st.getArrayCount()) { + throw new Error("Type of rside ("+an.getSrc().getType().toPrettyString()+") not compatible with type of lside ("+an.getDest().getType().toPrettyString()+")"+an.printNode(0)); + } else { + do { + dt = dt.dereference(); + st = st.dereference(); + } while(dt.isArray()); + if((st.isByte() || st.isShort() || st.isChar() || st.isInt()) + && (dt.isByte() || dt.isShort() || dt.isChar() || dt.isInt() || dt.isLong())) { + return; + } else { + throw new Error("Type of rside ("+an.getSrc().getType().toPrettyString()+") not compatible with type of lside ("+an.getDest().getType().toPrettyString()+")"+an.printNode(0)); + } + } + } else { + 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("Type of rside ("+an.getSrc().getType().toPrettyString()+") not compatible with type of lside ("+an.getDest().getType().toPrettyString()+")"+an.printNode(0)); + } + } 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); + 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()); @@ -616,92 +1032,98 @@ public class SemanticCheck { } - void checkCreateObjectNode(Descriptor md, SymbolTable nametable, CreateObjectNode con, TypeDescriptor td) { - TypeDescriptor[] tdarray=new TypeDescriptor[con.numArgs()]; - for(int i=0; i