###
# 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.
##

from nova.core import (
       is_number, VOID_ARGS, Compound, is_structure,
       add, get_cont, check_atomic,
       deref, make_special, cont, make_error)

#######################################################################
# 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.
##
def special_calln(args):
    alpha = deref(args[0])
    if is_structure(alpha):
        functor = alpha.functor
        oldargs = alpha.args
    else:
        functor = alpha
        check_atomic(functor)
        oldargs = VOID_ARGS
    arity = len(oldargs) + len(args) - 1
    if arity == 0:
        goal = functor
    else:
        if is_number(functor):
            raise make_error(Compound("type_error", ["atom", functor]))
        newargs = [NotImplemented] * arity
        i = 0
        while i < len(oldargs):
            newargs[i] = deref(oldargs[i])
            i += 1
        i = 0
        while i < len(args) - 1:
            newargs[i + len(oldargs)] = deref(args[i + 1])
            i += 1
        goal = Compound(functor, newargs)
    goal = Compound(".", [goal, get_cont().args[1]])
    cont(goal)
    return True


#######################################################################
# Asm Lib Init                                                        #
#######################################################################

def 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))

