klisp

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

commit 935eed72abb82a58c4ffe60c7746e7d0ec1a610c
parent bbd5e8ed9ef5381ed98a3660df03c2c5e0f24b44
Author: Andres Navarro <canavarro82@gmail.com>
Date:   Tue, 12 Apr 2011 17:11:02 -0300

Bugfix: Added code to kbigint_plus to check if the result could fit in a fixint.

Diffstat:
Msrc/kinteger.c | 24+++++++++++++++++++++---
Msrc/kinteger.h | 5+++++
2 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/src/kinteger.c b/src/kinteger.c @@ -14,6 +14,23 @@ #include "kstate.h" #include "kmem.h" +/* This tries to convert a bigint to a fixint */ +inline TValue kbigint_try_fixint(klisp_State *K, TValue n) +{ + Bigint *b = tv2bigint(n); + if (MP_USED(b) != 1) + return n; + + int64_t digit = (int64_t) MP_SINGLE(b); + if (MP_SIGN(b) == MP_NEG) digit = -digit; + if (kfit_int32_t(digit)) { + /* n shouln't be reachable but the let the gc do its job */ + return i2tv((int32_t) digit); + } else { + return n; + } +} + /* for now used only for reading */ /* NOTE: is uint to allow INT32_MIN as positive argument in read */ TValue kbigint_new(klisp_State *K, bool sign, uint32_t digit) @@ -78,8 +95,8 @@ bool kbigint_has_digits(klisp_State *K, TValue tv_bigint) return (mp_int_compare_zero(tv2bigint(tv_bigint)) != 0); } -/* Mutate the bigint to have the opposite sign, used in read, - write and abs */ +/* Mutate the bigint to have the opposite sign, used in read + and write*/ void kbigint_invert_sign(klisp_State *K, TValue tv_bigint) { Bigint *bigint = tv2bigint(tv_bigint); @@ -128,7 +145,7 @@ TValue kbigint_plus(klisp_State *K, TValue n1, TValue n2) { TValue res = kbigint_new(K, false, 0); UNUSED(mp_int_add(K, tv2bigint(n1), tv2bigint(n2), tv2bigint(res))); - return res; + return kbigint_try_fixint(K, res); } bool kbigint_negativep(TValue tv_bigint) @@ -156,6 +173,7 @@ TValue kbigint_abs(klisp_State *K, TValue tv_bigint) if (kbigint_negativep(tv_bigint)) { TValue copy = kbigint_new(K, false, 0); UNUSED(mp_int_abs(K, tv2bigint(tv_bigint), tv2bigint(copy))); + /* NOTE: this can never be a fixint if the parameter was a bigint */ return copy; } else { return tv_bigint; diff --git a/src/kinteger.h b/src/kinteger.h @@ -22,6 +22,11 @@ TValue kbigint_new(klisp_State *K, bool sign, uint32_t digit); /* used in write to destructively get the digits */ TValue kbigint_copy(klisp_State *K, TValue src); +/* Check to see if an int64_t fits in a int32_t */ +inline bool kfit_int32_t(int64_t n) { + return (n >= (int64_t) INT32_MIN && n <= (int64_t) INT32_MAX); +} + /* Create a stack allocated bigints from a fixint, useful for mixed operations, relatively light weight compared to creating it in the heap and burdening the gc */