diff options
author | Nicolas Williams <nico@cryptonector.com> | 2014-08-08 18:00:47 -0500 |
---|---|---|
committer | Nicolas Williams <nico@cryptonector.com> | 2014-08-08 19:16:01 -0500 |
commit | 32c08d48f32162db1f1b6f3daaecf8f24ed85368 (patch) | |
tree | 6c3b10ec4758c86d8a0c4aa752c4a66879b33bf0 | |
parent | fc52e78ed407247c0ce22a233647e52d2aa2c4e8 (diff) |
Add `def f($arg):` syntax (fix #524)
-rw-r--r-- | compile.c | 12 | ||||
-rw-r--r-- | compile.h | 1 | ||||
-rw-r--r-- | docs/content/3.manual/manual.yml | 8 | ||||
-rw-r--r-- | opcode_list.h | 1 | ||||
-rw-r--r-- | parser.y | 86 | ||||
-rw-r--r-- | tests/all.test | 5 |
6 files changed, 40 insertions, 73 deletions
@@ -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); } @@ -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); diff --git a/docs/content/3.manual/manual.yml b/docs/content/3.manual/manual.yml index bd3c82bb..c9e3ce09 100644 --- a/docs/content/3.manual/manual.yml +++ b/docs/content/3.manual/manual.yml @@ -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. diff --git a/opcode_list.h b/opcode_list.h index 5ecf57e3..119a70d3 100644 --- a/opcode_list.h +++ b/opcode_list.h @@ -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) @@ -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); } diff --git a/tests/all.test b/tests/all.test index c73e27a3..2e14afb0 100644 --- a/tests/all.test +++ b/tests/all.test @@ -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] |