From b5f0713fee3ba081685ce0bd03441db14cfe3217 Mon Sep 17 00:00:00 2001 From: bog Date: Sun, 7 Apr 2024 05:23:59 +0200 Subject: [PATCH] :sparkles: improved println :art: better global support :bug: string duplication with clone. --- .gitignore | 1 + lib/include/natives.h | 2 +- lib/include/nfun.h | 4 +-- lib/include/prog.h | 3 +- lib/include/state.h | 16 +++++++++- lib/include/sym.h | 4 ++- lib/src/compiler.c | 10 ++----- lib/src/exec.c | 22 ++++++++++++-- lib/src/fun.c | 2 +- lib/src/natives.c | 23 ++++++++++----- lib/src/nfun.c | 4 +-- lib/src/parser.c | 18 +++++++----- lib/src/state.c | 68 +++++++++++++++++++++++++++++++++++-------- lib/src/sym.c | 16 +++++----- lib/src/value.c | 2 +- 15 files changed, 140 insertions(+), 55 deletions(-) diff --git a/.gitignore b/.gitignore index 1e46243..600228e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ *\#* build .cache +vgcore* diff --git a/lib/include/natives.h b/lib/include/natives.h index a6d9379..f4050c9 100644 --- a/lib/include/natives.h +++ b/lib/include/natives.h @@ -10,7 +10,7 @@ void natives_decl(struct state* state, struct sym* sym, char* name, nfun_body fun, - size_t arity); + int arity); SK native_println(struct state* state, struct vec* args); diff --git a/lib/include/nfun.h b/lib/include/nfun.h index a313fca..915a1cd 100644 --- a/lib/include/nfun.h +++ b/lib/include/nfun.h @@ -9,10 +9,10 @@ typedef SK (*nfun_body)(struct state*, struct vec*); struct nfun { nfun_body body; - size_t arity; + int arity; }; -void nfun_init(struct nfun* self, nfun_body body, size_t arity); +void nfun_init(struct nfun* self, nfun_body body, int arity); void nfun_free(struct nfun* self); SK nfun_call(struct nfun* self, diff --git a/lib/include/prog.h b/lib/include/prog.h index 1743686..3eb2372 100644 --- a/lib/include/prog.h +++ b/lib/include/prog.h @@ -14,7 +14,8 @@ G(OP_NOT), G(OP_AND), G(OP_OR), \ G(OP_BR), G(OP_BRF), G(OP_LT), G(OP_GT), \ G(OP_EQUAL), G(OP_LOCAL_STORE), G(OP_LOCAL_LOAD), \ G(OP_CALL), G(OP_RET), G(OP_MAKE_REF), \ -G(OP_CLOSURE_LOAD), G(OP_CLOSURE_STORE) +G(OP_CLOSURE_LOAD), G(OP_CLOSURE_STORE), \ +G(OP_GLOBAL_LOAD) SK_ENUM_H(Opcode, OPCODE); diff --git a/lib/include/state.h b/lib/include/state.h index 7db78a3..bb22b4c 100644 --- a/lib/include/state.h +++ b/lib/include/state.h @@ -26,11 +26,19 @@ struct frame struct fun* fun; }; +struct global +{ + int id; + size_t addr; +}; + struct state { struct vec frames; size_t addr; + int global_id; struct vec globals; + struct vec global_values; }; typedef SK (*nfun_body)(struct state*, struct vec*); @@ -83,6 +91,9 @@ void state_closure_store(struct state* self, void state_local_load(struct state* self, int id); +void state_global_load(struct state* self, + int id); + void state_closure_load(struct state* self, int id); @@ -107,9 +118,12 @@ SK state_lt(struct state* self); SK state_gt(struct state* self); SK state_eq(struct state* self); +int state_add_global(struct state* self, + struct value* value); + 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); + int arity); #endif diff --git a/lib/include/sym.h b/lib/include/sym.h index b387ce6..5d0826b 100644 --- a/lib/include/sym.h +++ b/lib/include/sym.h @@ -12,6 +12,7 @@ struct symbol int native_id; char* name; bool is_const; + bool is_global; struct env* env; }; @@ -26,6 +27,7 @@ struct sym int id_counter; int closure_counter; int native_counter; + int global_counter; struct env* env; }; @@ -49,7 +51,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); +int sym_decl_global(struct sym* self, int id, char const* name); void sym_open_scope(struct sym* self); void sym_close_scope(struct sym* self); diff --git a/lib/src/compiler.c b/lib/src/compiler.c index 38f6c7a..92e78e5 100644 --- a/lib/src/compiler.c +++ b/lib/src/compiler.c @@ -189,14 +189,9 @@ void compiler_compile(struct compiler* self, itr = itr->parent; } - if (symbol->native_id != SK_NO_NATIVE) + if (symbol->is_global) { - 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); + prog_add_instr(prog, OP_GLOBAL_LOAD, symbol->id); } else if (symbol->closure_id != SK_NO_CLOSURE) { @@ -265,6 +260,7 @@ void compiler_compile(struct compiler* self, } } } + compiler_compile(self, body, p, fun->sym, state); union val val; diff --git a/lib/src/exec.c b/lib/src/exec.c index fe71ffc..8f73362 100644 --- a/lib/src/exec.c +++ b/lib/src/exec.c @@ -40,6 +40,11 @@ void exec_execute(struct exec* self, self->pc++; } break; + case OP_GLOBAL_LOAD: { + state_global_load(state, param); + self->pc++; + } break; + case OP_LOCAL_LOAD: { state_local_load(state, param); self->pc++; @@ -98,6 +103,7 @@ void exec_execute(struct exec* self, vec_init(&pvalues); SK function = state_pop(state); + for (size_t i=0; ival.ref ); + assert(val_fun); + if (val_fun->type == TYPE_NATIVE_FUN) { + struct vec ordered; + vec_init(&ordered); + for (size_t i=0; ival.nfun, state, - &pvalues); + &ordered); struct value* value = state_try_get_value(state, res); state_push( @@ -127,8 +143,10 @@ void exec_execute(struct exec* self, ); vec_free(&pvalues); - vec_free_elements(¶ms, NULL); + vec_free(&ordered); + vec_free_elements(¶ms, (void*) value_free); vec_free(¶ms); + value_free(f); free(f); self->pc++; break; diff --git a/lib/src/fun.c b/lib/src/fun.c index 91a8066..6648cf8 100644 --- a/lib/src/fun.c +++ b/lib/src/fun.c @@ -83,7 +83,7 @@ struct closure* fun_try_get_closure(struct fun* self, int id) for (size_t i=0; iclosures.size; i++) { struct closure* c = self->closures.data[i]; - + if (c->id == id) { return c; diff --git a/lib/src/natives.c b/lib/src/natives.c index d141078..d5101ec 100644 --- a/lib/src/natives.c +++ b/lib/src/natives.c @@ -5,26 +5,35 @@ void natives_populate(struct state* state, struct sym* sym) assert(state); assert(sym); - natives_decl(state, sym, "println", native_println, 1); + 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) + int arity) { assert(state); assert(sym); - int addr = state_add_nfun(state, fun, arity); - sym_decl_native(sym, name, addr); + sym_decl_global(sym, state->global_id, name); + state_add_nfun(state, fun, arity); } SK native_println(struct state* state, struct vec* args) { - struct value* arg - = state_try_get_value(state, (SK) args->data[0]); + for (size_t i=0; isize; i++) + { + struct value* arg + = state_try_get_value(state, (SK) args->data[i]); - printf("%s\n", arg->val.str); + struct str str; + str_init(&str); + value_str(arg, &str); + if (i > 0) { printf(" "); } + printf("%s", str.value); + str_free(&str); + } + printf("\n"); return state_push_bool(state, true, 0); } diff --git a/lib/src/nfun.c b/lib/src/nfun.c index 1e69f27..9c3ed33 100644 --- a/lib/src/nfun.c +++ b/lib/src/nfun.c @@ -1,6 +1,6 @@ #include "nfun.h" -void nfun_init(struct nfun* self, nfun_body body, size_t arity) +void nfun_init(struct nfun* self, nfun_body body, int arity) { assert(self); self->body = body; @@ -24,7 +24,7 @@ SK nfun_call(struct nfun* self, line = state_line(state, (SK) args->data[0]); } - if (self->arity != args->size) + if (self->arity >= 0 && self->arity != (int) args->size) { errors_push(line, "wrong arity, expected %zu, got %zu.", diff --git a/lib/src/parser.c b/lib/src/parser.c index 1a7b170..e6a248e 100644 --- a/lib/src/parser.c +++ b/lib/src/parser.c @@ -92,17 +92,17 @@ struct node* parser_try_expr(struct parser* self) if (lexer_next_is(&self->lexer, TOKEN_RETURN)) { struct node* node = malloc(sizeof(struct node)); - node_init(node, NODE_RETURN, + node_init(node, NODE_RETURN, lexer_try_new_next(&self->lexer)); - + struct node* child = SK_TRY(parser_try_expr); - + if (!child) { node_free(node); free(node); return NULL; } - + node_push_new_child(node, child); return node; } @@ -162,11 +162,11 @@ struct node* parser_try_fun_decl(struct parser* self) free(fun); return NULL; } - + struct node* ident = malloc(sizeof(struct node)); - node_init(ident, NODE_IDENT, + node_init(ident, NODE_IDENT, lexer_try_new_next(&self->lexer)); - + if (!lexer_next_is(&self->lexer, TOKEN_OPAR)) { node_free(fun); free(fun); @@ -214,7 +214,6 @@ struct node* parser_try_block(struct parser* self) } struct token* tok = lexer_try_new_next(&self->lexer); - struct node* node = SK_TRY(parser_try_inner_block); if (!node) @@ -226,9 +225,12 @@ struct node* parser_try_block(struct parser* self) if (!lexer_next_is(&self->lexer, TOKEN_END)) { node_free(node); free(node); + token_free(tok); free(tok); return NULL; } + token_free(tok); + free(tok); lexer_consume_next(&self->lexer); return node; } diff --git a/lib/src/state.c b/lib/src/state.c index f735f73..e22f681 100644 --- a/lib/src/state.c +++ b/lib/src/state.c @@ -41,7 +41,9 @@ void state_init(struct state* self) assert(self); vec_init(&self->frames); self->addr = 1; + self->global_id = 1456; state_push_frame(self); + vec_init(&self->global_values); vec_init(&self->globals); } @@ -51,7 +53,10 @@ void state_free(struct state* self) vec_free_elements(&self->frames, (void*) frame_free); vec_free(&self->frames); - vec_free_elements(&self->globals, (void*) value_free); + vec_free_elements(&self->global_values, (void*) value_free); + vec_free(&self->global_values); + + vec_free_elements(&self->globals, NULL); vec_free(&self->globals); } @@ -61,25 +66,30 @@ SK state_make_ref(struct state* self) struct value* value = state_try_get_value(self, val); struct value* on_heap = value_new_clone(value); - vec_push(&self->globals, on_heap); - return state_push_ref( + size_t addr = state_add_global( self, - self->globals.size - 1, - on_heap->line + on_heap ); + + return state_push_ref(self, addr, value->line); } struct value* state_try_deref(struct state* self, size_t ref) { assert(self); - if (ref >= self->globals.size) + for (size_t i=0; iglobals.size; i++) { - return NULL; + struct global const* global = self->globals.data[i]; + + if (global->addr == ref) + { + return self->global_values.data[ref]; + } } - return self->globals.data[ref]; + return NULL; } struct frame* state_frame(struct state* self) @@ -302,7 +312,25 @@ void state_local_load(struct state* self, } } - fprintf(stderr, "cannot load %d\n", id); + fprintf(stderr, "cannot load local %d\n", id); + abort(); +} + +void state_global_load(struct state* self, + int id) +{ + for (size_t i=0; iglobals.size; i++) + { + struct global const* global = self->globals.data[i]; + + if (global->id == id) + { + state_push_ref(self, global->addr, 0); + return; + } + } + + fprintf(stderr, "cannot load global %d\n", id); abort(); } @@ -726,6 +754,23 @@ SK state_eq(struct state* self) ); } +int state_add_global(struct state* self, + struct value* value) +{ + assert(self); + + vec_push(&self->global_values, value); + size_t addr = self->global_values.size - 1; + struct global* global = malloc(sizeof(struct global)); + global->id = self->global_id; + self->global_id++; + global->addr = addr; + + vec_push(&self->globals, global); + + return addr; +} + void state_call(struct state* self, struct fun* fun) { assert(self); @@ -742,7 +787,7 @@ void state_ret(struct state* self) SK state_add_nfun(struct state* self, nfun_body body, - size_t arity) + int arity) { struct nfun* fun = malloc(sizeof(struct nfun)); nfun_init(fun, body, arity); @@ -753,6 +798,5 @@ SK state_add_nfun(struct state* self, 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; + return state_add_global(self, value); } diff --git a/lib/src/sym.c b/lib/src/sym.c index 4ff857c..af87085 100644 --- a/lib/src/sym.c +++ b/lib/src/sym.c @@ -71,6 +71,7 @@ void symbol_init(struct symbol* self, self->id = id; self->name = strdup(name); self->is_const = false; + self->is_global = false; self->closure_id = SK_NO_CLOSURE; self->native_id = SK_NO_NATIVE; self->env = env; @@ -88,6 +89,7 @@ void sym_init(struct sym* self) self->id_counter = 1; self->closure_counter = 1; self->native_counter = 1; + self->global_counter = 1; self->env = malloc(sizeof(struct env)); env_init(self->env); } @@ -145,7 +147,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; @@ -156,20 +158,16 @@ 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) +int sym_decl_global(struct sym* self, int id, char const* name) { 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; + symbol_init(symbol, id, name, self->env); + symbol->is_global = true; vec_push(&self->env->symbols, symbol); - - self->native_counter++; - return self->native_counter - 1; + return id; } - void sym_open_scope(struct sym* self) { assert(self); diff --git a/lib/src/value.c b/lib/src/value.c index 27e46ca..6f56c54 100644 --- a/lib/src/value.c +++ b/lib/src/value.c @@ -70,7 +70,7 @@ struct value* value_new_clone(struct value* self) } break; case TYPE_STRING: { - val.str = self->val.str; + val.str = strdup(self->val.str); value_init(clone, TYPE_STRING, val, self->line); return clone; } break;