All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.redhat.ceylon.compiler.java.Util Maven / Gradle / Ivy

There is a newer version: 1.3.3
Show newest version
package com.redhat.ceylon.compiler.java;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;

import ceylon.language.ArraySequence;
import ceylon.language.AssertionError;
import ceylon.language.Callable;
import ceylon.language.Finished;
import ceylon.language.Integer;
import ceylon.language.Iterable;
import ceylon.language.Iterator;
import ceylon.language.Null;
import ceylon.language.OverflowException;
import ceylon.language.Ranged;
import ceylon.language.Sequence;
import ceylon.language.Sequential;
import ceylon.language.Tuple;
import ceylon.language.empty_;
import ceylon.language.finished_;
import ceylon.language.sequence_;

import com.redhat.ceylon.compiler.java.language.AbstractArrayIterable;
import com.redhat.ceylon.compiler.java.language.ObjectArrayIterable;
import com.redhat.ceylon.compiler.java.metadata.Class;
import com.redhat.ceylon.compiler.java.metadata.Name;
import com.redhat.ceylon.compiler.java.metadata.TypeInfo;
import com.redhat.ceylon.compiler.java.runtime.metamodel.Metamodel;
import com.redhat.ceylon.compiler.java.runtime.model.TypeDescriptor;
import com.redhat.ceylon.model.cmr.ArtifactResult;

/**
 * Helper class for generated Ceylon code that needs to call implementation logic.
 * 
 * @author Stéphane Épardaud 
 */
public class Util {

    static {
        // Make sure the rethrow class is loaded if ever we need to rethrow
        // errors such as StackOverflowError, otherwise if we have to rethrow it
        // we will not be able to load that class since we've ran out of stack
        // see https://github.com/ceylon/ceylon.language/issues/311
        ceylon.language.impl.rethrow_.class.toString();
    }
    
    private static final int INIT_ARRAY_SIZE = 10;
    private static final Object[] NO_ELEMENTS = new Object[0];
    
    public static String declClassName(String name) {
        return name.replace("::", ".");
    }

    public static void loadModule(String name, String version, 
    		ArtifactResult result, ClassLoader classLoader) {
        Metamodel.loadModule(name, version, result, classLoader);
    }
    
    public static boolean isReified(java.lang.Object o, TypeDescriptor type) {
        return Metamodel.isReified(o, type);
    }

    private static HashMap, Class> classCache
     = new HashMap<>();
    
    private static Class getClassAnnotationForIdentifiableOrBasic(
            final java.lang.Class klass) {
        if (classCache.containsKey(klass)) {
            return classCache.get(klass);
        }
        Class classAnnotation = klass.getAnnotation(Class.class);
        if(classAnnotation != null) {
            classCache.put(klass, classAnnotation);
            return classAnnotation;
        } else if (klass != null && klass != java.lang.Object.class) {
            // else keep looking up
            Class c = getClassAnnotationForIdentifiableOrBasic(klass.getSuperclass());
            classCache.put(klass, c);
            return c;
        } else {
            return null;
        }
    }

    /**
     * Returns true if the given object satisfies ceylon.language.Identifiable
     */
    public static boolean isIdentifiable(java.lang.Object o) {
        if(o == null)
            return false;
        return isIdentifiable(o.getClass());
    }
    
    public static boolean isIdentifiable(java.lang.Class klazz) {
        Class classAnnotation = getClassAnnotationForIdentifiableOrBasic(klazz);
        // unless marked as NOT identifiable, every instance is Identifiable
        return classAnnotation != null ? classAnnotation.identifiable() : true;
    }
    
    /**
     * Returns true if the given object extends ceylon.language.Basic
     */
    public static boolean isBasic(java.lang.Object o) {
        if (o == null)
            return false;
        return isBasic(o.getClass());
    }

    public static boolean isBasic(java.lang.Class klazz) {
        Class classAnnotation = getClassAnnotationForIdentifiableOrBasic(klazz);
        // unless marked as NOT identifiable, every instance is Basic
        return classAnnotation != null ? classAnnotation.basic() : true;
    }
    
    //
    // Java variadic conversions
    
    /** Return the size of the given iterable if we know it can be computed 
     * efficiently (typically without iterating the iterable)
     */
    private static  int fastIterableSize(Iterable iterable) {
        if (iterable instanceof Sequential
                || iterable instanceof AbstractArrayIterable) {
            return toInt(iterable.getSize());
        }
        return -1;
    }
    
    @SuppressWarnings("unchecked")
    private static  void fillArray(T[] array, int offset, 
            Iterable iterable) {
        Iterator iterator = iterable.iterator();
        Object o;
        int index = offset;
        while ((o = iterator.next()) != finished_.get_()) {
            array[index] = (T) o;
            index++;
        }
    }
    
    /**
     * Base class for a family of builders for Java native arrays.
     *  
     * Encapsulation has been sacraficed for efficiency.
     * 
     * @param  an array type such as int[]
     */
    public static abstract class ArrayBuilder {
        private static final int MIN_CAPACITY = 5;
        private static final int MAX_CAPACITY = java.lang.Integer.MAX_VALUE;
        /** The number of elements in {@link #array}. This is always <= {@link #capacity} */
        protected int size;
        /** The length of {@link #array} */
        protected int capacity;
        /** The array */
        protected A array;
        ArrayBuilder(int initialSize) {
            capacity = Math.max(initialSize, MIN_CAPACITY);
            array = allocate(capacity);
            size = 0;
        }
        /** Append all the elements in the given array */
        final void appendArray(A elements) {
            int increment = size(elements);
            int newsize = this.size + increment;
            ensure(newsize);
            System.arraycopy(elements, 0, array, this.size, increment);
            this.size = newsize;
        }
        /** Ensure the {@link #array} is as big, or bigger than the given capacity */
        protected final void ensure(int requestedCapacity) {
            if (this.capacity >= requestedCapacity) {
                return;
            }
            
            int newcapacity = requestedCapacity+(requestedCapacity>>1);
            if (newcapacity < MIN_CAPACITY) {
                newcapacity = MIN_CAPACITY;
            } else if (newcapacity > MAX_CAPACITY) {
                newcapacity = requestedCapacity;
                if (newcapacity > MAX_CAPACITY) {
                    throw new AssertionError("can't allocate array bigger than " + MAX_CAPACITY);
                }
            }
            
            A newArray = allocate(newcapacity);
            System.arraycopy(this.array, 0, newArray, 0, this.size);
            this.capacity = newcapacity;
            this.array = newArray;
        }
        
