// Copyright (c) 1996-2002 Brian D. Carlstrom

package bdc.scheme.procedure;

import bdc.scheme.Scheme;
import bdc.scheme.SchemeException;
import bdc.scheme.Stack;
import bdc.scheme.exception.ArgumentCountException;
import bdc.scheme.exception.PrimitiveException;
import bdc.scheme.expression.ProcedureN;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
    Primitive for Method.invoke
*/
public class MethodInvoke extends ProcedureN
{
    public Object applyN (int n, Stack stack) throws SchemeException
    {
        if (n < 2) {
            throw new ArgumentCountException(this, 2, n);
        }

        Object o1 = stack.array[stack.inUse-1];
        Object o2 = stack.array[stack.inUse-2];

        Method method = Scheme.method(o1, this);
        Object object = Scheme.object(o2);

        Object[] args = new Object[n-2];
        for (int i = 3; i <= n; i++) {
            args[i-3] = Scheme.object(stack.array[stack.inUse-i]);
        }

        try {
            return Scheme.nullToSchemeNull(method.invoke(object, args));
        }
        catch (IllegalAccessException e) {
            throw new PrimitiveException(e);
        }
        catch (InvocationTargetException e) {
            throw new PrimitiveException(e.getTargetException());
        }
    }
}
