import java.util.Collection; import java.util.ArrayList; aspect ErrorCheck { public Collection Program.errors() { Collection c = new ArrayList(); collectErrors(c); return c; } // generic traversal that collects errors in AST public void ASTNode.collectErrors(Collection c) { for(int i = 0; i < getNumChild(); i++) getChild(i).collectErrors(c); } // add an error msg associated with a certain context protected void ASTNode.error(Collection c, String s) { //c.add(getLine(getStart()) + ": " + s); c.add(s); } // add error for incompatible assignment public void AssignStmt.collectErrors(Collection c) { super.collectErrors(c); if(!getValue().type().isSubtypeOf(getVariable().type())) error(c, "Can not assign a variable of type " + getVariable().type().getName() + " to a value of type " + getValue().type().getName()); } // add error for cyclic class hierarchy public void ClassDecl.collectErrors(Collection c) { super.collectErrors(c); if(hasCycleOnSuperclassChain()) error(c, "Cyclic inheritance chain for class " + getName()); } // add error for non-boolean condition in while public void WhileStmt.collectErrors(Collection c) { super.collectErrors(c); if(!getCondition().type().isSubtypeOf(booleanType())) error(c, "Condition must be a boolean expression"); if(!getCondition().isValue()) error(c, "Condition must be a value"); } // add error for the first unbound name in a, possibly qualified, name public void IdUse.collectErrors(Collection c) { super.collectErrors(c); if(decl().isUnknown() && (!isQualified() || !qualifier().type().isUnknown())) error(c, "Unknown identifier " + getName()); } // TODO: maybe move these attributes to another module? eq Program.getBlock().isQualified() = false; eq Program.getPredefinedType(int i).isQualified() = false; eq Dot.getIdUse().isQualified() = true; inh boolean IdUse.isQualified(); inh boolean TypeDecl.isQualified(); eq Program.getBlock().qualifier() { throw new Error("Can not compute qualifier for non qualified names"); } eq Program.getPredefinedType(int i).qualifier() { throw new Error("Can not compute qualifier for non qualified names"); } eq Dot.getIdUse().qualifier() = getObjectReference(); inh Access IdUse.qualifier(); inh Access TypeDecl.qualifier(); }