Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: "return" is an always block



On Sun, 11 May 2008 17:41:19 +0100
Stephane Chazelas <Stephane_Chazelas@xxxxxxxx> wrote:
> I noticed that
> 
> f() { {} always {return}; echo here }
> 
> did output "here", that is, the "return" statement doesn't
> return from the function. Is this the intended behavior?

Well, kind of.  The point is that the "always" block happens between a
return in the try block, i.e.

  f() { { return } always { echo there } }

prints "there" before returning.  So currently we keep the return, break
and continue status from the try block.

However, I don't see why we shouldn't allow a return or break in the
always part to override it, as long as we don't ignore what's in the try
block if there's nothing in the always block; that seems to be a natural
part of what the always block is there for.  Hence

f() {
  integer loops
  while true; do
    while true; do
     {
        break 2 
     } always {
        break 1
     }
    done
    loops=1
    break
  done
  if (( loops )); then
    print always won
  else
    print try won
  fi
}

now prints "always won".

The always block previously claimed not to be part of a loop anyway, so
break and continue failed.  That was sensible with the old code, but if
we're going to allow it to do that it should just leave the count of
surrounding loops alone.

Index: Src/loop.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/loop.c,v
retrieving revision 1.21
diff -u -r1.21 loop.c
--- Src/loop.c	27 Jun 2007 13:56:11 -0000	1.21
+++ Src/loop.c	11 May 2008 18:57:02 -0000
@@ -631,7 +631,7 @@
 {
     Wordcode end, always;
     int endval;
-    int save_retflag, save_breaks, save_loops, save_contflag;
+    int save_retflag, save_breaks, save_contflag;
     zlong save_try_errflag, save_try_tryflag;
 
     end = state->pc + WC_TRY_SKIP(state->pc[-1]);
@@ -664,8 +664,6 @@
     retflag = 0;
     save_breaks = breaks;
     breaks = 0;
-    save_loops = loops;
-    loops = 0;
     save_contflag = contflag;
     contflag = 0;
 
@@ -674,10 +672,12 @@
 
     errflag = try_errflag ? 1 : 0;
     try_errflag = save_try_errflag;
-    retflag = save_retflag;
-    breaks = save_breaks;
-    loops = save_loops;
-    contflag = save_contflag;
+    if (!retflag)
+	retflag = save_retflag;
+    if (!breaks)
+	breaks = save_breaks;
+    if (!contflag)
+	contflag = save_contflag;
 
     cmdpop();
     popheap();
Index: Test/A01grammar.ztst
===================================================================
RCS file: /cvsroot/zsh/zsh/Test/A01grammar.ztst,v
retrieving revision 1.16
diff -u -r1.16 A01grammar.ztst
--- Test/A01grammar.ztst	12 Dec 2007 13:46:37 -0000	1.16
+++ Test/A01grammar.ztst	11 May 2008 18:57:02 -0000
@@ -332,6 +332,14 @@
 >Status after always block is 1.
 ?(eval):3: bad substitution
 
+  fn() { { return } always { echo always 1 }; echo not executed }
+  fn
+  fn() { { echo try 2 } always { return }; echo not executed }
+  fn
+0:Always block interaction with return
+>always 1
+>try 2
+
 # Outputting of structures from the wordcode is distinctly non-trivial,
 # we probably ought to have more like the following...
   fn1() { { echo foo; } }


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



Messages sorted by: Reverse Date, Date, Thread, Author