        /**
         * Allocate and return an array of the given size
         */
        protected abstract A allocate(int size);
        /**
         * The size of the given array
         */
        protected abstract int size(A array);
        
        /**
         * Returns an array of exactly the right size to contain all the 
         * appended elements.
         */
        A build() {
            if (this.capacity == this.size) {
                return array;
            }
            A result = allocate(this.size);
            System.arraycopy(this.array, 0, result, 0, this.size);
            return result;
        }
    }
    
    /** 
     * An array builder whose result is an {@code Object[]}.
     * @see ReflectingObjectArrayBuilder
     */
    static final class ObjectArrayBuilder 
            extends ArrayBuilder {
        ObjectArrayBuilder(int initialSize) {
            super(initialSize);
        }
        @Override
        protected Object[] allocate(int size) {
            return new Object[size];
        }
        @Override
        protected int size(Object[] array) {
            return array.length;
        }
        
        void appendRef(Object t) {
            ensure(size+1);
            array[size] = t;
            size++;
        }
    }
    /** 
     * An array builder whose result is an array of a given component type, that is, {@code T[]}.
     * The intermediate arrays are {@code Object[]}.
     * @see ObjectArrayBuilder
     */
    public static final class ReflectingObjectArrayBuilder 
            extends ArrayBuilder {
        private final java.lang.Class klass;
        public ReflectingObjectArrayBuilder(int initialSize, 
                java.lang.Class klass) {
            super(initialSize);
            this.klass = klass;
        }
        @SuppressWarnings("unchecked")
        @Override
        protected T[] allocate(int size) {
            return (T[])new Object[size];
        }
        @Override
        protected int size(T[] array) {
            return array.length;
        }
        
        public void appendRef(T t) {
            ensure(size+1);
            array[size] = t;
            size++;
        }
        public T[] build() {
            @SuppressWarnings("unchecked")
            T[] result = (T[])java.lang.reflect.Array.newInstance(klass, this.size);
            System.arraycopy(this.array, 0, result, 0, this.size);
            return result;
        }
    }
    /** 
     * An array builder whose result is a {@code int[]}.
     */
    static final class IntArrayBuilder 
            extends ArrayBuilder {

        IntArrayBuilder(int initialSize) {
            super(initialSize);
        }

        @Override
        protected int[] allocate(int size) {
            return new int[size];
        }

        @Override
        protected int size(int[] array) {
            return array.length;
        }
        
        void appendInt(int i) {
            ensure(size+1);
            array[size] = i;
            size++;
        }
        
        void appendLong(long i) {
            appendInt(toInt(i));
        }
    }
    
    /** 
     * An array builder whose result is a {@code long[]}.
     */
    static final class LongArrayBuilder 
            extends ArrayBuilder {

        LongArrayBuilder(int initialSize) {
            super(initialSize);
        }

        @Override
        protected long[] allocate(int size) {
            return new long[size];
        }

        @Override
        protected int size(long[] array) {
            return array.length;
        }
        
        void appendLong(long i) {
            ensure(size+1);
            array[size] = i;
            size++;
        }
    }
    
    /** 
     * An array builder whose result is a {@ocde boolean[]}.
     */
    static final class BooleanArrayBuilder 
            extends ArrayBuilder {

        BooleanArrayBuilder(int initialSize) {
            super(initialSize);
        }

        @Override
        protected boolean[] allocate(int size) {
            return new boolean[size];
        }

        @Override
        protected int size(boolean[] array) {
            return array.length;
        }
        
        void appendBoolean(boolean b) {
            ensure(size+1);
            array[size] = b;
            size++;
        }
    }
    
    /** 
     * An array builder whose result is a {@code byte[]}.
     */
    static final class ByteArrayBuilder 
            extends ArrayBuilder {

        ByteArrayBuilder(int initialSize) {
            super(initialSize);
        }

        @Override
        protected byte[] allocate(int size) {
            return new byte[size];
        }

        @Override
        protected int size(byte[] array) {
            return array.length;
        }
        
        void appendByte(byte b) {
            ensure(size+1);
            array[size] = b;
            size++;
        }
        
    }
    
    /** 
     * An array builder whose result is a {@code short[]}.
     */
    static final class ShortArrayBuilder 
            extends ArrayBuilder {

        ShortArrayBuilder(int initialSize) {
            super(initialSize);
        }

        @Override
        protected short[] allocate(int size) {
            return new short[size];
        }

        @Override
        protected int size(short[] array) {
            return array.length;
        }
        
        void appendShort(short b) {
            ensure(size+1);
            array[size] = b;
            size++;
        }
        
        void appendLong(long b) {
            appendShort(toShort(b));
        }
    }
    
    /** 
     * An array builder whose result is a {@code double[]}.
     */
    static final class DoubleArrayBuilder 
            extends ArrayBuilder {

        DoubleArrayBuilder(int initialSize) {
            super(initialSize);
        }

        @Override
        protected double[] allocate(int size) {
            return new double[size];
        }

        @Override
        protected int size(double[] array) {
            return array.length;
        }
        
        void appendDouble(double i) {
            ensure(size+1);
            array[size] = i;
            size++;
        }
    }
    
    /** 
     * An array builder whose result is a {@code float[]}.
     */
    static final class FloatArrayBuilder 
            extends ArrayBuilder {

        FloatArrayBuilder(int initialSize) {
            super(initialSize);
        }

        @Override
        protected float[] allocate(int size) {
            return new float[size];
        }

        @Override
        protected int size(float[] array) {
            return array.length;
        }
        
        void appendFloat(float i) {
            ensure(size+1);
            array[size] = i;
            size++;
        }
        
        void appendDouble(double d) {
            appendFloat((float)d);
        }
    }
    
    /** 
     * An array builder whose result is a {@code char[]}.
     */
    static final class CharArrayBuilder 
            extends ArrayBuilder {

        CharArrayBuilder(int initialSize) {
            super(initialSize);
        }

        @Override
        protected char[] allocate(int size) {
            return new char[size];
        }

        @Override
        protected int size(char[] array) {
            return array.length;
        }
        
        void appendChar(char b) {
            ensure(size+1);
            array[size] = b;
            size++;
        }
        
        void appendCodepoint(int codepoint) {
            if (Character.charCount(codepoint) == 1) {
                appendChar((char)codepoint);
            } else {
                appendChar(Character.highSurrogate(codepoint));
                appendChar(Character.lowSurrogate(codepoint));
            }
        }
    }
    
