commit 7b98068825e88e638af5ac324ce08ec415279bdc
parent 5d736f60adf21e3eb6e778e8b5a855a5c6fc6fcb
Author: Andres Navarro <canavarro82@gmail.com>
Date: Sat, 23 Apr 2011 16:05:29 -0300
Refactored shared token reader to use kinteger_read.
Diffstat:
2 files changed, 23 insertions(+), 62 deletions(-)
diff --git a/src/kinteger.c b/src/kinteger.c
@@ -66,47 +66,9 @@ TValue kbigint_copy(klisp_State *K, TValue src)
return copy;
}
-/* This algorithm is like a fused multiply add on bignums,
- unlike any other function here it modifies bigint. It is used in read
- and it assumes that bigint is positive */
-/* GC: Assumes tv_bigint is rooted */
-void kbigint_add_digit(klisp_State *K, TValue tv_bigint, int32_t base,
- int32_t digit)
-{
- Bigint *bigint = tv2bigint(tv_bigint);
- UNUSED(mp_int_mul_value(K, bigint, base, bigint));
- UNUSED(mp_int_add_value(K, bigint, digit, bigint));
-}
-
-/* This is used by the writer to get the digits of a number
- tv_bigint must be positive */
-/* GC: Assumes tv_bigint is rooted */
-int32_t kbigint_remove_digit(klisp_State *K, TValue tv_bigint, int32_t base)
-{
- UNUSED(K);
- Bigint *bigint = tv2bigint(tv_bigint);
- int32_t r;
- UNUSED(mp_int_div_value(K, bigint, base, bigint, &r));
- return r;
-}
-
-/* This is used by write to test if there is any digit left to print */
-bool kbigint_has_digits(klisp_State *K, TValue tv_bigint)
-{
- UNUSED(K);
- return (mp_int_compare_zero(tv2bigint(tv_bigint)) != 0);
-}
-
-/* Mutate the bigint to have the opposite sign, used in read
- and write*/
-/* GC: Assumes tv_bigint is rooted */
-void kbigint_invert_sign(klisp_State *K, TValue tv_bigint)
-{
- Bigint *bigint = tv2bigint(tv_bigint);
- UNUSED(mp_int_neg(K, bigint, bigint));
-}
-
-/* read/write interface */
+/*
+** 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,
diff --git a/src/ktoken.c b/src/ktoken.c
@@ -599,34 +599,33 @@ TValue ktok_read_special(klisp_State *K)
token, or a char constant or a number. srfi-38 tokens are a '#' a
decimal number and end with a '=' or a '#' */
if (buf_len > 2 && ktok_is_numeric(buf[1])) {
+ /* NOTE: it's important to check is_numeric to avoid problems with
+ sign in kinteger_read */
/* srfi-38 type token (can be either a def or ref) */
+ /* TODO: lift this implementation restriction */
/* IMPLEMENTATION RESTRICTION: only allow fixints in shared tokens */
- int32_t res = 0;
- int32_t i = 1;
- char ch = buf[i];
- while(i < buf_len && ch != '#' && ch != '=') {
- if (!ktok_is_numeric(ch)) {
- ktok_error(K, "Invalid char found in srfi-38 token");
- /* avoid warning */
- return KINERT;
- }
+ char ch = buf[buf_len-1]; /* remember last char */
+ buf[buf_len-1] = '\0'; /* replace last char with 0 to read number */
- int new_digit = ktok_digit_value(ch);
- if (can_add_digit(res, false, new_digit, 10)) {
- res = res * 10 + new_digit;
- } else {
- ktok_error(K, "IMP. RESTRICTION: shared token too big");
- /* avoid warning */
- return KINERT;
- }
- ch = buf[++i];
- }
- if (i == buf_len) {
+ if (ch != '#' && ch != '=') {
ktok_error(K, "Missing last char in srfi-38 token");
return KINERT;
} /* else buf[i] == '#' or '=' */
+ TValue n;
+ char *end;
+ /* 10 is the radix for srfi-38 tokens, buf+1 to jump over the '#',
+ end+1 to count the last char */
+ if (!kinteger_read(K, buf+1, 10, &n, &end) || end+1 - buf != buf_len) {
+ ktok_error(K, "Bad char in srfi-38 token");
+ return KINERT;
+ } else if (!ttisfixint(n)) {
+ ktok_error(K, "IMP. RESTRICTION: shared token too big");
+ /* avoid warning */
+ return KINERT;
+ }
ks_tbclear(K);
- return kcons(K, ch2tv(ch), i2tv(res));
+ /* GC: no need to root n, for now it's a fixint */
+ return kcons(K, ch2tv(ch), n);
}
/* REFACTOR: move to new function */