Compare commits

...

2 Commits

Author SHA1 Message Date
bog b8fa1df563 block with function do. 2024-03-30 20:04:07 +01:00
bog 61303f6825 float and int arithmetic. 2024-03-30 18:14:26 +01:00
10 changed files with 444 additions and 2 deletions

18
features/do.mk Normal file
View File

@ -0,0 +1,18 @@
(define a 4)
(do
(assert-eqv! 4 a)
(define a 'hello)
(assert-eqv! 'hello a)
(set! a 28)
(assert-eqv! 28 a)
)
(assert-eqv! 4 a)
(do
(set! a -63)
)
(assert-eqv! -63 a)

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 PUBLIC -Wall -Wextra -g -fPIC
) )
target_link_options(moka-core
PUBLIC -lm
)
target_include_directories(moka-core target_include_directories(moka-core
PUBLIC ${CMAKE_SOURCE_DIR}/lib PUBLIC ${CMAKE_SOURCE_DIR}/lib
) )

View File

@ -12,12 +12,22 @@ void register_builtins(struct moka* moka)
moka_decl_native(moka, "array", mk_array, -1); moka_decl_native(moka, "array", mk_array, -1);
moka_decl_native(moka, "assert-eqv!", mk_assert_eqv_mut, 2); moka_decl_native(moka, "assert-eqv!", mk_assert_eqv_mut, 2);
moka_decl_native(moka, "do", mk_do, -1);
moka_decl_native(moka, "set!", mk_set_mut, 2);
moka_decl_native(moka, "<", mk_lt, 2); moka_decl_native(moka, "<", mk_lt, 2);
moka_decl_native(moka, "<=", mk_le, 2); moka_decl_native(moka, "<=", mk_le, 2);
moka_decl_native(moka, ">", mk_gt, 2); moka_decl_native(moka, ">", mk_gt, 2);
moka_decl_native(moka, ">=", mk_ge, 2); moka_decl_native(moka, ">=", mk_ge, 2);
moka_decl_native(moka, "eqv?", mk_is_eqv, 2); moka_decl_native(moka, "eqv?", mk_is_eqv, 2);
moka_decl_native(moka, "nev?", mk_is_nev, 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) MOKA mk_println(struct moka* moka, struct vec* args)
@ -101,6 +111,48 @@ MOKA mk_assert_eqv_mut(struct moka* moka, struct vec* args)
return moka_push_bool(moka, true, line); return moka_push_bool(moka, true, line);
} }
MOKA mk_do(struct moka* moka, struct vec* args)
{
assert(moka);
assert(args);
MOKA value = 0;
symtable_open_scope(&moka->symtable);
for (size_t i=0; i<args->size; i++)
{
value = MK_EVAL((MOKA) args->data[i]);
}
symtable_close_scope(&moka->symtable);
return value;
}
MOKA mk_set_mut(struct moka* moka, struct vec* args)
{
assert(moka);
assert(args);
MOKA mk_name = (MOKA) args->data[0];
MOKA value = MK_EVAL((MOKA)args->data[1]);
struct frame* frame = moka_frame(moka);
struct value* name = frame->local_values.data[mk_name];
struct node* node = name->data.lazy;
struct entry* entry = symtable_try_get(
&moka->symtable,
node->token->value
);
moka_push(moka, value);
entry->addr = frame->local_values.size - 1;
return value;
}
// Comparisons // Comparisons
// =========== // ===========
MOKA mk_lt(struct moka* moka, struct vec* args) MOKA mk_lt(struct moka* moka, struct vec* args)
@ -186,3 +238,87 @@ MOKA mk_is_nev(struct moka* moka, struct vec* args)
moka_line(moka, lhs) 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

@ -13,6 +13,9 @@ MOKA mk_define(struct moka* moka, struct vec* args);
MOKA mk_array(struct moka* moka, struct vec* args); MOKA mk_array(struct moka* moka, struct vec* args);
MOKA mk_assert_eqv_mut(struct moka* moka, struct vec* args); MOKA mk_assert_eqv_mut(struct moka* moka, struct vec* args);
MOKA mk_do(struct moka* moka, struct vec* args);
MOKA mk_set_mut(struct moka* moka, struct vec* args);
// Comparisons // Comparisons
// =========== // ===========
MOKA mk_lt(struct moka* moka, struct vec* args); MOKA mk_lt(struct moka* moka, struct vec* args);
@ -22,4 +25,13 @@ MOKA mk_ge(struct moka* moka, struct vec* args);
MOKA mk_is_eqv(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); 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 #endif

View File

@ -8,6 +8,7 @@
#include <stdarg.h> #include <stdarg.h>
#include <stdbool.h> #include <stdbool.h>
#include <ctype.h> #include <ctype.h>
#include <math.h>
typedef size_t MOKA; 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); 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) bool moka_is(struct moka* self, MOKA value, TypeKind type)
{ {
return moka_type_of(self, value) == 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) if (native->arity > 0 && arg_count != native->arity)
{ {
status_push(self->status, status_push(self->status,
STATUS_ERROR, STATUS_ERROR,
line, line,
"<%d> arguments expected, got <%d>", "<%d> arguments expected, got <%d>",
native->arity, native->arity,
arg_count); arg_count);
vec_free(&args); vec_free(&args);
return moka_push_bool(self, false, line); return moka_push_bool(self, false, line);
} }
(native->fun)(self, &args); (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_gt(struct moka* self, MOKA mk_lhs, MOKA mk_rhs);
bool moka_is_eqv(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); bool moka_is(struct moka* self, MOKA value, TypeKind type);
TypeKind moka_type_of(struct moka* self, MOKA value); TypeKind moka_type_of(struct moka* self, MOKA value);

View File

@ -99,3 +99,25 @@ struct entry* symtable_try_get(struct symtable* self, char* name)
return env_try_get(self->root, name); return env_try_get(self->root, name);
} }
void symtable_open_scope(struct symtable* self)
{
struct env* env = malloc(sizeof(struct env));
env_init(env, self->root);
self->root = env;
}
void symtable_close_scope(struct symtable* self)
{
assert(self);
assert(self->root);
struct env* env = self->root->parent;
self->root->parent = NULL;
env_free(self->root);
free(self->root);
self->root = env;
}

View File

@ -42,4 +42,7 @@ void symtable_declare(struct symtable* self,
struct entry* symtable_try_get(struct symtable* self, char* name); struct entry* symtable_try_get(struct symtable* self, char* name);
void symtable_open_scope(struct symtable* self);
void symtable_close_scope(struct symtable* self);
#endif #endif