001 /* 002 * The JastAdd Extensible Java Compiler (http://jastadd.org) is covered 003 * by the modified BSD License. You should have received a copy of the 004 * modified BSD license with this compiler. 005 * 006 * Copyright (c) 2005-2008, Torbjorn Ekman 007 * All rights reserved. 008 */ 009 010 import java.util.Collection; 011 import java.util.ArrayList; 012 013 aspect EnhancedFor { 014 // type checking 015 public void EnhancedForStmt.typeCheck() { 016 if (!getExpr().type().isArrayDecl() && !getExpr().type().isIterable()) { 017 error("type " + getExpr().type().name() + 018 " of expression in foreach is neither array type nor java.lang.Iterable"); 019 } 020 else if(getExpr().type().isArrayDecl() && !getExpr().type().componentType().assignConversionTo(getVariableDeclaration().type(), null)) 021 error("parameter of type " + getVariableDeclaration().type().typeName() + " can not be assigned an element of type " + getExpr().type().componentType().typeName()); 022 else if(getExpr().type().isIterable() && !getExpr().type().isUnknown()) { 023 MethodDecl iterator = (MethodDecl)getExpr().type().memberMethods("iterator").iterator().next(); 024 MethodDecl next = (MethodDecl)iterator.type().memberMethods("next").iterator().next(); 025 TypeDecl componentType = next.type(); 026 if(!componentType.assignConversionTo(getVariableDeclaration().type(), null)) 027 error("parameter of type " + getVariableDeclaration().type().typeName() + " can not be assigned an element of type " + componentType.typeName()); 028 } 029 } 030 031 /** 032 * True if type is java.lang.Iterable or subtype 033 As long as we use the 1.4 API we check for java.util.Collection instead. 034 */ 035 syn lazy boolean TypeDecl.isIterable() = instanceOf(lookupType("java.lang", "Iterable")); 036 037 // variable lookup 038 inh SimpleSet EnhancedForStmt.lookupVariable(String name); 039 eq EnhancedForStmt.getVariableDeclaration().lookupVariable(String name) = localLookupVariable(name); 040 eq EnhancedForStmt.getExpr().lookupVariable(String name) = localLookupVariable(name); 041 eq EnhancedForStmt.getStmt().lookupVariable(String name) = localLookupVariable(name); 042 043 eq EnhancedForStmt.getVariableDeclaration().nameType() = NameType.TYPE_NAME; 044 045 EnhancedForStmt implements VariableScope; 046 eq EnhancedForStmt.getVariableDeclaration().outerScope() = this; 047 eq EnhancedForStmt.getExpr().outerScope() = this; 048 eq EnhancedForStmt.getStmt().outerScope() = this; 049 050 syn SimpleSet EnhancedForStmt.localLookupVariable(String name) { 051 if(getVariableDeclaration().name().equals(name)) { 052 return SimpleSet.emptySet.add(getVariableDeclaration()); 053 } 054 return lookupVariable(name); 055 } 056 057 // pretty printing 058 public void EnhancedForStmt.toString(StringBuffer s) { 059 s.append(indent()); 060 s.append("for ("); 061 getVariableDeclaration().getModifiers().toString(s); 062 getVariableDeclaration().getTypeAccess().toString(s); 063 s.append(" " + getVariableDeclaration().name()); 064 s.append(" : "); 065 getExpr().toString(s); 066 s.append(") "); 067 getStmt().toString(s); 068 } 069 070 // some attributes for the parameter 071 eq EnhancedForStmt.getVariableDeclaration().isMethodParameter() = false; 072 eq EnhancedForStmt.getVariableDeclaration().isConstructorParameter() = false; 073 eq EnhancedForStmt.getVariableDeclaration().isExceptionHandlerParameter() = false; 074 075 eq EnhancedForStmt.targetOf(ContinueStmt stmt) = !stmt.hasLabel(); 076 eq EnhancedForStmt.targetOf(BreakStmt stmt) = !stmt.hasLabel(); 077 078 // Unreachable Statements 079 eq EnhancedForStmt.canCompleteNormally() = reachable(); 080 eq EnhancedForStmt.getStmt().reachable() = reachable(); 081 082 // Definite Assignment 083 eq EnhancedForStmt.isDAafter(Variable v) { 084 if(!getExpr().isDAafter(v)) 085 return false; 086 /* 087 for(Iterator iter = targetBreaks().iterator(); iter.hasNext(); ) { 088 BreakStmt stmt = (BreakStmt)iter.next(); 089 if(!stmt.isDAafterReachedFinallyBlocks(v)) 090 return false; 091 } 092 */ 093 return true; 094 } 095 eq EnhancedForStmt.getExpr().isDAbefore(Variable v) = 096 v == getVariableDeclaration() || isDAbefore(v); 097 eq EnhancedForStmt.getStmt().isDAbefore(Variable v) = getExpr().isDAafter(v); 098 099 eq EnhancedForStmt.isDUafter(Variable v) { 100 if(!getExpr().isDUafter(v)) 101 return false; 102 for(Iterator iter = targetBreaks().iterator(); iter.hasNext(); ) { 103 BreakStmt stmt = (BreakStmt)iter.next(); 104 if(!stmt.isDUafterReachedFinallyBlocks(v)) 105 return false; 106 } 107 return true; 108 } 109 eq EnhancedForStmt.getExpr().isDUbefore(Variable v) = 110 v != getVariableDeclaration() && isDUbefore(v); 111 eq EnhancedForStmt.getStmt().isDUbefore(Variable v) = getExpr().isDUafter(v); 112 113 eq EnhancedForStmt.getStmt().insideLoop() = true; 114 eq EnhancedForStmt.continueLabel() = true; 115 116 }