]> granicus.if.org Git - jq/commitdiff
Add `def f($arg):` syntax (fix #524)
authorNicolas Williams <nico@cryptonector.com>
Fri, 8 Aug 2014 23:00:47 +0000 (18:00 -0500)
committerNicolas Williams <nico@cryptonector.com>
Sat, 9 Aug 2014 00:16:01 +0000 (19:16 -0500)
compile.c
compile.h
docs/content/3.manual/manual.yml
opcode_list.h
parser.y
tests/all.test

index cc5a8d0925f2ad79ec698bc2f6701ede58d81a7b..92c7d2c5d1fed70fba8d603815400b4e3f090ca1 100644 (file)
--- a/compile.c
+++ b/compile.c
@@ -451,8 +451,14 @@ block gen_import(const char* name, const char* as, const char* search) {
 }
 
 block gen_function(const char* name, block formals, block body) {
-  block_bind_each(formals, body, OP_IS_CALL_PSEUDO);
   inst* i = inst_new(CLOSURE_CREATE);
+  for (inst* i = formals.last; i; i = i->prev) {
+    if (i->op == CLOSURE_PARAM_REGULAR) {
+      i->op = CLOSURE_PARAM;
+      body = gen_var_binding(gen_call(i->symbol, gen_noop()), i->symbol, body);
+    }
+    block_bind_subblock(inst_block(i), body, OP_IS_CALL_PSEUDO | OP_HAS_BINDING);
+  }
   i->subfn = body;
   i->symbol = strdup(name);
   i->arglist = formals;
@@ -461,6 +467,10 @@ block gen_function(const char* name, block formals, block body) {
   return b;
 }
 
+block gen_param_regular(const char* name) {
+  return gen_op_unbound(CLOSURE_PARAM_REGULAR, name);
+}
+
 block gen_param(const char* name) {
   return gen_op_unbound(CLOSURE_PARAM, name);
 }
index a487c14c06aeb16937a5f16428130cb6ff7bd702..ff8b8972cb97c92d40d3c38eea595c2af8b0f84d 100644 (file)
--- a/compile.h
+++ b/compile.h
@@ -30,6 +30,7 @@ block gen_op_var_fresh(opcode op, const char* name);
 
 block gen_import(const char* name, const char *as, const char *search);
 block gen_function(const char* name, block formals, block body);
+block gen_param_regular(const char* name);
 block gen_param(const char* name);
 block gen_lambda(block body);
 block gen_call(const char* name, block body);
index bd3c82bb78b6abd66c629c3df1d0920da54eba79..c9e3ce093ce472fa87f88e5bed62e9f555d87492 100644 (file)
@@ -1931,9 +1931,13 @@ sections:
           If you want the value-argument behaviour for defining simple
           functions, you can just use a variable:
 
-              def addvalue(f): f as $value | map(. + $value);
+              def addvalue(f): f as $f | map(. + $f);
 
-          With that definition, `addvalue(.foo)` will add the current
+          Or use the short-hand:
+
+              def addvalue($f): ...;
+
+          With either definition, `addvalue(.foo)` will add the current
           input's `.foo` field to each element of the array.
 
           Multiple definitions using the same function name are allowed.
index 5ecf57e372979c5e13d3868f9180f0a84f41347d..119a70d32e8e61cce300a31d3954a024d62ec948 100644 (file)
@@ -36,4 +36,5 @@ OP(CLOSURE_CREATE, DEFINITION, 0, 0)
 OP(CLOSURE_CREATE_C, DEFINITION, 0, 0)
 
 OP(TOP, NONE, 0, 0)
+OP(CLOSURE_PARAM_REGULAR, DEFINITION, 0, 0)
 OP(DEPS, CONSTANT, 0, 0)
index 7117b4ca3c317d3b934b779d0e2ca31e3af196a5..1246483dd79294fbd2112ba5db4889b30dcbb03a 100644 (file)
--- a/parser.y
+++ b/parser.y
@@ -102,7 +102,7 @@ struct lexer_param;
 %precedence "catch"
 
 
-%type <blk> Exp Term MkDict MkDictPair ExpD ElseBody QQString FuncDef FuncDefs String Import Imports
+%type <blk> Exp Term MkDict MkDictPair ExpD ElseBody QQString FuncDef FuncDefs String Import Imports Param Params
 %{
 #include "lexer.h"
 struct lexer_param {
@@ -471,82 +471,28 @@ FuncDef:
   jv_free($2);
 } |
 
-"def" IDENT '(' IDENT ')' ':' Exp ';' {
-  $$ = gen_function(jv_string_value($2), 
-                    gen_param(jv_string_value($4)), 
-                    $7);
+"def" IDENT '(' Params ')' ':' Exp ';' {
+  $$ = gen_function(jv_string_value($2), $4, $7);
   jv_free($2);
-  jv_free($4);
-} |
+}
 
-"def" IDENT '(' IDENT ';' IDENT ')' ':' Exp ';' {
-  $$ = gen_function(jv_string_value($2), 
-                    BLOCK(gen_param(jv_string_value($4)), 
-                          gen_param(jv_string_value($6))),
-                    $9);
-  jv_free($2);
-  jv_free($4);
-  jv_free($6);
+Params:
+Param {
+  $$ = $1;
 } |
+Params ';' Param {
+  $$ = BLOCK($1, $3);
+}
 
-"def" IDENT '(' IDENT ';' IDENT ';' IDENT ')' ':' Exp ';' {
-  $$ = gen_function(jv_string_value($2), 
-                    BLOCK(gen_param(jv_string_value($4)), 
-                          gen_param(jv_string_value($6)),
-                          gen_param(jv_string_value($8))),
-                    $11);
+Param:
+'$' IDENT {
+  $$ = gen_param_regular(jv_string_value($2));
   jv_free($2);
-  jv_free($4);
-  jv_free($6);
-  jv_free($8);
 } |
 
-"def" IDENT '(' IDENT ';' IDENT ';' IDENT ';' IDENT ')' ':' Exp ';' {
-  $$ = gen_function(jv_string_value($2), 
-                    BLOCK(gen_param(jv_string_value($4)), 
-                          gen_param(jv_string_value($6)),
-                          gen_param(jv_string_value($8)),
-                          gen_param(jv_string_value($10))),
-                    $13);
-  jv_free($2);
-  jv_free($4);
-  jv_free($6);
-  jv_free($8);
-  jv_free($10);
-} |
-
-"def" IDENT '(' IDENT ';' IDENT ';' IDENT ';' IDENT ';' IDENT ')' ':' Exp ';' {
-  $$ = gen_function(jv_string_value($2), 
-                    BLOCK(gen_param(jv_string_value($4)), 
-                          gen_param(jv_string_value($6)),
-                          gen_param(jv_string_value($8)),
-                          gen_param(jv_string_value($10)),
-                          gen_param(jv_string_value($12))),
-                    $15);
-  jv_free($2);
-  jv_free($4);
-  jv_free($6);
-  jv_free($8);
-  jv_free($10);
-  jv_free($12);
-} |
-
-"def" IDENT '(' IDENT ';' IDENT ';' IDENT ';' IDENT ';' IDENT ';' IDENT ')' ':' Exp ';' {
-  $$ = gen_function(jv_string_value($2), 
-                    BLOCK(gen_param(jv_string_value($4)), 
-                          gen_param(jv_string_value($6)),
-                          gen_param(jv_string_value($8)),
-                          gen_param(jv_string_value($10)),
-                          gen_param(jv_string_value($12)),
-                          gen_param(jv_string_value($14))),
-                    $17);
-  jv_free($2);
-  jv_free($4);
-  jv_free($6);
-  jv_free($8);
-  jv_free($10);
-  jv_free($12);
-  jv_free($14);
+IDENT {
+  $$ = gen_param(jv_string_value($1));
+  jv_free($1);
 }
 
 
index c73e27a3d261419e093720f72fc6a846e6891562..2e14afb0076d72b9fd22c266df421d070c3cd4ca 100644 (file)
@@ -538,6 +538,11 @@ def id(x):x; 2000 as $x | def f(x):1 as $x | id([$x, x, x]); def g(x): 100 as $x
 "more testing"
 [1,100,2100.0,100,2100.0]
 
+# test def f($a) syntax
+def x(a;b): a as $a | b as $b | $a + $b; def y($a;$b): $a + $b; def check(a;b): [x(a;b)] == [y(a;b)]; check(.[];.[]*2)
+[1,2,3]
+true
+
 # test backtracking through function calls and returns
 # this test is *evil*
 [[20,10][1,0] as $x | def f: (100,200) as $y | def g: [$x + $y, .]; . + $x | g; f[0] | [f][0][1] | f]