    /** 
     * An array builder whose result is a {@code java.lang.String[]}.
     */
    static final class StringArrayBuilder 
            extends ArrayBuilder {

        StringArrayBuilder(int initialSize) {
            super(initialSize);
        }

        @Override
        protected java.lang.String[] allocate(int size) {
            return new java.lang.String[size];
        }

        @Override
        protected int size(java.lang.String[] array) {
            return array.length;
        }
        
        void appendString(java.lang.String b) {
            ensure(size+1);
            array[size] = b;
            size++;
        }
        
        void appendCeylonString(ceylon.language.String javaString) {
            appendString(javaString.value);
        }
    }
    
    @SuppressWarnings("unchecked")
    public static boolean[] 
    toBooleanArray(ceylon.language.Iterable sequence,
            boolean... initialElements) {
        if (sequence instanceof ceylon.language.List) {
            ceylon.language.List list = 
                    (ceylon.language.List) sequence;
            return toBooleanArray(list, initialElements);
        }
        BooleanArrayBuilder builder = 
                new BooleanArrayBuilder(initialElements.length+INIT_ARRAY_SIZE);
        builder.appendArray(initialElements);
        Iterator iterator = sequence.iterator();
        Object o;
        while (!((o = iterator.next()) instanceof Finished)) {
            builder.appendBoolean(((ceylon.language.Boolean) o).booleanValue());
        }
        return builder.build();
    }

    public static boolean[]
    toBooleanArray(ceylon.language.List list,
            boolean... initialElements) {
        if (list == null)
            return initialElements;
        int i=initialElements.length;
        boolean[] ret = new boolean[toInt(list.getSize() + i)];
        System.arraycopy(initialElements, 0, ret, 0, i);
        Iterator iterator = list.iterator();
        Object o;
        while ((o = iterator.next()) != finished_.get_()) {
            ret[i++] = ((ceylon.language.Boolean) o).booleanValue();
        }
        return ret;
    }
    
