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 */