package ceylon.language;

import java.util.ArrayList;
import java.util.List;

import com.redhat.ceylon.compiler.java.metadata.Ceylon;
import com.redhat.ceylon.compiler.java.metadata.Ignore;
import com.redhat.ceylon.compiler.java.metadata.Method;
import com.redhat.ceylon.compiler.java.metadata.Name;
import com.redhat.ceylon.compiler.java.metadata.Sequenced;
import com.redhat.ceylon.compiler.java.metadata.TypeInfo;
import com.redhat.ceylon.compiler.java.metadata.TypeParameter;
import com.redhat.ceylon.compiler.java.metadata.TypeParameters;

@Ceylon(major = 1)
@Method
public final class coalesce {

    private coalesce() {}

    @TypeParameters(@TypeParameter(value="Element", satisfies="ceylon.language.Object"))
    @TypeInfo("ceylon.language.Empty|ceylon.language.Sequence<Element>")
    public static <Element> Iterable<? extends Element> coalesce(
    @Name("values") @Sequenced
    @TypeInfo("ceylon.language.Iterable<ceylon.language.Nothing|Element>")
    final ceylon.language.Iterable<? extends Element> values) {
		List<Element> list = new ArrayList<Element>();
		java.lang.Object $tmp;
		for (Iterator<? extends Element> iter=values.getIterator(); !(($tmp = iter.next()) instanceof Finished);) {
			Element elem = (Element)$tmp;
			if (elem!=null) list.add(elem);
		}
        if (list.isEmpty()) {
            return (Iterable<? extends Element>) $empty.getEmpty();
        }
        else {
            return new ArraySequence<Element>(list);
        }
    }
    @Ignore
    public static <Element> Iterable<? extends Element> coalesce() {
        return (Iterable<? extends Element>) $empty.getEmpty();
    }
}

@@ -1025,291 +1025,758 @@
 ) %7B%0A
-%09%09List%3CElement%3E list = new ArrayList%3CElement%3E();%0A%09%09java.lang.Object $tmp;%0A%09%09for (Iterator%3C? extends Element%3E iter=values.getIterator(); !(($tmp = iter.next()) instanceof Finished);) %7B%0A%09%09%09Element elem = (Element)$tmp;%0A%09%09%09if (elem
+        if (values instanceof ArraySequence) %7B%0A            Element%5B%5D arr = ((ArraySequence%3CElement%3E)values).toArray();%0A            int lnn = arr.length;%0A            for (int i=arr.length-1; i%3E=0; i--) %7B%0A                if (arr%5Bi%5D == null) %7B%0A                    int j=i-1;%0A                    while (j%3E=0 && arr%5Bj%5D==null) j--;%0A                    if (j%3C0) j=0;%0A                    if (arr%5Bj%5D 
 !=
+ 
 null) 
-list.add(elem);%0A%09%09%7D%0A        if (list.isEmpty())
+%7B%0A                        lnn = i;%0A                        arr%5Bi%5D=arr%5Bj%5D;%0A                        arr%5Bj%5D=null;%0A                    %7D   %0A                %7D else lnn=i;%0A            %7D%0A            return lnn==arr.length ? (Iterable)$empty.getEmpty() : new ArraySequence(arr, lnn);%0A        %7D%0A        final class NotNullIterator implements Iterator%3CElement%3E
  %7B%0A 
@@ -1786,32 +1786,38 @@
         
-return (
+private final 
 Itera
-ble
+tor
 %3C? exten
@@ -1831,116 +1831,421 @@
 ent%3E
-) $empty.getEmpty();%0A        %7D%0A        else %7B%0A            return new ArraySequence%3CElement%3E(list);%0A        %7D
+ orig = values.getIterator();%0A            @Override public java.lang.Object next() %7B%0A                java.lang.Object tmp = null;%0A                while ((tmp = orig.next()) == null);%0A                return tmp;%0A            %7D%0A        %7D%0A        return new AbstractIterable%3CElement%3E() %7B%0A            @Override public Iterator%3C? extends Element%3E getIterator() %7B return new NotNullIterator(); %7D%0A        %7D.getSequence();
 %0A   

Optimize coalesce.java for #14