klisp

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

commit 75feefbe3784a24b36a0cd3a0643e24f9e9b940e
parent 57d3bff73d6d696c1e3add6c5df5b6205b2ed44d
Author: Andres Navarro <canavarro82@gmail.com>
Date:   Mon, 21 Mar 2011 17:05:33 -0300

Added div, mod, div-and-mod, div0, mod0 and div0-and-mod0 to the ground environment.

Diffstat:
Msrc/Makefile | 3++-
Msrc/kgnumbers.c | 97+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Msrc/kgnumbers.h | 14++++++++++++++
Msrc/kground.c | 14++++++++++++--
4 files changed, 123 insertions(+), 5 deletions(-)

diff --git a/src/Makefile b/src/Makefile @@ -128,4 +128,5 @@ kgports.o: kgports.c kgports.h kghelpers.h kstate.h klisp.h \ kgchars.o: kgchars.c kgchars.h kghelpers.h kstate.h klisp.h \ kobject.h kerror.h kapplicative.h koperative.h kcontinuation.h kgnumbers.o: kgnumbers.c kgnumbers.h kghelpers.h kstate.h klisp.h \ - kobject.h kerror.h kapplicative.h koperative.h kcontinuation.h + kobject.h kerror.h kapplicative.h koperative.h kcontinuation.h \ + ksymbol.h diff --git a/src/kgnumbers.c b/src/kgnumbers.c @@ -16,6 +16,7 @@ #include "koperative.h" #include "kcontinuation.h" #include "kerror.h" +#include "ksymbol.h" #include "kghelpers.h" #include "kgnumbers.h" @@ -229,10 +230,101 @@ void kminus(klisp_State *K, TValue *xparams, TValue ptree, TValue denv) bool kzerop(TValue n) { return kfast_zerop(n); } /* 12.5.8 div, mod, div-and-mod */ -/* TODO */ +/* use div_mod */ /* 12.5.9 div0, mod0, div0-and-mod0 */ -/* TODO */ +/* use div_mod */ + +/* Helpers for div, mod, div0 and mod0 */ + +/* zerop signals div0 and mod0 if true div and mod if false */ +inline void div_mod(bool zerop, int32_t n, int32_t d, int32_t *div, + int32_t *mod) +{ + *div = n / d; + *mod = n % d; + + if (zerop) { + /* div0, mod0 or div-and-mod0 */ + /* -|d/2| <= mod0 < |d/2| */ + + int32_t dabs = ((d<0? -d : d) + 1) / 2; + + if (*mod < -dabs) { + if (d < 0) { + *mod -= d; + ++(*div); + } else { + *mod += d; + --(*div); + } + } else if (*mod >= dabs) { + if (d < 0) { + *mod += d; + --(*div); + } else { + *mod -= d; + ++(*div); + } + } + } else { + /* div, mod or div-and-mod */ + /* 0 <= mod0 < |d| */ + if (*mod < 0) { + if (d < 0) { + *mod -= d; + ++(*div); + } else { + *mod += d; + --(*div); + } + } + } +} + +/* flags are FDIV_DIV, FDIV_MOD, FDIV_ZERO */ +void kdiv_mod(klisp_State *K, TValue *xparams, TValue ptree, TValue denv) +{ + /* + ** xparams[0]: name symbol + ** xparams[1]: div_mod_flags + */ + char *name = ksymbol_buf(xparams[0]); + int32_t flags = ivalue(xparams[1]); + + bind_2tp(K, name, ptree, "number", knumberp, tv_n, + "number", knumberp, tv_d); + + /* TEMP: only fixnums */ + TValue tv_div, tv_mod; + + if (kfast_zerop(tv_d)) { + klispE_throw_extra(K, name, ": division by zero"); + return; + } else if (ttiseinf(tv_n)) { + klispE_throw_extra(K, name, ": non finite dividend"); + return; + } else if (ttiseinf(tv_d)) { + tv_div = ((ivalue(tv_n) ^ ivalue(tv_d)) < 0)? KEPINF : KEMINF; + tv_mod = i2tv(0); + } else { + int32_t div, mod; + div_mod(flags & FDIV_ZERO, ivalue(tv_n), ivalue(tv_d), &div, &mod); + tv_div = i2tv(div); + tv_mod = i2tv(mod); + } + TValue res; + if (flags & FDIV_DIV) { + if (flags & FDIV_MOD) { /* return both div and mod */ + res = kcons(K, tv_div, kcons(K, tv_mod, KNIL)); + } else { + res = tv_div; + } + } else { + res = tv_mod; + } + kapply_cc(K, res); +} /* 12.5.10 positive?, negative? */ /* use ftyped_predp */ @@ -267,3 +359,4 @@ void kabs(klisp_State *K, TValue *xparams, TValue ptree, TValue denv) return; } } + diff --git a/src/kgnumbers.h b/src/kgnumbers.h @@ -80,6 +80,20 @@ bool knegativep(TValue n); bool koddp(TValue n); bool kevenp(TValue n); +/* 12.5.8 div, mod, div-and-mod */ +/* use div_mod */ + +/* 12.5.9 div0, mod0, div0-and-mod0 */ +/* use div_mod */ + +/* Helper for div and mod */ +#define FDIV_DIV 1 +#define FDIV_MOD 2 +#define FDIV_ZERO 4 + +void kdiv_mod(klisp_State *K, TValue *xparams, TValue ptree, TValue denv); + + /* 12.5.12 abs */ void kabs(klisp_State *K, TValue *xparams, TValue ptree, TValue denv); diff --git a/src/kground.c b/src/kground.c @@ -522,10 +522,20 @@ void kinit_ground_env(klisp_State *K) p2tv(knumberp), p2tv(kzerop)); /* 12.5.8 div, mod, div-and-mod */ - /* TODO */ + add_applicative(K, ground_env, "div", kdiv_mod, 2, symbol, + i2tv(FDIV_DIV)); + add_applicative(K, ground_env, "mod", kdiv_mod, 2, symbol, + i2tv(FDIV_MOD)); + add_applicative(K, ground_env, "div-and-mod", kdiv_mod, 2, symbol, + i2tv(FDIV_DIV | FDIV_MOD)); /* 12.5.9 div0, mod0, div0-and-mod0 */ - /* TODO */ + add_applicative(K, ground_env, "div0", kdiv_mod, 2, symbol, + i2tv(FDIV_ZERO | FDIV_DIV)); + add_applicative(K, ground_env, "mod0", kdiv_mod, 2, symbol, + i2tv(FDIV_ZERO | FDIV_MOD)); + add_applicative(K, ground_env, "div0-and-mod0", kdiv_mod, 2, symbol, + i2tv(FDIV_ZERO | FDIV_DIV | FDIV_MOD)); /* 12.5.10 positive?, negative? */ add_applicative(K, ground_env, "positive?", ftyped_predp, 3, symbol,