zsh-workers
 help / color / mirror / code / Atom feed
* Re: Bug with continue?
       [not found] ` <16795430.3614208.1679998628194@mail.virginmedia.com>
@ 2023-03-28 11:19   ` Mikael Magnusson
  2023-03-28 13:16     ` Peter Stephenson
       [not found]   ` <805138511.3622784.1680002886460@mail.virginmedia.com>
  1 sibling, 1 reply; 5+ messages in thread
From: Mikael Magnusson @ 2023-03-28 11:19 UTC (permalink / raw)
  To: Peter Stephenson; +Cc: zsh workers

On 3/28/23, Peter Stephenson <p.w.stephenson@ntlworld.com> wrote:
>> On 28/03/2023 10:32 Felipe Contreras <felipe.contreras@gmail.com> wrote:
>> I notice this works differently in zsh than in other shells:
>>
>>   for x in 1 2 3 4; do
>>     continue &&
>>     list="$list$x " &&
>>     echo "x: $x"
>>   done
>>   echo "list: $list"
>>
>> Why did the statement after `continue` gets evaluated?
>>
>> The original code tries to do something useful `case "$x" in 1)
>> continue ;; esac &&` but it shouldn't matter.
>>
>> I tried in bash, ksh, and dash, and all of them continue immediately,
>> except zsh.
>>
>> That can't be the desired behavior, can it?
>
> That looks like it probably ought to be regarded as a bug to me, yes ---
> I guess it's been hidden because the test "if this statement successfully
> jumped somewhere completely different then..." isn't spectacularly useful.
> However, it's not logically wrong, either.
>
> I think we had something a little similar to this recently; it usually
> boils down to something quite simple once you've found it and I'll
> have a look when I've got more time.  (Patch would go to zsh-workers.)

Some observations that may or may not be helpful:

Replacing continue && with ! continue || has the same effect,
chaining continue && false && a=b still does the assignment,
doing continue && { a=b } works, eg it does not do the assignment,
same with if continue; then ...

-- 
Mikael Magnusson


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

* Re: Bug with continue?
       [not found]   ` <805138511.3622784.1680002886460@mail.virginmedia.com>
@ 2023-03-28 11:56     ` Peter Stephenson
  2023-03-29 10:02     ` Peter Stephenson
  1 sibling, 0 replies; 5+ messages in thread
From: Peter Stephenson @ 2023-03-28 11:56 UTC (permalink / raw)
  To: zsh workers

> On 28/03/2023 12:28 Peter Stephenson <p.w.stephenson@ntlworld.com> wrote:
> > On 28/03/2023 11:17 Peter Stephenson <p.w.stephenson@ntlworld.com> wrote:
> > > On 28/03/2023 10:32 Felipe Contreras <felipe.contreras@gmail.com> wrote:
> > > I notice this works differently in zsh than in other shells:
> > > 
> > >   for x in 1 2 3 4; do
> > >     continue &&
> > >     list="$list$x " &&
> > >     echo "x: $x"
> > >   done
> > >   echo "list: $list"
> > > 
> > > Why did the statement after `continue` gets evaluated?
>...
> The bug I'm thinking of is zsh-workers/51125, though it looks like I
> committed the fix under zsh-workers/51134.  That was about wheter
> "! return" should invert the status of the return given it's already
> returned by the time that would happen.  This is similar, but looks
> like it's not the same.
> 
> This one is a little weird as if the immediately next statement is a
> print it doesn't get executed.  I'm suspecting some subtlety with handling
> retflag.
> 
> pws

(I meant "breaks", of course.)  Redirected to zsh-workers as previously
advertised.

"breaks" means multiple things, but I think they all have the same
implication for a successful "continue".  If I can think of some
further useful tests I'll add them.

Added the corresponding test for return for safety.

pws

diff --git a/Src/exec.c b/Src/exec.c
index 3330bbce8..6454e4ccf 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -1491,7 +1491,7 @@ execlist(Estate state, int dont_change_job, int exiting)
 		 * we find a sublist followed by ORNEXT.                   */
 		if ((ret = ((WC_SUBLIST_FLAGS(code) & WC_SUBLIST_SIMPLE) ?
 			    execsimple(state) :
-			    execpline(state, code, Z_SYNC, 0)))) {
+			    execpline(state, code, Z_SYNC, 0))) || breaks) {
 		    state->pc = next;
 		    code = *state->pc++;
 		    next = state->pc + WC_SUBLIST_SKIP(code);
diff --git a/Test/A01grammar.ztst b/Test/A01grammar.ztst
index b3aea1055..88928980f 100644
--- a/Test/A01grammar.ztst
+++ b/Test/A01grammar.ztst
@@ -982,3 +982,21 @@ F:its expectations.
  }
  fn
 1:! does not affect return status of explicit return
+
+  msg=unset
+  for x in 1 2 3 4 5; do
+    continue && msg=set && print Not executed
+    print Not executed, neither.
+  done
+  print $msg
+0:continue causes immediate continuation
+>unset
+
+  msg=unset
+  () {
+    return && msg=set && print Not executed
+    print Not executed, not nor neither.
+  }
+  print $msg
+0:return causes immediate return
+>unset


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

* Re: Bug with continue?
  2023-03-28 11:19   ` Bug with continue? Mikael Magnusson
