From e9c4d48cf9289fe64f423edf87bfde6873aa0590 Mon Sep 17 00:00:00 2001 From: ProgramSnail Date: Thu, 7 Nov 2024 00:56:21 +0300 Subject: [PATCH] closure fix --- byterun/include/stack.h | 1 + byterun/src/interpreter.c | 7 ++++--- byterun/src/stack.c | 26 ++++++++++++++++++-------- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/byterun/include/stack.h b/byterun/include/stack.h index c63ef6e3c..e03e8badb 100644 --- a/byterun/include/stack.h +++ b/byterun/include/stack.h @@ -9,6 +9,7 @@ void **s_top(struct State *s); bool s_is_empty(struct State *s); +void **s_nth(struct State *s, aint n); void **s_peek(struct State *s); aint *s_peek_i(struct State *s); diff --git a/byterun/src/interpreter.c b/byterun/src/interpreter.c index c961aa3ec..039b62790 100644 --- a/byterun/src/interpreter.c +++ b/byterun/src/interpreter.c @@ -283,15 +283,16 @@ void run(bytefile *bf) { break; } - case 5: // CALLC %d // call clojure - ip_read_int(&s.ip); // args count + case 5: { // CALLC %d // call clojure + aint args_count = ip_read_int(&s.ip); // args count call_happened = true; s.is_closure_call = true; s.call_ip = s.ip; - s.ip = Belem(s.sp, BOX(0)); // use offset instead ?? + s.ip = Belem(*s_nth(&s, args_count), BOX(0)); // use offset instead ?? break; + } case 6: { // CALL 0x%.8x %d // call function int call_p = ip_read_int(&s.ip); diff --git a/byterun/src/stack.c b/byterun/src/stack.c index bf428ed91..19ca47e3b 100644 --- a/byterun/src/stack.c +++ b/byterun/src/stack.c @@ -45,6 +45,20 @@ bool s_is_empty(struct State* s) { return false; } +void **s_nth(struct State *s, aint n) { + if (n < 0) { + failure("can't access stack by negative index"); + } + if (s->sp + n >= s_top(s)) { + failure("not enough elements in stack"); + } + if (s->fp != NULL && s->sp + n >= f_locals(s->fp)) { + failure("not enough elements in function stack"); + } + + return s->sp + n; +} + void** s_peek(struct State* s) { if (s->sp == s_top(s)) { failure("empty stack"); @@ -115,21 +129,17 @@ void s_enter_f(struct State *s, char *rp, bool is_closure_call, auint args_sz, a printf("-> %i locals sz\n", locals_sz); // check that params count is valid - if (s->sp + (aint)args_sz - 1 >= s_top(s)) { + if (s->sp + (aint)args_sz - (is_closure_call ? 0 : 1) >= s_top(s)) { failure("not enough parameters in stack"); } - if (s->fp != NULL && s->sp + (aint)args_sz - 1 >= f_locals(s->fp)) { + if (s->fp != NULL && s->sp + (aint)args_sz - (is_closure_call ? 0 : 1) >= f_locals(s->fp)) { failure("not enough parameters in function stack"); } - if (!is_closure_call) { - s_push_nil(s); - } - - void* closure = s_peek(s); + void* closure = is_closure_call ? s_nth(s, args_sz) : NULL; // s_push_nil(s); // sp contains value, frame starts with next value - s_pushn_nil(s, frame_sz() - 1); + s_pushn_nil(s, frame_sz()); // create frame struct Frame frame = {