package foreign;

import nova.*;

import java.util.*;

/**
 * Warranty & Liability
 * To the extent permitted by applicable law and unless explicitly
 * otherwise agreed upon, XLOG Technologies AG makes no warranties
 * regarding the provided information. XLOG Technologies AG assumes
 * no liability that any problems might be solved with the information
 * provided by XLOG Technologies AG.
 *
 * Rights & License
 * All industrial property rights regarding the information - copyright
 * and patent rights in particular - are the sole property of XLOG
 * Technologies AG. If the company was not the originator of some
 * excerpts, XLOG Technologies AG has at least obtained the right to
 * reproduce, change and translate the information.
 *
 * Reproduction is restricted to the whole unaltered document. Reproduction
 * of the information is only allowed for non-commercial uses. Selling,
 * giving away or letting of the execution of the library is prohibited.
 * The library can be distributed as part of your applications and libraries
 * for execution provided this comment remains unchanged.
 *
 * Restrictions
 * Only to be distributed with programs that add significant and primary
 * functionality to the library. Not to be distributed with additional
 * software intended to replace any components of the library.
 *
 * Trademarks
 * Jekejeke is a registered trademark of XLOG Technologies AG.
 */
public final class asmlib {

    /******************************************************************/
    /* call/2-4                                                       */
    /******************************************************************/

    /**
     * call(F, A1, .., An): [Corr.2 8.15.4.4]
     * The predicate succeeds in calling the goal which results from
     * appending the arguments A1, .., An to the callable F.
     */
    private static Object special_calln(Object[] args) {
        Object alpha = Machine.deref(args[0]);
        Object functor;
        Object[] oldargs;
        if (Store.is_structure(alpha)) {
            functor = ((Store.Structure) alpha).functor;
            oldargs = ((Store.Structure) alpha).args;
        } else {
            functor = alpha;
            special.check_atomic(alpha);
            oldargs = Machine.VOID_ARGS;
        }
        int arity = oldargs.length + args.length - 1;
        Object goal;
        if (arity == 0) {
            goal = functor;
        } else {
            if (Machine.is_number(functor))
                throw Machine.make_error(new Store.Compound("type_error",
                        new Object[]{"atom", functor}));
            Object[] newargs = new Object[arity];
            for (int i = 0; i < oldargs.length; i++)
                newargs[i] = Machine.deref(oldargs[i]);
            for (int i = 0; i < args.length - 1; i++)
                newargs[i + oldargs.length] = Machine.deref(args[i + 1]);
            goal = new Store.Compound(functor, newargs);
        }
        goal = new Store.Compound(".", new Object[]{goal,
                ((Store.Structure) Machine.call).args[1]});
        Machine.cont(goal);
        return Boolean.TRUE;
    }

    /******************************************************************/
    /* Asm Lib Init                                                  */
    /******************************************************************/

    public static void main() {
        Store.add("call", 2, special.make_special(asmlib::special_calln));
        Store.add("call", 3, special.make_special(asmlib::special_calln));
        Store.add("call", 4, special.make_special(asmlib::special_calln));
        Store.add("call", 5, special.make_special(asmlib::special_calln));
        Store.add("call", 6, special.make_special(asmlib::special_calln));
        Store.add("call", 7, special.make_special(asmlib::special_calln));
        Store.add("call", 8, special.make_special(asmlib::special_calln));
    }

}
