klisp

an open source interpreter for the Kernel Programming Language.
git clone http://git.hanabi.in/repos/klisp.git
Log | Files | Refs | README

commit 5d736f60adf21e3eb6e778e8b5a855a5c6fc6fcb
parent a17b92ab13765fbab1277fd5978f28bbf7717d22
Author: Andres Navarro <canavarro82@gmail.com>
Date:   Sat, 23 Apr 2011 15:12:06 -0300

Changed read_number to use imath directly.

Diffstat:
Msrc/kinteger.c | 17+++++++++++++++++
Msrc/kinteger.h | 6++++++
Msrc/ktoken.c | 72+++++++++++-------------------------------------------------------------
3 files changed, 34 insertions(+), 61 deletions(-)

diff --git a/src/kinteger.c b/src/kinteger.c @@ -16,8 +16,10 @@ #include "kgc.h" /* This tries to convert a bigint to a fixint */ +/* XXX this doesn't need K really */ inline TValue kbigint_try_fixint(klisp_State *K, TValue n) { + UNUSED(K); Bigint *b = tv2bigint(n); if (MP_USED(b) != 1) return n; @@ -104,6 +106,21 @@ void kbigint_invert_sign(klisp_State *K, TValue tv_bigint) UNUSED(mp_int_neg(K, bigint, bigint)); } +/* read/write interface */ + +/* this works for bigints & fixints, returns true if ok */ +bool kinteger_read(klisp_State *K, char *buf, int32_t base, TValue *out, + char **end) +{ + TValue res = kbigint_new(K, false, 0); + krooted_tvs_push(K, res); + bool ret_val = (mp_int_read_cstring(K, tv2bigint(res), base, + buf, end) == MP_OK); + krooted_tvs_pop(K); + *out = kbigint_try_fixint(K, res); + return ret_val; +} + /* this is used by write to estimate the number of chars necessary to print the number */ int32_t kbigint_print_size(TValue tv_bigint, int32_t base) diff --git a/src/kinteger.h b/src/kinteger.h @@ -71,6 +71,12 @@ bool kbigint_has_digits(klisp_State *K, TValue tv_bigint); /* Mutate the bigint to have the opposite sign, used in read & write */ void kbigint_invert_sign(klisp_State *K, TValue tv_bigint); +/* read/write interface */ + +/* this works for bigints & fixints, returns true if ok */ +bool kinteger_read(klisp_State *K, char *buf, int32_t base, TValue *out, + char **end); + /* this is used by write to estimate the number of chars necessary to print the number */ int32_t kbigint_print_size(TValue tv_bigint, int32_t base); diff --git a/src/ktoken.c b/src/ktoken.c @@ -13,8 +13,9 @@ ** TODO: ** ** From the Report: -** - Support other number types besides integers and exact infinities -** - Support for complete number syntax (inexacts, rationals, reals, complex) +** - Support other number types besides integers, rationals and exact +** infinities +** - Support for complete number syntax (inexacts, reals, complex) ** ** NOT from the Report: ** - Support for unicode (strings, char and symbols). @@ -36,6 +37,7 @@ #include "kobject.h" #include "kstate.h" #include "kinteger.h" +#include "krational.h" #include "kpair.h" #include "kstring.h" #include "ksymbol.h" @@ -393,72 +395,20 @@ int32_t ktok_read_until_delimiter(klisp_State *K) ** The digits are in buf, that must be freed after use, ** len should be at least one */ -TValue ktok_read_number(klisp_State *K, char *buf, int32_t len, +TValue ktok_read_number(klisp_State *K, char *buf, int32_t len, bool has_exactp, bool exactp, bool has_radixp, int32_t radix) { - /* TODO use IMATH library to do this */ - uint32_t fixint_res = 0; - bool is_fixint = true; - TValue bigint_res; - - int32_t i = 0; - bool is_pos = true; - /* first check the sign */ - if (buf[i] == '+' || buf[i] == '-') { - is_pos = (buf[i] == '+'); - ++i; - if (i == len) { - ktok_error(K, "No digit found in number"); - /* avoid warning */ + UNUSED(len); /* not needed really, buf ends with '\0' */ + TValue n; + if (!kinteger_read(K, buf, radix, &n, NULL)) { + /* TODO throw meaningful error msgs, use last param */ + ktok_error(K, "Bad format in number"); return KINERT; - } - } - - while(i < len) { - char ch = buf[i++]; - - if (!ktok_is_digit(ch, radix)) { - /* TODO show the char */ - if (ktok_is_digit(ch, 16)) { - ktok_error(K, "Invalid digit in this radix"); - return KINERT; - } else { - ktok_error(K, "Invalid char found in number"); - return KINERT; - } - } - int32_t new_digit = ktok_digit_value(ch); - - if (is_fixint && can_add_digit(fixint_res, !is_pos, new_digit, - radix)) { - fixint_res = fixint_res * radix + new_digit; - } else { - if (is_fixint) { - /* up to the last loop was fixint, but can't be anymore. - Create a bigint and mutate to add the new digits. This - avoids unnecessary consing and discarding values that would - occur if it used the regular bigint+ and bigint* */ - is_fixint = false; - bigint_res = kbigint_new(K, false, fixint_res); - krooted_vars_push(K, &bigint_res); - } - kbigint_add_digit(K, bigint_res, radix, new_digit); - } } ks_tbclear(K); - - if (is_fixint) { - int32_t fixint = (is_pos)? (int32_t) fixint_res : - (int32_t) -((int64_t) fixint_res); - return i2tv(fixint); - } else { - if (!is_pos) - kbigint_invert_sign(K, bigint_res); - krooted_vars_pop(K); - return bigint_res; - } + return n; } TValue ktok_read_maybe_signed_numeric(klisp_State *K)