From: cassowarii <2374677+cassowarii@users.noreply.github.com> Date: Fri, 10 Jul 2026 15:59:36 +0000 (-0700) Subject: flip calling convention: evaluate right to left X-Git-Url: https://www.git.cassowary.me/gitweb.cgi?a=commitdiff_plain;h=04adada269d09b5b4f321909bcb940e35705ab15;p=sarabande.git flip calling convention: evaluate right to left --- diff --git a/src/compile/ir.c b/src/compile/ir.c index 4503cd3..3e214be 100644 --- a/src/compile/ir.c +++ b/src/compile/ir.c @@ -686,7 +686,7 @@ static void compile_ast_stmt(hIrChunk ck, sbAst node, flag implicit_return) { 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; @@ -732,11 +732,11 @@ static void compile_ast_stmt(hIrChunk ck, sbAst node, flag implicit_return) { 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) { @@ -872,9 +872,11 @@ static sbIrExpr *compile_ast_list(hIrChunk ck, sbAst 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; } @@ -937,9 +939,9 @@ static sbIrBindList *compile_ast_bind_list(hIrChunk ck, sbAst node, flag create_ 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; @@ -954,11 +956,11 @@ static sbIrBindList *compile_ast_bind_list(hIrChunk ck, sbAst node, flag create_ 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; diff --git a/src/lib/lib.c b/src/lib/lib.c index edd339f..9c919ec 100644 --- a/src/lib/lib.c +++ b/src/lib/lib.c @@ -30,14 +30,14 @@ void sbLib_resolve_method(hVm vm) { 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: diff --git a/src/lib/method/float.c b/src/lib/method/float.c index 5372808..9accacb 100644 --- a/src/lib/method/float.c +++ b/src/lib/method/float.c @@ -8,7 +8,6 @@ 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); diff --git a/src/lib/method/integer.c b/src/lib/method/integer.c index f9598e8..bb9d9e1 100644 --- a/src/lib/method/integer.c +++ b/src/lib/method/integer.c @@ -9,7 +9,6 @@ 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); diff --git a/src/lib/method/list.c b/src/lib/method/list.c index 0fbc761..839a87a 100644 --- a/src/lib/method/list.c +++ b/src/lib/method/list.c @@ -17,7 +17,6 @@ static void length(hVm vm, hV *list, usize num_params) { 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)); @@ -28,7 +27,6 @@ static void push(hVm vm, hV *list, usize num_params) { 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); } @@ -38,7 +36,6 @@ static void reverse(hVm vm, hV *list, usize num_params) { 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); @@ -64,7 +61,6 @@ static void join(hVm vm, hV *list, usize num_params) { 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); @@ -141,7 +137,6 @@ sbCFuncStatus list_each_cfunc(hVm vm, flag init) { 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; @@ -172,7 +167,6 @@ sbCFuncStatus list_map_cfunc(hVm vm, flag init) { 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); @@ -209,7 +203,6 @@ sbCFuncStatus list_filter_cfunc(hVm vm, flag init) { 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); @@ -251,7 +244,6 @@ sbCFuncStatus list_any_cfunc(hVm vm, flag init) { 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; @@ -290,7 +282,6 @@ sbCFuncStatus list_all_cfunc(hVm vm, flag init) { 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; diff --git a/src/lib/method/string.c b/src/lib/method/string.c index 5fc1125..1e9e966 100644 --- a/src/lib/method/string.c +++ b/src/lib/method/string.c @@ -14,7 +14,6 @@ void list_all_cfunc(hVm vm, flag init); 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); @@ -29,7 +28,6 @@ static void to_string(hVm vm, hV *target, usize num_params) { 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); diff --git a/src/parse/parser.c b/src/parse/parser.c index 082bdac..b255e5a 100644 --- a/src/parse/parser.c +++ b/src/parse/parser.c @@ -383,12 +383,10 @@ static sbAst id_sym_node(hParser pr, sbLexToken token) { 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 { @@ -408,8 +406,11 @@ static sbAst parse_comma_exprs(hParser pr, sbAst after) { 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; @@ -611,9 +612,9 @@ static sbAst parse_expr(hParser pr, u8 min_precedence) { 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; @@ -621,7 +622,6 @@ static sbAst parse_expr(hParser pr, u8 min_precedence) { /* (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); @@ -823,7 +823,7 @@ static sbAst parse_stmt(hParser 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); } diff --git a/src/vm/exec.c b/src/vm/exec.c index f6ec602..1e8ecb2 100644 --- a/src/vm/exec.c +++ b/src/vm/exec.c @@ -644,16 +644,14 @@ void execute_instruction(hVm vm) { 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: