From: cassowarii Date: Sat, 11 Jul 2026 00:19:53 +0000 (-0700) Subject: fix list-spill, also make pipe a bit more elegant X-Git-Url: https://git.cassowary.me/gitweb.cgi?a=commitdiff_plain;h=1446f1652bcefff55d6d92dd9ca5f6bd5b3d3333;p=sarabande.git fix list-spill, also make pipe a bit more elegant --- diff --git a/sample/project_euler/pe06.sa b/sample/project_euler/pe06.sa index d003cb5..3587fe3 100644 --- a/sample/project_euler/pe06.sa +++ b/sample/project_euler/pe06.sa @@ -10,12 +10,16 @@ def square num { num * num } +def map f { + => l { l.map(f) } +} + def sum_squares list { - list.map(square) | sum + list | (square | map) | sum } def square_sum list { - sum list | square + list | sum | square } -list::iota 1, 101 | (square_sum _) - (sum_squares _) | println +...[1, 101] | list::iota | (square_sum _) - (sum_squares _) | println diff --git a/src/compile/ir.c b/src/compile/ir.c index ec21e3b..6ee0b51 100644 --- a/src/compile/ir.c +++ b/src/compile/ir.c @@ -1032,15 +1032,25 @@ static sbIrExpr *compile_ast_expr(hIrChunk ck, sbAst node, flag list_context) { } else if (node->op.type == AST_OP_PIPE) { /* assign LHS to our temporary secret pipe variable, * then use RHS as our value */ - sbIrExpr *left = compile_ast_expr(ck, node->op.left, FALSE); - put_assign(ck, pipe_var(ck), left); - sbIrExpr *right = compile_ast_expr(ck, node->op.right, FALSE); - if (!node->op.right->has_us) { + if (node->op.right->has_us) { + /* TODO: I realized this doesn't really make sense if we nest | within (). + * like, a | (b | c _) _ won't work properly. so really we need a whole + * stack of these temporary variables potentially... maybe we need to save + * the current pipe var here and restore it again after? also, whither + * something like a(b | c, d | e)? oh god... */ + sbIrExpr *left = compile_ast_expr(ck, node->op.left, FALSE); + put_assign(ck, pipe_var(ck), left); + return compile_ast_expr(ck, node->op.right, FALSE); + } else { /* if there is no _ to the right of the "|", assume it is a function - * call that we are passing the left side to as a singular argument */ - right = expr_call(ck, right, expr_list(ck, expr_var(ck, pipe_var(ck)))); + * call that we are passing the left side to as a singular argument. this + * means we don't actually need a temporary variable*/ + return expr_call(ck, + /* thing to call */ + compile_ast_expr(ck, node->op.right, FALSE), + /* parameter list (weirdly i guess the left thing could be a splat) */ + expr_list(ck, compile_ast_expr(ck, node->op.left, TRUE))); } - return right; } else { sbIrExpr *left = NULL, *right = NULL; if (node->op.left != NO_NODE) { diff --git a/src/parse/parser.c b/src/parse/parser.c index 3ee2ed6..bc47632 100644 --- a/src/parse/parser.c +++ b/src/parse/parser.c @@ -178,6 +178,7 @@ static unop unops[] = { { T_MINUS, 85, AST_OP_UNMINUS }, { T_AMPERSAND, 85, AST_OP_REF }, { T_ASTERISK, 85, AST_OP_DEREF }, + { T_ELLIPSIS, 85, AST_OP_SPLAT }, }; static const usize NUM_BINOPS = sizeof(binops) / sizeof(binops[0]); diff --git a/src/vm/exec.c b/src/vm/exec.c index fd8d407..bc2a549 100644 --- a/src/vm/exec.c +++ b/src/vm/exec.c @@ -694,8 +694,9 @@ void execute_instruction(hVm vm) { CHECK("internal violation: LIST_SPILL should receive an integer on top of stack"); } x = sbList_get_value(v->list, &count); - for (usize i = 0; i < count; i++) { + for (usize i = count - 1; ; i--) { push_stack(vm, &x[i]); + if (i == 0) break; } res.integer += count; push_stack_immediate(vm, &res);