✨ float and int arithmetic.
parent
1c5ad117d8
commit
61303f6825
|
@ -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))
|
||||
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
|
||||
typedef size_t MOKA;
|
||||
|
||||
|
|
215
lib/moka.c
215
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; 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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue