float and int arithmetic.

main
bog 2024-03-30 18:14:26 +01:00
parent 1c5ad117d8
commit 61303f6825
7 changed files with 353 additions and 2 deletions

24
features/num.mk Normal file
View File

@ -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))

View File

@ -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
)

View File

@ -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; i<args->size; 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; i<args->size; 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; i<args->size; 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; i<args->size; 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; i<args->size; 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; i<args->size; i++)
{
MOKA arg = MK_EVAL((MOKA) args->data[i]);
moka_push(moka, arg);
}
return moka_pow(moka);
}

View File

@ -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

View File

@ -8,6 +8,7 @@
#include <stdarg.h>
#include <stdbool.h>
#include <ctype.h>
#include <math.h>
typedef size_t MOKA;

View File

@ -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; i<count; i++)
{
MOKA arg = moka_pop(self);
struct value* value = frame->local_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; i<count; i++)
{
MOKA arg = moka_pop(self);
vec_push(&args, (void*) arg);
}
for (int i=0; i<count; i++)
{
MOKA arg = (MOKA) args.data[count - 1 - i];
struct value* value = frame->local_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; i<count; i++)
{
MOKA arg = moka_pop(self);
struct value* value = frame->local_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; i<count; i++)
{
MOKA arg = moka_pop(self);
vec_push(&args, (void*) arg);
}
for (int i=0; i<count; i++)
{
MOKA arg = (MOKA) args.data[count - 1 - i];
struct value* value = frame->local_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);

View File

@ -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);