###
# 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 (exec_build,
    check_integer, Compound, add, exec_unify,
    make_check, make_error, check_number, check_atom)


#######################################################################
# Number Formatting                                                   #
#######################################################################

###
# sys_float_atom(F, S, N, A):
# The built-in succeeds in A with the number F
# formatted according to the format specifier S
# and the number of digits N.
##
def test_sys_float_atom(args):
    value = exec_build(args[0])
    check_number(value)
    spec = exec_build(args[1])
    check_atom(spec)
    digs = exec_build(args[2])
    check_integer(digs)
    if digs < 0:
        raise make_error(Compound("domain_error",
            ["not_less_than_zero", digs]))
    try:
        value = float(value)
    except OverflowError:
        raise make_error(Compound("evaluation_error", ["float_overflow"]))
    if spec == "f":
        text = ("%."+str(digs)+"f") % value
        text = shape_float(text)
    elif spec == "e":
        text = ("%."+str(digs)+"e") % value
        text = shape_float(text)
    elif spec == "g":
        text = ("%."+str(digs)+"g") % value
        text = shape_float(text)
    else:
        raise make_error(Compound("existence_error",
            ["format_character", spec]))
    return exec_unify(args[3], text)


###
# Shape the number string so that it has no exponent positive
# sign and lower case exponent. Further remove the exponent
# from leading zeros.
#
# @param res The ascii number string.
# @return The shaped number string.
##
def shape_float(res):
    peek = res.find("e")
    if peek != -1:
        res = shape_float_mantissa(res[0:peek]) + \
              "e" + shape_float_exponent(res[peek+1:])
    else:
        res = shape_float_mantissa(res)
    return res


def shape_float_mantissa(res):
    return res


def shape_float_exponent(res):
    if 0 < len(res) and ord(res[0]) == 43:  # '+'
        res = res[1:]
    if res.startswith("0") and 1 < len(res):
        res = res[1:]
    elif res.startswith("-0") and 2 < len(res):
        res = "-" + res[2:]
    return res


#######################################################################
# Str Lib Init                                                        #
#######################################################################

def main():
    add("sys_float_atom", 4, make_check(test_sys_float_atom))
