From 61303f6825226a37fcdf320c1d8953b30570945e Mon Sep 17 00:00:00 2001 From: bog Date: Sat, 30 Mar 2024 18:14:26 +0100 Subject: [PATCH] :sparkles: float and int arithmetic. --- features/num.mk | 24 +++++ lib/CMakeLists.txt | 4 + lib/builtins.c | 91 +++++++++++++++++++ lib/builtins.h | 9 ++ lib/commons.h | 1 + lib/moka.c | 219 ++++++++++++++++++++++++++++++++++++++++++++- lib/moka.h | 7 ++ 7 files changed, 353 insertions(+), 2 deletions(-) create mode 100644 features/num.mk diff --git a/features/num.mk b/features/num.mk new file mode 100644 index 0000000..bbae006 --- /dev/null +++ b/features/num.mk @@ -0,0 +1,24 @@ +(assert-eqv! 0 (+)) +(assert-eqv! 5 (+ 5)) +(assert-eqv! 8 (+ 5 3)) +(assert-eqv! 17 (+ 5 3 9)) + +(assert-eqv! 0 (-)) +(assert-eqv! -5 (- 5)) +(assert-eqv! 2 (- 5 3)) +(assert-eqv! -7 (- 5 3 9)) + +(assert-eqv! 1 (*)) +(assert-eqv! 2 (* 2)) +(assert-eqv! 42 (* 6 7)) +(assert-eqv! 24 (* 2 3 4)) + +(assert-eqv! 1 (/)) +(assert-eqv! 0.5 (/ 2.0)) +(assert-eqv! 0 (/ 2)) +(assert-eqv! 6 (/ 36 6)) +(assert-eqv! 3 (/ 36 6 2)) + +(assert-eqv! 8 (^ 2 3)) +(assert-eqv! 1.5 (% 7.5 2.0)) + diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 2b0476e..8736c2f 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -30,6 +30,10 @@ target_compile_options(moka-core PUBLIC -Wall -Wextra -g -fPIC ) +target_link_options(moka-core + PUBLIC -lm +) + target_include_directories(moka-core PUBLIC ${CMAKE_SOURCE_DIR}/lib ) diff --git a/lib/builtins.c b/lib/builtins.c index f999bbd..33d1dac 100644 --- a/lib/builtins.c +++ b/lib/builtins.c @@ -18,6 +18,13 @@ void register_builtins(struct moka* moka) moka_decl_native(moka, ">=", mk_ge, 2); moka_decl_native(moka, "eqv?", mk_is_eqv, 2); moka_decl_native(moka, "nev?", mk_is_nev, 2); + + moka_decl_native(moka, "+", mk_add, -1); + moka_decl_native(moka, "-", mk_sub, -1); + moka_decl_native(moka, "*", mk_mul, -1); + moka_decl_native(moka, "/", mk_div, -1); + moka_decl_native(moka, "%", mk_mod, 2); + moka_decl_native(moka, "^", mk_pow, 2); } MOKA mk_println(struct moka* moka, struct vec* args) @@ -186,3 +193,87 @@ MOKA mk_is_nev(struct moka* moka, struct vec* args) moka_line(moka, lhs) ); } + +MOKA mk_add(struct moka* moka, struct vec* args) +{ + assert(moka); + assert(args); + + for (size_t i=0; isize; i++) + { + MOKA arg = MK_EVAL((MOKA) args->data[i]); + moka_push(moka, arg); + } + + return moka_add(moka, args->size); +} + +MOKA mk_sub(struct moka* moka, struct vec* args) +{ + assert(moka); + assert(args); + + for (size_t i=0; isize; i++) + { + MOKA arg = MK_EVAL((MOKA) args->data[i]); + moka_push(moka, arg); + } + + return moka_sub(moka, args->size); +} + +MOKA mk_mul(struct moka* moka, struct vec* args) +{ + assert(moka); + assert(args); + + for (size_t i=0; isize; i++) + { + MOKA arg = MK_EVAL((MOKA) args->data[i]); + moka_push(moka, arg); + } + + return moka_mul(moka, args->size); +} + +MOKA mk_div(struct moka* moka, struct vec* args) +{ + assert(moka); + assert(args); + + for (size_t i=0; isize; i++) + { + MOKA arg = MK_EVAL((MOKA) args->data[i]); + moka_push(moka, arg); + } + + return moka_div(moka, args->size); +} + +MOKA mk_mod(struct moka* moka, struct vec* args) +{ + assert(moka); + assert(args); + + for (size_t i=0; isize; i++) + { + MOKA arg = MK_EVAL((MOKA) args->data[i]); + moka_push(moka, arg); + } + + return moka_mod(moka); +} + +MOKA mk_pow(struct moka* moka, struct vec* args) +{ + assert(moka); + assert(args); + + for (size_t i=0; isize; i++) + { + MOKA arg = MK_EVAL((MOKA) args->data[i]); + moka_push(moka, arg); + } + + return moka_pow(moka); +} diff --git a/lib/builtins.h b/lib/builtins.h index 0fdfade..e2f8b2e 100644 --- a/lib/builtins.h +++ b/lib/builtins.h @@ -22,4 +22,13 @@ MOKA mk_ge(struct moka* moka, struct vec* args); MOKA mk_is_eqv(struct moka* moka, struct vec* args); MOKA mk_is_nev(struct moka* moka, struct vec* args); +// Num Arithmetic +// ============== +MOKA mk_add(struct moka* moka, struct vec* args); +MOKA mk_sub(struct moka* moka, struct vec* args); +MOKA mk_mul(struct moka* moka, struct vec* args); +MOKA mk_div(struct moka* moka, struct vec* args); +MOKA mk_mod(struct moka* moka, struct vec* args); +MOKA mk_pow(struct moka* moka, struct vec* args); + #endif diff --git a/lib/commons.h b/lib/commons.h index 09e6e4d..5721041 100644 --- a/lib/commons.h +++ b/lib/commons.h @@ -8,6 +8,7 @@ #include #include #include +#include typedef size_t MOKA; diff --git a/lib/moka.c b/lib/moka.c index 18de3b6..f62dc53 100644 --- a/lib/moka.c +++ b/lib/moka.c @@ -328,6 +328,221 @@ bool moka_is_eqv(struct moka* self, MOKA mk_lhs, MOKA mk_rhs) return value_is_eqv(lhs, rhs, self); } +MOKA moka_add(struct moka* self, int count) +{ + assert(self); + struct frame* frame = moka_frame(self); + + float base = 0.0f; + bool is_int = true; + int line = 0; + + for (int i=0; ilocal_values.data[arg]; + line = value->line; + + if (value->type == TY_INT) + { + base += value->data.integer; + } + else if (value->type == TY_FLOAT) + { + base += value->data.real; + is_int = false; + } + } + + if (is_int) + { + return moka_push_int(self, (int) base, line); + } + + return moka_push_float(self, base, line); +} + +MOKA moka_sub(struct moka* self, int count) +{ + assert(self); + struct frame* frame = moka_frame(self); + + float base = 0.0f; + bool is_int = true; + int line = 0; + + struct vec args; + vec_init(&args); + + for (int i=0; ilocal_values.data[arg]; + line = value->line; + + if (value->type == TY_INT) + { + base += i == 0 + ? value->data.integer + : -value->data.integer;; + } + else if (value->type == TY_FLOAT) + { + base += i == 0 + ? value->data.real + : -value->data.real; + } + } + + vec_free(&args); + + if (count == 1) + { + base *= -1.0f; + } + + if (is_int) + { + return moka_push_int(self, (int) base, line); + } + + return moka_push_float(self, base, line); +} + +MOKA moka_mul(struct moka* self, int count) +{ + assert(self); + struct frame* frame = moka_frame(self); + + float base = 1.0f; + bool is_int = true; + int line = 0; + + for (int i=0; ilocal_values.data[arg]; + line = value->line; + + if (value->type == TY_INT) + { + base *= value->data.integer; + } + else if (value->type == TY_FLOAT) + { + base *= value->data.real; + is_int = false; + } + } + + if (is_int) + { + return moka_push_int(self, (int) base, line); + } + + return moka_push_float(self, base, line); +} + +MOKA moka_div(struct moka* self, int count) +{ + assert(self); + struct frame* frame = moka_frame(self); + + float base = 1.0f; + bool is_int = true; + int line = 0; + + struct vec args; + vec_init(&args); + + for (int i=0; ilocal_values.data[arg]; + line = value->line; + + if (value->type == TY_INT) + { + base *= i == 0 + ? value->data.integer + : 1.0f/value->data.integer;; + } + else if (value->type == TY_FLOAT) + { + base *= i == 0 + ? value->data.real + : 1.0f/value->data.real; + is_int = false; + } + } + + vec_free(&args); + + if (count == 1) + { + base = 1.0f/base; + } + + if (is_int) + { + return moka_push_int(self, (int) base, line); + } + + return moka_push_float(self, base, line); +} + +MOKA moka_mod(struct moka* self) +{ + struct frame* frame = moka_frame(self); + struct value* rhs = frame->local_values.data[moka_pop(self)]; + struct value* lhs = frame->local_values.data[moka_pop(self)]; + + if (lhs->type == TY_FLOAT || rhs->type == TY_FLOAT) + { + return moka_push_float(self, + fmod(lhs->data.real, rhs->data.real), + lhs->line); + } + + return moka_push_int(self, + fmod(lhs->data.integer, rhs->data.integer), + lhs->line); +} + +MOKA moka_pow(struct moka* self) +{ + struct frame* frame = moka_frame(self); + struct value* rhs = frame->local_values.data[moka_pop(self)]; + struct value* lhs = frame->local_values.data[moka_pop(self)]; + + if (lhs->type == TY_FLOAT || rhs->type == TY_FLOAT) + { + return moka_push_float(self, + powf(lhs->data.real, rhs->data.real), + lhs->line); + } + + return moka_push_int(self, + pow(lhs->data.integer, rhs->data.integer), + lhs->line); +} + bool moka_is(struct moka* self, MOKA value, TypeKind type) { return moka_type_of(self, value) == type; @@ -464,14 +679,14 @@ MOKA moka_call(struct moka* self, int arg_count) if (native->arity > 0 && arg_count != native->arity) { - status_push(self->status, + status_push(self->status, STATUS_ERROR, line, "<%d> arguments expected, got <%d>", native->arity, arg_count); vec_free(&args); - return moka_push_bool(self, false, line); + return moka_push_bool(self, false, line); } (native->fun)(self, &args); diff --git a/lib/moka.h b/lib/moka.h index 99b6af1..6f3749e 100644 --- a/lib/moka.h +++ b/lib/moka.h @@ -67,6 +67,13 @@ bool moka_is_lt(struct moka* self, MOKA mk_lhs, MOKA mk_rhs); bool moka_is_gt(struct moka* self, MOKA mk_lhs, MOKA mk_rhs); bool moka_is_eqv(struct moka* self, MOKA mk_lhs, MOKA mk_rhs); +MOKA moka_add(struct moka* self, int count); +MOKA moka_sub(struct moka* self, int count); +MOKA moka_mul(struct moka* self, int count); +MOKA moka_div(struct moka* self, int count); +MOKA moka_mod(struct moka* self); +MOKA moka_pow(struct moka* self); + bool moka_is(struct moka* self, MOKA value, TypeKind type); TypeKind moka_type_of(struct moka* self, MOKA value);