diff --git a/lib/builtins.c b/lib/builtins.c index f4ef24c..0b93af1 100644 --- a/lib/builtins.c +++ b/lib/builtins.c @@ -2,6 +2,7 @@ #include "node.h" #include "path.h" #include "module.h" +#include "moka.h" void register_builtins(struct moka* moka) { @@ -9,6 +10,7 @@ void register_builtins(struct moka* moka) moka_decl_native(moka, "println", mk_println); moka_decl_native(moka, "define", mk_define); moka_decl_native(moka, "array", mk_array); + moka_decl_native(moka, "assert-eqv!", mk_assert_eqv_mut); } MOKA mk_println(struct moka* moka, struct vec* args) @@ -64,3 +66,30 @@ MOKA mk_array(struct moka* moka, struct vec* args) return moka_top(moka); } + +MOKA mk_assert_eqv_mut(struct moka* moka, struct vec* args) +{ + assert(moka); + assert(args); + + MOKA lhs = MK_EVAL((MOKA) args->data[0]); + MOKA rhs = MK_EVAL((MOKA) args->data[1]); + int line = moka_line(moka, lhs); + + char lhs_buf[MK_STRLEN]; + moka_str(moka, lhs, lhs_buf, MK_STRLEN); + + char rhs_buf[MK_STRLEN]; + moka_str(moka, rhs, rhs_buf, MK_STRLEN); + + if (!moka_is_eqv(moka, lhs, rhs)) + { + status_push(moka->status, STATUS_ERROR, line, + "assertion failed\nlhs = %s\nrhs = %s", + lhs_buf, rhs_buf); + + return moka_push_bool(moka, false, line); + } + + return moka_push_bool(moka, true, line); +} diff --git a/lib/builtins.h b/lib/builtins.h index 354345b..c990f38 100644 --- a/lib/builtins.h +++ b/lib/builtins.h @@ -11,5 +11,6 @@ void register_builtins(struct moka* moka); MOKA mk_println(struct moka* moka, struct vec* args); MOKA mk_define(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); #endif diff --git a/lib/compiler.c b/lib/compiler.c index 59a2e60..7a34e88 100644 --- a/lib/compiler.c +++ b/lib/compiler.c @@ -244,9 +244,6 @@ void compiler_quote(struct compiler* self, switch (node->kind) { - case NODE_INT: { - compiler_compile(self, node, prog, moka); - } break; case NODE_IDENT: { node->kind = NODE_SYMBOL; compiler_compile(self, node, prog, moka); @@ -262,9 +259,7 @@ void compiler_quote(struct compiler* self, node->children.size); } break; default: { - fprintf(stderr, "cannot quote node <%s>\n", - NodeKindStr[node->kind]); - abort(); + compiler_compile(self, node, prog, moka); } break; } } diff --git a/lib/exec.c b/lib/exec.c index 63d8553..972afc2 100644 --- a/lib/exec.c +++ b/lib/exec.c @@ -1,4 +1,5 @@ #include "exec.h" +#include "status.h" void exec_init(struct exec* self) { @@ -24,6 +25,11 @@ void exec_prog(struct exec* self, moka, prog, prog->instructions.data[self->pc]); + + if (!status_is_ok(moka->status)) + { + return; + } } } @@ -44,6 +50,11 @@ void exec_instr(struct exec* self, case OP_CALL: { moka_call(moka, param); + if (!status_is_ok(moka->status)) + { + return; + } + self->pc++; } break; diff --git a/lib/lexer.c b/lib/lexer.c index 44b39af..8b4e287 100644 --- a/lib/lexer.c +++ b/lib/lexer.c @@ -21,6 +21,7 @@ void lexer_init(struct lexer* self, str_push(&self->separators, ')'); str_push(&self->separators, '['); str_push(&self->separators, ']'); + str_push(&self->separators, '\''); } void lexer_free(struct lexer* self) @@ -425,14 +426,8 @@ bool lexer_is_ident(struct lexer* self, size_t index) { return false; } - char c = self->source[index]; - return isalnum(c) - || c == '_' - || c == '!' - || c == '?' - || c == '-' - || c == ':'; + return !lexer_is_sep(self, index); } struct token* lexer_try_new_text(struct lexer* self, diff --git a/lib/module.c b/lib/module.c index 6b18358..68e50a4 100644 --- a/lib/module.c +++ b/lib/module.c @@ -109,6 +109,10 @@ int module_load_from_str(struct module* self, char const* source) exec_init(&exec); exec_prog(&exec, &self->moka, &self->prog); + if (!status_is_ok(self->moka.status)) + { + status_dump(self->moka.status); + } exec_free(&exec); free_compiler: diff --git a/lib/moka.c b/lib/moka.c index 2a52623..c4448db 100644 --- a/lib/moka.c +++ b/lib/moka.c @@ -229,6 +229,49 @@ MOKA moka_pop(struct moka* self) vec_pop(&frame->stack); return val; } + +int moka_line(struct moka* self, MOKA value) +{ + assert(self); + struct frame* frame = moka_frame(self); + struct value const* val = frame->local_values.data[value]; + return val->line; +} + +size_t moka_str(struct moka* self, MOKA value, + char* buffer, size_t size) +{ + struct frame* frame = moka_frame(self); + struct value* val = frame->local_values.data[value]; + + if (moka_is(self, value, TY_REF)) + { + val = self->global_values.data[val->data.ref]; + } + + return value_str(val, buffer, size, self); +} + +bool moka_is_eqv(struct moka* self, MOKA mk_lhs, MOKA mk_rhs) +{ + struct frame* frame = moka_frame(self); + struct value* lhs = frame->local_values.data[mk_lhs]; + struct value* rhs = frame->local_values.data[mk_rhs]; + + if (lhs->type != rhs->type) + { + return false; + } + + if (moka_is(self, mk_lhs, TY_REF)) + { + lhs = self->global_values.data[lhs->data.ref]; + rhs = self->global_values.data[rhs->data.ref]; + } + + return value_is_eqv(lhs, rhs, self); +} + bool moka_is(struct moka* self, MOKA value, TypeKind type) { return moka_type_of(self, value) == type; @@ -264,7 +307,7 @@ void moka_dump(struct moka* self, MOKA value) else { char buffer[MK_STRLEN]; - value_str(val, buffer, MK_STRLEN); + value_str(val, buffer, MK_STRLEN, self); printf("%s", buffer); } diff --git a/lib/moka.h b/lib/moka.h index 67891b5..ae340f0 100644 --- a/lib/moka.h +++ b/lib/moka.h @@ -58,6 +58,11 @@ bool moka_has_top(struct moka* self); MOKA moka_top(struct moka* self); MOKA moka_pop(struct moka* self); +int moka_line(struct moka* self, MOKA value); +size_t moka_str(struct moka* self, MOKA value, + char* buffer, size_t size); +bool moka_is_eqv(struct moka* self, MOKA mk_lhs, MOKA mk_rhs); + bool moka_is(struct moka* self, MOKA value, TypeKind type); TypeKind moka_type_of(struct moka* self, MOKA value); diff --git a/lib/value.c b/lib/value.c index ba51d81..b201a79 100644 --- a/lib/value.c +++ b/lib/value.c @@ -1,5 +1,6 @@ #include "value.h" #include "node.h" +#include "moka.h" MK_ENUM_C(TypeKind, TYPE_KIND); @@ -88,11 +89,14 @@ void value_init_array(struct value* self, struct vec* new_values, int line) self->line = line; } -size_t value_str(struct value* self, char* buffer, size_t size) +size_t value_str(struct value* self, + char* buffer, + size_t size, + struct moka* moka) { assert(self); assert(buffer); - + switch (self->type) { case TY_INT: { @@ -104,7 +108,7 @@ size_t value_str(struct value* self, char* buffer, size_t size) } break; case TY_BOOL: { - return snprintf(buffer, size, "%s", + return snprintf(buffer, size, "%s", self->data.boolean ? "true" : "false"); } break; @@ -123,16 +127,27 @@ size_t value_str(struct value* self, char* buffer, size_t size) case TY_NATIVE: { return snprintf(buffer, size, "", self->data.native); } break; - + case TY_LAZY: { - return snprintf(buffer, size, "", + return snprintf(buffer, size, "", NodeKindStr[self->data.lazy->kind] + strlen("NODE_")); } break; case TY_ARRAY: { size_t sz = 0; - sz += snprintf(buffer + sz, size - sz, "[array]"); + sz += snprintf(buffer + sz, size - sz, "["); + for (size_t i=0; idata.array->values.size; i++) + { + if (i > 0) + { + sz += snprintf(buffer + sz, size - sz, " "); + } + + MOKA val = (MOKA) self->data.array->values.data[i]; + sz += moka_str(moka, val, buffer + sz, size - sz); + } + sz += snprintf(buffer + sz, size - sz, "]"); return sz; } break; @@ -142,16 +157,77 @@ size_t value_str(struct value* self, char* buffer, size_t size) abort(); } break; } +} -// void value_init_int(struct value* self, int value, int line); -// void value_init_float(struct value* self, float value, int line); -// void value_init_bool(struct value* self, bool value, int line); -// void value_init_string(struct value* self, char const* value, int line); -// void value_init_symbol(struct value* self, char const* value, int line); -// void value_init_ref(struct value* self, size_t value, int line); -// void value_init_native(struct value* self, struct native* value, int line); -// void value_init_lazy(struct value* self, struct node* value, int line); -// void value_init_array(struct value* self, struct vec* new_values, int line); +bool value_is_eqv(struct value* self, + struct value* rhs, + struct moka* moka) +{ + if (self->type != rhs->type) + { + return false; + } + + switch (self->type) + { + case TY_INT: { + return self->data.integer == rhs->data.integer; + } break; + + case TY_FLOAT: { + return self->data.real == rhs->data.real; + } break; + + case TY_BOOL: { + return self->data.boolean == rhs->data.boolean; + } break; + + case TY_STRING: { + return strcmp(self->data.str, rhs->data.str) == 0; + } break; + + case TY_SYMBOL: { + return strcmp(self->data.sym, rhs->data.sym) == 0; + } break; + + case TY_REF: { + return self->data.ref == rhs->data.ref; + } break; + + case TY_ARRAY: { + if (self->data.array->values.size + != rhs->data.array->values.size) + { + return false; + } + + for (size_t i=0; idata.array->values.size; i++) + { + MOKA first = (MOKA) self->data.array->values.data[i]; + MOKA second = (MOKA) rhs->data.array->values.data[i]; + if (!moka_is_eqv(moka, first, second)) + { + return false; + } + } + + return true; + } break; + + case TY_NATIVE: { + return false; + } break; + + case TY_LAZY: { + return true; + } break; + + default: { + fprintf(stderr, "cannot test eqv on type <%s>\n", + TypeKindStr[self->type]); + abort(); + } break; + } } void value_free(struct value* self) @@ -180,3 +256,6 @@ void value_free(struct value* self) free(self->data.array); } } + + + diff --git a/lib/value.h b/lib/value.h index 0e39bd9..0d4c635 100644 --- a/lib/value.h +++ b/lib/value.h @@ -42,7 +42,14 @@ void value_init_native(struct value* self, struct native* value, int line); void value_init_lazy(struct value* self, struct node* value, int line); void value_init_array(struct value* self, struct vec* new_values, int line); -size_t value_str(struct value* self, char* buffer, size_t size); +size_t value_str(struct value* self, + char* buffer, + size_t size, + struct moka* moka); + +bool value_is_eqv(struct value* self, + struct value* rhs, + struct moka* moka); void value_free(struct value* self);