implicit calling of functions on right side of | operator
authorcassowarii <cassowary@cassowary.me>
Fri, 10 Jul 2026 23:30:56 +0000 (16:30 -0700)
committercassowarii <cassowary@cassowary.me>
Fri, 10 Jul 2026 23:30:56 +0000 (16:30 -0700)
sample/project_euler/pe06.sa
src/compile/ir.c
src/parse/ast.h
src/parse/parser.c

index 6c32957..d003cb5 100644 (file)
@@ -11,11 +11,11 @@ def square num {
 }
 
 def sum_squares list {
-  list.map(square) | sum _
+  list.map(square) | sum
 }
 
 def square_sum list {
-  sum list | square _
+  sum list | square
 }
 
-list::iota 1, 101 | (square_sum _) - (sum_squares _) | println _
+list::iota 1, 101 | (square_sum _) - (sum_squares _) | println
index 5ab9b6c..ec21e3b 100644 (file)
@@ -1034,7 +1034,13 @@ static sbIrExpr *compile_ast_expr(hIrChunk ck, sbAst node, flag list_context) {
        * then use RHS as our value */
       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);
+      sbIrExpr *right = compile_ast_expr(ck, node->op.right, FALSE);
+      if (!node->op.right->has_us) {
+        /* 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))));
+      }
+      return right;
     } else {
       sbIrExpr *left = NULL, *right = NULL;
       if (node->op.left != NO_NODE) {
index 0c80e38..8ad0257 100644 (file)
@@ -78,6 +78,7 @@ typedef enum sbAstOp {
 } sbAstOp;
 
 typedef struct sbAstNode {
+  flag has_us : 1; /* has some child that is var name '_' */
   sbAstType type;
   union {
     hString str;
index 79898aa..3ee2ed6 100644 (file)
@@ -307,6 +307,7 @@ static sbAst unop_node(hParser pr, sbAstOp operation, sbAst child) {
     .op.type = operation,
     .op.left = child,
     .op.right = NO_NODE,
+    .has_us = child->has_us,
   };
   return new_node(pr, &n);
 }
@@ -317,6 +318,7 @@ static sbAst binop_node(hParser pr, sbAstOp operation, sbAst left, sbAst right)
     .op.type = operation,
     .op.left = left,
     .op.right = right,
+    .has_us = left->has_us || right->has_us,
   };
   return new_node(pr, &n);
 }
@@ -326,6 +328,7 @@ static sbAst seq_node(hParser pr, sbAstType type, sbAst left, sbAst right) {
     .type = type,
     .seq.left = left,
     .seq.right = right,
+    .has_us = left->has_us || right->has_us,
   };
   return new_node(pr, &n);
 }
@@ -336,6 +339,7 @@ static sbAst tri_node(hParser pr, sbAstType type, sbAst left, sbAst center, sbAs
     .tri.left = left,
     .tri.center = center,
     .tri.right = right,
+    .has_us = left->has_us || center->has_us || right->has_us,
   };
   return new_node(pr, &n);
 }
@@ -345,6 +349,7 @@ static sbAst wrap_node(hParser pr, sbAstType type, sbAst left) {
     .type = type,
     .seq.left = left,
     .seq.right = NO_NODE,
+    .has_us = left->has_us,
   };
   return new_node(pr, &n);
 }
@@ -361,9 +366,15 @@ static sbAst name_node(hParser pr, sbLexToken token) {
     PANIC("can't create name node with token of type %d", token.type);
   }
 
+  flag has_us = FALSE;
+  if (sbstrncmp(sbSymbol_name(token.symb), "_", 1) == 0) {
+    has_us = TRUE;
+  }
+
   sbAstNode n = (sbAstNode) {
     .type = AST_NODE_NAME,
     .symb = token.symb,
+    .has_us = has_us,
   };
   return new_node(pr, &n);
 }