@ 2023-03-28 13:16     ` Peter Stephenson
  2023-03-30  8:08       ` Felipe Contreras
  0 siblings, 1 reply; 5+ messages in thread
From: Peter Stephenson @ 2023-03-28 13:16 UTC (permalink / raw)
  To: zsh workers

> On 28/03/2023 12:19 Mikael Magnusson <mikachu@gmail.com> wrote:
> Replacing continue && with ! continue || has the same effect,

Missed this one, thanks.

pws

diff --git a/Src/exec.c b/Src/exec.c
index 3330bbce8..4328975b9 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -1491,7 +1491,7 @@ execlist(Estate state, int dont_change_job, int exiting)
 		 * we find a sublist followed by ORNEXT.                   */
 		if ((ret = ((WC_SUBLIST_FLAGS(code) & WC_SUBLIST_SIMPLE) ?
 			    execsimple(state) :
-			    execpline(state, code, Z_SYNC, 0)))) {
+			    execpline(state, code, Z_SYNC, 0))) || breaks) {
 		    state->pc = next;
 		    code = *state->pc++;
 		    next = state->pc + WC_SUBLIST_SKIP(code);
@@ -1524,7 +1524,7 @@ execlist(Estate state, int dont_change_job, int exiting)
 		 * we find a sublist followed by ANDNEXT.              */
 		if (!(ret = ((WC_SUBLIST_FLAGS(code) & WC_SUBLIST_SIMPLE) ?
 			     execsimple(state) :
-			     execpline(state, code, Z_SYNC, 0)))) {
+			     execpline(state, code, Z_SYNC, 0))) || breaks) {
 		    state->pc = next;
 		    code = *state->pc++;
 		    next = state->pc + WC_SUBLIST_SKIP(code);
diff --git a/Test/A01grammar.ztst b/Test/A01grammar.ztst
index b3aea1055..d57085798 100644
--- a/Test/A01grammar.ztst
+++ b/Test/A01grammar.ztst
@@ -982,3 +982,39 @@ F:its expectations.
  }
  fn
 1:! does not affect return status of explicit return
+
+  msg=unset
+  for x in 1 2 3 4 5; do
+    continue && msg=set && print Not executed
+    print Not executed, neither.
+  done
+  print $msg
+0:continue causes immediate continuation
+>unset
+
+  msg=unset
+  () {
+    return && msg=set && print Not executed
+    print Not executed, not nor neither.
+  }
+  print $msg
+0:return causes immediate return
+>unset
+
+  msg=unset
+  for x in 1 2 3 4 5; do
+    ! continue || msg=set && print Not executed
+    print Not executed, neither.
+  done
+  print $msg
+0:! continue causes immediate continuation
+>unset
+
+  msg=unset
+  () {
+    ! return || msg=set && print Not executed
+    print Not executed, not nor neither.
+  }
+  print $msg
+0:! return causes immediate return
+>unset


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

* Re: Bug with continue?
       [not found]   ` <805138511.3622784.1680002886460@mail.virginmedia.com>
  2023-03-28 11:56     ` Peter Stephenson
