Package ceylon.language

Source Code of ceylon.language.Array

package ceylon.language;

import static com.redhat.ceylon.compiler.java.Util.toInt;
import static java.lang.System.arraycopy;
import static java.util.Arrays.copyOfRange;

import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;

import ceylon.language.impl.BaseIterator;
import ceylon.language.impl.BaseList;
import ceylon.language.impl.rethrow_;
import ceylon.language.meta.declaration.ClassDeclaration;
import ceylon.language.meta.declaration.GenericDeclaration;
import ceylon.language.meta.declaration.ValueDeclaration;
import ceylon.language.meta.model.Type;
import ceylon.language.serialization.Deconstructed;
import ceylon.language.serialization.Deconstructor;

import com.redhat.ceylon.compiler.java.Util;
import com.redhat.ceylon.compiler.java.language.AbstractArrayIterable;
import com.redhat.ceylon.compiler.java.metadata.Annotation;
import com.redhat.ceylon.compiler.java.metadata.Annotations;
import com.redhat.ceylon.compiler.java.metadata.Ceylon;
import com.redhat.ceylon.compiler.java.metadata.Class;
import com.redhat.ceylon.compiler.java.metadata.Defaulted;
import com.redhat.ceylon.compiler.java.metadata.FunctionalParameter;
import com.redhat.ceylon.compiler.java.metadata.Ignore;
import com.redhat.ceylon.compiler.java.metadata.Name;
import com.redhat.ceylon.compiler.java.metadata.SatisfiedTypes;
import com.redhat.ceylon.compiler.java.metadata.Transient;
import com.redhat.ceylon.compiler.java.metadata.TypeInfo;
import com.redhat.ceylon.compiler.java.metadata.TypeParameter;
import com.redhat.ceylon.compiler.java.metadata.TypeParameters;
import com.redhat.ceylon.compiler.java.runtime.metamodel.Metamodel;
import com.redhat.ceylon.compiler.java.runtime.model.TypeDescriptor;
import com.redhat.ceylon.compiler.java.runtime.serialization.Serializable;
import com.redhat.ceylon.compiler.java.runtime.serialization.$Serialization$;

