commit 0a79a514a0e4fc5bfccb611cfd4522f422318e02
parent 4f5daf62aa855fbcd1b36f8538d75e80a8ce3fb7
Author: Ed van Bruggen <edvb@uw.edu>
Date:   Wed, 21 Nov 2018 16:44:52 -0800
Add *,/,mod math functions, only allow 2 arguments
Arbitrary number of arguments should be handled by another function, not
the primitives
Diffstat:
9 files changed, 63 insertions(+), 46 deletions(-)
diff --git a/t/math/add.expect b/t/math/add.expect
@@ -1,6 +1,3 @@
 2
-6
-6
-6
-6
-4369
+4
+1312
diff --git a/t/math/add.tsp b/t/math/add.tsp
@@ -1,6 +1,3 @@
 (+ 1 1)
-(+ 1 2 3)
-(+ 1 2 (+ 1 2))
-(+ 1 (+ 1 2) 2)
-(+ (+ 1 2) 1 2)
-(+ 1029 283 1928 28 189 912)
+(+ 1 (+ 1 2))
+(+ 1029 283)
diff --git a/t/math/sub.expect b/t/math/sub.expect
@@ -2,5 +2,4 @@
 -3
 289
 1
-5
 -35
diff --git a/t/math/sub.tsp b/t/math/sub.tsp
@@ -2,5 +2,4 @@
 (- +3)
 (- -289)
 (- 5 4)
-(- 40 20 15)
 (- 53 88)
diff --git a/t/prim/lambda.expect b/t/prim/lambda.expect
@@ -1,5 +1,5 @@
 3
-6
+3
 9
 4
 5
diff --git a/t/prim/lambda.tsp b/t/prim/lambda.tsp
@@ -1,5 +1,5 @@
 ((lambda (x) x) 3)
-((lambda (x) x) (+ 1 2 3))
+((lambda (x) x) (+ 1 2))
 ((lambda (x) (+ x 1)) 8)
 ((lambda (a b) (+ a b)) 2 2)
 ((lambda () 5))
diff --git a/t/simple/comments.expect b/t/simple/comments.expect
@@ -1,2 +1,2 @@
-3
+2
 4
diff --git a/t/simple/comments.tsp b/t/simple/comments.tsp
@@ -1,6 +1,6 @@
 ; commment
 ; (+ 1 1)
-(+ 1 1 ; more comments
+(+ 1 ; more comments
    1)
 
    ; white space too
diff --git a/tib/math.c b/tib/math.c
@@ -15,39 +15,61 @@
 } while(0)
 
 
-#define INC(SIGN, FUNC) do {                                                               \
-	if (car(v)->t == INTEGER)                                                          \
-		i = i SIGN car(v)->v.i;                                                    \
-	else                                                                               \
-		warnf(FUNC ": expected integer, recieved type [%s]", type_str(car(v)->t)); \
-} while (0)
+#define PRIM_OP(NAME, OP, FUNC)                                                        \
+static Val                                                                             \
+prim_##NAME(Env env, Val args)                                                         \
+{                                                                                      \
+	Val a, b;                                                                      \
+	int len = list_len(args);                                                      \
+	if (len != 2)                                                                  \
+		warnf(FUNC ": expected 2 arguments, recieved %d", len);                \
+	if (!(a = tisp_eval(env, car(args))) || !(b = tisp_eval(env, car(cdr(args))))) \
+		return NULL;                                                           \
+	if (a->t != INTEGER)                                                           \
+		warnf(FUNC ": expected integer, recieved type [%s]", type_str(a->t));  \
+	if (b->t != INTEGER)                                                           \
+		warnf(FUNC ": expected integer, recieved type [%s]", type_str(b->t));  \
+	return mk_int(a->v.i OP b->v.i);                                               \
+}
+
+PRIM_OP(add, +, "+")
+PRIM_OP(mul, *, "*")
+PRIM_OP(mod, %, "mod")
 
 static Val
-prim_add(Env env, Val args)
+prim_sub(Env env, Val args)
 {
-	Val v;
-	int i = 0;
-	if (!(v = tisp_eval_list(env, args)))
+	Val a, b;
+	int len = list_len(args);
+	if (len != 2 && len != 1)
+		warnf("-: expected 1 or 2 arguments, recieved %d", len);
+	if (!(a = tisp_eval(env, car(args))))
+		return NULL;
+	if (a->t != INTEGER)
+		warnf("-: expected integer, recieved type [%s]", type_str(a->t));
+	if (len == 1)
+		return mk_int(-a->v.i);
+	if (!(b = tisp_eval(env, car(cdr(args)))))
 		return NULL;
-	for (; !nilp(v); v = cdr(v))
-		INC(+, "+");
-	return mk_int(i);
+	if (b->t != INTEGER)
+		warnf("-: expected integer, recieved type [%s]", type_str(b->t));
+	return mk_int(a->v.i - b->v.i);
 }
 
 static Val
-prim_sub(Env env, Val args)
+prim_div(Env env, Val args)
 {
-	Val v;
-	int i = 0;
-	if (!(v = tisp_eval_list(env, args)))
+	Val a, b;
+	int len = list_len(args);
+	if (len != 2)
+		warnf("/: expected 2 arguments, recieved %d", len);
+	if (!(a = tisp_eval(env, car(args))) || !(b = tisp_eval(env, car(cdr(args)))))
 		return NULL;
-	INC(+, "-");
-	v = cdr(v);
-	if (nilp(v))
-		return mk_int(-i);
-	for (; !nilp(v); v = cdr(v))
-		INC(-, "-");
-	return mk_int(i);
+	if (a->t != INTEGER)
+		warnf("/: expected integer, recieved type [%s]", type_str(a->t));
+	if (b->t != INTEGER)
+		warnf("/: expected integer, recieved type [%s]", type_str(b->t));
+	return mk_rat(a->v.i, b->v.i);
 }
 
 #define INT_TEST(V, FUNC) do {                                                        \
@@ -77,10 +99,13 @@ PRIM_COMPARE(gte, >=, ">=")
 void
 tib_env_math(Env env)
 {
-	tisp_env_add(env, "+",  mk_prim(prim_add));
-	tisp_env_add(env, "-",  mk_prim(prim_sub));
-	tisp_env_add(env, "<",  mk_prim(prim_lt));
-	tisp_env_add(env, ">",  mk_prim(prim_gt));
-	tisp_env_add(env, "<=", mk_prim(prim_lte));
-	tisp_env_add(env, ">=", mk_prim(prim_gte));
+	tisp_env_add(env, "+",   mk_prim(prim_add));
+	tisp_env_add(env, "-",   mk_prim(prim_sub));
+	tisp_env_add(env, "*",   mk_prim(prim_mul));
+	tisp_env_add(env, "/",   mk_prim(prim_div));
+	tisp_env_add(env, "mod", mk_prim(prim_mod));
+	tisp_env_add(env, "<",   mk_prim(prim_lt));
+	tisp_env_add(env, ">",   mk_prim(prim_gt));
+	tisp_env_add(env, "<=",  mk_prim(prim_lte));
+	tisp_env_add(env, ">=",  mk_prim(prim_gte));
 }