001 import java.util.Collection; 002 import java.util.ArrayList; 003 004 aspect ErrorCheck { 005 syn lazy Collection Program.errors() { 006 Collection c = new ArrayList(); 007 collectErrors(c); 008 return c; 009 } 010 011 // generic traversal that collects errors in AST 012 public void ASTNode.collectErrors(Collection c) { 013 for(int i = 0; i < getNumChild(); i++) 014 getChild(i).collectErrors(c); 015 } 016 017 // add an error msg associated with a certain context 018 protected void ASTNode.error(Collection c, String s) { 019 //c.add(getLine(getStart()) + ": " + s); 020 c.add(s); 021 } 022 023 // add error for incompatible assignment 024 public void AssignStmt.collectErrors(Collection c) { 025 super.collectErrors(c); 026 if(!getValue().type().isSubtypeOf(getVariable().type())) 027 error(c, "Can not assign a variable of type " + getVariable().type().getName() + 028 " to a value of type " + getValue().type().getName()); 029 } 030 031 // add error for cyclic class hierarchy 032 public void ClassDecl.collectErrors(Collection c) { 033 super.collectErrors(c); 034 if(hasCycleOnSuperclassChain()) 035 error(c, "Cyclic inheritance chain for class " + getName()); 036 } 037 038 // add error for non-boolean condition in while 039 public void WhileStmt.collectErrors(Collection c) { 040 super.collectErrors(c); 041 if(!getCondition().type().isSubtypeOf(booleanType())) 042 error(c, "Condition must be a boolean expression"); 043 if(!getCondition().isValue()) 044 error(c, "Condition must be a value"); 045 } 046 047 // add error for the first unbound name in a, possibly qualified, name 048 public void IdUse.collectErrors(Collection c) { 049 super.collectErrors(c); 050 if(decl().isUnknown() && (!isQualified() || !qualifier().type().isUnknown())) 051 error(c, "Unknown identifier " + getName()); 052 } 053 054 // TODO: maybe move these attributes to another module? 055 eq Program.getBlock().isQualified() = false; 056 eq Program.getPredefinedType(int i).isQualified() = false; 057 eq Dot.getIdUse().isQualified() = true; 058 inh boolean IdUse.isQualified(); 059 inh boolean TypeDecl.isQualified(); 060 061 eq Program.getBlock().qualifier() { 062 throw new Error("Can not compute qualifier for non qualified names"); 063 } 064 eq Program.getPredefinedType(int i).qualifier() { 065 throw new Error("Can not compute qualifier for non qualified names"); 066 } 067 eq Dot.getIdUse().qualifier() = getObjectReference(); 068 inh Access IdUse.qualifier(); 069 inh Access TypeDecl.qualifier(); 070 071 }