From 645f16115c30a02a2089a63113aa97c862b740ad Mon Sep 17 00:00:00 2001 From: "L. Pereira" Date: Tue, 28 Jan 2025 09:04:47 -0800 Subject: [PATCH] Fix @/! when stack is empty Both loading from the memory (@) and storing (!) require popping the address from the stack. If it's empty, POP_D() will yield NaN -- making the conversion to int32_t yield an out-of-bounds value. Handle this condition. This also gets rid of the STORE() and LOAD() macro, that were only used inside one function each. --- src/samples/forthsalon/forth.c | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/src/samples/forthsalon/forth.c b/src/samples/forthsalon/forth.c index 13c7cbcce..5ea7a1863 100644 --- a/src/samples/forthsalon/forth.c +++ b/src/samples/forthsalon/forth.c @@ -84,7 +84,7 @@ struct forth_ctx { size_t pos; } r_stack, d_stack; - double memory[64]; + double memory[16]; bool is_inside_word_def; }; @@ -126,20 +126,6 @@ struct forth_vars { } \ v; \ }) -#define LOAD(addr_) \ - ({ \ - size_t v = (size_t)(int32_t)(addr_); \ - if (v > N_ELEMENTS(ctx->memory)) \ - return false; \ - ctx->memory[v]; \ - }) -#define STORE(addr_, value_) \ - ({ \ - size_t v = (size_t)(int32_t)(addr_); \ - if (v > N_ELEMENTS(ctx->memory)) \ - return false; \ - ctx->memory[v] = (value_); \ - }) #if DUMP_CODE static void dump_code(const struct forth_code *code) @@ -662,16 +648,20 @@ BUILTIN("r@") BUILTIN("@") { - double slot = POP_D(); - PUSH_D(LOAD(slot)); + int32_t slot = (int32_t)POP_D(); + if (UNLIKELY(slot < 0)) + return false; + PUSH_D(ctx->memory[slot % (int32_t)N_ELEMENTS(ctx->memory)]); return true; } BUILTIN("!") { - double v1 = POP_D(); - double v2 = POP_D(); - STORE(v2, v1); + double v = POP_D(); + int32_t slot = (int32_t)POP_D(); + if (UNLIKELY(slot < 0)) + return false; + ctx->memory[slot % (int32_t)N_ELEMENTS(ctx->memory)] = v; return true; }