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 aspect EnhancedForToBytecode { 011 // Code generation 012 syn lazy int EnhancedForStmt.cond_label() = hostType().constantPool().newLabel(); 013 syn lazy int EnhancedForStmt.update_label() = hostType().constantPool().newLabel(); 014 syn lazy int EnhancedForStmt.end_label() = hostType().constantPool().newLabel(); 015 016 syn lazy int EnhancedForStmt.extraLocalIndex() = localNum(); 017 eq EnhancedForStmt.getVariableDeclaration().localNum() = localNum() + (getExpr().type().isArrayDecl() ? 2 : 1); 018 eq EnhancedForStmt.getStmt().localNum() = getVariableDeclaration().localNum() + getVariableDeclaration().type().size(); 019 020 // EnhancedForStmt can be both break and continue target 021 eq EnhancedForStmt.break_label() = end_label(); 022 eq EnhancedForStmt.continue_label() = update_label(); 023 024 public void EnhancedForStmt.createBCode(CodeGeneration gen) { 025 if(getExpr().type().isArrayDecl()) { 026 getExpr().createBCode(gen); 027 gen.emitStoreReference(extraLocalIndex()); 028 IntegerLiteral.push(gen, 0); 029 gen.emit(Bytecode.ISTORE).add(extraLocalIndex()+1); 030 gen.addLabel(cond_label()); 031 gen.emit(Bytecode.ILOAD).add(extraLocalIndex()+1); 032 gen.emitLoadReference(extraLocalIndex()); 033 gen.emit(Bytecode.ARRAYLENGTH); 034 gen.emitCompare(Bytecode.IF_ICMPGE, end_label()); 035 gen.emitLoadReference(extraLocalIndex()); 036 gen.emit(Bytecode.ILOAD).add(extraLocalIndex()+1); 037 gen.emit(getExpr().type().componentType().arrayLoad()); 038 getExpr().type().componentType().emitCastTo(gen, getVariableDeclaration().type()); 039 getVariableDeclaration().type().emitStoreLocal(gen, getVariableDeclaration().localNum()); 040 getStmt().createBCode(gen); 041 gen.addLabel(update_label()); 042 gen.emit(Bytecode.IINC).add(extraLocalIndex()+1).add(1); 043 gen.emitGoto(cond_label()); 044 gen.addLabel(end_label()); 045 } 046 else { 047 getExpr().createBCode(gen); 048 iteratorMethod().emitInvokeMethod(gen, lookupType("java.lang", "Iterable")); 049 gen.emitStoreReference(extraLocalIndex()); 050 gen.addLabel(cond_label()); 051 gen.emitLoadReference(extraLocalIndex()); 052 hasNextMethod().emitInvokeMethod(gen, lookupType("java.util", "Iterator")); 053 gen.emitCompare(Bytecode.IFEQ, end_label()); 054 gen.emitLoadReference(extraLocalIndex()); 055 nextMethod().emitInvokeMethod(gen, lookupType("java.util", "Iterator")); 056 VariableDeclaration obj = getVariableDeclaration(); 057 if (!obj.type().boxed().isUnknown()) { 058 gen.emitCheckCast(obj.type().boxed()); 059 obj.type().boxed().emitCastTo(gen, obj.type()); 060 obj.type().emitStoreLocal(gen, obj.localNum()); 061 } else { 062 gen.emitCheckCast(obj.type()); 063 gen.emitStoreReference(obj.localNum()); 064 } 065 getStmt().createBCode(gen); 066 gen.addLabel(update_label()); 067 gen.emitGoto(cond_label()); 068 gen.addLabel(end_label()); 069 } 070 } 071 072 private MethodDecl EnhancedForStmt.iteratorMethod() { 073 TypeDecl typeDecl = lookupType("java.lang", "Iterable"); 074 for (Iterator iter = typeDecl.memberMethods("iterator").iterator(); iter.hasNext();) { 075 MethodDecl m = (MethodDecl)iter.next(); 076 if (m.getNumParameter() == 0) { 077 return m; 078 } 079 } 080 throw new Error("Could not find java.lang.Iterable.iterator()"); 081 } 082 private MethodDecl EnhancedForStmt.hasNextMethod() { 083 TypeDecl typeDecl = lookupType("java.util", "Iterator"); 084 for (Iterator iter = typeDecl.memberMethods("hasNext").iterator(); iter.hasNext();) { 085 MethodDecl m = (MethodDecl)iter.next(); 086 if (m.getNumParameter() == 0) { 087 return m; 088 } 089 } 090 throw new Error("Could not find java.util.Collection.hasNext()"); 091 } 092 private MethodDecl EnhancedForStmt.nextMethod() { 093 TypeDecl typeDecl = lookupType("java.util", "Iterator"); 094 for (Iterator iter = typeDecl.memberMethods("next").iterator(); iter.hasNext();) { 095 MethodDecl m = (MethodDecl)iter.next(); 096 if (m.getNumParameter() == 0) { 097 return m; 098 } 099 } 100 throw new Error("Could not find java.util.Collection.next()"); 101 } 102 }