    @SuppressWarnings("unchecked")
    public static byte[] 
    toByteArray(ceylon.language.Iterable sequence,
            byte... initialElements) {
        if (sequence instanceof ceylon.language.List) {
            ceylon.language.List list = 
                    (ceylon.language.List) sequence;
            return toByteArray(list, initialElements);
        }
        ByteArrayBuilder builder = 
                new ByteArrayBuilder(initialElements.length+INIT_ARRAY_SIZE);
        int i=0;
        for(;i iterator = sequence.iterator();
        Object o;
        while (!((o = iterator.next()) instanceof Finished)) {
            builder.appendByte(((ceylon.language.Byte) o).byteValue());
        }
        return builder.build();
    }

    public static byte[]
    toByteArray(ceylon.language.List list,
            byte... initialElements) {
        byte[] ret = new byte[(list == null ? 0 : toInt(list.getSize()) + initialElements.length)];
        int i=0;
        for (;i iterator = list.iterator();
            Object o;
            while ((o = iterator.next()) != finished_.get_()) {
                ret[i++] = ((ceylon.language.Byte) o).byteValue();
            }
        }
        return ret;
    }
    
    @SuppressWarnings("unchecked")
    public static short[] 
    toShortArray(ceylon.language.Iterable sequence,
            long... initialElements) {
        if(sequence instanceof ceylon.language.List) {
            ceylon.language.List list = 
                    (ceylon.language.List) sequence;
            return toShortArray(list, initialElements);
        }
        ShortArrayBuilder builder = 
                new ShortArrayBuilder(initialElements.length+INIT_ARRAY_SIZE);
        int i=0;
        for(;i iterator = sequence.iterator();
        Object o;
        while (!((o = iterator.next()) instanceof Finished)) {
            builder.appendLong(((ceylon.language.Integer) o).longValue());
        }
        return builder.build();
    }

    public static short[]
    toShortArray(ceylon.language.List list,
            long... initialElements) {
        short[] ret = new short[(list == null ? 0 : toInt(list.getSize()) + initialElements.length)];
        int i=0;
        for (;i iterator = list.iterator();
            Object o;
            while ((o = iterator.next()) != finished_.get_()) {
                ret[i++] = toShort(((ceylon.language.Integer) o).longValue());
            }
        }
        return ret;
    }
    
    @SuppressWarnings("unchecked")
    public static int[] 
    toIntArray(ceylon.language.Iterable sequence,
            long... initialElements) {
        if(sequence instanceof ceylon.language.List) {
            ceylon.language.List list = 
                    (ceylon.language.List) sequence;
            return toIntArray(list,
                    initialElements);
        }
        IntArrayBuilder builder = 
                new IntArrayBuilder(initialElements.length+INIT_ARRAY_SIZE);
        int i=0;
        for(;i iterator = sequence.iterator();
        Object o;
        while (!((o = iterator.next()) instanceof Finished)) {
            builder.appendLong(((ceylon.language.Integer) o).longValue());
        }
        return builder.build();
    }

    public static int[]
    toIntArray(ceylon.language.List list,
            long... initialElements) {
        int[] ret = new int[(list == null ? 0 : toInt(list.getSize()) + initialElements.length)];
        int i=0;
        for (;i iterator = list.iterator();
            Object o;
            while ((o = iterator.next()) != finished_.get_()) {
                ret[i++] = toInt(((ceylon.language.Integer) o).longValue());
            }
        }
        return ret;
    }
    
    @SuppressWarnings("unchecked")
    public static long[] 
    toLongArray(ceylon.language.Iterable sequence,
            long... initialElements) {
        if(sequence instanceof ceylon.language.List) {
            ceylon.language.List list = 
                    (ceylon.language.List) sequence;
            return toLongArray(list, initialElements);
        }
        LongArrayBuilder builder = 
                new LongArrayBuilder(initialElements.length+INIT_ARRAY_SIZE);
        builder.appendArray(initialElements);
        Iterator iterator = sequence.iterator();
        Object o;
        while (!((o = iterator.next()) instanceof Finished)) {
            builder.appendLong(((ceylon.language.Integer) o).longValue());
        }
        return builder.build();
    }

    public static long[]
    toLongArray(ceylon.language.List list,
            long... initialElements) {
        if (list == null)
            return initialElements;
        int i=initialElements.length;
        long[] ret = new long[toInt(list.getSize() + i)];
        System.arraycopy(initialElements, 0, ret, 0, i);
        Iterator iterator = list.iterator();
        Object o;
        while ((o = iterator.next()) != finished_.get_()) {
            ret[i++] = ((ceylon.language.Integer) o).longValue();
        }
        return ret;
    }

    @SuppressWarnings("unchecked")
    public static float[] 
    toFloatArray(ceylon.language.Iterable sequence, 
            double... initialElements) {
        if(sequence instanceof ceylon.language.List) {
            ceylon.language.List list = 
                    (ceylon.language.List) sequence;
            return toFloatArray(list, initialElements);
        }
        FloatArrayBuilder builder = 
                new FloatArrayBuilder(initialElements.length+INIT_ARRAY_SIZE);
        int i=0;
        for (;i iterator = sequence.iterator();
        Object o;
        while (!((o = iterator.next()) instanceof Finished)) {
            builder.appendDouble(((ceylon.language.Float)o).doubleValue());
        }
        return builder.build();
    }

    public static float[]
    toFloatArray(ceylon.language.List list,
            double... initialElements) {
        float[] ret = new float[(list == null ? 0 : toInt(list.getSize()) + initialElements.length)];
        int i=0;
        for (;i iterator = list.iterator();
            Object o;
            while ((o = iterator.next()) != finished_.get_()) {
                ret[i++] = (float)((ceylon.language.Float) o).doubleValue();
            }
        }
        return ret;
    }

    @SuppressWarnings("unchecked")
    public static double[] 
    toDoubleArray(ceylon.language.Iterable sequence,
            double... initialElements) {
        if (sequence instanceof ceylon.language.List) {
            ceylon.language.List list = 
                    (ceylon.language.List) sequence;
            return toDoubleArray(list, initialElements);
        }
        DoubleArrayBuilder builder = 
                new DoubleArrayBuilder(initialElements.length+INIT_ARRAY_SIZE);
        builder.appendArray(initialElements);
        Iterator iterator = sequence.iterator();
        Object o;
        while (!((o = iterator.next()) instanceof Finished)) {
            builder.appendDouble(((ceylon.language.Float) o).doubleValue());
        }
        return builder.build();
    }

    public static double[]
    toDoubleArray(ceylon.language.List list,
            double... initialElements) {
        if (list == null)
            return initialElements;
        int i=initialElements.length;
        double[] ret = new double[toInt(list.getSize() + i)];
        System.arraycopy(initialElements, 0, ret, 0, i);
        Iterator iterator = list.iterator();
        Object o;
        while ((o = iterator.next()) != finished_.get_()) {
            ret[i++] = ((ceylon.language.Float) o).doubleValue();
        }
        return ret;
    }

    public static char[] 
	toCharArray(ceylon.language.Iterable sequence,
	        int... initialElements) {
        // Note the List optimization doesn't work because 
        // the number of codepoints in the sequence
        // doesn't equal the size of the result array.
        CharArrayBuilder builder = 
                new CharArrayBuilder(initialElements.length+INIT_ARRAY_SIZE);
        int i=0;
        for(;i iterator = sequence.iterator();
        Object o;
        while (!((o = iterator.next()) instanceof Finished)) {
            builder.appendCodepoint(((ceylon.language.Character) o).codePoint);
        }
        return builder.build();
    }

    public static char[] 
	toCharArray(ceylon.language.List sequence,
	        int... initialElements) {
        return toCharArray((ceylon.language.Iterable)sequence, initialElements);
    }

    @SuppressWarnings("unchecked")
    public static int[] 
	toCodepointArray(ceylon.language.Iterable sequence,
	        int... initialElements) {
        if (sequence instanceof ceylon.language.List) {
            ceylon.language.List list = 
                    (ceylon.language.List)sequence;
            return toCodepointArray(list, initialElements);
        }
        IntArrayBuilder builder = 
                new IntArrayBuilder(initialElements.length+INIT_ARRAY_SIZE);
        builder.appendArray(initialElements);
        Iterator iterator = sequence.iterator();
        Object o;
        while (!((o = iterator.next()) instanceof Finished)) {
            builder.appendInt(((ceylon.language.Character) o).codePoint);
        }
        return builder.build();
    }

    public static int[]
    toCodepointArray(ceylon.language.List list,
            int... initialElements) {
        if (list == null)
            return initialElements;
        int i=initialElements.length;
        int[] ret = new int[toInt(list.getSize() + i)];
        System.arraycopy(initialElements, 0, ret, 0, i);
        Iterator iterator = list.iterator();
        Object o;
        while ((o = iterator.next()) != finished_.get_()) {
            ret[i++] = ((ceylon.language.Character)o).intValue();
        }
        return ret;
    }

    @SuppressWarnings("unchecked")
    public static java.lang.String[] 
    toJavaStringArray(ceylon.language.Iterable sequence,
            java.lang.String... initialElements) {
        if (sequence instanceof ceylon.language.List) {
            ceylon.language.List list = 
                    (ceylon.language.List) sequence;
            return toJavaStringArray(list, initialElements);
        }
        StringArrayBuilder builder = 
                new StringArrayBuilder(initialElements.length+INIT_ARRAY_SIZE);
        builder.appendArray(initialElements);
        Iterator iterator = sequence.iterator();
        Object o;
        while (!((o = iterator.next()) instanceof Finished)) {
            builder.appendString(((ceylon.language.String)o).value);
        }
        return builder.build();
    }

    public static java.lang.String[]
    toJavaStringArray(ceylon.language.List list,
            java.lang.String... initialElements) {
        if (list == null)
            return initialElements;
        int i=initialElements.length;
        java.lang.String[] ret = new java.lang.String[toInt(list.getSize() + i)];
        System.arraycopy(initialElements, 0, ret, 0, i);
        Iterator iterator = list.iterator();
        Object o;
        while ((o = iterator.next()) != finished_.get_()) {
            ret[i++] = ((ceylon.language.String) o).toString();
        }
        return ret;
    }

    @SuppressWarnings("unchecked")
    public static  T[] toArray(ceylon.language.List sequence,
            T[] ret, T... initialElements) {
        if (sequence == null)
            return initialElements;
        int i=initialElements.length;
        System.arraycopy(initialElements, 0, ret, 0, i);
        Iterator iterator = sequence.iterator();
        Object o;
        while ((o = iterator.next()) != finished_.get_()) {
            ret[i++] = (T)o;
        }
        return ret;
    }

    
    @SuppressWarnings("unchecked")
    public static  T[] toArray(ceylon.language.Iterable iterable,
            java.lang.Class klass, T... initialElements) {
        if (iterable == null) {
            return initialElements;
        }
        T[] ret;
        int size = fastIterableSize(iterable);
        if (size != -1) {
            ret = (T[]) java.lang.reflect.Array.newInstance(klass, 
                    size + initialElements.length);
            if (initialElements.length != 0) {
                // fast copy of list
                System.arraycopy(initialElements, 0, ret, 0, 
                        initialElements.length);
            }    
            fillArray(ret, initialElements.length, iterable);
        } else {
            ReflectingObjectArrayBuilder builder = 
                    new ReflectingObjectArrayBuilder
                        (initialElements.length+INIT_ARRAY_SIZE, klass);
            builder.appendArray(initialElements);
            Iterator iterator = iterable.iterator();
            Object o;
            while (!((o = iterator.next()) instanceof Finished)) {
                builder.appendRef((T) o);
            }
            ret = builder.build();
        }
        return ret;
    }

    @SuppressWarnings("unchecked")
    public static  T[] toArray(ceylon.language.List list,
            java.lang.Class klass, T... initialElements) {
        if (list == null)
            return initialElements;
        int i=initialElements.length;
        T[] ret = (T[]) java.lang.reflect.Array.newInstance(klass,
                toInt(list.getSize() + i));
        System.arraycopy(initialElements, 0, ret, 0, i);
        Iterator iterator = list.iterator();
        Object o;
        while ((o = iterator.next()) != finished_.get_()) {
            ret[i++] = (T)o;
        }
        return ret;
    }
    
    public static  T checkNull(T t) {
        if(t == null)
            throw new AssertionError("null value returned from native call not assignable to Object");
        return t;
    }
    
    /** 
     * Generates a default message for when a Throwable lacks a non-null 
     * message of its own. This can only happen for non-Ceylon throwable types, 
     * but due to type erasure it's not possible to know at a catch site which 
     * whether you have a Ceylon throwable
     */
    public static String throwableMessage(java.lang.Throwable t) {
        String message = t.getMessage();
        if (message == null) {
            java.lang.Throwable c = t.getCause();
            if (c != null) {
                message = c.getMessage();
            } else {
                message = "";
            }
        }
        return message;
    }
    
    /**
     * Return a {@link Sequential} wrapping the given elements
     * (subsequent changes to the array will be visible in 
     * the returned {@link Sequential}).
     * @param $reifiedT The reified type parameter
     * @param elements The elements
     * @return A Sequential
     */
    @SuppressWarnings({"unchecked","rawtypes"})
    public static  Sequential 
    sequentialWrapper(TypeDescriptor $reifiedT, T[] elements) {
        if (elements.length == 0) {
            return (Sequential) empty_.get_();
        }
        return new Tuple>($reifiedT, elements);
    }

    /** 
     * 

Return a {@link Sequential Sequential<String>} wrapping the * given {@code java.lang.String[]} elements * (subsequent changes to the array will be visible in * the returned {@link Sequential}).

* *

Used to obtain a {@code Sequential} from a {@code java.lang.String[]} * obtained from an annotation.

*/ @SuppressWarnings({"unchecked","rawtypes"}) public static Sequential sequentialWrapperBoxed(java.lang.String[] elements) { if (elements.length == 0) { return (Sequential) empty_.get_(); } int total = elements.length; java.lang.Object[] newArray = new java.lang.Object[total]; int i = 0; for(java.lang.String element : elements) { newArray[i++] = ceylon.language.String.instance(element); } return new Tuple(ceylon.language.String.$TypeDescriptor$, newArray); } /** *

Return a {@link Sequential Sequential<Integer>} wrapping the * given {@code long[]} elements * (subsequent changes to the array will be visible in * the returned {@link Sequential}).

* *

Used to obtain a {@code Sequential} from a {@code long[]} * obtained from an annotation.

*/ @SuppressWarnings({"unchecked","rawtypes"}) public static Sequential sequentialWrapperBoxed(long[] elements) { if (elements.length == 0) { return (Sequential)empty_.get_(); } int total = elements.length; java.lang.Object[] newArray = new java.lang.Object[total]; int i = 0; for(long element : elements) { newArray[i++] = ceylon.language.Integer.instance(element); } return new Tuple(ceylon.language.Integer.$TypeDescriptor$, newArray); } /** *

Return a {@link Sequential Sequential<Character>} wrapping the * given {@code int[]} elements * (subsequent changes to the array will be visible in * the returned {@link Sequential}).

* *

Used to obtain a {@code Sequential} from a {@code int[]} * obtained from an annotation.

*/ @SuppressWarnings({"unchecked","rawtypes"}) public static Sequential sequentialWrapperBoxed(int[] elements) { if (elements.length == 0) { return (Sequential)empty_.get_(); } int total = elements.length; java.lang.Object[] newArray = new java.lang.Object[total]; int i = 0; for(int element : elements) { newArray[i++] = ceylon.language.Character.instance(element); } return new Tuple(ceylon.language.Character.$TypeDescriptor$, newArray); } /** *

Return a {@link Sequential Sequential<Boolean>} wrapping the * given {@code boolean[]} elements * (subsequent changes to the array will be visible in * the returned {@link Sequential}).

* *

Used to obtain a {@code Sequential} from a {@code boolean[]} * obtained from an annotation.

*/ @SuppressWarnings({"unchecked","rawtypes"}) public static Sequential sequentialWrapperBoxed(boolean[] elements) { if (elements.length == 0) { return (Sequential)empty_.get_(); } int total = elements.length; java.lang.Object[] newArray = new java.lang.Object[total]; int i = 0; for(boolean element : elements) { newArray[i++] = ceylon.language.Boolean.instance(element); } return new Tuple(ceylon.language.Boolean.$TypeDescriptor$, newArray); } /** *

Return a {@link Sequential Sequential<Float>} wrapping the * given {@code double[]} elements * (subsequent changes to the array will be visible in * the returned {@link Sequential}).

* *

Used to obtain a {@code Sequential} from a {@code double[]} * obtained from an annotation.

*/ @SuppressWarnings({"unchecked","rawtypes"}) public static Sequential sequentialWrapperBoxed(double[] elements) { if (elements.length == 0) { return (Sequential)empty_.get_(); } int total = elements.length; java.lang.Object[] newArray = new java.lang.Object[total]; int i = 0; for(double element : elements) { newArray[i++] = ceylon.language.Float.instance(element); } return new Tuple(ceylon.language.Float.$TypeDescriptor$, newArray); } /** * Return {@link empty_#getEmpty$ empty} or an {@link ArraySequence} * wrapping the given elements, depending on whether the given array * and varargs are empty. * * @deprecated because it's too easy to end up evaluating the arguments * in the wrong order. Use {@link #sequentialCopy(TypeDescriptor, Object[], Sequential)} * * @param rest The elements at the end of the sequence * @param elements the elements at the start of the sequence * @return A Sequential */ @Deprecated public static Sequential sequentialCopy(TypeDescriptor $reifiedT, Sequential rest, Object... elements) { return sequentialCopy($reifiedT, 0, elements.length, elements, rest); } /** * Return {@link empty_#getEmpty$ empty} or an {@link ArraySequence} * wrapping the given elements, depending on whether the given array * and varargs are empty. * * @param rest The elements at the end of the sequence * @param elements the elements at the start of the sequence * @return A Sequential */ public static Sequential sequentialCopy(TypeDescriptor $reifiedT, Object[] initialElements, Sequential rest) { return sequentialCopy($reifiedT, 0, initialElements.length, initialElements, rest); } /** * Returns a Sequential made by concatenating the {@code length} elements * of {@code elements} starting from {@code state} with the elements of * {@code rest}: {*elements[start:length], *rest}. * * This method does not copy {@code elements} unless it has to */ public static Sequential sequentialCopy( TypeDescriptor $reifiedT, int start, int length, Object[] elements, Sequential rest) { return sequentialCopy($reifiedT, start, length, elements, rest, false); } /** * Returns a Sequential made by concatenating the {@code length} elements * of {@code elements} starting from {@code state} with the elements of * {@code rest}: {*elements[start:length], *rest}. * * This method does not copy {@code elements} unless it has to * or unless forceCopy is true */ @SuppressWarnings("unchecked") public static Sequential sequentialCopy( TypeDescriptor $reifiedT, int start, int length, Object[] elements, Sequential rest, boolean forceCopy) { if (length == 0) { if(rest.getEmpty()) { return (Sequential)empty_.get_(); } // otherwise we MUST copy it if(!forceCopy) return rest; } // elements is not empty if(rest.getEmpty()) { return new ObjectArrayIterable($reifiedT, elements) .skip(start).take(length).sequence(); } // we have both (or must copy), let's find the total size int total = toInt(rest.getSize() + length); java.lang.Object[] newArray = new java.lang.Object[total]; System.arraycopy(elements, start, newArray, 0, length); Iterator iterator = rest.iterator(); int i = length; for(Object elem; (elem = iterator.next()) != finished_.get_(); i++) { newArray[i] = elem; } return new ObjectArrayIterable($reifiedT, (T[])newArray).sequence(); } /** *

Equivalent to the Ceylon {@code sequential(iterable) else []}, this * converts an {@code Iterable} to a {@code Sequential} without calling * {@code Iterable.sequence()}.

* *

This is used for spread arguments in * tuple literals: {@code [*foo]}

* a */ @SuppressWarnings({ "rawtypes", "unchecked" }) public static Sequential sequentialOf(TypeDescriptor reified$Element, final Iterable iterable) { Object result = sequence_.sequence(reified$Element, Null.$TypeDescriptor$, iterable); if (result == null) { return (Sequential)empty_.get_(); } return (Sequential)result; } /** * Returns a runtime exception. To be used by implementors * of mixin methods used to access super-interfaces $impl fields * for final classes that don't and will never need them */ public static RuntimeException makeUnimplementedMixinAccessException() { return new RuntimeException("Internal error: should never be called"); } /** * Specialised version of Tuple.spanFrom for when the * typechecker determines that it can do better than the * generic one that returns a Sequential. Here we return * a Tuple, although our type signature hides this. */ public static Sequential tuple_spanFrom(Ranged tuple, ceylon.language.Integer index) { Sequential seq = (Sequential)tuple; long i = index.longValue(); while(i-- > 0) { seq = seq.getRest(); } return seq; } /** Called to initialize an {@code BooleanArray} when one is instantiated */ public static boolean[] fillArray(boolean[] array, boolean val) { Arrays.fill(array, val); return array; } /** Called to initialize a {@code ByteArray} when one is instantiated */ public static byte[] fillArray(byte[] array, byte val) { Arrays.fill(array, val); return array; } /** Called to initialize an {@code ShortArray} when one is instantiated */ public static short[] fillArray(short[] array, short val) { Arrays.fill(array, val); return array; } /** Called to initialize an {@code IntArray} when one is instantiated */ public static int[] fillArray(int[] array, int val) { Arrays.fill(array, val); return array; } /** Called to initialize a {@code LongArray} when one is instantiated */ public static long[] fillArray(long[] array, long val) { Arrays.fill(array, val); return array; } /** Called to initialize a {@code FloatArray} when one is instantiated */ public static float[] fillArray(float[] array, float val) { Arrays.fill(array, val); return array; } /** Called to initialize a {@code DoubleArray} when one is instantiated */ public static double[] fillArray(double[] array, double val) { Arrays.fill(array, val); return array; } /** Called to initialize a {@code CharArray} when one is instantiated */ public static char[] fillArray(char[] array, char val) { Arrays.fill(array, val); return array; } /** Called to initialize an {@code ObjectArray} when one it instantiated */ public static T[] fillArray(T[] array, T val) { Arrays.fill(array, val); return array; } private static void checkArrayElementType(TypeDescriptor $reifiedElement) { if ($reifiedElement instanceof TypeDescriptor.Composite) { throw new AssertionError("cannot create Java array with union or intersection element type " + $reifiedElement.toString()); } else if ($reifiedElement instanceof TypeDescriptor.Nothing) { throw new AssertionError("cannot create Java array with bottom element type Nothing"); } } @SuppressWarnings("unchecked") public static T[] makeArray(TypeDescriptor $reifiedElement, int size) { checkArrayElementType($reifiedElement); return (T[]) java.lang.reflect.Array.newInstance($reifiedElement.getArrayElementClass(), size); } @SuppressWarnings("unchecked") public static T[] makeArray(TypeDescriptor $reifiedElement, int... dimensions) { checkArrayElementType($reifiedElement); return (T[]) java.lang.reflect.Array.newInstance($reifiedElement.getArrayElementClass(), dimensions); } /** * Returns a runtime exception. To be used by implementors * of Java array methods used to make sure they are never * called */ public static RuntimeException makeJavaArrayWrapperException() { return new RuntimeException("Internal error: should never be called"); } /** * Throws an exception without having to declare it. This * uses a Ceylon helper that does this because Ceylon does * not have checked exceptions. This is merely to avoid a * javac check wrt. checked exceptions. * Stef tried using Unsafe.throwException() but * Unsafe.getUnsafe() throws if we have a ClassLoader, and * the only other way is using reflection to get to it, * which starts to smell real bad when we can just use a * Ceylon helper. */ public static void rethrow(final Throwable t) { ceylon.language.impl.rethrow_.rethrow(t); } /** * Null-safe equals. */ public static boolean eq(Object a, Object b) { if(a == null) return b == null; if(b == null) return false; return a.equals(b); } /** * Applies the given function to the given arguments. The * argument types are assumed to be correct and will not * be checked. This method will properly deal with variadic * functions. The arguments are expected to be spread in the * given sequential, even in the case of variadic functions, * which means that there will be no spreading of any * Sequential instance in the given arguments. On the * contrary, a portion of the given arguments may be packaged * into a Sequential if the given function is variadic. * * This version trusts the type of the Sequential used for any variadic parameter * and will not copy it. * * @param function the function to apply * @param arguments the argument values to pass to the function * @return the function's return value */ public static Return apply(Callable function, Sequential arguments) { return apply(function, arguments, null); } /** * Applies the given function to the given arguments. The * argument types are assumed to be correct and will not * be checked. This method will properly deal with variadic * functions. The arguments are expected to be spread in the * given sequential, even in the case of variadic functions, * which means that there will be no spreading of any * Sequential instance in the given arguments. On the * contrary, a portion of the given arguments may be packaged * into a Sequential if the given function is variadic. * * Any variadic parameter will be copied into a new sequence * if variadicElementType is specified. Use this if you don't * trust the arguments type (or its span types). * * @param function the function to apply * @param arguments the argument values to pass to the function * @param variadicElementType if non-null, the type of variadic sequential elements * to pass to the receiver, copied from the given arguments list. Use this if * you do not trust the arguments sequence to be of the right type * @return the function's return value */ public static Return apply(Callable function, Sequential arguments, TypeDescriptor variadicElementType) { int variadicParameterIndex = function.$getVariadicParameterIndex$(); switch (toInt(arguments.getSize())) { case 0: // even if the function is variadic it will overload $call so we're good return function.$call$(); case 1: // if the first param is variadic, just pass the sequence along if(variadicParameterIndex == 0) return function.$callvariadic$(safeSpanFrom(arguments, 0, variadicElementType)); return function.$call$(arguments.getFromFirst(0)); case 2: switch(variadicParameterIndex) { // pass the sequence along case 0: return function.$callvariadic$(safeSpanFrom(arguments, 0, variadicElementType)); // extract the first, pass the rest case 1: return function.$callvariadic$(arguments.getFromFirst(0), safeSpanFrom(arguments, 1, variadicElementType)); // no variadic param, or after we run out of elements to pass default: return function.$call$(arguments.getFromFirst(0), arguments.getFromFirst(1)); } case 3: switch(variadicParameterIndex) { // pass the sequence along case 0: return function.$callvariadic$(safeSpanFrom(arguments, 0, variadicElementType)); // extract the first, pass the rest case 1: return function.$callvariadic$(arguments.getFromFirst(0), safeSpanFrom(arguments, 1, variadicElementType)); // extract the first and second, pass the rest case 2: return function.$callvariadic$(arguments.getFromFirst(0), arguments.getFromFirst(1), safeSpanFrom(arguments, 2, variadicElementType)); // no variadic param, or after we run out of elements to pass default: return function.$call$(arguments.getFromFirst(0), arguments.getFromFirst(1), arguments.getFromFirst(2)); } default: switch(variadicParameterIndex) { // pass the sequence along case 0: return function.$callvariadic$(safeSpanFrom(arguments, 0, variadicElementType)); // extract the first, pass the rest case 1: return function.$callvariadic$(arguments.getFromFirst(0), safeSpanFrom(arguments, 1, variadicElementType)); // extract the first and second, pass the rest case 2: return function.$callvariadic$(arguments.getFromFirst(0), arguments.getFromFirst(1), safeSpanFrom(arguments, 2, variadicElementType)); case 3: return function.$callvariadic$(arguments.getFromFirst(0), arguments.getFromFirst(1), arguments.getFromFirst(2), safeSpanFrom(arguments, 3, variadicElementType)); // no variadic param case -1: java.lang.Object[] args = Util.toArray(arguments, new java.lang.Object[toInt(arguments.getSize())]); return function.$call$(args); // we have a variadic param in there bothering us default: // we stuff everything before the variadic into an array int beforeVariadic = Math.min(toInt(arguments.getSize()), variadicParameterIndex); boolean needsVariadic = beforeVariadic < arguments.getSize(); args = new java.lang.Object[beforeVariadic + (needsVariadic ? 1 : 0)]; Iterator iterator = arguments.iterator(); java.lang.Object it; int i=0; while(i < beforeVariadic && (it = iterator.next()) != finished_.get_()) { args[i++] = it; } // add the remainder as a variadic arg if required if(needsVariadic) { args[i] = safeSpanFrom(arguments, beforeVariadic, variadicElementType); return function.$callvariadic$(args); } return function.$call$(args); } } } /** * Makes sure the sub-sequence at arguments[start...] is copied in a sequence of the given type if it's given * @param arguments total list of arguments (flat) * @param start index of the start of the arguments we want to slice * @param variadicElementType element type of the varargs sequence we need, or null if we don't care and trust it * @return a new sequence or the original sequence's span */ private static Sequential safeSpanFrom(Sequential arguments, int start, TypeDescriptor variadicElementType) { if(variadicElementType == null){ if(start == 0) return arguments; return arguments.spanFrom(Integer.instance(start)); } // we don't trust it, we need to copy it Sequential ret; if(start == 0) ret = arguments; else ret = arguments.spanFrom(Integer.instance(start)); return sequentialCopy(variadicElementType, 0, 0, NO_ELEMENTS, ret, true); } @SuppressWarnings("unchecked") public static java.lang.Class getJavaClassForDescriptor(TypeDescriptor descriptor) { if(descriptor == TypeDescriptor.NothingType || descriptor == ceylon.language.Object.$TypeDescriptor$ || descriptor == ceylon.language.Anything.$TypeDescriptor$ || descriptor == ceylon.language.Basic.$TypeDescriptor$ || descriptor == ceylon.language.Null.$TypeDescriptor$ || descriptor == ceylon.language.Identifiable.$TypeDescriptor$) return (java.lang.Class) Object.class; if(descriptor instanceof TypeDescriptor.Class) return (java.lang.Class) ((TypeDescriptor.Class) descriptor).getKlass(); if(descriptor instanceof TypeDescriptor.Member) return getJavaClassForDescriptor(((TypeDescriptor.Member) descriptor).getMember()); if(descriptor instanceof TypeDescriptor.Intersection) return (java.lang.Class) Object.class; if(descriptor instanceof TypeDescriptor.Union) { TypeDescriptor.Union union = (TypeDescriptor.Union) descriptor; TypeDescriptor[] members = union.getMembers(); // special case for optional types if(members.length == 2) { if(members[0] == ceylon.language.Null.$TypeDescriptor$) return getJavaClassForDescriptor(members[1]); if(members[1] == ceylon.language.Null.$TypeDescriptor$) return getJavaClassForDescriptor(members[0]); } return (java.lang.Class) Object.class; } return (java.lang.Class) Object.class; } public static int arrayLength(Object o) { if (o instanceof Object[]) return ((Object[])o).length; else if (o instanceof boolean[]) return ((boolean[])o).length; else if (o instanceof float[]) return ((float[])o).length; else if (o instanceof double[]) return ((double[])o).length; else if (o instanceof char[]) return ((char[])o).length; else if (o instanceof byte[]) return ((byte[])o).length; else if (o instanceof short[]) return ((short[])o).length; else if (o instanceof int[]) return ((int[])o).length; else if (o instanceof long[]) return ((long[])o).length; throw new ClassCastException(notArrayType(o)); } /** * Used by the JVM backend to get unboxed items from an Array<Integer> backing array */ public static long getIntegerArray(Object o, int index) { if (o instanceof short[]) return ((short[])o)[index]; else if (o instanceof int[]) return ((int[])o)[index]; else if (o instanceof long[]) return ((long[])o)[index]; throw new ClassCastException(notArrayType(o)); } /** * Used by the JVM backend to get unboxed items from an Array<Float> backing array */ public static double getFloatArray(Object o, int index) { if (o instanceof float[]) return ((float[])o)[index]; else if (o instanceof double[]) return ((double[])o)[index]; throw new ClassCastException(notArrayType(o)); } /** * Used by the JVM backend to get unboxed items from an Array<Character> backing array */ public static int getCharacterArray(Object o, int index) { if (o instanceof int[]) return ((int[])o)[index]; throw new ClassCastException(notArrayType(o)); } /** * Used by the JVM backend to get unboxed items from an Array<Byte> backing array */ public static byte getByteArray(Object o, int index) { if (o instanceof byte[]) return ((byte[])o)[index]; throw new ClassCastException(notArrayType(o)); } /** * Used by the JVM backend to get unboxed items from an Array<Boolean> backing array */ public static boolean getBooleanArray(Object o, int index) { if (o instanceof boolean[]) return ((boolean[])o)[index]; throw new ClassCastException(notArrayType(o)); } /** * Used by the JVM backend to get unboxed items from an Array<Integer> backing array */ public static java.lang.String getStringArray(Object o, int index) { if (o instanceof java.lang.String[]) return ((java.lang.String[])o)[index]; throw new ClassCastException(notArrayType(o)); } /** * Used by the JVM backend to get items from an ArraySequence object. Beware: do not use that * for Array<Object> as there's too much magic in there. */ public static Object getObjectArray(Object o, int index) { if (o instanceof Object[]) return ((Object[])o)[index]; else if (o instanceof boolean[]) return ceylon.language.Boolean.instance(((boolean[])o)[index]); else if (o instanceof float[]) return ceylon.language.Float.instance(((float[])o)[index]); else if (o instanceof double[]) return ceylon.language.Float.instance(((double[])o)[index]); else if (o instanceof char[]) return ceylon.language.Character.instance(((char[])o)[index]); else if (o instanceof byte[]) return ceylon.language.Byte.instance(((byte[])o)[index]); else if (o instanceof short[]) return ceylon.language.Integer.instance(((short[])o)[index]); else if (o instanceof int[]) return ceylon.language.Integer.instance(((int[])o)[index]); else if (o instanceof long[]) return ceylon.language.Integer.instance(((long[])o)[index]); throw new ClassCastException(notArrayType(o)); } private static String notArrayType(Object o) { return (o == null ? "null" : o.getClass().getName()) + " is not an array type"; } @SuppressWarnings({ "rawtypes", "unchecked" }) public static Sequential suppressedExceptions( @Name("exception") @TypeInfo("ceylon.language::Exception") final java.lang.Throwable exception) { java.lang.Throwable[] sup = exception.getSuppressed(); if (sup.length > 0) { return new ObjectArrayIterable (TypeDescriptor.klass(java.lang.Throwable.class), sup) .sequence(); } else { return (Sequential) empty_.get_(); } } public static Sequence asSequence(Sequential sequential) { if (sequential instanceof Sequence) { return (Sequence) sequential; } else { throw new AssertionError("Assertion failed: Sequence expected"); } } /** *

Typecast a {@code long} to an {@code int}, or throw if the {@code long} * cannot be safely converted.

* *

We need to do this:

*
    *
  • when creating or indexing into an array,
  • *
  • when invoking a Java method which takes an {@code int},
  • *
  • when assigning to a Java {@code int} field.
  • *
      * @throws ceylon.language.OverflowException */ public static int toInt(long value) { int result = (int) value; if (result != value) { throw new OverflowException(value + " cannot be safely converted into a 32-bit integer"); } return result; } /** *

      Typecast a {@code long} to a {@code short}, or throw if the {@code long} * cannot be safely converted.

      * *

      We need to do this:

      *
        *
      • when invoking a Java method which takes a {@code short},
      • *
      • when assigning to a Java {@code short} field.
      • *
          * @throws ceylon.language.OverflowException */ public static short toShort(long value) { short result = (short) value; if (result != value) { throw new OverflowException(value + " cannot be safely converted into a 16-bit integer"); } return result; } /** *

          Typecast a {@code long} to a {@code byte}, or throw if the {@code long} * cannot be safely converted.

          * *

          We need to do this:

          *
            *
          • when creating or indexing into an array,
          • *
          • when invoking a Java method which takes a {@code byte},
          • *
          • when assigning to a Java {@code byte} field.
          • *
              * @throws ceylon.language.OverflowException */ public static byte toByte(long value) { byte result = (byte) value; if (result != value) { throw new OverflowException(value + " cannot be safely converted into a 8-bit integer"); } return result; } /** * Used during deserialization to obtain a MethodHandle used for resetting final fields. * @param lookup The lookup on the class containing the field * @param fieldName The name of the field whose value is to be set * @return The method handle * @throws ReflectiveOperationException */ public static MethodHandle setter(MethodHandles.Lookup lookup, String fieldName) throws ReflectiveOperationException { // Should this be an instance method of some thing passed to the derserialize method Field field = lookup.lookupClass().getDeclaredField(fieldName); field.setAccessible(true); MethodHandle handle = lookup.unreflectSetter(field); return handle; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy