package de.renew.formalism.function;

import de.renew.expression.Function;
import de.renew.unify.Impossible;
import de.renew.unify.Tuple;
import de.renew.util.Value;

/**
 * A function that retrieves an element from an array.
 */
public final class ArrayFunction implements Function {
    /**
     * The shared instance of the array access function.
     */
    public static final Function FUN = new ArrayFunction();

    private ArrayFunction() {}

    @Override
    public Object function(Object param) throws Impossible {
        Tuple tuple = (Tuple) param;
        if (tuple.getArity() != 2) {
            throw new Impossible();
        }

        try {
            Object arr = tuple.getComponent(0);
            Object idx = Value.unvalueAndCast(tuple.getComponent(1), Integer.TYPE);
            return Value.possiblyWrap(
                java.lang.reflect.Array.get(arr, (Integer) idx),
                arr.getClass().getComponentType().isPrimitive());
        } catch (Exception e) {
            throw new Impossible("Exception occurred during method call: " + e);
        }
    }
}