From 619a2ed04e2430d791a14c4485be718f6c15234b Mon Sep 17 00:00:00 2001 From: Sami Samhuri Date: Wed, 20 Apr 2011 13:40:50 -0700 Subject: [PATCH] define math primitives + - * and / --- int.c | 5 --- int.h | 1 - lake.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- lake.h | 2 ++ 4 files changed, 108 insertions(+), 10 deletions(-) diff --git a/int.c b/int.c index a2d65b1..363f66f 100644 --- a/int.c +++ b/int.c @@ -40,11 +40,6 @@ LakeInt *int_from_c(int n) return i; } -int int_val(LakeInt *i) -{ - return i->val; -} - LakeInt *int_cmp(LakeInt *a, LakeInt *b) { int aN = a->val, bN = b->val; diff --git a/int.h b/int.h index e972e50..dc1dc59 100644 --- a/int.h +++ b/int.h @@ -15,7 +15,6 @@ LakeInt *int_make(void); LakeInt *int_copy(LakeInt *i); LakeInt *int_from_c(int n); -int int_val(LakeInt *i); LakeInt *int_cmp(LakeInt *a, LakeInt *b); LakeBool *int_eq(LakeInt *a, LakeInt *b); LakeStr *int_to_str(LakeInt *i); diff --git a/lake.c b/lake.c index 2f0746f..acf1051 100644 --- a/lake.c +++ b/lake.c @@ -48,14 +48,116 @@ static LakeVal *prim_not(LakeList *args) return VAL(not); } +static LakeVal *prim_add(LakeList *args) +{ + int result = 0; + size_t n = LIST_N(args); + size_t i; + for (i = 0; i < n; ++i) { + LakeVal *v = LIST_VAL(args, i); + if (!IS(TYPE_INT, v)) { + ERR("argument %zu is not an integer: %s", i, repr(v)); + return NULL; + } + result += INT_VAL(INT(v)); + } + return VAL(int_from_c(result)); +} + +static LakeVal *prim_sub(LakeList *args) +{ + size_t n = LIST_N(args); + + if (n < 1) { + ERR("- requires at least one argument"); + return NULL; + } + + int result = 0; + size_t i; + for (i = 0; i < n; ++i) { + LakeVal *v = LIST_VAL(args, i); + if (!IS(TYPE_INT, v)) { + ERR("argument %zu is not an integer: %s", i, repr(v)); + return NULL; + } + result -= INT_VAL(INT(v)); + } + return VAL(int_from_c(result)); +} + +static LakeVal *prim_mul(LakeList *args) +{ + int result = 1; + size_t n = LIST_N(args); + size_t i; + for (i = 0; i < n; ++i) { + LakeVal *v = LIST_VAL(args, i); + if (!IS(TYPE_INT, v)) { + ERR("argument %zu is not an integer: %s", i, repr(v)); + return NULL; + } + result *= INT_VAL(INT(v)); + } + return VAL(int_from_c(result)); +} + +#define DIVIDE_BY_ZERO() ERR("divide by zero") + +static LakeVal *prim_div(LakeList *args) +{ + size_t n = LIST_N(args); + + if (n < 1) { + ERR("/ requires at least one argument"); + return NULL; + } + + LakeVal *v = LIST_VAL(args, 0); + if (!IS(TYPE_INT, v)) { + ERR("argument 0 is not an integer: %s", repr(v)); + return NULL; + } + int result = INT_VAL(INT(v)); + + if (n == 1) { + if (result == 0) { + DIVIDE_BY_ZERO(); + return NULL; + } + result = 1 / result; + } + else { + size_t i; + for (i = 1; i < n; ++i) { + v = LIST_VAL(args, i); + if (!IS(TYPE_INT, v)) { + ERR("argument %zu is not an integer: %s", i, repr(v)); + return NULL; + } + int val = INT_VAL(INT(v)); + if (val == 0) { + DIVIDE_BY_ZERO(); + return NULL; + } + result /= val; + } + } + return VAL(int_from_c(result)); +} + static Env *primitive_bindings(void) { - #define DEFINE(name, arity, fn) env_define(env, sym_intern(name), VAL(prim_make(name, arity, fn))) + #define DEFINE(name, fn, arity) env_define(env, sym_intern(name), VAL(prim_make(name, arity, fn))) Env *env = env_toplevel(); - DEFINE("null?", 1, prim_nullP); - DEFINE("pair?", 1, prim_pairP); - DEFINE("not", 1, prim_not); + DEFINE("null?", prim_nullP, 1); + DEFINE("pair?", prim_pairP, 1); + DEFINE("not", prim_not, 1); + DEFINE("+", prim_add, ARITY_VARARGS); + DEFINE("-", prim_sub, ARITY_VARARGS); + DEFINE("*", prim_mul, ARITY_VARARGS); + DEFINE("/", prim_div, ARITY_VARARGS); return env; } diff --git a/lake.h b/lake.h index 6622dcd..7e278f0 100644 --- a/lake.h +++ b/lake.h @@ -77,6 +77,8 @@ struct lake_int { }; typedef struct lake_int LakeInt; +#define INT_VAL(x) (x->val) + struct lake_str { LakeVal base; size_t n;