zsh-workers
 help / color / mirror / code / Atom feed
* PATCH: arguments to anonymous function
@ 2011-06-19 18:14 Peter Stephenson
  2011-06-19 18:56 ` Bart Schaefer
  2011-06-20  1:28 ` Mikael Magnusson
  0 siblings, 2 replies; 4+ messages in thread
From: Peter Stephenson @ 2011-06-19 18:14 UTC (permalink / raw)
  To: Zsh Hackers' List

This adds arguments to anonymous functions.  The only easy way of doing
this without trampling on other syntax is to pass them after the final
brace, where previously it would have caused a syntax error so it's
unproblematic.  I hope that's not going to be too inconvenient.

Index: Doc/Zsh/func.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/func.yo,v
retrieving revision 1.27
diff -p -u -r1.27 func.yo
--- Doc/Zsh/func.yo	13 Jan 2011 09:31:08 -0000	1.27
+++ Doc/Zsh/func.yo	19 Jun 2011 18:08:21 -0000
@@ -158,9 +158,13 @@ If no name is given for a function, it i
 specially.  Either form of function definition may be used: a `tt(())' with
 no preceding name, or a `tt(function)' with an immediately following open
 brace.  The function is executed immediately at the point of definition and
-is not stored for future use.  The function name is set to `tt((anon))' and
-the parameter list passed to the function is empty.  Note that this means
+is not stored for future use.  The function name is set to `tt((anon))'.
+
+Arguments to the function may be specified as words following the
+closing brace defining the function, hence if there are none no
+arguments (other than tt($0)) are set.  Note that this means
 the argument list of any enclosing script or function is hidden.
+
 Redirections may be applied to the anonymous function in the same manner as
 to a current-shell structure enclosed in braces.  The main use of anonymous
 functions is to provide a scope for local variables.  This is particularly
@@ -172,13 +176,13 @@ For example,
 example(variable=outside
 function {
   local variable=inside
-  print "I am $variable"
-}
+  print "I am $variable with arguments $*"
+} this and that
 print "I am $variable")
 
 outputs the following:
 
