From 88aad1ee75f347ca9c7a869b6213b69a462b2fce Mon Sep 17 00:00:00 2001 From: bog Date: Sat, 6 Apr 2024 20:44:58 +0200 Subject: [PATCH] :sparkles: native functions. --- lib/CMakeLists.txt | 3 ++ lib/include/commons.h | 1 + lib/include/compiler.h | 15 ++++-- lib/include/module.h | 2 + lib/include/natives.h | 17 +++++++ lib/include/nfun.h | 21 +++++++++ lib/include/state.h | 7 ++- lib/include/sym.h | 4 ++ lib/include/value.h | 4 +- lib/src/compiler.c | 102 ++++++++++++++++++++++++----------------- lib/src/exec.c | 51 ++++++++++++++++++++- lib/src/module.c | 29 ++++-------- lib/src/natives.c | 30 ++++++++++++ lib/src/nfun.c | 39 ++++++++++++++++ lib/src/state.c | 23 ++++++++-- lib/src/sym.c | 19 +++++++- lib/src/value.c | 19 ++++++++ 17 files changed, 307 insertions(+), 79 deletions(-) create mode 100644 lib/include/natives.h create mode 100644 lib/include/nfun.h create mode 100644 lib/src/natives.c create mode 100644 lib/src/nfun.c diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 6af2c95..29c744d 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -25,6 +25,9 @@ add_library(skopy-lib SHARED src/sym.c src/fun.c + + src/nfun.c + src/natives.c ) file(GLOB_RECURSE diff --git a/lib/include/commons.h b/lib/include/commons.h index 658d560..abbc15d 100644 --- a/lib/include/commons.h +++ b/lib/include/commons.h @@ -13,6 +13,7 @@ #include "vec.h" #include "errors.h" + #define SK_ENUM_ENUM(X) X #define SK_ENUM_STR(X) #X diff --git a/lib/include/compiler.h b/lib/include/compiler.h index f4ab2ce..5206ac5 100644 --- a/lib/include/compiler.h +++ b/lib/include/compiler.h @@ -5,6 +5,8 @@ #include "prog.h" #include "sym.h" +struct state; + struct compiler { struct vec var_names; @@ -16,12 +18,14 @@ void compiler_free(struct compiler* self); void compiler_compile(struct compiler* self, struct node* node, struct prog* prog, - struct sym* sym); + struct sym* sym, + struct state* state); void compiler_compile_children(struct compiler* self, struct node* node, struct prog* prog, - struct sym* sym); + struct sym* sym, + struct state* state); void compiler_compile_value(struct compiler* self, struct node* node, @@ -32,17 +36,20 @@ void compiler_compile_value(struct compiler* self, void compiler_compile_and(struct compiler* self, struct node* node, struct prog* prog, - struct sym* sym); + struct sym* sym, + struct state* state); void compiler_compile_or(struct compiler* self, struct node* node, struct prog* prog, - struct sym* sym); + struct sym* sym, + struct state* state); void compiler_compile_if(struct compiler* self, struct node* node, struct prog* prog, struct sym* sym, + struct state* state, struct vec* to_end); #endif diff --git a/lib/include/module.h b/lib/include/module.h index 2fd08fe..7ed8bf9 100644 --- a/lib/include/module.h +++ b/lib/include/module.h @@ -4,12 +4,14 @@ #include "commons.h" #include "prog.h" #include "sym.h" +#include "state.h" struct module { struct str source; struct prog prog; struct sym sym; + struct state state; }; void module_init(struct module* self); diff --git a/lib/include/natives.h b/lib/include/natives.h new file mode 100644 index 0000000..a6d9379 --- /dev/null +++ b/lib/include/natives.h @@ -0,0 +1,17 @@ +#ifndef SK_NATIVES_H +#define SK_NATIVES_H + +#include "commons.h" +#include "state.h" +#include "sym.h" + +void natives_populate(struct state* state, struct sym* sym); +void natives_decl(struct state* state, + struct sym* sym, + char* name, + nfun_body fun, + size_t arity); + +SK native_println(struct state* state, struct vec* args); + +#endif diff --git a/lib/include/nfun.h b/lib/include/nfun.h new file mode 100644 index 0000000..a313fca --- /dev/null +++ b/lib/include/nfun.h @@ -0,0 +1,21 @@ +#ifndef SK_NFUN_H +#define SK_NFUN_H + +#include "commons.h" +#include "state.h" + +typedef SK (*nfun_body)(struct state*, struct vec*); + +struct nfun +{ + nfun_body body; + size_t arity; +}; + +void nfun_init(struct nfun* self, nfun_body body, size_t arity); +void nfun_free(struct nfun* self); + +SK nfun_call(struct nfun* self, + struct state* state, + struct vec* args); +#endif diff --git a/lib/include/state.h b/lib/include/state.h index f4ec45f..7db78a3 100644 --- a/lib/include/state.h +++ b/lib/include/state.h @@ -1,7 +1,6 @@ #ifndef SK_STATE_H #define SK_STATE_H -#include "commons.h" #include "value.h" #define SK size_t @@ -34,6 +33,8 @@ struct state struct vec globals; }; +typedef SK (*nfun_body)(struct state*, struct vec*); + void stack_value_init(struct stack_value* self, size_t addr, struct value* new_value); @@ -53,7 +54,6 @@ struct frame* state_frame(struct state* self); void state_push_frame(struct state* self); void state_pop_frame(struct state* self); -bool state_has_top(struct state* self); SK state_top(struct state* self); struct value* state_try_get_value(struct state* self, SK value); struct local* state_try_get_local_by_id(struct state* self, int id); @@ -109,4 +109,7 @@ SK state_eq(struct state* self); void state_call(struct state* self, struct fun* fun); void state_ret(struct state* self); +SK state_add_nfun(struct state* self, + nfun_body body, + size_t arity); #endif diff --git a/lib/include/sym.h b/lib/include/sym.h index b2af415..b387ce6 100644 --- a/lib/include/sym.h +++ b/lib/include/sym.h @@ -3,11 +3,13 @@ #include "commons.h" #define SK_NO_CLOSURE (-1) +#define SK_NO_NATIVE (-1) struct symbol { int id; int closure_id; + int native_id; char* name; bool is_const; struct env* env; @@ -23,6 +25,7 @@ struct sym { int id_counter; int closure_counter; + int native_counter; struct env* env; }; @@ -46,6 +49,7 @@ void sym_free(struct sym* self); int sym_decl_var(struct sym* self, char const* name); int sym_decl_const(struct sym* self, char const* name); int sym_decl_closure(struct sym* self, int id, char const* name); +int sym_decl_native(struct sym* self, char const* name, int addr); void sym_open_scope(struct sym* self); void sym_close_scope(struct sym* self); diff --git a/lib/include/value.h b/lib/include/value.h index 46911e8..091b934 100644 --- a/lib/include/value.h +++ b/lib/include/value.h @@ -7,7 +7,8 @@ #define TYPE_KIND(G) \ G(TYPE_INT), G(TYPE_BOOL), G(TYPE_FLOAT), \ -G(TYPE_STRING), G(TYPE_FUN), G(TYPE_REF) +G(TYPE_STRING), G(TYPE_FUN), G(TYPE_REF), \ +G(TYPE_NATIVE_FUN) SK_ENUM_H(TypeKind, TYPE_KIND); @@ -18,6 +19,7 @@ union val bool boolean; char* str; struct fun* fun; + struct nfun* nfun; size_t ref; }; diff --git a/lib/src/compiler.c b/lib/src/compiler.c index 2859978..38f6c7a 100644 --- a/lib/src/compiler.c +++ b/lib/src/compiler.c @@ -1,5 +1,7 @@ #include "compiler.h" #include "token.h" +#include "state.h" +#include "natives.h" void compiler_init(struct compiler* self) { @@ -16,7 +18,8 @@ void compiler_free(struct compiler* self) void compiler_compile(struct compiler* self, struct node* node, struct prog* prog, - struct sym* sym) + struct sym* sym, + struct state* state) { assert(self); assert(node); @@ -28,7 +31,7 @@ void compiler_compile(struct compiler* self, for (size_t i=0; ichildren.size; i++) { compiler_compile(self, node->children.data[i], - prog, sym); + prog, sym, state); } } break; @@ -37,7 +40,7 @@ void compiler_compile(struct compiler* self, for (size_t i=0; ichildren.size; i++) { compiler_compile(self, node->children.data[i], - prog, sym); + prog, sym, state); } sym_close_scope(sym); } break; @@ -49,10 +52,10 @@ void compiler_compile(struct compiler* self, for (size_t i=0; ichildren.size; i++) { compiler_compile(self, args->children.data[i], - prog, sym); + prog, sym, state); } - compiler_compile(self, target, prog, sym); + compiler_compile(self, target, prog, sym, state); prog_add_instr(prog, OP_CALL, args->children.size); } break; @@ -60,7 +63,8 @@ void compiler_compile(struct compiler* self, struct vec to_end; vec_init(&to_end); - compiler_compile_if(self, node, prog, sym, &to_end); + compiler_compile_if(self, node, prog, sym, state, + &to_end); size_t end_point = prog->params.size; for (size_t i=0; ichildren.data[1]; - compiler_compile(self, expr, prog, sym); + compiler_compile(self, expr, prog, sym, state); int id = sym_decl_var(sym, ident->token->value); @@ -122,7 +126,7 @@ void compiler_compile(struct compiler* self, ident->token->value); } struct node* expr = node->children.data[1]; - compiler_compile(self, expr, prog, sym); + compiler_compile(self, expr, prog, sym, state); int id = sym_decl_const(sym, ident->token->value); prog_add_instr(prog, OP_LOCAL_STORE, id); char* name = vec_pop(&self->var_names); @@ -148,7 +152,7 @@ void compiler_compile(struct compiler* self, break; } - compiler_compile(self, expr, prog, sym); + compiler_compile(self, expr, prog, sym, state); if (symbol->closure_id != SK_NO_CLOSURE) { @@ -165,28 +169,34 @@ void compiler_compile(struct compiler* self, node->token->value); if (!symbol) { + errors_push(node->token->line, + "unknown identifier '%s'.", + node->token->value); break; } struct env* itr = sym->env->parent; - struct symbol* context = NULL; while (itr) { - struct symbol* s = env_try_get(itr, symbol->name); + struct symbol const* s = env_try_get(itr, symbol->name); if (s) { - context = s; break; } itr = itr->parent; } - if (0 && context) + if (symbol->native_id != SK_NO_NATIVE) { - prog_add_instr(prog, OP_LOCAL_LOAD, context->id); + struct value* value = malloc(sizeof(struct value)); + union val val; + val.ref = symbol->native_id; + value_init(value, TYPE_REF, val, node->token->line); + size_t idx = prog_add_constant(prog, value); + prog_add_instr(prog, OP_PUSH, idx); } else if (symbol->closure_id != SK_NO_CLOSURE) { @@ -200,7 +210,7 @@ void compiler_compile(struct compiler* self, case NODE_RETURN: { compiler_compile(self, node->children.data[0], - prog, sym); + prog, sym, state); prog_add_instr(prog, OP_RET, SK_NO_PARAM); } break; @@ -210,6 +220,8 @@ void compiler_compile(struct compiler* self, prog_init(p); fun_init(fun, p); + natives_populate(state, fun->sym); + struct node* params = node->children.data[0]; struct node* body = node->children.data[1]; @@ -253,7 +265,7 @@ void compiler_compile(struct compiler* self, } } } - compiler_compile(self, body, p, fun->sym); + compiler_compile(self, body, p, fun->sym, state); union val val; val.fun = fun; @@ -291,70 +303,70 @@ void compiler_compile(struct compiler* self, } break; case NODE_LT: { - compiler_compile_children(self, node, prog, sym); + compiler_compile_children(self, node, prog, sym, state); prog_add_instr(prog, OP_LT, SK_NO_PARAM); } break; case NODE_LE: { - compiler_compile_children(self, node, prog, sym); + compiler_compile_children(self, node, prog, sym, state); prog_add_instr(prog, OP_GT, SK_NO_PARAM); prog_add_instr(prog, OP_NOT, SK_NO_PARAM); } break; case NODE_GT: { - compiler_compile_children(self, node, prog, sym); + compiler_compile_children(self, node, prog, sym, state); prog_add_instr(prog, OP_GT, SK_NO_PARAM); } break; case NODE_GE: { - compiler_compile_children(self, node, prog, sym); + compiler_compile_children(self, node, prog, sym, state); prog_add_instr(prog, OP_LT, SK_NO_PARAM); prog_add_instr(prog, OP_NOT, SK_NO_PARAM); } break; case NODE_EQUAL: { - compiler_compile_children(self, node, prog, sym); + compiler_compile_children(self, node, prog, sym, state); prog_add_instr(prog, OP_EQUAL, SK_NO_PARAM); } break; case NODE_NOT_EQUAL: { - compiler_compile_children(self, node, prog, sym); + compiler_compile_children(self, node, prog, sym, state); prog_add_instr(prog, OP_EQUAL, SK_NO_PARAM); prog_add_instr(prog, OP_NOT, SK_NO_PARAM); } break; case NODE_ADD: { - compiler_compile_children(self, node, prog, sym); + compiler_compile_children(self, node, prog, sym, state); prog_add_instr(prog, OP_ADD, SK_NO_PARAM); } break; case NODE_SUB: { - compiler_compile_children(self, node, prog, sym); + compiler_compile_children(self, node, prog, sym, state); prog_add_instr(prog, OP_SUB, SK_NO_PARAM); } break; case NODE_MUL: { - compiler_compile_children(self, node, prog, sym); + compiler_compile_children(self, node, prog, sym, state); prog_add_instr(prog, OP_MUL, SK_NO_PARAM); } break; case NODE_DIV: { - compiler_compile_children(self, node, prog, sym); + compiler_compile_children(self, node, prog, sym, state); prog_add_instr(prog, OP_DIV, SK_NO_PARAM); } break; case NODE_MOD: { - compiler_compile_children(self, node, prog, sym); + compiler_compile_children(self, node, prog, sym, state); prog_add_instr(prog, OP_MOD, SK_NO_PARAM); } break; case NODE_POW: { - compiler_compile_children(self, node, prog, sym); + compiler_compile_children(self, node, prog, sym, state); prog_add_instr(prog, OP_POW, SK_NO_PARAM); } break; case NODE_USUB: { - compiler_compile_children(self, node, prog, sym); + compiler_compile_children(self, node, prog, sym, state); prog_add_instr(prog, OP_USUB, SK_NO_PARAM); } break; @@ -369,7 +381,8 @@ void compiler_compile(struct compiler* self, void compiler_compile_children(struct compiler* self, struct node* node, struct prog* prog, - struct sym* sym) + struct sym* sym, + struct state* state) { assert(self); assert(node); @@ -378,7 +391,7 @@ void compiler_compile_children(struct compiler* self, for (size_t i=0; ichildren.size; i++) { struct node* child = node->children.data[i]; - compiler_compile(self, child, prog, sym); + compiler_compile(self, child, prog, sym, state); } } @@ -399,7 +412,8 @@ void compiler_compile_value(struct compiler* self, void compiler_compile_and(struct compiler* self, struct node* node, struct prog* prog, - struct sym* sym) + struct sym* sym, + struct state* state) { assert(self); assert(node); @@ -412,7 +426,7 @@ void compiler_compile_and(struct compiler* self, for (size_t i =0; ichildren.size; i++) { struct node* child = node->children.data[i]; - compiler_compile(self, child, prog, sym); + compiler_compile(self, child, prog, sym, state); size_t brf = prog_add_instr(prog, OP_BRF, 0); // to false vec_push(&to_false, (void*) brf); } @@ -442,7 +456,8 @@ void compiler_compile_and(struct compiler* self, void compiler_compile_or(struct compiler* self, struct node* node, struct prog* prog, - struct sym* sym) + struct sym* sym, + struct state* state) { assert(self); assert(node); @@ -454,7 +469,7 @@ void compiler_compile_or(struct compiler* self, for (size_t i =0; ichildren.size; i++) { struct node* child = node->children.data[i]; - compiler_compile(self, child, prog, sym); + compiler_compile(self, child, prog, sym, state); prog_add_instr(prog, OP_NOT, 0); size_t brf = prog_add_instr(prog, OP_BRF, 0); // to true vec_push(&to_true, (void*) brf); @@ -486,15 +501,16 @@ void compiler_compile_if(struct compiler* self, struct node* node, struct prog* prog, struct sym* sym, + struct state* state, struct vec* to_end) { struct node* cond = node->children.data[0]; struct node* block = node->children.data[1]; - compiler_compile(self, cond, prog, sym); + compiler_compile(self, cond, prog, sym, state); size_t brf = prog_add_instr(prog, OP_BRF, 40); // to next - compiler_compile(self, block, prog, sym); + compiler_compile(self, block, prog, sym, state); size_t br = prog_add_instr(prog, OP_BR, 0); // to end vec_push(to_end, (void*) br); @@ -507,11 +523,11 @@ void compiler_compile_if(struct compiler* self, struct node* next = node->children.data[2]; if (next->kind == NODE_IF) { - compiler_compile_if(self, next, prog, sym, to_end); + compiler_compile_if(self, next, prog, sym, state, to_end); } else { - compiler_compile(self, next, prog, sym); + compiler_compile(self, next, prog, sym, state); } } } diff --git a/lib/src/exec.c b/lib/src/exec.c index 188e540..fe71ffc 100644 --- a/lib/src/exec.c +++ b/lib/src/exec.c @@ -1,6 +1,7 @@ #include "exec.h" #include "sym.h" #include "fun.h" +#include "nfun.h" void exec_init(struct exec* self) { @@ -93,19 +94,57 @@ void exec_execute(struct exec* self, struct vec params; vec_init(¶ms); + struct vec pvalues; + vec_init(&pvalues); + SK function = state_pop(state); for (size_t i=0; ival.ref - )->val.fun; + ); + + if (val_fun->type == TYPE_NATIVE_FUN) + { + SK res = nfun_call(val_fun->val.nfun, + state, + &pvalues); + struct value* value = + state_try_get_value(state, res); + state_push( + state, + value->type, + value->val, + value->line + ); + + vec_free(&pvalues); + vec_free_elements(¶ms, NULL); + vec_free(¶ms); + free(f); + self->pc++; + break; + } + + vec_free(&pvalues); + if (!val_fun) + { + vec_free_elements(¶ms, NULL); + vec_free(¶ms); + errors_push(f->line, "cannot deref nil ref"); + free(f); + return; + } + + struct fun* fun = val_fun->val.fun; state_call(state, fun); for (size_t i=0; ival.ref, + constant->line + ); + } break; + case TYPE_BOOL: { state_push_bool( state, diff --git a/lib/src/module.c b/lib/src/module.c index 3d794fe..9027239 100644 --- a/lib/src/module.c +++ b/lib/src/module.c @@ -3,13 +3,17 @@ #include "compiler.h" #include "state.h" #include "exec.h" +#include "natives.h" void module_init(struct module* self) { assert(self); str_init(&self->source); prog_init(&self->prog); + state_init(&self->state); sym_init(&self->sym); + + natives_populate(&self->state, &self->sym); } void module_free(struct module* self) @@ -18,6 +22,7 @@ void module_free(struct module* self) str_free(&self->source); prog_free(&self->prog); sym_free(&self->sym); + state_free(&self->state); } void module_load_source(struct module* self, @@ -54,14 +59,13 @@ int module_compile(struct module* self) struct compiler compiler; compiler_init(&compiler); - compiler_compile(&compiler, root, &self->prog, &self->sym); + compiler_compile(&compiler, root, &self->prog, &self->sym, + &self->state); struct exec exec; exec_init(&exec); - struct state state; - state_init(&state); - exec_execute(&exec, &state, &self->prog); + exec_execute(&exec, &self->state, &self->prog); if (!errors_ok()) { @@ -69,25 +73,8 @@ int module_compile(struct module* self) goto free_state; } - if (state_has_top(&state)) - { - struct value* value = state_try_get_value( - &state, - state_top(&state) - ); - - assert(value); - - struct str str; - str_init(&str); - value_str(value, &str); - printf("%s\n", str.value); - str_free(&str); - } - // Free free_state: - state_free(&state); exec_free(&exec); compiler_free(&compiler); free_node: diff --git a/lib/src/natives.c b/lib/src/natives.c new file mode 100644 index 0000000..d141078 --- /dev/null +++ b/lib/src/natives.c @@ -0,0 +1,30 @@ +#include "natives.h" + +void natives_populate(struct state* state, struct sym* sym) +{ + assert(state); + assert(sym); + + natives_decl(state, sym, "println", native_println, 1); +} + +void natives_decl(struct state* state, + struct sym* sym, + char* name, + nfun_body fun, + size_t arity) +{ + assert(state); + assert(sym); + int addr = state_add_nfun(state, fun, arity); + sym_decl_native(sym, name, addr); +} + +SK native_println(struct state* state, struct vec* args) +{ + struct value* arg + = state_try_get_value(state, (SK) args->data[0]); + + printf("%s\n", arg->val.str); + return state_push_bool(state, true, 0); +} diff --git a/lib/src/nfun.c b/lib/src/nfun.c new file mode 100644 index 0000000..1e69f27 --- /dev/null +++ b/lib/src/nfun.c @@ -0,0 +1,39 @@ +#include "nfun.h" + +void nfun_init(struct nfun* self, nfun_body body, size_t arity) +{ + assert(self); + self->body = body; + self->arity = arity; +} + +void nfun_free(struct nfun* self) +{ + assert(self); +} + +SK nfun_call(struct nfun* self, + struct state* state, + struct vec* args) +{ + assert(self); + int line = 0; + + if (args->size > 0) + { + line = state_line(state, (SK) args->data[0]); + } + + if (self->arity != args->size) + { + errors_push(line, + "wrong arity, expected %zu, got %zu.", + self->arity, + args->size); + return state_push_bool(state, false, line); + } + + SK result = (*self->body)(state, args); + + return result; +} diff --git a/lib/src/state.c b/lib/src/state.c index f905c24..f735f73 100644 --- a/lib/src/state.c +++ b/lib/src/state.c @@ -1,4 +1,5 @@ #include "state.h" +#include "nfun.h" void stack_value_init(struct stack_value* self, size_t addr, @@ -105,11 +106,6 @@ void state_pop_frame(struct state* self) frame_free(frame); free(frame); } -bool state_has_top(struct state* self) -{ - struct frame* frame = state_frame(self); - return frame->stack.size > 0; -} SK state_top(struct state* self) { @@ -743,3 +739,20 @@ void state_ret(struct state* self) assert(self); state_pop_frame(self); } + +SK state_add_nfun(struct state* self, + nfun_body body, + size_t arity) +{ + struct nfun* fun = malloc(sizeof(struct nfun)); + nfun_init(fun, body, arity); + + union val val; + val.nfun = fun; + + struct value* value = malloc(sizeof(struct value)); + value_init(value, TYPE_NATIVE_FUN, val, 0); + + vec_push(&self->globals, value); + return self->globals.size - 1; +} diff --git a/lib/src/sym.c b/lib/src/sym.c index 3d2907c..4ff857c 100644 --- a/lib/src/sym.c +++ b/lib/src/sym.c @@ -21,6 +21,7 @@ struct env* env_new_clone(struct env* self) new_symbol->name = strdup(symbol->name); new_symbol->is_const = symbol->is_const; new_symbol->closure_id = symbol->closure_id; + new_symbol->native_id = symbol->native_id; new_symbol->env = clone; vec_push(&clone->symbols, new_symbol); @@ -71,6 +72,7 @@ void symbol_init(struct symbol* self, self->name = strdup(name); self->is_const = false; self->closure_id = SK_NO_CLOSURE; + self->native_id = SK_NO_NATIVE; self->env = env; } @@ -85,6 +87,7 @@ void sym_init(struct sym* self) assert(self); self->id_counter = 1; self->closure_counter = 1; + self->native_counter = 1; self->env = malloc(sizeof(struct env)); env_init(self->env); } @@ -142,7 +145,7 @@ int sym_decl_closure(struct sym* self, int id, char const* name) { assert(self); assert(name); - + struct symbol* symbol = malloc(sizeof(struct symbol)); symbol_init(symbol, self->closure_counter, name, self->env); symbol->is_const = false; @@ -153,6 +156,20 @@ int sym_decl_closure(struct sym* self, int id, char const* name) return self->closure_counter - 1; } +int sym_decl_native(struct sym* self, char const* name, int addr) +{ + assert(self); + assert(name); + struct symbol* symbol = malloc(sizeof(struct symbol)); + symbol_init(symbol, self->native_counter, name, self->env); + symbol->is_const = false; + symbol->native_id = addr; + vec_push(&self->env->symbols, symbol); + + self->native_counter++; + return self->native_counter - 1; +} + void sym_open_scope(struct sym* self) { assert(self); diff --git a/lib/src/value.c b/lib/src/value.c index f76aa4b..27e46ca 100644 --- a/lib/src/value.c +++ b/lib/src/value.c @@ -1,4 +1,5 @@ #include "value.h" +#include "nfun.h" SK_ENUM_C(TypeKind, TYPE_KIND); @@ -27,6 +28,12 @@ void value_free(struct value* self) fun_free(self->val.fun); free(self->val.fun); } + + if (self->type == TYPE_NATIVE_FUN) + { + nfun_free(self->val.nfun); + free(self->val.nfun); + } } struct value* value_new_clone(struct value* self) @@ -74,6 +81,14 @@ struct value* value_new_clone(struct value* self) return clone; } break; + case TYPE_NATIVE_FUN: { + val.nfun = malloc(sizeof(struct nfun)); + val.nfun->body = self->val.nfun->body; + val.nfun->arity = self->val.nfun->arity; + value_init(clone, TYPE_NATIVE_FUN, val, self->line); + return clone; + } break; + default: { fprintf(stderr, "cannot clone value '%s'\n", TypeKindStr[self->type]); @@ -111,6 +126,10 @@ void value_str(struct value* self, struct str* dest) str_format(dest, "", self->val.fun); } break; + case TYPE_NATIVE_FUN: { + str_format(dest, "", self->val.nfun); + } break; + case TYPE_REF: { str_format(dest, "", self->val.ref); } break;