From: cassowarii <2374677+cassowarii@users.noreply.github.com> Date: Mon, 20 Jul 2026 07:16:39 +0000 (-0700) Subject: fix a couple bugs w/ pointers + like half of index assignment X-Git-Url: https://www.git.cassowary.me/gitweb.cgi?a=commitdiff_plain;h=5d99ef2dbe499b1888ab02da52b279404dc042b2;p=sarabande.git fix a couple bugs w/ pointers + like half of index assignment --- diff --git a/src/compile/emit.c b/src/compile/emit.c index fb38ba6..2c61541 100644 --- a/src/compile/emit.c +++ b/src/compile/emit.c @@ -16,6 +16,8 @@ struct labelpos { void compile_chunk(sbVmCompiler *cm, sbIrChunk *chunk); void compile_stmt(sbVmCompiler *cm, sbIrStmt *stmt); void compile_expr(sbVmCompiler *cm, sbIrExpr *expr); +void compile_ref(sbVmCompiler *cm, sbIrExpr *expr, flag is_lref); +void compile_op(sbVmCompiler *cm, sbAstOp op); void sbEmit_compile_program(sbVmProgram *vp, sbIrProgram *ir, flag debugmode) { sbVmCompiler cm = sbVmCompiler_create(4096, 4096, debugmode); @@ -202,9 +204,21 @@ void compile_stmt(sbVmCompiler *cm, sbIrStmt *stmt) { compile_expr(cm, stmt->assign.where->op.left); /* this should leave us with a pointer to expr on top of stack */ EMIT(BC_REF_PUT); + } else if (stmt->assign.where->type == IR_E_OP && stmt->assign.where->op.type == AST_OP_INDEX) { + /* a[b] = whatever, a::b = whatever */ + /* there is an IMPLICIT DEREFERENCE that occurs here. op::refindex returns an LREF, + * then we assign through the reference we receive, i.e. + * a[b] = c + * really means + * *(a{op::refindex}(b)) = c + * The reason for this has to do with assigning through nested data structures. + * Doing it this way just makes the whole semantics feel more natural. It's similar + * to returning a reference from indexing in C++, I guess. */ + compile_ref(cm, stmt->assign.where->op.left, TRUE); /* thing we are indexing into */ + compile_expr(cm, stmt->assign.where->op.right); /* index we are using */ + EMIT(BC_OP_INDEXLREF); + EMIT(BC_REF_PUT); } else { - /* TODO: Now we can support stuff like index-assignment also if we want to. - * Probably do this next */ PANIC("This type of assignment operation is not supported!"); } break; @@ -345,13 +359,11 @@ void compile_bind_list(sbVmCompiler *cm, sbIrBindList *list) { } } -void compile_ref(sbVmCompiler *cm, sbIrExpr *expr); -void compile_op(sbVmCompiler *cm, sbAstOp op); void compile_expr(sbVmCompiler *cm, sbIrExpr *expr) { switch(expr->type) { case IR_E_OP: if (expr->op.type == AST_OP_REF) { - compile_ref(cm, expr->op.left); + compile_ref(cm, expr->op.left, FALSE); } else { compile_expr(cm, expr->op.left); if (expr->op.right) { @@ -442,18 +454,30 @@ void compile_expr(sbVmCompiler *cm, sbIrExpr *expr) { } } -/* compiling the left hand side of an assignment (that isn't straightforwardly - * a variable) to return some kind of reference */ -void compile_assign_left(sbVmCompiler *cm, sbIrExpr *expr) { -} - /* when we see an expression of the form '&expr', we have to * handle this specially depending on what 'expr' is (and sometimes - * we just aren't allowed to do it) */ -void compile_ref(sbVmCompiler *cm, sbIrExpr *expr) { + * we just aren't allowed to do it). this is also used for compiling + * certain indexing structures on the left side of assignment operators */ +void compile_ref(sbVmCompiler *cm, sbIrExpr *expr, flag is_lref) { if (expr->type == IR_E_VAR) { - EMIT(BC_LD_RREF); + if (expr->var->is_upvalue) { + EMIT(BC_LD_UPREF); + } else if (is_lref) { + EMIT(BC_LD_LREF); + } else { + EMIT(BC_LD_RREF); + } EARG(expr->var->slot_id); + } else if (expr->type == IR_E_OP && expr->op.type == AST_OP_INDEX) { + compile_ref(cm, expr->op.left, is_lref); /* thing we are indexing into */ + compile_expr(cm, expr->op.right); /* index we are using */ + if (is_lref) { + /* a[0] = ? / a::b = ? */ + EMIT(BC_OP_INDEXLREF); + } else { + /* &a[0] / &a::b */ + EMIT(BC_OP_INDEXRREF); + } } else { PANIC("cannot & non-variable-name! (todo)"); } diff --git a/src/vm/exec.c b/src/vm/exec.c index da484a4..abdeafc 100644 --- a/src/vm/exec.c +++ b/src/vm/exec.c @@ -3,6 +3,7 @@ #include "vm/operations.h" #include "data/list.h" #include "data/closure.h" +#include "data/symbol.h" #include "lib/lib.h" #include "lib/sentinel.h" @@ -137,10 +138,41 @@ void sbVm_print_stack(hVm vm) { /* --- */ +void print_val(hVal *p) { + if (p->type == IT_NIL) { + debug("nil"); + } else if (p->type == IT_BOOLEAN && p->boolean) { + debug("true"); + } else if (p->type == IT_BOOLEAN) { + debug("false"); + } else if (p->type == IT_REF) { + debug("&("); + print_val(sbVar_get_value_ptr(sbVar_deref(p))); + debug(")"); + } else if (p->type == IT_SYMBOL) { + debug(":%s", sbSymbol_name(p->symbol)); + } else if (p->type == IT_INTEGER) { + debug("%lld", (long long)p->integer); + } else if (p->type == IT_LIST) { + debug("[...]"); + } else if (p->type == IT_HASH) { + debug("{...}"); + } else if (p->type > 0 && (p->type & IT_FLAG_BOUND_METHOD)) { + debug("(bound method #%lld:%lld)", (long long)p->type, (long long)(p->closure & ~0x80000000000000)); + } else if (p->type > 0 && p->closure > 0) { + debug("(closure #%lld:%lld)", (long long)p->type, (long long)(p->closure & ~0x8000000000000000)); + } else if (p->type > 0) { + debug("(block #%lld)", (long long)p->type); + } else { + debug("%16llx %16llx", (long long)p->type, (long long)p->data); + } +} + void print_stack(hVm vm) { debug("Stack: "); for (hVal *p = (hVal*)vm->vstack; p < (hVal*)vm->vsp; p++) { - debug("%16llx %16llx ", (long long)p->type, (long long)p->data); + print_val(p); + debug(" "); } debug("\n"); }