-example(I am inside
+example(I am inside with arguments this and that
 I am outside)
 
 Note that function definitions with arguments that expand to nothing,
Index: Src/exec.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/exec.c,v
retrieving revision 1.196
diff -p -u -r1.196 exec.c
--- Src/exec.c	24 May 2011 15:49:03 -0000	1.196
+++ Src/exec.c	19 Jun 2011 18:08:22 -0000
@@ -4184,10 +4184,19 @@ execfuncdef(Estate state, UNUSED(int do_
 	     * Anonymous function, execute immediately.
 	     * Function name is "(anon)", parameter list is empty.
 	     */
-	    LinkList args = newlinklist();
+	    LinkList args;
 
+	    state->pc = end;
+	    end += *state->pc++;
+	    args = ecgetlist(state, *state->pc++, EC_DUPTOK, &htok);
+	    
+	    if (htok && args)
+		execsubst(args);
+
+	    if (!args)
+		args = newlinklist();
 	    shf->node.nam = "(anon)";
-	    addlinknode(args, shf->node.nam);
+	    pushnode(args, shf->node.nam);
 
 	    execshfunc(shf, args);
 	    ret = lastval;
Index: Src/parse.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/parse.c,v
retrieving revision 1.87
diff -p -u -r1.87 parse.c
--- Src/parse.c	19 Jun 2011 16:26:11 -0000	1.87
+++ Src/parse.c	19 Jun 2011 18:08:22 -0000
@@ -1480,12 +1480,25 @@ par_funcdef(void)
     ecbuf[p + num + 4] = ecnpats;
     ecbuf[p + 1] = num;
 
-    lineno += oldlineno;
     ecnpats = onp;
     ecssub = oecssub;
     ecnfunc++;
 
     ecbuf[p] = WCB_FUNCDEF(ecused - 1 - p);
+
+    if (num == 0) {
+	/* Unnamed function */
+	int parg = ecadd(0);
+	ecadd(0);
+	while (tok == STRING) {
+	    ecstr(tokstr);
+	    num++;
+	    zshlex();
+	}
+	ecbuf[parg] = ecused - parg; /*?*/
+	ecbuf[parg+1] = num;
+    }
+    lineno += oldlineno;
 }
 
 /*
@@ -1730,13 +1743,26 @@ par_simple(int *complex, int nr)
 	    ecbuf[p + argc + 3] = ecsoffs - so;
 	    ecbuf[p + argc + 4] = ecnpats;
 
-	    lineno += oldlineno;
 	    ecnpats = onp;
 	    ecssub = oecssub;
 	    ecnfunc++;
 
 	    ecbuf[p] = WCB_FUNCDEF(ecused - 1 - p);
 
+	    if (argc == 0) {
+		/* Unnamed function */
+		int parg = ecadd(0);
+		ecadd(0);
+		while (tok == STRING) {
+		    ecstr(tokstr);
+		    argc++;
+		    zshlex();
+		}
+		ecbuf[parg] = ecused - parg; /*?*/
+		ecbuf[parg+1] = argc;
+	    }
+	    lineno += oldlineno;
+
 	    isfunc = 1;
 	    isnull = 0;
 	    break;
Index: Src/text.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/text.c,v
retrieving revision 1.28
diff -p -u -r1.28 text.c
--- Src/text.c	9 May 2011 10:27:32 -0000	1.28
+++ Src/text.c	19 Jun 2011 18:08:22 -0000
@@ -253,6 +253,7 @@ struct tstack {
 	struct {
 	    char *strs;
 	    Wordcode end;
+	    int nargs;
 	} _funcdef;
 	struct {
 	    Wordcode end;
@@ -456,19 +457,31 @@ gettext2(Estate state)
 	    if (!s) {
 		Wordcode p = state->pc;
 		Wordcode end = p + WC_FUNCDEF_SKIP(code);
+		int nargs = *state->pc++;
 
-		taddlist(state, *state->pc++);
+		taddlist(state, nargs);
+		if (nargs)
+		    taddstr(" ");
 		if (tjob) {
-		    taddstr(" () { ... }");
+		    taddstr("() { ... }");
 		    state->pc = end;
+		    if (!nargs) {
+			/*
+			 * Unnamed fucntion.
+			 * We're not going to pull any arguments off
+			 * later, so skip them now...
+			 */
+			state->pc += *end;
+		    }
 		    stack = 1;
 		} else {
-		    taddstr(" () {");
+		    taddstr("() {");
 		    tindent++;
 		    taddnl(1);
 		    n = tpush(code, 1);
 		    n->u._funcdef.strs = state->strs;
 		    n->u._funcdef.end = end;
+		    n->u._funcdef.nargs = nargs;
 		    state->strs += *state->pc;
 		    state->pc += 3;
 		}
@@ -478,6 +491,17 @@ gettext2(Estate state)
 		dec_tindent();
 		taddnl(0);
 		taddstr("}");
+		if (s->u._funcdef.nargs == 0) {
+		    /* Unnamed function with post-arguments */
+		    int nargs;
+		    s->u._funcdef.end += *state->pc++;
+		    nargs = *state->pc++;
+		    if (nargs) {
+			taddstr(" ");
+			taddlist(state, nargs);
+		    }
+		    state->pc = s->u._funcdef.end;
+		}
 		stack = 1;
 	    }
 	    break;
Index: Test/C04funcdef.ztst
===================================================================
RCS file: /cvsroot/zsh/zsh/Test/C04funcdef.ztst,v
retrieving revision 1.7
diff -p -u -r1.7 C04funcdef.ztst
--- Test/C04funcdef.ztst	11 Jul 2009 16:43:01 -0000	1.7
+++ Test/C04funcdef.ztst	19 Jun 2011 18:08:22 -0000
@@ -26,7 +26,7 @@
     print regress expansion of function names
   }
   f$$
-0:Regression test: `function f$$ () { ... }'
+0:Regression test: 'function f$$ () { ... }'
 >regress expansion of function names
 
   function foo () print bar
@@ -109,6 +109,8 @@
 >really useful
 >args
 
+# ' deconfuse emacs
+
   command_not_found_handler() {
      print "Your command:" >&2
      print "$1" >&2
@@ -201,6 +203,31 @@
 >Da de da
 >Do be do
 
+  () { print This has arguments $*; } of all sorts; print After the function
+  function { print More stuff $*; } and why not; print Yet more
+0:Anonymous function with arguments
+>This has arguments of all sorts
+>After the function
+>More stuff and why not
+>Yet more
+
+  fn() {
+    (){ print Anonymous function 1 $*; } with args
+    function { print Anonymous function 2 $*; } with more args
+    print Following bit
+  }
+  functions fn
+0:Text representation of anonymous function with arguments
+>fn () {
+>	() {
+>		print Anonymous function 1 $*
+>	} with args
+>	() {
+>		print Anonymous function 2 $*
+>	} with more args
+>	print Following bit
+>}
+
 %clean
 
  rm -f file.in file.out

-- 
Peter Stephenson <p.w.stephenson@ntlworld.com>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: PATCH: arguments to anonymous function
  2011-06-19 18:14 PATCH: arguments to anonymous function Peter Stephenson
@ 2011-06-19 18:56 ` Bart Schaefer
  2011-06-20  1:28 ` Mikael Magnusson
  1 sibling, 0 replies; 4+ messages in thread
From: Bart Schaefer @ 2011-06-19 18:56 UTC (permalink / raw)
  To: Zsh Hackers' List

On Jun 19,  7:14pm, Peter Stephenson wrote:
}
} This adds arguments to anonymous functions.

Nice; one added remark:

} +Arguments to the function may be specified as words following the
} +closing brace defining the function, hence if there are none no
} +arguments (other than tt($0)) are set.  Note that this means
}  the argument list of any enclosing script or function is hidden.

A consequence of this is that the only real use for this syntax is to
pass along some of the positional parameters of the caller.  E.g.,

    function { print Caller arguments: "$@" } "$@"

Anything not referencing the caller's positionals can already be done
by using "set -- ..." as the first line of the anonymous function.


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: PATCH: arguments to anonymous function
  2011-06-19 18:14 PATCH: arguments to anonymous function Peter Stephenson
  2011-06-19 18:56 ` Bart Schaefer
@ 2011-06-20  1:28 ` Mikael Magnusson
  2011-06-20  8:49   ` Peter Stephenson
  1 sibling, 1 reply; 4+ messages in thread
From: Mikael Magnusson @ 2011-06-20  1:28 UTC (permalink / raw)
  To: Zsh Hackers' List

On 19 June 2011 20:14, Peter Stephenson <p.w.stephenson@ntlworld.com> wrote:
> This adds arguments to anonymous functions.  The only easy way of doing
> this without trampling on other syntax is to pass them after the final
> brace, where previously it would have caused a syntax error so it's
> unproblematic.  I hope that's not going to be too inconvenient.

Cool, I remember wanting this a few times. I just don't remember what
for :). It sort of lets you do array things to globs without assigning
a var first pretty easily, () { print -l /foo/${(U)^@} } Src/*.c

Or arbitrarily nested glob qualifiers, I'm sometimes bothered by not
being able to do foo(xyz)/bar(abc) where xyz would be glob quals to
apply on the foo segment, and abc on bar.

() { () { print -l $^@(e:'REPLY=${(U)REPLY}':) } $^@/*(.) } *(/)
(This is a stupid example, but maybe it gets the point across. :) No
idea why I'm so fond of uppercasing things tonight.)

A heads up, this patch may make zsh crash on startup when reading .zwc
files from before the change. A simple workaround is to either touch
the source file or remove the .zwc files. (Maybe we should bump the
-dev version so this doesn't affect too many people?)

-- 
Mikael Magnusson


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: PATCH: arguments to anonymous function
  2011-06-20  1:28 ` Mikael Magnusson
@ 2011-06-20  8:49   ` Peter Stephenson
  0 siblings, 0 replies; 4+ messages in thread
From: Peter Stephenson @ 2011-06-20  8:49 UTC (permalink / raw)
  To: Zsh Hackers' List

On Mon, 20 Jun 2011 03:28:23 +0200
Mikael Magnusson <mikachu@gmail.com> wrote:
> A heads up, this patch may make zsh crash on startup when reading .zwc
> files from before the change. A simple workaround is to either touch
> the source file or remove the .zwc files. (Maybe we should bump the
> -dev version so this doesn't affect too many people?)

This occurred to me, too, and I've done that.

-- 
Peter Stephenson <pws@csr.com>            Software Engineer
Tel: +44 (0)1223 692070                   Cambridge Silicon Radio Limited
Churchill House, Cambridge Business Park, Cowley Road, Cambridge, CB4 0WZ, UK
 



Member of the CSR plc group of companies. CSR plc registered in England and Wales, registered number 4187346, registered office Churchill House, Cambridge Business Park, Cowley Road, Cambridge, CB4 0WZ, United Kingdom
More information can be found at www.csr.com. Follow CSR on Twitter at http://twitter.com/CSR_PLC and read our blog at www.csr.com/blog


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2011-06-20  8:49 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-06-19 18:14 PATCH: arguments to anonymous function Peter Stephenson
2011-06-19 18:56 ` Bart Schaefer
2011-06-20  1:28 ` Mikael Magnusson
2011-06-20  8:49   ` Peter Stephenson

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).