From 157b493552603c9a02a710eeb0bc05e8a6396446 Mon Sep 17 00:00:00 2001 From: Elijah Cohen Date: Sat, 17 Aug 2024 04:42:01 +0000 Subject: [PATCH] added basic arithmetic operations --- src/builtins/arithmetic.c | 104 ++++++++++++++++++++++++++++++++++++-- src/builtins/arithmetic.h | 12 ++++- src/test.c | 5 ++ 3 files changed, 114 insertions(+), 7 deletions(-) diff --git a/src/builtins/arithmetic.c b/src/builtins/arithmetic.c index 18327c1..521ba17 100644 --- a/src/builtins/arithmetic.c +++ b/src/builtins/arithmetic.c @@ -11,7 +11,7 @@ Sexpr* a_plus(Sexpr* b, Sexpr* rest, Sexpr* env) { - if(ARITH_PLUS_ARGS != u64_get_num_args(b)) { + if(ARITH_ADD_ARGS != u64_get_num_args(b)) { return cons(b, rest); } Sexpr* args = b->value.b.args; @@ -25,12 +25,81 @@ Sexpr* a_plus(Sexpr* b, Sexpr* rest, Sexpr* env) { return cons(from_uint(m + n), rest); } +Sexpr* a_minus(Sexpr* b, Sexpr* rest, Sexpr* env) { + if(ARITH_SUB_ARGS != u64_get_num_args(b)) { + return cons(b, rest); + } + Sexpr* args = b->value.b.args; + Sexpr* i = eval(clone(car(args)), env); + Sexpr* j = eval(clone(car(cdr(args))), env); + uint64_t m = unquote(i)->value.u; + uint64_t n = unquote(j)->value.u; + sexpr_free(b); + sexpr_free(i); + sexpr_free(j); + return cons(from_uint(n - m), rest); +} + +Sexpr* a_mul(Sexpr* b, Sexpr* rest, Sexpr* env) { + if(ARITH_MUL_ARGS != u64_get_num_args(b)) { + return cons(b, rest); + } + Sexpr* args = b->value.b.args; + Sexpr* i = eval(clone(car(args)), env); + Sexpr* j = eval(clone(car(cdr(args))), env); + uint64_t m = unquote(i)->value.u; + uint64_t n = unquote(j)->value.u; + sexpr_free(b); + sexpr_free(i); + sexpr_free(j); + return cons(from_uint(m * n), rest); +} + +Sexpr* a_div(Sexpr* b, Sexpr* rest, Sexpr* env) { + if(ARITH_DIV_ARGS != u64_get_num_args(b)) { + return cons(b, rest); + } + Sexpr* args = b->value.b.args; + Sexpr* i = eval(clone(car(args)), env); + Sexpr* j = eval(clone(car(cdr(args))), env); + uint64_t m = unquote(i)->value.u; + uint64_t n = unquote(j)->value.u; + sexpr_free(b); + sexpr_free(i); + sexpr_free(j); + return cons(from_uint(n / m), rest); +} + +Sexpr* a_mod(Sexpr* b, Sexpr* rest, Sexpr* env) { + if(ARITH_MOD_ARGS != u64_get_num_args(b)) { + return cons(b, rest); + } + Sexpr* args = b->value.b.args; + Sexpr* i = eval(clone(car(args)), env); + Sexpr* j = eval(clone(car(cdr(args))), env); + uint64_t m = unquote(i)->value.u; + uint64_t n = unquote(j)->value.u; + sexpr_free(b); + sexpr_free(i); + sexpr_free(j); + return cons(from_uint(n % m), rest); +} + + Sexpr* x_arith_dispatch(Sexpr* b, Sexpr* rest, Sexpr* env) { uint64_t code = b->value.b.opcode & 0xff; switch(code) { - case ARITH_PLUS: + case ARITH_ADD: return a_plus(b, rest, env); + case ARITH_SUB: + return a_minus(b, rest, env); + case ARITH_MUL: + return a_mul(b, rest, env); + case ARITH_DIV: + return a_div(b, rest, env); + case ARITH_MOD: + return a_mod(b, rest, env); default: return from_nil(); } @@ -39,11 +108,36 @@ Sexpr* x_arith_dispatch(Sexpr* b, Sexpr* rest, Sexpr* env) { Sexpr* load_arith_env(Sexpr* env) { Sexpr* k; + Sexpr* v; k = from_sym("+"); - Sexpr* a_plus = from_opcode((ARITH_PREFIX << 8) | ARITH_PLUS); - append_to_dict(env, k, a_plus); - sexpr_free(a_plus); + v = from_opcode((ARITH_PREFIX << 8) | ARITH_ADD); + append_to_dict(env, k, v); + sexpr_free(v); + sexpr_free(k); + + k = from_sym("-"); + v = from_opcode((ARITH_PREFIX << 8) | ARITH_SUB); + append_to_dict(env, k, v); + sexpr_free(v); + sexpr_free(k); + + k = from_sym("*"); + v = from_opcode((ARITH_PREFIX << 8) | ARITH_MUL); + append_to_dict(env, k, v); + sexpr_free(v); + sexpr_free(k); + + k = from_sym("/"); + v = from_opcode((ARITH_PREFIX << 8) | ARITH_DIV); + append_to_dict(env, k, v); + sexpr_free(v); + sexpr_free(k); + + k = from_sym("%"); + v = from_opcode((ARITH_PREFIX << 8) | ARITH_MOD); + append_to_dict(env, k, v); + sexpr_free(v); sexpr_free(k); return env; } diff --git a/src/builtins/arithmetic.h b/src/builtins/arithmetic.h index bbfa4f0..0969286 100644 --- a/src/builtins/arithmetic.h +++ b/src/builtins/arithmetic.h @@ -6,8 +6,16 @@ #define ARITH_PREFIX 0x01 -#define ARITH_PLUS 0x00 -#define ARITH_PLUS_ARGS 2 +#define ARITH_ADD 0x00 +#define ARITH_ADD_ARGS 2 +#define ARITH_SUB 0x01 +#define ARITH_SUB_ARGS 2 +#define ARITH_MUL 0x02 +#define ARITH_MUL_ARGS 2 +#define ARITH_DIV 0x03 +#define ARITH_DIV_ARGS 2 +#define ARITH_MOD 0x04 +#define ARITH_MOD_ARGS 2 Sexpr* x_arith_dispatch(Sexpr* s, Sexpr* rest, Sexpr* env); Sexpr* load_arith_env(Sexpr* env); diff --git a/src/test.c b/src/test.c index 6eabb6d..0a970b8 100644 --- a/src/test.c +++ b/src/test.c @@ -288,6 +288,11 @@ void eval_tests() { run_eval_test("(not 4326)"); run_eval_test("(not nil)"); run_eval_test("(def asdf 545)"); + run_eval_test("(- 100 20)"); + run_eval_test("(* 100 20)"); + run_eval_test("(/ 100 20)"); + run_eval_test("(/ 100 21)"); + run_eval_test("(% 54 7)"); } -- 2.39.2