@Ceylon(major = 7)
@Class(extendsType="ceylon.language::Basic")
@TypeParameters(@TypeParameter(value = "Element"))
@SatisfiedTypes({
    "ceylon.language::List<Element>",
    "ceylon.language::Ranged<ceylon.language::Integer,Element,ceylon.language::Array<Element>>"
})
public final class Array<Element>
        extends BaseList<Element>
        implements List<Element>, Serializable {
   
    private final java.lang.Object array;
    private final int size;
    private final TypeDescriptor $reifiedElement;
    private final ArrayType elementType;

   
    @Ignore
    public Array(final TypeDescriptor $reifiedElement,
            int size, Element element) {
        this($reifiedElement,
                createArrayWithElement($reifiedElement, size, element));
    }
   
    public Array(@Ignore final TypeDescriptor $reifiedElement,
            @Name("elements")
            @TypeInfo("ceylon.language::Iterable<Element,ceylon.language::Null>")
            final ceylon.language.Iterable<? extends Element,?> elements) {
        this($reifiedElement,
                createArrayFromIterable($reifiedElement, elements));
    }

    @SuppressWarnings("unchecked")
    private static <Element> java.lang.Object createArrayFromIterable(
        final TypeDescriptor $reifiedElement,
        final Iterable<? extends Element,?> elements) {
     
      if (elements instanceof List) {
        return createArrayFromList($reifiedElement, (List<? extends Element>) elements);
      }
     
      final ArrayList<Element> list = new ArrayList<Element>();
      Iterator<?> iterator = elements.iterator();
      java.lang.Object elem;
      while ((elem=iterator.next())!=finished_.get_()) {
        list.add((Element) elem);
      }
     
      final int size = list.size();

      switch (elementType($reifiedElement)) {
      case CeylonString:
          //note: we don't unbox strings in an Array<String?>
          //      because it would break javaObjectArray()
          java.lang.String[] stringArray = new java.lang.String[size];
          for (int i=0; i<size; i++) {
              String string = (String) list.get(i);
              stringArray[i] = string==null ? null : string.value;
          }
          return stringArray;
      case CeylonInteger:
          long[] longPrecisionArray = new long[size];
          for (int i=0; i<size; i++) {
              longPrecisionArray[i] = ((Integer) list.get(i)).value;
          }
          return longPrecisionArray;
      case CeylonFloat:
          double[] doublePrecisionArray = new double[size];
          for (int i=0; i<size; i++) {
              doublePrecisionArray[i] = ((Float) list.get(i)).value;
          }
          return doublePrecisionArray;
      case CeylonCharacter:
          int[] codepointArray = new int[size];
          for (int i=0; i<size; i++) {
              codepointArray[i] = ((Character) list.get(i)).codePoint;
          }
          return codepointArray;
      case CeylonBoolean:
          boolean[] boolArray = new boolean[size];
          for (int i=0; i<size; i++) {
              boolArray[i] = ((Boolean) list.get(i)).booleanValue();
          }
          return boolArray;
      case CeylonByte:
          byte[] bitsArray = new byte[size];
          for (int i=0; i<size; i++) {
              bitsArray[i] = ((Byte) list.get(i)).value;
          }
          return bitsArray;
      case JavaBoolean:
          boolean[] booleanArray = new boolean[size];
          for (int i=0; i<size; i++) {
              booleanArray[i] = (java.lang.Boolean) list.get(i);
          }
          return booleanArray;
      case JavaCharacter:
          char[] charArray = new char[size];
          for (int i=0; i<size; i++) {
              charArray[i] = (java.lang.Character) list.get(i);
          }
          return charArray;
      case JavaFloat:
          float[] floatArray = new float[size];
          for (int i=0; i<size; i++) {
              floatArray[i] = (java.lang.Float) list.get(i);
          }
          return floatArray;
      case JavaDouble:
          double[] doubleArray = new double[size];
          for (int i=0; i<size; i++) {
              doubleArray[i] = (java.lang.Double) list.get(i);
          }
          return doubleArray;
      case JavaByte:
          byte[] byteArray = new byte[size];
          for (int i=0; i<size; i++) {
              byteArray[i] = (java.lang.Byte) list.get(i);
          }
          return byteArray;
      case JavaShort:
          short[] shortArray = new short[size];
          for (int i=0; i<size; i++) {
              shortArray[i] = (java.lang.Short) list.get(i);
          }
          return shortArray;
      case JavaInteger:
          int[] intArray = new int[size];
          for (int i=0; i<size; i++) {
              intArray[i] = (java.lang.Integer) list.get(i);
          }
          return intArray;
      case JavaLong:
          long[] longArray = new long[size];
          for (int i=0; i<size; i++) {
              longArray[i] =(java.lang.Long) list.get(i);
          }
          return longArray;
      default:
          java.lang.Class<?> clazz =
                  $reifiedElement.getArrayElementClass();
          java.lang.Object[] array = (java.lang.Object[])
                  java.lang.reflect.Array.newInstance(clazz, size);
          for (int i=0; i<size; i++) {
              array[i] = list.get(i);
          }
          return array;
      }

    }
   
    private static <Element> java.lang.Object createArrayFromList(
            final TypeDescriptor $reifiedElement,
            final List<? extends Element> elements) {
       
      if (elements instanceof Array) {
        return createArrayFromArray($reifiedElement,
                (Array<? extends Element>) elements);
      }
     
        int size = Util.toInt(elements.getSize());
       
        if (elements instanceof ceylon.language.String
                && !$reifiedElement.containsNull()) {
            int[] array = new int[size];
            java.lang.String string = elements.toString();
            for (int i=0, offset = 0; i<size; i++) {
                int codePoint = string.codePointAt(offset);
                offset += java.lang.Character.charCount(codePoint);
                array[i] = codePoint;
            }
            return array;
        }

        switch (elementType($reifiedElement)) {
        case CeylonString:
            //note: we don't unbox strings in an Array<String?>
            //      because it would break javaObjectArray()
            java.lang.String[] stringArray = new java.lang.String[size];
            for (int i=0; i<size; i++) {
                String string = (String) elements.getFromFirst(i);
                stringArray[i] = string==null ? null : string.value;
            }
            return stringArray;
        case CeylonInteger:
            long[] longPrecisionArray = new long[size];
            for (int i=0; i<size; i++) {
                Integer e = (Integer) elements.getFromFirst(i);
                longPrecisionArray[i] = e.value;
            }
            return longPrecisionArray;
        case CeylonFloat:
            double[] doublePrecisionArray = new double[size];
            for (int i=0; i<size; i++) {
                Float e = (Float) elements.getFromFirst(i);
                doublePrecisionArray[i] = e.value;
            }
            return doublePrecisionArray;
        case CeylonCharacter:
            int[] codepointArray = new int[size];
            for (int i=0; i<size; i++) {
                Character e = (Character) elements.getFromFirst(i);
                codepointArray[i] = e.codePoint;
            }
            return codepointArray;
        case CeylonBoolean:
            boolean[] boolArray = new boolean[size];
            for (int i=0; i<size; i++) {
                Boolean e = (Boolean) elements.getFromFirst(i);
                boolArray[i] = e.booleanValue();
            }
            return boolArray;
        case CeylonByte:
            byte[] bitsArray = new byte[size];
            for (int i=0; i<size; i++) {
                Byte e = (Byte) elements.getFromFirst(i);
                bitsArray[i] = e.value;
            }
            return bitsArray;
        case JavaBoolean:
            boolean[] booleanArray = new boolean[size];
            for (int i=0; i<size; i++) {
                booleanArray[i] = (java.lang.Boolean)
                        elements.getFromFirst(i);
            }
            return booleanArray;
        case JavaCharacter:
            char[] charArray = new char[size];
            for (int i=0; i<size; i++) {
                charArray[i] = (java.lang.Character)
                        elements.getFromFirst(i);
            }
            return charArray;
        case JavaFloat:
            float[] floatArray = new float[size];
            for (int i=0; i<size; i++) {
                floatArray[i] = (java.lang.Float)
                        elements.getFromFirst(i);
            }
            return floatArray;
        case JavaDouble:
            double[] doubleArray = new double[size];
            for (int i=0; i<size; i++) {
                doubleArray[i] = (java.lang.Double)
                        elements.getFromFirst(i);
            }
            return doubleArray;
        case JavaByte:
            byte[] byteArray = new byte[size];
            for (int i=0; i<size; i++) {
                byteArray[i] = (java.lang.Byte)
                        elements.getFromFirst(i);
            }
            return byteArray;
        case JavaShort:
            short[] shortArray = new short[size];
            for (int i=0; i<size; i++) {
                shortArray[i] = (java.lang.Short)
                        elements.getFromFirst(i);
            }
            return shortArray;
        case JavaInteger:
            int[] intArray = new int[size];
            for (int i=0; i<size; i++) {
                intArray[i] = (java.lang.Integer)
                        elements.getFromFirst(i);
            }
            return intArray;
        case JavaLong:
            long[] longArray = new long[size];
            for (int i=0; i<size; i++) {
                longArray[i] = (java.lang.Long)
                        elements.getFromFirst(i);
            }
            return longArray;
        default:
            java.lang.Class<?> clazz =
                    $reifiedElement.getArrayElementClass();
            java.lang.Object[] objectArray = (java.lang.Object[])
                    java.lang.reflect.Array.newInstance(clazz, size);
            for (int i=0; i<size; i++) {
                objectArray[i] = elements.getFromFirst(i);
            }
            return objectArray;
        }
    }

    private static <Element> java.lang.Object createArrayFromArray(
            final TypeDescriptor $reifiedElement,
            final Array<? extends Element> elements) {

        final int size = Util.toInt(elements.getSize());
        final java.lang.Class<?> clazz =
                $reifiedElement.getArrayElementClass();

        switch (elementType($reifiedElement)) {
        case CeylonString: 
            //note: we don't unbox strings in an Array<String?>
            //      because it would break javaObjectArray()
            java.lang.String[] stringArray = new java.lang.String[size];
            arraycopy(elements.array, 0, stringArray, 0, size);
            return stringArray;
        case CeylonInteger:
            long[] longPrecisionArray = new long[size];
            arraycopy(elements.array, 0, longPrecisionArray, 0, size);
        case CeylonFloat:
            double[] doublePrecisionArray = new double[size];
            arraycopy(elements.array, 0, doublePrecisionArray, 0, size);
            return doublePrecisionArray;
        case CeylonCharacter:
            int[] codepointArray = new int[size];
            arraycopy(elements.array, 0, codepointArray, 0, size);
            return codepointArray;
        case CeylonBoolean:
            boolean[] boolArray = new boolean[size];
            arraycopy(elements.array, 0, boolArray, 0, size);
            return boolArray;
        case CeylonByte:
            byte[] bitsArray = new byte[size];
            arraycopy(elements.array, 0, bitsArray, 0, size);
            return bitsArray;
        case JavaBoolean:
            boolean[] booleanArray = new boolean[size];
            arraycopy(elements.array, 0, booleanArray, 0, size);
            return booleanArray;
        case JavaCharacter:
            char[] charArray = new char[size];
            arraycopy(elements.array, 0, charArray, 0, size);
            return charArray;
        case JavaFloat:
            float[] floatArray = new float[size];
            arraycopy(elements.array, 0, floatArray, 0, size);
            return floatArray;
        case JavaDouble:
            double[] doubleArray = new double[size];
            arraycopy(elements.array, 0, doubleArray, 0, size);
            return doubleArray;
        case JavaByte:
            byte[] byteArray = new byte[size];
            arraycopy(elements.array, 0, byteArray, 0, size);
            return byteArray;
        case JavaShort:
            short[] shortArray = new short[size];
            arraycopy(elements.array, 0, shortArray, 0, size);
            return shortArray;
        case JavaInteger:
            int[] intArray = new int[size];
            arraycopy(elements.array, 0, intArray, 0, size);
            return intArray;
        case JavaLong:
            long[] longArray = new long[size];
            arraycopy(elements.array, 0, longArray, 0, size);
            return longArray;
        default:
            java.lang.Object[] objectArray = (java.lang.Object[])
            java.lang.reflect.Array.newInstance(clazz, size);
            java.lang.Object otherArray = elements.array;
            if (otherArray.getClass()==objectArray.getClass()) {
                arraycopy(otherArray, 0, objectArray, 0, size);
            }
            else {
                for (int i=0; i<size; i++) {
                    objectArray[i] = elements.getFromFirst(i);
                }
            }
            return objectArray;
        }
    }
   
    private static <Element> java.lang.Object createArrayWithElement(
        final TypeDescriptor $reifiedElement,
        final int size, final Element element) {
        switch (elementType($reifiedElement)) {
        case CeylonInteger:
            long[] longPrecisionArray = new long[size];
            if (element!=null) {
                long value = ((Integer) element).value;
                if (value!=0l) Arrays.fill(longPrecisionArray, value);
            }
            return longPrecisionArray;
        case JavaLong:
            long[] longArray = new long[size];
            if (element!=null) {
                long longValue = (java.lang.Long) element;
                if (longValue!=0l) Arrays.fill(longArray, longValue);
            }
            return longArray;
        case CeylonFloat:
            double[] doublePrecisionArray = new double[size];
            if (element!=null) {
                double value = ((Float) element).value;
                if (value!=0.0d) Arrays.fill(doublePrecisionArray, value);
            }
            return doublePrecisionArray;
        case JavaDouble:
            double[] doubleArray = new double[size];
            if (element!=null) {
                double value = (java.lang.Double) element;
                if (value!=0.0d) Arrays.fill(doubleArray, value);
            }
            return doubleArray;
        case CeylonCharacter:
            int[] codepointArray = new int[size];
            if (element!=null) {
                int value = ((Character) element).codePoint;
                if (value!=0) Arrays.fill(codepointArray, value);
            }
            return codepointArray;
        case JavaInteger:
            int[] intArray = new int[size];
            if (element!=null) {
                int intValue = (java.lang.Integer) element;
                if (intValue!=0) Arrays.fill(intArray, intValue);
            }
            return intArray;
        case CeylonByte:
            byte[] byteArray = new byte[size];
            if (element!=null) {
                byte value = ((Byte) element).value;
                if (value!=0) Arrays.fill(byteArray, value);
            }
            return byteArray;
        case JavaByte:
            byte[] bitsArray = new byte[size];
            byte value = (java.lang.Byte) element;
            if (value!=0) Arrays.fill(bitsArray, value);
            return bitsArray;
        case CeylonBoolean:
            boolean[] boolArray = new boolean[size];
            if (element!=null) {
                boolean boolValue = ((Boolean) element).booleanValue();
                if (boolValue!=false) Arrays.fill(boolArray, boolValue);
            }
            return boolArray;
        case JavaBoolean:
            boolean[] booleanArray = new boolean[size];
            if (element!=null) {
                boolean booleanValue = (java.lang.Boolean) element;
                if (booleanValue!=false) Arrays.fill(booleanArray, booleanValue);
            }
            return booleanArray;
        case JavaCharacter:
            char[] charArray = new char[size];
            if (element!=null) {
                char charValue = (java.lang.Character) element;
                if (charValue!=0) Arrays.fill(charArray, charValue);
            }
            return charArray;
        case JavaShort:
            short[] shortArray = new short[size];
            if (element!=null) {
                short shortValue = (java.lang.Short) element;
                if (shortValue!=0) Arrays.fill(shortArray, shortValue);
            }
            return shortArray;
        case JavaFloat:
            float[] floatArray = new float[size];
            if (element!=null) {
                float floatValue = (java.lang.Float) element;
                if (floatValue!=0.0f) Arrays.fill(floatArray, floatValue);
            }
            return floatArray;
        case CeylonString:
            //note: we don't unbox strings in an Array<String?>
            //      because it would break javaObjectArray()
            java.lang.String[] stringArray = new java.lang.String[size];
            if (element!=null) {
                String string = (String) element;
                Arrays.fill(stringArray, string.value);
            }
            return stringArray;
        default:
            java.lang.Class<?> elementClass =
                    $reifiedElement.getArrayElementClass();
            java.lang.Object[] objectArray = (java.lang.Object[])
                    java.lang.reflect.Array.newInstance(elementClass, size);
            if (element!=null) {
                Arrays.fill(objectArray, element);
            }
            return objectArray;
        }
    }
       
    @Ignore
    private Array(@Ignore TypeDescriptor $reifiedElement, java.lang.Object array) {
        super($reifiedElement);
        this.$reifiedElement = $reifiedElement;
        assert(array.getClass().isArray());
        this.array = array;
        this.elementType = elementType($reifiedElement);
        this.size = java.lang.reflect.Array.getLength(array);
    }
   
    @Ignore
    public static <T> Array<T> instance(T[] array) {
        if (array == null) {
            return null;
        }
        java.lang.Class<?> componentType = array.getClass().getComponentType();
        TypeDescriptor optionalType = TypeDescriptor.union(Null.$TypeDescriptor$,
                TypeDescriptor.klass(componentType));
        return new Array<T>(optionalType, array);
    }
   
    private static final TypeDescriptor CHAR_TYPE =
            TypeDescriptor.klass(java.lang.Character.class);
    @Ignore
    public static Array<java.lang.Character> instance(char[] array) {
        if (array == null) {
            return null;
        }
        return new Array<java.lang.Character>(CHAR_TYPE, array);
    }

    private static final TypeDescriptor BYTE_TYPE =
            TypeDescriptor.klass(java.lang.Byte.class);
    @Ignore
    public static Array<java.lang.Byte> instance(byte[] array) {
        if (array == null) {
            return null;
        }
        return new Array<java.lang.Byte>(BYTE_TYPE, array);
    }

    private static final TypeDescriptor SHORT_TYPE =
            TypeDescriptor.klass(java.lang.Short.class);
    @Ignore
    public static Array<java.lang.Short> instance(short[] array) {
        if (array == null) {
            return null;
        }
        return new Array<java.lang.Short>(SHORT_TYPE, array);
    }
   
    private static final TypeDescriptor INT_TYPE =
            TypeDescriptor.klass(java.lang.Integer.class);
    @Ignore
    public static Array<java.lang.Integer> instance(int[] array) {
        if (array == null) {
            return null;
        }
        return new Array<java.lang.Integer>(INT_TYPE, array);
    }
   
    private static final TypeDescriptor LONG_TYPE =
            TypeDescriptor.klass(java.lang.Long.class);
    @Ignore
    public static Array<java.lang.Long> instance(long[] array) {
        if (array == null) {
            return null;
        }
        return new Array<java.lang.Long>(LONG_TYPE, array);
    }
   
    private static final TypeDescriptor FLOAT_TYPE =
            TypeDescriptor.klass(java.lang.Float.class);
    @Ignore
    public static Array<java.lang.Float> instance(float[] array) {
        if (array == null) {
            return null;
        }
        return new Array<java.lang.Float>(FLOAT_TYPE, array);
    }
   
    private static final TypeDescriptor DOUBLE_TYPE =
            TypeDescriptor.klass(java.lang.Double.class);
    @Ignore
    public static Array<java.lang.Double> instance(double[] array) {
        if (array == null) {
            return null;
        }
        return new Array<java.lang.Double>(DOUBLE_TYPE, array);
    }
   
    private static final TypeDescriptor BOOLEAN_TYPE =
            TypeDescriptor.klass(java.lang.Boolean.class);
    @Ignore
    public static Array<java.lang.Boolean> instance(boolean[] array) {
        if (array == null) {
            return null;
        }
        return new Array<java.lang.Boolean>(BOOLEAN_TYPE, array);
    }
   
    @Ignore
    public static Array<Float> instanceForFloats(double[] array) {
        if (array == null) {
            return null;
        }
        return new Array<Float>(Float.$TypeDescriptor$, array);
    }

    @Ignore
    public static Array<Boolean> instanceForBooleans(boolean[] array) {
        if (array == null) {
            return null;
        }
        return new Array<Boolean>(Boolean.$TypeDescriptor$, array);
    }
   
    @Ignore
    public static Array<Byte> instanceForBytes(byte[] array) {
        if (array == null) {
            return null;
        }
        return new Array<Byte>(Byte.$TypeDescriptor$, array);
    }
   
    @Ignore
    public static Array<Character> instanceForCodePoints(int[] array) {
        if (array == null) {
            return null;
        }
        return new Array<Character>(Character.$TypeDescriptor$, array);
    }

    @Ignore
    public static Array<Integer> instanceForIntegers(long[] array) {
        if (array == null) {
            return null;
        }
        return new Array<Integer>(Integer.$TypeDescriptor$, array);
    }

    @Override
    public Array<Element> spanFrom(@Name("from") Integer from) {
        return span(from, Integer.instance(size));
    }
   
    @Override
    public Array<Element> spanTo(@Name("to") Integer to) {
        return span(Integer.instance(0), to);
    }
   
    private static final java.lang.Object[] EMPTY_ARRAY = new java.lang.Object[0];
   
    @Override
    public Array<Element> span(@Name("from") Integer from,
            @Name("to") Integer to) {
        long fromIndex = from.longValue(); //inclusive
        long toIndex = to.longValue(); //inclusive
        boolean revert = toIndex < fromIndex;
        if (revert) {
            long swap = toIndex;
            toIndex = fromIndex;
            fromIndex = swap;
        }
        if (fromIndex<0) {
            fromIndex = 0;
        }
        if (toIndex>=size) {
            toIndex = size-1;
        }
        if (fromIndex>=size || toIndex<0 || toIndex<fromIndex) {
            return new Array<Element>($reifiedElement, EMPTY_ARRAY);
        }
        else {
            int resultFromIndex = toInt(fromIndex); //inclusive
            int resultToIndex = toInt(toIndex+1); //exclusive
            java.lang.Object newArray;
            if (array instanceof char[]) {
                char[] copy = copyOfRange((char[])array,
                        resultFromIndex, resultToIndex);
                if (revert) {
                    for (int i = 0; i<copy.length/2; i++) {
                        char temp = copy[i];
                        copy[i] = copy[copy.length-1-i];
                        copy[copy.length-1-i] = temp;
                    }
                }
                newArray = copy;
            }
            else if (array instanceof byte[]) {
                byte[] copy = copyOfRange((byte[])array,
                        resultFromIndex, resultToIndex);
                if (revert) {
                    for (int i = 0; i<copy.length/2; i++) {
                        byte temp = copy[i];
                        copy[i] = copy[copy.length-1-i];
                        copy[copy.length-1-i] = temp;
                    }
                }
                newArray = copy;
            }
            else if (array instanceof short[]) {
                short[] copy = copyOfRange((short[])array,
                        resultFromIndex, resultToIndex);
                if (revert) {
                    for (int i = 0; i<copy.length/2; i++) {
                        short temp = copy[i];
                        copy[i] = copy[copy.length-1-i];
                        copy[copy.length-1-i] = temp;
                    }
                }
                newArray = copy;
            }
            else if (array instanceof int[]) {
                int[] copy = copyOfRange((int[])array,
                        resultFromIndex, resultToIndex);
                if (revert) {
                    for (int i = 0; i<copy.length/2; i++) {
                        int temp = copy[i];
                        copy[i] = copy[copy.length-1-i];
                        copy[copy.length-1-i] = temp;
                    }
                }
                newArray = copy;
            }
            else if (array instanceof long[]) {
                long[] copy = copyOfRange((long[])array,
                    resultFromIndex, resultToIndex);
                if (revert) {
                    for (int i = 0; i<copy.length/2; i++) {
                        long temp = copy[i];
                        copy[i] = copy[copy.length-1-i];
                        copy[copy.length-1-i] = temp;
                    }
                }
                newArray = copy;
            }
            else if (array instanceof float[]) {
                float[] copy = copyOfRange((float[])array,
                    resultFromIndex, resultToIndex);
                if (revert) {
                    for (int i = 0; i<copy.length/2; i++) {
                        float temp = copy[i];
                        copy[i] = copy[copy.length-1-i];
                        copy[copy.length-1-i] = temp;
                    }
                }
                newArray = copy;
            }
            else if (array instanceof double[]) {
                double[] copy = copyOfRange((double[])array,
                    resultFromIndex, resultToIndex);
                if (revert) {
                    for (int i = 0; i<copy.length/2; i++) {
                        double temp = copy[i];
                        copy[i] = copy[copy.length-1-i];
                        copy[copy.length-1-i] = temp;
                    }
                }
                newArray = copy;
            }
            else if (array instanceof boolean[]) {
                boolean[] copy = copyOfRange((boolean[])array,
                    resultFromIndex, resultToIndex);
                if (revert) {
                    for (int i = 0; i<copy.length/2; i++) {
                        boolean temp = copy[i];
                        copy[i] = copy[copy.length-1-i];
                        copy[copy.length-1-i] = temp;
                    }
                }
                newArray = copy;
            }
            else {
                java.lang.Object[] copy =
                        copyOfRange((java.lang.Object[])array,
                    resultFromIndex, resultToIndex);
                if (revert) {
                    for (int i = 0; i<copy.length/2; i++) {
                        java.lang.Object temp = copy[i];
                        copy[i] = copy[copy.length-1-i];
                        copy[copy.length-1-i] = temp;
                    }
                }
                newArray = copy;
            }
            return new Array<Element>($reifiedElement, newArray);
        }
    }

    @Override
    public Array<Element> measure(@Name("from") Integer from,
            @Name("length") long length) {
        long fromIndex = from.longValue(); //inclusive
        long toIndex = fromIndex + length; //exclusive
        if (fromIndex<0) {
            fromIndex=0;
        }
        if (toIndex > size) {
            toIndex = size;
        }
        if (fromIndex>=size || toIndex<=0) {
            return new Array<Element>($reifiedElement, EMPTY_ARRAY);
        }
        else {
            int resultToIndex = toInt(toIndex);
            int resultFromIndex = toInt(fromIndex);
            java.lang.Object newArray;
            if (array instanceof char[]) {
                newArray = copyOfRange((char[])array,
                    resultFromIndex, resultToIndex);
            }
            else if (array instanceof byte[]) {
                newArray = copyOfRange((byte[])array,
                        resultFromIndex, resultToIndex);
            }
            else if (array instanceof short[]) {
                newArray = copyOfRange((short[])array,
                        resultFromIndex, resultToIndex);
            }
            else if (array instanceof int[]) {
                newArray = copyOfRange((int[])array,
                        resultFromIndex, resultToIndex);
            }
            else if (array instanceof long[]) {
                newArray = copyOfRange((long[])array,
                        resultFromIndex, resultToIndex);
            }
            else if (array instanceof float[]) {
                newArray = copyOfRange((float[])array,
                        resultFromIndex, resultToIndex);
            }
            else if (array instanceof double[]) {
                newArray = copyOfRange((double[])array,
                        resultFromIndex, resultToIndex);
            }
            else if (array instanceof boolean[]) {
                newArray = copyOfRange((boolean[])array,
                        resultFromIndex, resultToIndex);
            }
            else {
                newArray = copyOfRange((java.lang.Object[])array,
                        resultFromIndex, resultToIndex);
            }
            return new Array<Element>($reifiedElement, newArray);
        }
    }

    @Override
    @TypeInfo("ceylon.language::Null|ceylon.language::Integer")
    public Integer getLastIndex() {
        return getEmpty() ? null : Integer.instance(size - 1);
    }

    @Override
    public boolean getEmpty() {
        return size == 0;
    }

    @Override
    public long getSize() {
        return size;
    }

    @Override
    public boolean defines(@Name("index") Integer key) {
        long ind = key.longValue();
        return ind >= 0 && ind < size;
    }
   
    @Ignore
    private final class ArrayIterator extends BaseIterator<Element> {
       
        private int index = 0;
        // ok to cast here, since we know the size must fit in an int
       
        private ArrayIterator(TypeDescriptor $reified$Element) {
            super($reified$Element);
        }

        @Override
        public java.lang.Object next() {
            if (index<size) {
                return unsafeItem(index++);
            }
            else {
                return finished_.get_();
            }
        }

        @Override
        public java.lang.String toString() {
            return Array.this.toString() + ".iterator()";
        }
    }
   
    @Ignore
    final class ArrayIterable
    extends AbstractArrayIterable<Element, java.lang.Object> {

        ArrayIterable() {
            // ok to cast here, since we know the size must fit in an int
            super($reifiedElement, array, (int)size);
        }
       
        protected ArrayIterable(java.lang.Object array, int start,
                int len, int step) {
            super($reifiedElement, array, start, len, step);
        }

        @Override
        protected ArrayIterable newInstance(java.lang.Object array,
                int start, int len, int step) {
            return new ArrayIterable(array, start, len, step);
        }

        @Override
        protected Element get(java.lang.Object array, int index) {
            return unsafeItem(index);
        }
       
        /**
         * If this is an Iterable over an {@code Array<Character>}
         * (wrapping a {@code int[]}) with unit step size, then
         * returns a String of those codepoints.
         * Otherwise returns null.
         */
        @Ignore
        java.lang.String stringValue() {
            if (array instanceof int[]
                    && step == 1) {
                // ok to cast here, since we know the size must fit in an int
                return new java.lang.String((int[])array, start,
                        (int)this.getSize());
            }
            return null;
        }
    }
   
    @Override
    public Iterator<Element> iterator() {
        return new ArrayIterator($reifiedElement);
    }
   
//    @Override
//    @TypeInfo("ceylon.language::Null|Element")
//    public Element get(@Name("index") Integer key) {
//        return getFromFirst(key.longValue());
//    }

    @Override
    @TypeInfo("ceylon.language::Null|Element")
    public Element getFromLast(@Name("index") long index) {
        if (index < 0 || index >= size) {
            return null;
        }
        else {
            //typecast is safe because we just checked
            return unsafeItem(size-1-(int) index);
        }
    }
   
    @Override
    @TypeInfo("ceylon.language::Null|Element")
    public Element getFromFirst(@Name("index") long index) {
        if (index < 0 || index >= size) {
            return null;
        }
        else {
            //typecast is safe because we just checked
            return unsafeItem((int) index);
        }
    }
   
    // Used by the jvm backend code to avoid boxing the index
    @SuppressWarnings("unchecked")
    @Ignore
    public Element unsafeItem(int index) {
        switch (elementType) {
        case CeylonInteger:
            return (Element) Integer.instance(((long[])array)[index]);
        case JavaLong:
            return (Element) (java.lang.Long) ((long[])array)[index];
        case CeylonFloat:
            return (Element) Float.instance(((double[])array)[index]);
        case JavaDouble:
            return (Element) (java.lang.Double) ((double[])array)[index];
        case CeylonCharacter:
            return (Element) Character.instance(((int[])array)[index]);
        case JavaInteger:
            return (Element) (java.lang.Integer) ((int[])array)[index];
        case CeylonByte:
            return (Element) Byte.instance(((byte[])array)[index]);
        case JavaByte:
            return (Element) (java.lang.Byte) ((byte[])array)[index];
        case CeylonBoolean:
            return (Element) Boolean.instance(((boolean[])array)[index]);
        case JavaBoolean:
            return (Element) (java.lang.Boolean) ((boolean[])array)[index];
        case JavaCharacter:
            return (Element) (java.lang.Character) ((char[])array)[index];
        case JavaShort:
            return (Element) (java.lang.Short) ((short[])array)[index];
        case JavaFloat:
            return (Element) (java.lang.Float) ((float[])array)[index];
        case CeylonString:
            return (Element) String.instance(((java.lang.String[])array)[index]);
        case JavaString:
            return (Element) ((java.lang.String[])array)[index];
        case Other:
            return (Element) ((java.lang.Object[])array)[index];
        default:
            throw new AssertionError("unknown element type");
        }
    }

    public void set(
            @Name("index") @TypeInfo("ceylon.language::Integer") long index,
            @Name("element") @TypeInfo("Element") Element element) {
        if (index<0) {
            throw new AssertionError("array index " + index +
                    " may not be negative");
        }
        else if (index>=size) {
            throw new AssertionError("array index " + index +
                    " must be less than size of array " + size);
        }
        else {
            int idx = (int) index; //typecast is safe 'cos we just checked above
            switch (elementType) {
            case CeylonInteger:
                ((long[]) array)[idx] = ((Integer) element).value;
                break;
            case JavaLong:
                ((long[]) array)[idx] = (java.lang.Long) element;
                break;
            case CeylonFloat:
                ((double[]) array)[idx] = ((Float) element).value;
                break;
            case JavaDouble:
                ((double[]) array)[idx] = (java.lang.Double) element;
                break;
            case CeylonCharacter:
                ((int[]) array)[idx] = ((Character) element).codePoint;
                break;
            case JavaInteger:
                ((int[]) array)[idx] = (java.lang.Integer) element;
                break;
            case CeylonByte:
                ((byte[]) array)[idx] = ((Byte)element).value;
                break;
            case JavaByte:
                ((byte[]) array)[idx] = (java.lang.Byte) element;
                break;
            case CeylonBoolean:
                ((boolean[]) array)[idx] = ((Boolean) element).booleanValue();
                break;
            case JavaBoolean:
                ((boolean[]) array)[idx] = (java.lang.Boolean) element;
                break;
            case JavaCharacter:
                ((char[]) array)[idx] = (java.lang.Character) element;
                break;
            case JavaShort:
                ((short[]) array)[idx] = (java.lang.Short) element;
                break;
            case JavaFloat:
                ((float[]) array)[idx] = (java.lang.Float) element;
                break;
            case CeylonString:
                ((java.lang.String[]) array)[idx] = ((String) element).value;
                break;
            case JavaString:
                ((java.lang.String[]) array)[idx] = (java.lang.String) element;
                break;
            case Other:
                ((java.lang.Object[]) array)[idx] = element;
                break;
            default:
                throw new AssertionError("unknown element type");
            }
        }
    }

   
    @Override
    public Array<Element> $clone() {
        return new Array<Element>($reifiedElement, copyArray());
    }
   
    private java.lang.Object copyArray() {
        if (array instanceof java.lang.Object[]) {
            return Arrays.copyOf((java.lang.Object[]) array,
                    ((java.lang.Object[]) array).length);
        }
        else if (array instanceof long[]) {
            return Arrays.copyOf((long[]) array,
                    ((long[]) array).length);
        }
        else if (array instanceof double[]) {
            return Arrays.copyOf((double[]) array,
                    ((double[]) array).length);
        }
        else if (array instanceof boolean[]) {
            return Arrays.copyOf((boolean[]) array,
                    ((boolean[]) array).length);
        }
        else if (array instanceof int[]) {
            return Arrays.copyOf((int[]) array,
                    ((int[]) array).length);
        }
        else if (array instanceof byte[]) {
            return Arrays.copyOf((byte[]) array,
                    ((byte[]) array).length);
        }
        else if (array instanceof short[]) {
            return Arrays.copyOf((short[]) array,
                    ((short[]) array).length);
        }
        else if (array instanceof float[]) {
            return Arrays.copyOf((float[]) array,
                    ((float[]) array).length);
        }
        else if (array instanceof char[]) {
            return Arrays.copyOf((char[]) array,
                    ((char[]) array).length);
        }
        else {
            throw new AssertionError("impossible array type");
        }
    }

    @Ignore
    public java.lang.Object toArray() {
        return array;
    }

    @Override
    public boolean contains(@Name("element")
    @TypeInfo("ceylon.language::Object")
    java.lang.Object element) {
        // FIXME Very inefficient for primitive types due to boxing
        for (int i=0; i<size; i++) {
            Element elem = getFromFirst(i);
            if (elem != null && elem.equals(element)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public long count(@Name("selecting")@FunctionalParameter("(element)")
    @TypeInfo("ceylon.language::Callable<ceylon.language::Boolean,ceylon.language::Tuple<Element,Element,ceylon.language::Empty>>")
    Callable<? extends Boolean> selecting) {
        // FIXME Very inefficient for primitive types due to boxing
        int count=0;
        for (int i=0; i<size; i++) {
            Element elem = getFromFirst(i);
            if (elem != null && selecting.$call$(elem).booleanValue()) {
                count++;
            }
        }
        return count;
    }

    @Override
    @Annotations({ @Annotation("actual") })
    @TypeInfo("ceylon.language::Null|Element")
    public Element getFirst() {
        if (size>0) {
            return unsafeItem(0);
        }
        else {
            return null;
        }
    }
   
    @Override
    @Annotations({ @Annotation("actual") })
    @TypeInfo("ceylon.language::Null|Element")
    public Element getLast() {
        return size > 0 ? unsafeItem(size-1) : null;
    }
   
    @SuppressWarnings("unchecked")
    @Override
    @TypeInfo("ceylon.language::Sequential<Element>")
    public Sequential<? extends Element>
    sort(@Name("comparing") @FunctionalParameter("(x,y)")
    @TypeInfo("ceylon.language::Callable<ceylon.language::Comparison,ceylon.language::Tuple<Element,Element,ceylon.language::Tuple<Element,Element,ceylon.language::Empty>>>")
    Callable<? extends Comparison> comparing) {
        if (getEmpty()) {
            return (Sequential<? extends Element>) empty_.get_();
        }
        Array<Element> clone = $clone();
        clone.sortInPlace(comparing);
        return new ArraySequence<Element>($reifiedElement, clone);
    }
    /*@SuppressWarnings("unchecked")
    @TypeInfo("ceylon.language::Sequential<Element>")
    public Sequential<? extends Element>
    reverse() {
        if (getEmpty()) {
            return (Sequential<? extends Element>) empty_.get_();
        }
        Array<Element> clone = $clone();
        clone.reverseInPlace();
        return new ArraySequence<Element>($reifiedElement, clone);
    }*/
   
    @Override
    @Annotations({ @Annotation("actual") })
    @TypeInfo("ceylon.language::Iterable<Element,ceylon.language::Null>")
    public Iterable<? extends Element, ?>
    skip(@Name("skipping") long skipping) {
        int intSkip = toInt(skipping);
        // ok to cast here, since we know the size must fit in an int
        int length = (int) size;
        if (skipping <= 0) {
            return this;
        }
        return new ArrayIterable(this.array, intSkip,
                Math.max(0, length-intSkip), 1);
    }

    @Override
    @Annotations({ @Annotation("actual") })
    @TypeInfo("ceylon.language::Iterable<Element,ceylon.language::Null>")
    public Iterable<? extends Element, ?>
    take(@Name("taking") long taking) {
        // ok to cast here, since we know the size must fit in an int
        int length = (int)size;
        if (taking >= length) {
            return this;
        }
        return new ArrayIterable(this.array, 0,
                Math.max(toInt(taking), 0), 1);
    }

    @Override
    @Annotations({ @Annotation("actual") })
    @TypeInfo("ceylon.language::Iterable<Element,ceylon.language::Null>")
    public Iterable<? extends Element, ?>
    by(@Name("step") long step) {
        if (step <= 0) {
            throw new AssertionError("step size must be greater than zero");
        }
        else if (step == 1) {
            return this;
        }
        return new ArrayIterable(array, 0,
                toInt((size+step-1)/step),
                toInt(step));
    }
   
    @SuppressWarnings("unchecked")
    @Override
    @TypeInfo("ceylon.language::Sequential<Element>")
    public Sequential<? extends Element> sequence() {
        if (getEmpty()) {
            return (Sequential<? extends Element>) empty_.get_();
        }
        else {
            return new ArraySequence<Element>($reifiedElement,
                    new Array<Element>($reifiedElement, copyArray()));
        }
    }
   
    @Ignore
    public int copyTo$sourcePosition(Element[] destination){
        return 0;
    }

    @Ignore
    public int copyTo$destinationPosition(Element[] destination,
            int sourcePosition){
        return 0;
    }

    @Ignore
    public int copyTo$length(Element[] destination,
            int sourcePosition, int destinationPosition){
        return java.lang.reflect.Array.getLength(array)-sourcePosition;
    }

    @Ignore
    public void copyTo(Array<Element> destination){
        copyTo(destination, 0, 0);
    }

    @Ignore
    public void copyTo(Array<Element> destination, int sourcePosition){
        copyTo(destination, sourcePosition, 0);
    }

    @Ignore
    public void copyTo(Array<Element> destination,
            int sourcePosition, int destinationPosition){
        copyTo(destination, sourcePosition, destinationPosition,
                java.lang.reflect.Array.getLength(array)-sourcePosition);
    }

    public void copyTo(@Name("destination") Array<Element> destination,
                       @Name("sourcePosition") @Defaulted int sourcePosition,
                       @Name("destinationPosition") @Defaulted int destinationPosition,
                       @Name("length") @Defaulted int length){
        arraycopy(array, sourcePosition, destination.array,
                        destinationPosition, length);
    }
   
    @Override
    @Ignore
    public TypeDescriptor $getType$() {
        return TypeDescriptor.klass(Array.class, $reifiedElement);
    }
   
    public void reverseInPlace() {
        if (array instanceof java.lang.Object[]) {
            for (int index=0; index<size/2; index++) {
                java.lang.Object[] arr = (java.lang.Object[]) array;
                java.lang.Object swap = arr[index];
                int indexFromLast = size-index-1;
                arr[index] = arr[indexFromLast];
                arr[indexFromLast] = swap;
            }
        }
        else if (array instanceof long[]) {
            for (int index=0; index<size/2; index++) {
                long[] arr = (long[]) array;
                long swap = arr[index];
                int indexFromLast = size-index-1;
                arr[index] = arr[indexFromLast];
                arr[indexFromLast] = swap;
            }
        }
        else if (array instanceof int[]) {
            for (int index=0; index<size/2; index++) {
                int[] arr = (int[]) array;
                int swap = arr[index];
                int indexFromLast = size-index-1;
                arr[index] = arr[indexFromLast];
                arr[indexFromLast] = swap;
            }
        }
        else if (array instanceof short[]) {
            for (int index=0; index<size/2; index++) {
                short[] arr = (short[]) array;
                short swap = arr[index];
                int indexFromLast = size-index-1;
                arr[index] = arr[indexFromLast];
                arr[indexFromLast] = swap;
            }
        }
        else if (array instanceof byte[]) {
            for (int index=0; index<size/2; index++) {
                byte[] arr = (byte[]) array;
                byte swap = arr[index];
                int indexFromLast = size-index-1;
                arr[index] = arr[indexFromLast];
                arr[indexFromLast] = swap;
            }
        }
        else if (array instanceof double[]) {
            for (int index=0; index<size/2; index++) {
                double[] arr = (double[]) array;
                double swap = arr[index];
                int indexFromLast = size-index-1;
                arr[index] = arr[indexFromLast];
                arr[indexFromLast] = swap;
            }
        }
        else if (array instanceof float[]) {
            for (int index=0; index<size/2; index++) {
                float[] arr = (float[]) array;
                float swap = arr[index];
                int indexFromLast = size-index-1;
                arr[index] = arr[indexFromLast];
                arr[indexFromLast] = swap;
            }
        }
        else if (array instanceof boolean[]) {
            for (int index=0; index<size/2; index++) {
                boolean[] arr = (boolean[]) array;
                boolean swap = arr[index];
                int indexFromLast = size-index-1;
                arr[index] = arr[indexFromLast];
                arr[indexFromLast] = swap;
            }
        }
        else if (array instanceof char[]) {
            for (int index=0; index<size/2; index++) {
                char[] arr = (char[]) array;
                char swap = arr[index];
                int indexFromLast = size-index-1;
                arr[index] = arr[indexFromLast];
                arr[indexFromLast] = swap;
            }
        }
        else {
            throw new AssertionError("illegal array type");
        }
    }
   
    public void sortInPlace(
            @Name("comparing") @FunctionalParameter("(x,y)")
            @TypeInfo("ceylon.language::Callable<ceylon.language::Comparison,ceylon.language::Tuple<Element,Element,ceylon.language::Tuple<Element,Element,ceylon.language::Empty>>>")
            final Callable<? extends Comparison> comparing) {
        java.util.List<Element> list =
                new java.util.AbstractList<Element>() {
            @Override
            public Element get(int index) {
                return unsafeItem(index);
            }
            @Override
            public Element set(int index, Element element) {
                // Strictly this method should return the element that was at
                // the given index, but that might require even more boxing
                // and in practice the return value
                // doesn't seem to be used by the sorting algorithm
                Array.this.set(index, element);
                return null;
            }
            @Override
            public int size() {
                return (int)size;
            }
            @Override
            public java.lang.Object[] toArray() {
                if (array instanceof java.lang.Object[] &&
                    !(array instanceof java.lang.String[])) {
                    return (java.lang.Object[]) array;
                }
                else {
                    int size = size();
                    java.lang.Object[] result =
                            new java.lang.Object[size];
                    for (int i=0; i<size; i++) {
                        result[i] = unsafeItem(i);
                    }
                    return result;
                }
            }
        };
        Comparator<Element> comparator =
                new Comparator<Element>() {
            public int compare(Element x, Element y) {
                Comparison result = comparing.$call$(x, y);
                if (result==larger_.get_()) return 1;
                if (result==smaller_.get_()) return -1;
                return 0;
            }
        };
        Collections.<Element>sort(list, comparator);
    }
   
    private enum ArrayType {
        CeylonInteger,   // 0
        JavaLong,        // 1
        CeylonFloat,     // 2
        JavaDouble,      // 3
        CeylonCharacter, // 4
        JavaInteger,     // 5
        CeylonByte,      // 6
        JavaByte,        // 7
        CeylonBoolean,   // 8
        JavaBoolean,     // 9
        JavaCharacter,   // 10
        JavaShort,       // 11
        JavaFloat,       // 12
        CeylonString,    // 13
        JavaString,      // 14
        Other            // 15
    }
   
    private static ArrayType elementType(TypeDescriptor $reifiedElement) {
        if ($reifiedElement.containsNull()) {
            return ArrayType.Other;
        }
       
        java.lang.Class<?> arrayElementClass =
                $reifiedElement.getArrayElementClass();
        if (arrayElementClass == Integer.class) {
            return ArrayType.CeylonInteger;
        }
        else if (arrayElementClass == java.lang.Long.class) {
            return ArrayType.JavaLong;
        }
        else if (arrayElementClass == Float.class) {
            return ArrayType.CeylonFloat;
        }
        else if (arrayElementClass == java.lang.Double.class) {
            return ArrayType.JavaDouble;
        }
        else if (arrayElementClass == Character.class) {
            return ArrayType.CeylonCharacter;
        }
        else if (arrayElementClass == java.lang.Integer.class) {
            return ArrayType.JavaInteger;
        }
        else if (arrayElementClass == Byte.class) {
            return ArrayType.CeylonByte;
        }
        else if (arrayElementClass == java.lang.Byte.class) {
            return ArrayType.JavaByte;
        }
        else if (arrayElementClass == Boolean.class) {
            return ArrayType.CeylonBoolean;
        }
        else if (arrayElementClass == java.lang.Boolean.class) {
            return ArrayType.JavaBoolean;
        }
        else if (arrayElementClass == java.lang.Character.class) {
            return ArrayType.JavaCharacter;
        }
        else if (arrayElementClass == java.lang.Short.class) {
            return ArrayType.JavaShort;
        }
        else if (arrayElementClass == java.lang.Float.class) {
            return ArrayType.JavaFloat;
        }
        else if (arrayElementClass == String.class) {
            return ArrayType.CeylonString;
        }
        else if (arrayElementClass == java.lang.String.class) {
            return ArrayType.JavaString;
        }
        else {
            return ArrayType.Other;
        }
    }
   

    @Override
    public boolean equals(
            @Name("that")
            java.lang.Object that) {
        // overridden so the native model is identical to the ceylon model
        return super.equals(that);
    }
   
    @Override
    @Transient
    public int hashCode() {
        // overridden so the native model is identical to the ceylon model
        return super.hashCode();
    }
   
    @Ignore
    public Array($Serialization$ ignored, TypeDescriptor $reifiedElement) {
        super(ignored, $reifiedElement);
        this.$reifiedElement = $reifiedElement;
        this.elementType = elementType($reifiedElement);
        this.array = null;
        this.size = 0;
       
    }
   
    @Ignore
    @Override
    public void $serialize$(Callable<? extends Deconstructor> deconstructor) {
        //super.$serialize$(deconstructor);
        Deconstructor dtor = deconstructor.$call$(ceylon.language.meta.typeLiteral_.typeLiteral($getType$()));
       
        ceylon.language.meta.declaration.TypeParameter elementTypeParameter = ((GenericDeclaration)Metamodel.getOrCreateMetamodel(Array.class)).getTypeParameterDeclaration("Element");
        dtor.putTypeArgument(elementTypeParameter, Metamodel.getAppliedMetamodel(this.$reifiedElement));
       
        ValueDeclaration sizeAttribute = (ValueDeclaration)((ClassDeclaration)Metamodel.getOrCreateMetamodel(Array.class)).getMemberDeclaration(ceylon.language.meta.declaration.ValueDeclaration.$TypeDescriptor$, "size");
       
        dtor.putValue(Integer.$TypeDescriptor$,
                sizeAttribute,
                Integer.instance(getSize()));
       
        for (int ii = 0; ii < getSize(); ii++) {
            dtor.<Element>putElement(this.$reifiedElement, ii, unsafeItem(ii));
        }
    }

    @Ignore
    @Override
    public void $deserialize$(Deconstructed dted) {
        //super.$deserialize$(dted);
        try {
            //ceylon.language.meta.declaration.TypeParameter elementTypeParameter = ((GenericDeclaration)Metamodel.getOrCreateMetamodel(Array.class)).getTypeParameterDeclaration("Element");
            //TypeDescriptor reifiedElement = Metamodel.getTypeDescriptor(dted.getTypeArgument(elementTypeParameter));
            //Util.setter(MethodHandles.lookup(), "$reifiedElement").invokeExact(this, reifiedElement);
           
            ValueDeclaration sizeAttribute = (ValueDeclaration)((ClassDeclaration)Metamodel.getOrCreateMetamodel(Array.class)).getMemberDeclaration(ceylon.language.meta.declaration.ValueDeclaration.$TypeDescriptor$, "size");
            Integer size = (Integer)dted.getValue(Integer.$TypeDescriptor$, sizeAttribute);
            Util.setter(MethodHandles.lookup(), "size").invokeExact(this, Util.toInt(size.value));
            Util.setter(MethodHandles.lookup(), "array").invokeExact(this, createArrayWithElement(this.$reifiedElement, Util.toInt(size.value), (Element)null));
           
            for (int ii = 0; ii < size.value; ii++) {
                java.lang.Object elementValOrRef = dted.<Element>getElement(this.$reifiedElement, ii);
                Element element;
                if (elementValOrRef instanceof ceylon.language.serialization.Reference) {
                    element = (Element)((com.redhat.ceylon.compiler.java.runtime.serialization.$InstanceLeaker$)elementValOrRef).$leakInstance$();
                } else {
                    element = (Element)elementValOrRef;
                }
                set(ii, element);
            }
        } catch (java.lang.Throwable e) {
            rethrow_.rethrow(e);
        }
    }
}
TOP

Related Classes of ceylon.language.Array

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.