/**
 * Modern Albufeira Prolog Interpreter
 *
 * 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.
 */

import {
    add, deref, is_structure, Compound, make_special,
    is_number, make_error, VOID_ARGS, cont, get_cont,
    check_atomic
} from "../nova/core.mjs";

/*********************************************************************/
/* 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.
 */
function special_calln(args) {
    let alpha = deref(args[0]);
    let functor;
    let oldargs;
    if (is_structure(alpha)) {
        functor = alpha.functor;
        oldargs = alpha.args;
    } else {
        functor = alpha;
        check_atomic(functor);
        oldargs = VOID_ARGS;
    }
    let arity = oldargs.length + args.length - 1;
    let goal;
    if (arity === 0) {
        goal = functor;
    } else {
        if (is_number(functor))
            throw make_error(new Compound("type_error", ["atom", functor]));
        let newargs = new Array(arity);
        for (let i = 0; i < oldargs.length; i++)
            newargs[i] = deref(oldargs[i]);
        for (let i = 0; i < args.length - 1; i++)
            newargs[i + oldargs.length] = deref(args[i + 1]);
        goal = new Compound(functor, newargs);
    }
    goal = new Compound(".", [goal, get_cont().args[1]]);
    cont(goal);
    return true;
}

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

export function main() {
    add("call", 2, make_special(special_calln));
    add("call", 3, make_special(special_calln));
    add("call", 4, make_special(special_calln));
    add("call", 5, make_special(special_calln));
    add("call", 6, make_special(special_calln));
    add("call", 7, make_special(special_calln));
    add("call", 8, make_special(special_calln));
}