@ 2023-03-29 10:02     ` Peter Stephenson
  1 sibling, 0 replies; 5+ messages in thread
From: Peter Stephenson @ 2023-03-29 10:02 UTC (permalink / raw)
  To: zsh workers

> On 28/03/2023 12:28 Peter Stephenson <p.w.stephenson@ntlworld.com> wrote:
> > On 28/03/2023 11:17 Peter Stephenson <p.w.stephenson@ntlworld.com> wrote:
> > > On 28/03/2023 10:32 Felipe Contreras <felipe.contreras@gmail.com> wrote:
> > > I notice this works differently in zsh than in other shells:
> > > 
> > >   for x in 1 2 3 4; do
> > >     continue &&
> > >     list="$list$x " &&
> > >     echo "x: $x"
> > >   done
> > >   echo "list: $list"
> > > 
> > > Why did the statement after `continue` gets evaluated?
>
> This one is a little weird as if the immediately next statement is a
> print it doesn't get executed.

For what it's worth, I suspect this difference is because the
assignment is going through execsimple() rather than the execcmd_...
series.  As it's name suggests execsimple() doesn't do a lot of testing.

I'd rather not tinker with that; the fix we have should be good enough.

pws


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

* Re: Bug with continue?
  2023-03-28 13:16     ` Peter Stephenson
@ 2023-03-30  8:08       ` Felipe Contreras
  0 siblings, 0 replies; 5+ messages in thread
From: Felipe Contreras @ 2023-03-30  8:08 UTC (permalink / raw)
  To: Peter Stephenson; +Cc: zsh workers

On Tue, Mar 28, 2023 at 7:17 AM Peter Stephenson
<p.w.stephenson@ntlworld.com> wrote:
>
> > On 28/03/2023 12:19 Mikael Magnusson <mikachu@gmail.com> wrote:
> > Replacing continue && with ! continue || has the same effect,
>
> Missed this one, thanks.
>
> pws
>
> diff --git a/Src/exec.c b/Src/exec.c
> index 3330bbce8..4328975b9 100644
> --- a/Src/exec.c
> +++ b/Src/exec.c
> @@ -1491,7 +1491,7 @@ execlist(Estate state, int dont_change_job, int exiting)
>                  * we find a sublist followed by ORNEXT.                   */
>                 if ((ret = ((WC_SUBLIST_FLAGS(code) & WC_SUBLIST_SIMPLE) ?
>                             execsimple(state) :
> -                           execpline(state, code, Z_SYNC, 0)))) {
> +                           execpline(state, code, Z_SYNC, 0))) || breaks) {
>                     state->pc = next;
>                     code = *state->pc++;
>                     next = state->pc + WC_SUBLIST_SKIP(code);
> @@ -1524,7 +1524,7 @@ execlist(Estate state, int dont_change_job, int exiting)
>                  * we find a sublist followed by ANDNEXT.              */
>                 if (!(ret = ((WC_SUBLIST_FLAGS(code) & WC_SUBLIST_SIMPLE) ?
>                              execsimple(state) :
> -                            execpline(state, code, Z_SYNC, 0)))) {
> +                            execpline(state, code, Z_SYNC, 0))) || breaks) {
>                     state->pc = next;
>                     code = *state->pc++;
>                     next = state->pc + WC_SUBLIST_SKIP(code);

FWIW I can confirm this fixes the issue both in my toy case, and the
real code that prompted me to report the issue.

Thanks.

-- 
Felipe Contreras


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

end of thread, other threads:[~2023-03-30  8:09 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <CAMP44s3NCDJU9TcSuSgy5oH=-iK3zpP3Vc1+95d3n16uydHhFA@mail.gmail.com>
     [not found] ` <16795430.3614208.1679998628194@mail.virginmedia.com>
2023-03-28 11:19   ` Bug with continue? Mikael Magnusson
2023-03-28 13:16     ` Peter Stephenson
2023-03-30  8:08       ` Felipe Contreras
     [not found]   ` <805138511.3622784.1680002886460@mail.virginmedia.com>
2023-03-28 11:56     ` Peter Stephenson
2023-03-29 10:02     ` 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).