From: cassowarii <2374677+cassowarii@users.noreply.github.com> Date: Sat, 11 Jul 2026 05:19:29 +0000 (-0700) Subject: block pipe in situations where it is buggy for now. how to fix? X-Git-Url: https://www.git.cassowary.me/gitweb.cgi?a=commitdiff_plain;h=8abc89f12abd567e4fd80b3b9549c96e29328bcb;p=sarabande.git block pipe in situations where it is buggy for now. how to fix? --- diff --git a/sample/project_euler/pe06.sa b/sample/project_euler/pe06.sa index 3587fe3..51aad0e 100644 --- a/sample/project_euler/pe06.sa +++ b/sample/project_euler/pe06.sa @@ -15,11 +15,11 @@ def map f { } def sum_squares list { - list | (square | map) | sum + list.map(square) | sum } def square_sum list { list | sum | square } -...[1, 101] | list::iota | (square_sum _) - (sum_squares _) | println +list::iota 1, 101 | (square_sum _) - (sum_squares _) | println diff --git a/src/compile/analyze.c b/src/compile/analyze.c new file mode 100644 index 0000000..09a734f --- /dev/null +++ b/src/compile/analyze.c @@ -0,0 +1,61 @@ +#include "compile/analyze.h" + +#include "parse/ast.h" +#include "data/symbol.h" + +i32 sbAst_count_pipe_underscores(sbAst node) { + if (node == NULL) return 0; + + switch (node->type) { + case AST_NULL: + /* like the end of a list or whatever */ + return 0; + case AST_NODE_NAME: + if (sbstrncmp(sbSymbol_name(node->symb), "_", 1) == 0) { + return 1; + } else { + return 0; + } + case AST_NODE_SEQ: + case AST_NODE_NEXT: + case AST_NODE_MULTIVAL: + case AST_NODE_FUNCCALL: + case AST_VAL_FUNC: + case AST_VAL_IMFUNC: + case AST_VAL_OBJ: + case AST_NODE_HASHENTRY: + return sbAst_count_pipe_underscores(node->seq.left) + + sbAst_count_pipe_underscores(node->seq.right); + case AST_NODE_OP: + if (node->op.type == AST_OP_PIPE) { + /* for a pipe, underscores on the right side don't count + * towards this, because they refer to the result of whatever + * is on the left side. but underscores on the left side do + * refer to what we're binding, so they do count */ + return sbAst_count_pipe_underscores(node->op.left); + } else { + return sbAst_count_pipe_underscores(node->op.left); + + sbAst_count_pipe_underscores(node->op.right); + } + case AST_NODE_ASSIGN: + case AST_NODE_LET: + /* for declarations and assignments, we only count the expressions + * on the right, not the things on the left (this might happen if we + * have a pipe into a function literal that contains statements etc) */ + return sbAst_count_pipe_underscores(node->op.right); + case AST_VAL_LIST: + case AST_VAL_HASH: + /* check the things inside the whatever */ + return sbAst_count_pipe_underscores(node->op.left); + case AST_VAL_NIL: + case AST_VAL_INT: + case AST_VAL_STRING: + case AST_VAL_FLOAT: + case AST_VAL_SYMBOL: + case AST_VAL_BOOLEAN: + /* these are not the name "_" */ + return 0; + default: + PANIC("aah! (%lld)", (long long)node->type); + } +} diff --git a/src/compile/analyze.h b/src/compile/analyze.h new file mode 100644 index 0000000..6978779 --- /dev/null +++ b/src/compile/analyze.h @@ -0,0 +1,4 @@ +#include "common.h" + +struct sbAstNode; +i32 sbAst_count_pipe_underscores(struct sbAstNode *node); diff --git a/src/compile/ir.c b/src/compile/ir.c index 6ee0b51..31e96a8 100644 --- a/src/compile/ir.c +++ b/src/compile/ir.c @@ -1,5 +1,6 @@ #include "compile/ir.h" +#include "compile/analyze.h" #include "parse/ast.h" #include "data/symbol.h" #include "data/integer.h" @@ -1032,15 +1033,22 @@ 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 */ - if (node->op.right->has_us) { + i32 num_bindings = sbAst_count_pipe_underscores(node->op.right); + if (num_bindings > 0) { /* 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... */ + if (ck->pipe_var_in_use || list_context) { + PANIC("Pipe cannot currently be used in this context. I will fix it"); + } 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); + ck->pipe_var_in_use = TRUE; + sbIrExpr *right = compile_ast_expr(ck, node->op.right, FALSE); + ck->pipe_var_in_use = FALSE; + return right; } 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. this @@ -1048,8 +1056,11 @@ static sbIrExpr *compile_ast_expr(hIrChunk ck, sbAst node, flag list_context) { 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))); + /* parameter list (true = the left thing can be a splat, because it does work, + * but you can't have commas. but you can do ...[x, y, z] | stuff) */ + //expr_list(ck, compile_ast_expr(ck, node->op.left, TRUE))); + // ok currently you can't. but we will + expr_list(ck, compile_ast_expr(ck, node->op.left, FALSE))); } } else { sbIrExpr *left = NULL, *right = NULL; diff --git a/src/compile/ir.h b/src/compile/ir.h index d1a378c..21a3cde 100644 --- a/src/compile/ir.h +++ b/src/compile/ir.h @@ -142,6 +142,7 @@ struct sbIrProgram; typedef struct sbIrChunk { struct sbIrProgram *program; + flag pipe_var_in_use : 1; i32 id; i16 num_args; i16 num_upvalues;