E1 = NIL_EXPR;
} else {
/* TODO handle multival here */
- E1 = compile_ast_expr(ck, node->seq.left->seq.left, FALSE);
+ E1 = compile_ast_expr(ck, node->seq.left->seq.right, FALSE);
}
put_return(ck, E1);
break;
N1 = node->seq.left; /* things to bind to */
N2 = node->seq.right; /* values to assign */
while (N1 != NO_NODE && N2 != NO_NODE) {
- V1 = compile_ast_var(ck, N1->seq.left);
- E1 = compile_ast_expr(ck, N2->seq.left, TRUE);
+ V1 = compile_ast_var(ck, N1->seq.right);
+ E1 = compile_ast_expr(ck, N2->seq.right, TRUE);
put_assign(ck, V1, E1);
- N1 = N1->seq.right;
- N2 = N2->seq.right;
+ N1 = N1->seq.left;
+ N2 = N2->seq.left;
}
if (N1 != NO_NODE) {
sbIrExpr *list = IR_EMPTY_LIST;
sbIrExpr **place_here = &list;
while (considering != NO_NODE) {
- *place_here = expr_list(ck, compile_ast_expr(ck, considering->seq.left, TRUE));
+ /* we compile the list right-to-left so that it ends up being on the stack with
+ * the earliest elements closest to the top */
+ *place_here = expr_list(ck, compile_ast_expr(ck, considering->seq.right, TRUE));
place_here = &(*place_here)->list.next;
- considering = considering->seq.right;
+ considering = considering->seq.left;
}
return list;
}
usize pre_splat_count = 0;
while (considering != NO_NODE) {
/* bind list needs to be reversed, because we're going to bind to some stack
- * that was built bottom-to-top. so we build it in the reverse order from a
+ * that was built top-to-bottom. so we build it in the reverse order from a
* value list. */
- sbAst elem = considering->seq.left;
+ sbAst elem = considering->seq.right;
if (elem->type == AST_NODE_OP && elem->op.type == AST_OP_SPLAT) {
if (!was_splat) {
was_splat = TRUE;
pre_splat_count ++;
}
sbIrBindList *new_list = new_bind_list(
- ck, compile_ast_binding(ck, considering->seq.left, create_vars, type), pre_splat_count
+ ck, compile_ast_binding(ck, elem, create_vars, type), pre_splat_count
);
new_list->next = list;
list = new_list;
- considering = considering->seq.right;
+ considering = considering->seq.left;
}
return list;
if (argc->type != IT_INTEGER) {
CHECK("argc of send should be integer!");
}
- /* subtract 1 because the method name is itself a param */
- usize num_params = argc->integer - 1;
- hV *method_name_val = sbVm_peek(vm, num_params);
+ hV *method_name_val = sbVm_pop(vm);
if (method_name_val->type != IT_SYMBOL) {
/* TODO this may become not true */
PANIC("method name must be symbol!");
}
+ /* subtract 1 because the method name is itself a param */
+ usize num_params = argc->integer - 1;
hLibTable table_to_use = NULL;
switch(target->type) {
case IT_LIST:
sbLibTable g_float_methods;
static void to_string(hVm vm, hV *target, usize num_params) {
- sbVm_pop(vm); /* remove method name */
char stackbuf[1024];
char *buf = stackbuf;
usize length = snprintf(buf, 1024, "%g", target->float_val);
sbLibTable g_integer_methods;
static void to_string(hVm vm, hV *target, usize num_params) {
- sbVm_pop(vm); /* remove method name */
char stackbuf[1024];
char *buf = stackbuf;
usize length = sbInteger_snprint(buf, 1024, target->integer);
if (num_params != 0) {
PANIC("list#length takes no arguments!");
}
- sbVm_pop(vm); /* remove method name */
usize length;
sbList_get_value(list->list, &length);
sbVm_push_immediate(vm, &HVINT(length));
PANIC("list#push expects 1 argument!");
}
hV *to_append = sbVm_pop(vm);
- sbVm_pop(vm); /* remove method name */
sbList_append(list->list, to_append);
sbVm_push_immediate(vm, &HVNIL);
}
PANIC("list#reverse takes no arguments!");
}
/* TODO maybe mutate in place if no other refs */
- sbVm_pop(vm); /* remove method name */
usize length;
hV *elems = sbList_get_value(list->list, &length);
hList new_list = sbList_new(length);
join_with = TRUE;
delimiter = delimiter_v->string;
}
- sbVm_pop(vm); /* remove method name */
usize length;
hV *elems = sbList_get_value(list->list, &length);
hString joined = sbString_new("", 0);
sbVm_request_var_space(vm, 3);
hV *iterating_list = sbVm_pop(vm);
hV *loop_func = sbVm_pop(vm);
- sbVm_pop(vm); /* remove method name */
hV index = HVINT(0);
vm->fp->locals[0] = *iterating_list;
vm->fp->locals[1] = index;
sbVm_request_var_space(vm, 4);
hV *iterating_list = sbVm_pop(vm);
hV *map_func = sbVm_pop(vm);
- sbVm_pop(vm); /* remove method name */
usize length;
sbList_get_value(iterating_list->list, &length);
hV index = HVINT(0);
sbVm_request_var_space(vm, 4);
hV *iterating_list = sbVm_pop(vm);
hV *filter_func = sbVm_pop(vm);
- sbVm_pop(vm); /* remove method name */
usize length;
sbList_get_value(iterating_list->list, &length);
hV index = HVINT(0);
sbVm_request_var_space(vm, 3);
hV *iterating_list = sbVm_pop(vm);
hV *pred_func = sbVm_pop(vm);
- sbVm_pop(vm); /* remove method name */
hV index = HVINT(0);
vm->fp->locals[0] = *iterating_list;
sbVm_request_var_space(vm, 3);
hV *iterating_list = sbVm_pop(vm);
hV *pred_func = sbVm_pop(vm);
- sbVm_pop(vm); /* remove method name */
hV index = HVINT(0);
vm->fp->locals[0] = *iterating_list;
sbLibTable g_string_methods;
static void split(hVm vm, hV *target, usize num_params) {
- sbVm_pop(vm); /* remove method name */
usize length;
char scratch[8];
const char *buf = sbString_get_value(target->string, scratch, &length);
if (num_params != 0) {
PANIC("to_string takes no parameters");
}
- sbVm_pop(vm); /* remove method name */
/* to_string for a string just returns itself */
sbVm_push_immediate(vm, target);
static sbAst parse_expr(hParser pr, u8 min_precedence);
static sbAst parse_comma_exprs(hParser pr, sbAst after) {
sbAst result = NO_NODE;
- sbAst *put_here = &result;
sbAst expr;
if (after) {
- *put_here = seq_node(pr, AST_NODE_MULTIVAL, after, NO_NODE);
- put_here = &(*put_here)->seq.right;
+ result = after;
}
do {
if (expr == NO_NODE) break;
}
- *put_here = seq_node(pr, AST_NODE_MULTIVAL, expr, NO_NODE);
- put_here = &(*put_here)->seq.right;
+ /* we build up our linked list in 'reverse' order, with later elements
+ * closer to the root of the tree, because lists are passed on the stack
+ * with the first elements at the top, which means we want to evaluate
+ * the last ones first */
+ result = seq_node(pr, AST_NODE_MULTIVAL, result, expr);
} while (expect(pr, T_COMMA));
return result;
method_name = parse_name_as_sym(pr);
}
if (method_name == NO_NODE) return syntax_error(pr);
- sbAst params = NO_NODE;
+ rhs = seq_node(pr, AST_NODE_MULTIVAL, NO_NODE, method_name);
if (expect(pr, T_LPAREN)) {
- params = parse_comma_exprs(pr, NULL);
+ rhs = parse_comma_exprs(pr, rhs);
if (!expect(pr, T_RPAREN)) return syntax_error(pr);
}
ast_type = AST_NODE_METHODCALL;
/* (whatever)->x is rewritten as (*whatever).x */
lhs = unop_node(pr, AST_OP_DEREF, lhs);
}
- rhs = seq_node(pr, AST_NODE_MULTIVAL, method_name, params);
} else if (op.type == T_BACKSQUIGARROW) {
/* a <~ b, c, d can have multiple comma things on the right side */
if (!expect(pr, T_LPAREN)) return syntax_error(pr);
if (expr->type != AST_NODE_MULTIVAL) {
/* if we have an = with one thing on the left side,
* wrap it in a multival anyway for consistency */
- expr = seq_node(pr, AST_NODE_MULTIVAL, expr, NO_NODE);
+ expr = seq_node(pr, AST_NODE_MULTIVAL, NO_NODE, expr);
}
expr = seq_node(pr, AST_NODE_ASSIGN, expr, assigned_values);
}
CHECK("internal violation: LIST_GATHER should receive an integer on top of stack");
}
param = v->integer;
- count = param;
+ count = 0;
res = sbV_empty_list(param);
- while (count > 0) {
- /* list gets built from bottom up, because first thing pushed is lower
- * on the stack */
- w = peek_stack(vm, count - 1);
+ while (count < param) {
+ /* list gets built from top of stack down */
+ w = pop_stack(vm);
sbV_append(&res, w);
- count --;
+ count ++;
}
- npop_stack(vm, param);
push_stack_immediate(vm, &res);
break;
case BC_HASH_GATHER: