compile_expr(cm, stmt->assign.expr);
if (stmt->assign.var->is_upvalue) {
EMIT(BC_ST_UPVAL);
- } else if (stmt->assign.var->closed_over) {
- EMIT(BC_ST_IND);
} else {
EMIT(BC_ST_VAR);
}
* we don't actually check that it's a variable that the "..." is
* attached to, and we may fail in weird cases like "...2". but we
* need to restructure the BindList data structure. */
- if (elem->op.left->var->closed_over) {
- EMIT(BC_ST_IND);
- } else {
- EMIT(BC_ST_VAR);
- }
+ EMIT(BC_ST_VAR);
EARG(elem->op.left->var->slot_id);
if (list->pre_splat_count > 0) {
/* put pre splat count back if we need it, to bind the rest of
} else if (elem->type == IR_E_VAR) {
/* normal sequence, no splat (so far): top thing goes in this
* variable using ST_ARG */
- if (elem->var->closed_over) {
- EMIT(BC_ST_ARG_IND);
- } else {
- EMIT(BC_ST_ARG);
- }
+ EMIT(BC_ST_ARG);
EARG(elem->var->slot_id);
} else {
PANIC("bind todo!");
case IR_E_VAR:
if (expr->var->is_upvalue) {
EMIT(BC_LD_UPVAL);
- } else if (expr->var->closed_over) {
- EMIT(BC_LD_IND);
} else {
EMIT(BC_LD_VAR);
}
if (expr->func.bound.size > 0) {
BUFFER_ITER(expr->func.bound, sbIrVariable*, var) {
if ((*var)->is_upvalue) {
- /* the closure-generator expects a series of values
- * of type reference to close over. BC_LD_UPVAL normally
- * pushes whatever is *behind* the reference, which we
- * don't want. UPREF will push the reference value
- * itself from the closure so we can close over it
- * a second time */
+ /* BC_LD_UPREF: closed over variables are always on
+ * the heap, so all upval refs are rrefs */
EMIT(BC_LD_UPREF);
} else if ((*var)->closed_over) {
- /* note: BC_LD_REF here, not BC_LD_IND! this will push
- * the pointer value, not the variable itself, because
- * we want to put the pointer (well, the sbRef) inside
- * the closure, not the value */
- /* BC_LD_REF is actually almost the same as BC_LD_VAR,
- * except that if a variable hasn't been initialized
- * it will create a new reference to nil. (this is
- * necessary for mutually calling functions, who want to
- * close over each other before all of them have been
- * defined.) */
- EMIT(BC_LD_REF);
+ /* BC_LD_RREF: everything we are closing over from the
+ * current scope needs to move to the heap */
+ EMIT(BC_LD_RREF);
} else {
PANIC("cannot have a direct variable in closure!");
}
case AST_OP_NOT: EMIT(BC_OP_NOT); break;
case AST_OP_AND: EMIT(BC_OP_AND); break;
case AST_OP_OR: EMIT(BC_OP_OR); break;
- case AST_OP_INDEX: EMIT(BC_OP_INDEX); break;
+ case AST_OP_INDEX: EMIT(BC_OP_INDEXVAL); break;
case AST_OP_RANGEINDEX: EMIT(BC_OP_RANGEINDEX); break;
/* op range is currently only used in rangeindex; just pass them to it directly */
case AST_OP_RANGE: break;
set_key(t, key, value);
}
-hVal sbHash_find_value(hHash h, hVal *key) {
+hVal *sbHash_find_value(hHash h, hVal *key) {
hashtbl *t = find_tbl_for_handle(h);
usize index = find_index_by_key(t, key);
hVal *keys;
sbVar *values;
get_ptrs_for_tbl(t, &keys, &values);
if (keys[index].type == IT_NOTHING) {
- return HVNOTHING;
+ return NULL;
} else {
- return sbVar_get_value(&values[index]);
+ return sbVar_get_value_ptr(&values[index]);
}
}
hHash sbHash_create(usize initial_size);
-hVal *sbHash_find(hHash h, hVal *key);
+hVal *sbHash_find_value(hHash h, hVal *key);
+
+hVal sbHash_find_lvalue_ref(hHash h, hVal *key);
+
+hVal sbHash_find_rvalue_ref(hHash h, hVal *key);
void sbHash_insert(hHash h, hVal *key, hVal *value);
.string = sbString_new(text, length),
};
- hVal *result = sbHash_find(symbol_table, &symkey);
+ hVal *result = sbHash_find_value(symbol_table, &symkey);
if (result == NULL) {
/* add new symbol */
static void get_index(hVm vm, hVal *target, usize num_params) {
hVal *key = sbVm_pop(vm);
- hVal *result = sbHash_find(target->hash, key);
- if (result == IT_NOTHING) {
+ hVal *result = sbHash_find_value(target->hash, key);
+ if (result == NULL) {
sbVm_push_immediate(vm, &HVNIL);
} else {
sbVm_push(vm, result);
BC_LD_CONST, // push constants[index] to stack
BC_LD_CTX, // look up key in context object and push result
BC_LD_VAR, // push value onto stack from variable
- BC_LD_LREF, // push lvalue reference onto stack from variable
- BC_LD_RREF, // push rvalue reference onto stack from variable
+ BC_LD_LREF, // push lref to variable onto stack
+ BC_LD_RREF, // push rref to variable onto stack
BC_LD_UPVAL, // push value onto stack from closure
BC_LD_UPREF, // push pointer to closure value onto stack (to close over again)
BC_LD_BLK, // push reference to function onto stack
BC_OP_LE, // less than or equal to
BC_OP_AND, // logical and
BC_OP_OR, // logical or
- BC_OP_INDEX, // index [] or ::
+ BC_OP_INDEXVAL, // a[...]
+ BC_OP_INDEXLREF, // a[...] = ...
+ BC_OP_INDEXRREF, // &a[...]
BC_OP_RANGEINDEX, // index [a..b]
BC_ALLOC_VARS, // create space in rstack for local variables
BC_CLOSURE, // create closure from top elements of stack
v = peek_stack(vm, 0);
sbV_decr(v);
break;
- case BC_OP_INDEX:
- sbV_index(vm);
+ case BC_OP_INDEXVAL:
+ sbV_index_value(vm);
break;
case BC_OP_RANGEINDEX:
v = peek_stack(vm, 2);
hVal sbV_append(hVal *a, hVal *b);
-void sbV_index(hVm vm);
+void sbV_index_value(hVm vm);
hVal sbV_rangeindex(hVal *a, hVal *b, hVal *c);