From 78e913762f56d659426e1a0b48aedfa136b53741 Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Sat, 8 Oct 2011 09:42:25 +0200 Subject: [PATCH] arrays iterators --- .../jet/codegen/ExpressionCodegen.java | 14 +- .../jetbrains/jet/codegen/JetTypeMapper.java | 36 +-- .../org/jetbrains/jet/codegen/StackValue.java | 3 + .../jet/codegen/intrinsics/ArrayIterator.java | 65 +++++ .../codegen/intrinsics/IntrinsicMethods.java | 11 + compiler/frontend/src/jet/Library.jet | 2 +- .../jet/lang/types/JetStandardLibrary.java | 3 +- .../jetbrains/jet/codegen/ArrayGenTest.java | 28 ++ stdlib/src/jet/arrays/ArrayIterator.java | 274 ++++++++++++++++++ 9 files changed, 410 insertions(+), 26 deletions(-) create mode 100644 compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/ArrayIterator.java create mode 100644 stdlib/src/jet/arrays/ArrayIterator.java diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 91c126fd77d..6caf932976d 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -52,8 +52,10 @@ public class ExpressionCodegen extends JetVisitor { private final InstructionAdapter v; private final FrameMap myMap; private final JetTypeMapper typeMapper; + private final GenerationState state; private final Type returnType; + private final BindingContext bindingContext; private final Map typeParameterExpressions = new HashMap(); private final ClassContext context; @@ -74,6 +76,14 @@ public class ExpressionCodegen extends JetVisitor { this.intrinsics = state.getIntrinsics(); } + public GenerationState getState() { + return state; + } + + public BindingContext getBindingContext() { + return bindingContext; + } + public JetTypeMapper getTypeMapper() { return state.getTypeMapper(); } @@ -921,7 +931,7 @@ public class ExpressionCodegen extends JetVisitor { callableMethod = ClosureCodegen.asCallableMethod((FunctionDescriptor) fd); } else if (fd instanceof FunctionDescriptor) { - callableMethod = ClosureCodegen.asCallableMethod((FunctionDescriptor) fd); + callableMethod = typeMapper.mapToCallableMethod((FunctionDescriptor) fd, null); } else { throw new UnsupportedOperationException("can't resolve declaration to callable: " + fd); @@ -2076,7 +2086,7 @@ public class ExpressionCodegen extends JetVisitor { } } - void generateTypeInfo(JetType jetType) { + public void generateTypeInfo(JetType jetType) { String knownTypeInfo = typeMapper.isKnownTypeInfo(jetType); if(knownTypeInfo != null) { v.getstatic("jet/typeinfo/TypeInfo", knownTypeInfo, "Ljet/typeinfo/TypeInfo;"); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java index 2b6513a7a0f..a78333d30c9 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -2,7 +2,6 @@ package org.jetbrains.jet.codegen; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; -import jet.Function1; import jet.JetObject; import jet.typeinfo.TypeInfo; import jet.typeinfo.TypeInfoProjection; @@ -58,6 +57,7 @@ public class JetTypeMapper { private final HashMap knowTypes = new HashMap(); public static final Type TYPE_FUNCTION1 = Type.getObjectType("jet/Function1"); + public static final Type TYPE_ITERATOR = Type.getObjectType("jet/Iterator"); public JetTypeMapper(JetStandardLibrary standardLibrary, BindingContext bindingContext) { this.standardLibrary = standardLibrary; @@ -464,17 +464,16 @@ public class JetTypeMapper { } - private Method mapSignature(JetNamedFunction f, List valueParameterTypes, OwnerKind kind) { - final JetTypeReference receiverTypeRef = f.getReceiverTypeRef(); - final JetType receiverType = receiverTypeRef == null ? null : bindingContext.get(BindingContext.TYPE, receiverTypeRef); - final List parameters = f.getValueParameters(); + private Method mapSignature(FunctionDescriptor f, List valueParameterTypes, OwnerKind kind) { + final ReceiverDescriptor receiverTypeRef = f.getReceiver(); + final JetType receiverType = receiverTypeRef == ReceiverDescriptor.NO_RECEIVER ? null : receiverTypeRef.getType(); + final List parameters = f.getValueParameters(); List parameterTypes = new ArrayList(); if (receiverType != null) { parameterTypes.add(mapType(receiverType)); } - FunctionDescriptor functionDescriptor = bindingContext.get(BindingContext.FUNCTION, f); if(kind == OwnerKind.TRAIT_IMPL) { - ClassDescriptor containingDeclaration = (ClassDescriptor) functionDescriptor.getContainingDeclaration(); + ClassDescriptor containingDeclaration = (ClassDescriptor) f.getContainingDeclaration(); JetType jetType = TraitImplBodyCodegen.getSuperClass(containingDeclaration, bindingContext); Type type = mapType(jetType); if(type.getInternalName().equals("java/lang/Object")) { @@ -484,24 +483,15 @@ public class JetTypeMapper { valueParameterTypes.add(type); parameterTypes.add(type); } - for (JetParameter parameter : parameters) { - final Type type = mapType(bindingContext.get(BindingContext.TYPE, parameter.getTypeReference())); + for (ValueParameterDescriptor parameter : parameters) { + final Type type = mapType(parameter.getOutType()); valueParameterTypes.add(type); parameterTypes.add(type); } for (int n = f.getTypeParameters().size(); n > 0; n--) { parameterTypes.add(TYPE_TYPEINFO); } - final JetTypeReference returnTypeRef = f.getReturnTypeRef(); - Type returnType; - if (returnTypeRef == null) { - assert functionDescriptor != null; - final JetType type = functionDescriptor.getReturnType(); - returnType = mapReturnType(type); - } - else { - returnType = mapReturnType(bindingContext.get(BindingContext.TYPE, returnTypeRef)); - } + Type returnType = mapReturnType(f.getReturnType()); return new Method(f.getName(), returnType, parameterTypes.toArray(new Type[parameterTypes.size()])); } @@ -515,9 +505,13 @@ public class JetTypeMapper { JetNamedFunction f = (JetNamedFunction) declaration; final FunctionDescriptor functionDescriptor = bindingContext.get(BindingContext.FUNCTION, f); assert functionDescriptor != null; + return mapToCallableMethod(functionDescriptor, kind); + } + + public CallableMethod mapToCallableMethod(FunctionDescriptor functionDescriptor, OwnerKind kind) { final DeclarationDescriptor functionParent = functionDescriptor.getContainingDeclaration(); final List valueParameterTypes = new ArrayList(); - Method descriptor = mapSignature(f, valueParameterTypes, kind); + Method descriptor = mapSignature(functionDescriptor.getOriginal(), valueParameterTypes, kind); String owner; int invokeOpcode; boolean needsReceiver; @@ -525,7 +519,7 @@ public class JetTypeMapper { if (functionParent instanceof NamespaceDescriptor) { owner = NamespaceCodegen.getJVMClassName(DescriptorRenderer.getFQName(functionParent)); invokeOpcode = Opcodes.INVOKESTATIC; - needsReceiver = f.getReceiverTypeRef() != null; + needsReceiver = functionDescriptor.getReceiver() != ReceiverDescriptor.NO_RECEIVER; } else if (functionParent instanceof ClassDescriptor) { ClassDescriptor containingClass = (ClassDescriptor) functionParent; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java index 7a7c280f8e1..f60fc9804cc 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java @@ -197,6 +197,9 @@ public abstract class StackValue { if (type.getSort() == Type.BOOLEAN) { v.checkcast(JetTypeMapper.JL_BOOLEAN_TYPE); } + else if (type.getSort() == Type.CHAR) { + v.checkcast(JetTypeMapper.JL_CHAR_TYPE); + } else { v.checkcast(JetTypeMapper.JL_NUMBER_TYPE); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/ArrayIterator.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/ArrayIterator.java new file mode 100644 index 00000000000..c61130a7b15 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/ArrayIterator.java @@ -0,0 +1,65 @@ +package org.jetbrains.jet.codegen.intrinsics; + +import com.intellij.psi.PsiElement; +import org.jetbrains.jet.codegen.ExpressionCodegen; +import org.jetbrains.jet.codegen.JetTypeMapper; +import org.jetbrains.jet.codegen.StackValue; +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; +import org.jetbrains.jet.lang.psi.JetCallExpression; +import org.jetbrains.jet.lang.psi.JetExpression; +import org.jetbrains.jet.lang.psi.JetSimpleNameExpression; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.types.JetStandardLibrary; +import org.jetbrains.jet.lang.types.JetType; +import org.objectweb.asm.Type; +import org.objectweb.asm.commons.InstructionAdapter; + +import java.util.List; + +/** + * @author alex.tkachman + */ +public class ArrayIterator implements IntrinsicMethod { + @Override + public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List arguments, StackValue receiver) { + receiver.put(JetTypeMapper.TYPE_OBJECT, v); + JetCallExpression call = (JetCallExpression) element; + FunctionDescriptor funDescriptor = (FunctionDescriptor) codegen.getBindingContext().get(BindingContext.REFERENCE_TARGET, (JetSimpleNameExpression) call.getCalleeExpression()); + ClassDescriptor containingDeclaration = (ClassDescriptor) funDescriptor.getContainingDeclaration().getOriginal(); + JetStandardLibrary standardLibrary = codegen.getState().getStandardLibrary(); + if(containingDeclaration.equals(standardLibrary.getArray())) { + codegen.generateTypeInfo(funDescriptor.getReturnType().getArguments().get(0).getType()); + v.invokestatic("jet/arrays/ArrayIterator", "iterator", "([Ljava/lang/Object;Ljet/typeinfo/TypeInfo;)Ljet/Iterator;"); + } + else if(containingDeclaration.equals(standardLibrary.getByteArrayClass())) { + v.invokestatic("jet/arrays/ArrayIterator", "iterator", "([B)Ljet/Iterator;"); + } + else if(containingDeclaration.equals(standardLibrary.getShortArrayClass())) { + v.invokestatic("jet/arrays/ArrayIterator", "iterator", "([S)Ljet/Iterator;"); + } + else if(containingDeclaration.equals(standardLibrary.getIntArrayClass())) { + v.invokestatic("jet/arrays/ArrayIterator", "iterator", "([I)Ljet/Iterator;"); + } + else if(containingDeclaration.equals(standardLibrary.getLongArrayClass())) { + v.invokestatic("jet/arrays/ArrayIterator", "iterator", "([J)Ljet/Iterator;"); + } + else if(containingDeclaration.equals(standardLibrary.getFloatArrayClass())) { + v.invokestatic("jet/arrays/ArrayIterator", "iterator", "([F)Ljet/Iterator;"); + } + else if(containingDeclaration.equals(standardLibrary.getDoubleArrayClass())) { + v.invokestatic("jet/arrays/ArrayIterator", "iterator", "([D)Ljet/Iterator;"); + } + else if(containingDeclaration.equals(standardLibrary.getCharArrayClass())) { + v.invokestatic("jet/arrays/ArrayIterator", "iterator", "([C)Ljet/Iterator;"); + } + else if(containingDeclaration.equals(standardLibrary.getBooleanArrayClass())) { + v.invokestatic("jet/arrays/ArrayIterator", "iterator", "([Z)Ljet/Iterator;"); + } + else { + throw new UnsupportedOperationException(containingDeclaration.toString()); + } + return StackValue.onStack(JetTypeMapper.TYPE_ITERATOR); + } +} diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java index ce4c0e29b46..3c2eee1cadc 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java @@ -34,6 +34,7 @@ public class IntrinsicMethods { private final Project myProject; private final JetStandardLibrary myStdLib; private final Map myMethods = new HashMap(); + private static final IntrinsicMethod ARRAY_ITERATOR = new ArrayIterator(); public IntrinsicMethods(Project project, JetStandardLibrary stdlib) { myProject = project; @@ -87,6 +88,16 @@ public class IntrinsicMethods { declareIntrinsicProperty("DoubleArray", "size", ARRAY_SIZE); declareIntrinsicProperty("CharArray", "size", ARRAY_SIZE); declareIntrinsicProperty("BooleanArray", "size", ARRAY_SIZE); + + declareOverload(myStdLib.getArray().getDefaultType().getMemberScope().getFunctions("iterator"), 0, ARRAY_ITERATOR); + declareOverload(myStdLib.getByteArrayClass().getDefaultType().getMemberScope().getFunctions("iterator"), 0, ARRAY_ITERATOR); + declareOverload(myStdLib.getShortArrayClass().getDefaultType().getMemberScope().getFunctions("iterator"), 0, ARRAY_ITERATOR); + declareOverload(myStdLib.getIntArrayClass().getDefaultType().getMemberScope().getFunctions("iterator"), 0, ARRAY_ITERATOR); + declareOverload(myStdLib.getLongArrayClass().getDefaultType().getMemberScope().getFunctions("iterator"), 0, ARRAY_ITERATOR); + declareOverload(myStdLib.getFloatArrayClass().getDefaultType().getMemberScope().getFunctions("iterator"), 0, ARRAY_ITERATOR); + declareOverload(myStdLib.getDoubleArrayClass().getDefaultType().getMemberScope().getFunctions("iterator"), 0, ARRAY_ITERATOR); + declareOverload(myStdLib.getCharArrayClass().getDefaultType().getMemberScope().getFunctions("iterator"), 0, ARRAY_ITERATOR); + declareOverload(myStdLib.getBooleanArrayClass().getDefaultType().getMemberScope().getFunctions("iterator"), 0, ARRAY_ITERATOR); } private void declareIntrinsicStringMethods() { diff --git a/compiler/frontend/src/jet/Library.jet b/compiler/frontend/src/jet/Library.jet index f11575b99d3..1c97f0374d4 100644 --- a/compiler/frontend/src/jet/Library.jet +++ b/compiler/frontend/src/jet/Library.jet @@ -42,7 +42,7 @@ fun Any?.toString() : String// = this === other trait Iterator { fun next() : T - abstract fun hasNext() : Boolean + fun hasNext() : Boolean } trait Iterable { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/JetStandardLibrary.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/JetStandardLibrary.java index 2036d25cafb..6029d19c358 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/JetStandardLibrary.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/JetStandardLibrary.java @@ -312,8 +312,7 @@ public class JetStandardLibrary { @NotNull public JetType getArrayType(@NotNull JetType argument) { - Variance variance = Variance.INVARIANT; - return getArrayType(variance, argument); + return getArrayType(Variance.INVARIANT, argument); } @NotNull diff --git a/idea/tests/org/jetbrains/jet/codegen/ArrayGenTest.java b/idea/tests/org/jetbrains/jet/codegen/ArrayGenTest.java index dcd5e4d9783..292fdbd2518 100644 --- a/idea/tests/org/jetbrains/jet/codegen/ArrayGenTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/ArrayGenTest.java @@ -58,4 +58,32 @@ public class ArrayGenTest extends CodegenTestCase { System.out.println(invoke.getClass()); assertTrue(invoke instanceof Integer); } + + public void testIterator () throws Exception { + loadText("fun box() { val x = Array(5, { it } ).iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }"); + System.out.println(generateToText()); + Method foo = generateFunction(); + foo.invoke(null); + } + + public void testPrimitiveIterator () throws Exception { + loadText("fun box() { val x = ByteArray(5).iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }"); + System.out.println(generateToText()); + Method foo = generateFunction(); + foo.invoke(null); + } + + public void testLongIterator () throws Exception { + loadText("fun box() { val x = LongArray(5).iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }"); + System.out.println(generateToText()); + Method foo = generateFunction(); + foo.invoke(null); + } + + public void testCharIterator () throws Exception { + loadText("fun box() { val x = CharArray(5).iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }"); + System.out.println(generateToText()); + Method foo = generateFunction(); + foo.invoke(null); + } } diff --git a/stdlib/src/jet/arrays/ArrayIterator.java b/stdlib/src/jet/arrays/ArrayIterator.java new file mode 100644 index 00000000000..3bbfac045f3 --- /dev/null +++ b/stdlib/src/jet/arrays/ArrayIterator.java @@ -0,0 +1,274 @@ +package jet.arrays; + +import jet.Iterator; +import jet.typeinfo.TypeInfo; +import jet.typeinfo.TypeInfoProjection; + +import java.lang.reflect.GenericArrayType; +import java.util.Arrays; + +/** + * @author alex.tkachman + */ +public abstract class ArrayIterator implements Iterator { + private final int size; + protected int index; + + protected ArrayIterator(int size) { + this.size = size; + } + + @Override + public boolean hasNext() { + return index < size; + } + + private static class GenericIterator extends ArrayIterator { + private final T[] array; + private final TypeInfo elementTypeInfo; + + private GenericIterator(T[] array, TypeInfo elementTypeInfo) { + super(array.length); + this.array = array; + this.elementTypeInfo = elementTypeInfo; + } + + @Override + public T next() { + return array[index++]; + } + + @Override + public TypeInfo getTypeInfo() { + return TypeInfo.getTypeInfo(GenericIterator.class, false, null, new TypeInfoProjection[] {(TypeInfoProjection) elementTypeInfo}); + } + } + + public static Iterator iterator(T[] array, TypeInfo elementTypeInfo) { + return new GenericIterator(array, elementTypeInfo); + } + + private static class ByteIterator extends ArrayIterator { + private final byte[] array; + private static final TypeInfo typeInfo = TypeInfo.getTypeInfo(ByteIterator.class, false); + + private ByteIterator(byte[] array) { + super(array.length); + this.array = array; + } + + @Override + public Byte next() { + return array[index++]; + } + + @Override + public TypeInfo getTypeInfo() { + return typeInfo; + } + } + + public static Iterator iterator(byte[] array) { + return new ByteIterator(array); + } + + private static class ShortIterator extends ArrayIterator { + private final short[] array; + private static final TypeInfo typeInfo = TypeInfo.getTypeInfo(ShortIterator.class, false); + + private ShortIterator(short[] array) { + super(array.length); + this.array = array; + } + + @Override + public Short next() { + return array[index++]; + } + + @Override + public TypeInfo getTypeInfo() { + return typeInfo; + } + } + + public static Iterator iterator(short[] array) { + return new ShortIterator(array); + } + + private static class IntegerIterator extends ArrayIterator { + private final int[] array; + private static final TypeInfo typeInfo = TypeInfo.getTypeInfo(IntegerIterator.class, false); + + private IntegerIterator(int[] array) { + super(array.length); + this.array = array; + } + + @Override + public Integer next() { + return array[index++]; + } + + @Override + public TypeInfo getTypeInfo() { + return typeInfo; + } + } + + public static Iterator iterator(int[] array) { + return new IntegerIterator(array); + } + + private static class LongIterator extends ArrayIterator { + private final long[] array; + private static final TypeInfo typeInfo = TypeInfo.getTypeInfo(LongIterator.class, false); + + private LongIterator(long[] array) { + super(array.length); + this.array = array; + } + + @Override + public Long next() { + return array[index++]; + } + + @Override + public TypeInfo getTypeInfo() { + return typeInfo; + } + } + + public static Iterator iterator(long[] array) { + return new LongIterator(array); + } + + private static class FloatIterator extends ArrayIterator { + private final float[] array; + private static final TypeInfo typeInfo = TypeInfo.getTypeInfo(FloatIterator.class, false); + + private FloatIterator(float[] array) { + super(array.length); + this.array = array; + } + + @Override + public Float next() { + return array[index++]; + } + + @Override + public TypeInfo getTypeInfo() { + return typeInfo; + } + } + + public static Iterator iterator(float[] array) { + return new FloatIterator(array); + } + + private static class DoubleIterator extends ArrayIterator { + private final double[] array; + private static final TypeInfo typeInfo = TypeInfo.getTypeInfo(DoubleIterator.class, false); + + private DoubleIterator(double[] array) { + super(array.length); + this.array = array; + } + + @Override + public Double next() { + return array[index++]; + } + + @Override + public TypeInfo getTypeInfo() { + return typeInfo; + } + } + + public static Iterator iterator(double[] array) { + return new DoubleIterator(array); + } + + private static class CharacterIterator extends ArrayIterator { + private final char[] array; + private static final TypeInfo typeInfo = TypeInfo.getTypeInfo(CharacterIterator.class, false); + + private CharacterIterator(char[] array) { + super(array.length); + this.array = array; + } + + @Override + public Character next() { + return array[index++]; + } + + @Override + public TypeInfo getTypeInfo() { + return typeInfo; + } + } + + public static Iterator iterator(char[] array) { + return new CharacterIterator(array); + } + + private static class BooleanIterator extends ArrayIterator { + private final boolean[] array; + private static final TypeInfo typeInfo = TypeInfo.getTypeInfo(BooleanIterator.class, false); + + private BooleanIterator(boolean[] array) { + super(array.length); + this.array = array; + } + + @Override + public Boolean next() { + return array[index++]; + } + + @Override + public TypeInfo getTypeInfo() { + return typeInfo; + } + } + + public static Iterator iterator(boolean[] array) { + return new BooleanIterator(array); + } + + public static void main(String[] args) { + String[] strings = {"Byte", "byte", "Short", "short", "Integer", "int", "Long", "long", "Float", "float", "Double", "double", "Character", "char", "Boolean", "boolean"}; + for(int i = 0; i != strings.length; i += 2) { + String boxed = strings[i]; + String unboxed = strings[i+1]; + System.out.println(" private static class " + boxed + "Iterator extends ArrayIterator<" + boxed + "> {\n" + + " private final " + unboxed + "[] array;\n" + + " private static final TypeInfo typeInfo = TypeInfo.getTypeInfo(" + boxed + "Iterator.class, false);\n" + + "\n" + + " private " + boxed + "Iterator(" + unboxed + "[] array) {\n" + + " super(array.length);\n" + + " this.array = array;\n" + + " }\n" + + "\n" + + " @Override\n" + + " public " + boxed + " next() {\n" + + " return array[index++];\n" + + " }\n" + + "\n" + + " @Override\n" + + " public TypeInfo getTypeInfo() {\n" + + " return typeInfo;\n" + + " }\n" + + " }\n" + + "\n" + + " public static Iterator<" + boxed + "> iterator(" + unboxed + "[] array) {\n" + + " return new " + boxed + "Iterator(array);\n" + + " }\n" + + ""); + } + } +}