bugGNU Octave - Bugs: bug #55995, "continue" is...

 
 

bug #55995: "continue" is dynamically, not lexically scoped - callable from functions without for loops

Submitter:  Andrew Janke <apjanke>
Submitted:  Mon 25 Mar 2019 07:42:24 AM UTC
   
 
Category:  Interpreter Severity:  3 - Normal
Priority:  5 - Normal Item Group:  Other
Status:  Fixed Assigned to:  None
Originator Name:  Open/Closed:  * Closed
Release:  * dev Operating System:  * Any
Fixed Release:  None Planned Release:  None
* Mandatory Fields

Add a New Comment Rich Markup
   

Jump to the original submission

Fri 29 Mar 2019 03:28:07 PM UTC, comment #12: 

I simplified the error message when continue or break fail to parse (https://hg.savannah.gnu.org/hgweb/octave/rev/258195ea1a76).  This bug is well and truly fixed now, closing report.

Rik <rik5>
Group administrator
Tue 26 Mar 2019 08:41:11 PM UTC, comment #11: 

Instead of calling subfcn, I put the continue statement in an outside script.  That also correctly errors.

Isn't it enough to explain that continue and break must occur within a text block containing a loop, and ignore the part about being in the same file?

For example, this errors out correctly even though subfcn is never called.  The bareword "continue" in subfcn() is outside any text loop body whatsoever.


1;

for i = 1:5
  disp ("Before");
  #subfcn();
  printf ("Call #%d\n", i);
  disp ("After");
endfor

function subfcn ()
  continue;
endfunction



Rik <rik5>
Group administrator
Tue 26 Mar 2019 04:57:13 PM UTC, comment #10: 

I agree that the message about "same file" could be clearer.  What it means is that the continue or break command can't be inside a script that is called from inside the loop.  That doesn't do the same thing as using continue inside the loop in the same .m file.  Does that make sense?  If not, I can provide an example, and I think this behavior with scripts used inside loops is what Matlab does, but we could test again to be sure.

John W. Eaton <jwe>
Group administrator
Tue 26 Mar 2019 04:27:26 PM UTC, comment #9: 

I think this is the right philosophical choice.  I tested with this file tst_cont.m


1;

for i = 1:5
  disp ("Before");
  subfcn()
  printf ("Call #%d\n", i);
  disp ("After");
endfor

function subfcn ()
  break;
#  continue;
endfunction


which now shows


parse error near line 11 of file /home/rik/wip/Projects_Mine/octave-dev/tst_cont.m

  continue must appear in a loop in the same file as loop command

>>>   continue;
             ^

octave:1> tst_cont
parse error near line 11 of file /home/rik/wip/Projects_Mine/octave-dev/tst_cont.m

  break must appear in a loop in the same file as loop command

>>>   break;


The two loop keywords are now treated identically.

Last request would be to change the error message to be more precise.  It is notthe case that the keyword can occur in the same file as the loop command, it actually needs to be within the same scope or syntactic block.  The test script I used has continue in a subfunction which is within the same file, but that is not good enough.

Also, should there be a note in the NEWS file about this change?  I hope nobody is actually relying on this feature, but it might be good to point out the change.

Rik <rik5>
Group administrator
Tue 26 Mar 2019 04:15:37 PM UTC, comment #8: 

That was fast!

Works for me as expected with a fresh build of default.


$ octave-default
octave:1> ls
call_break.m looper.m     other_fcn.m
octave:2> looper
before
parse error near line 2 of file /Users/janke/tmp/octave-continue/other_fcn.m

  continue must appear in a loop in the same file as loop command

>>>   continue
             ^

error: called from
    looper at line 4 column 5
octave:2> continue
parse error:

  continue must appear in a loop in the same file as loop command

>>> continue
           ^

octave:2>


Andrew Janke <apjanke>
Tue 26 Mar 2019 03:49:47 PM UTC, comment #7: 
John W. Eaton <jwe>
Group administrator
Tue 26 Mar 2019 05:04:05 AM UTC, comment #6: 

Andrew:  Thanks.  Then I think the patch I posted should be fine.

Rik: Unless there is a good reason to do otherwise, I'd go with compatibility here.

John W. Eaton <jwe>
Group administrator
Tue 26 Mar 2019 03:50:21 AM UTC, comment #5: 


> In Matlab, is this a parse error, or a run-time error?


Parse error.

Andrew Janke <apjanke>
Tue 26 Mar 2019 03:45:59 AM UTC, comment #4: 

Fixing continue to work like break is fairly simple.  See the attached patch.

In Matlab, is this a parse error, or a run-time error?  I think you could check with something like


function foo (cond)
  if (cond)
    break;
  end
end


and if this fails with an error when you execute "foo (false)", then it looks like a parse error to me.  If it only fails when executing "foo (true)", then we are still not compatible because Octave detects break outside of a loop when the function is parsed.

I don't remember whether I asked this question when I made break error when it appears outside of a loop, but it occurs to me now...


(file #46639)

John W. Eaton <jwe>
Group administrator
Mon 25 Mar 2019 08:39:14 PM UTC, comment #3: 

This behavior may not be Matlab compatible, but it is not unknown.  I just tested with Perl and it recognizes a dynamically scoped "next" statement (equivalent of continue).  The "last" statement (equivalent of break) is also dynamically scoped.

This probably should be discussed on the Octave Maintainer's e-mail list since it is a somewhat philosophical point.  One advantage of the current behavior is that it is already coded.  I don't know how difficult it would be to change it to have the same behavior as the break statement.


Rik <rik5>
Group administrator
Mon 25 Mar 2019 08:26:24 AM UTC, comment #2: 

both matlab R2015a and R2018b report


before
Error: File: other_fcn.m Line: 2 Column: 3
A CONTINUE may only be used within a FOR or WHILE loop.

Error in looper (line 5)
    other_fcn ();


A.R. Burgers <arb>
Mon 25 Mar 2019 07:43:35 AM UTC, comment #1: 

Oops. Messed up the formatting and it lost most of my post. Re-post:

In Octave, you can call "continue" from within a function that does not itself contain a for loop, and it will either cause a continuation in a for loop in a calling function, or do nothing.

Example:

looper.m:


function looper
  for i = 1:5
    fprintf ("before\n");
    other_fcn ();
    fprintf ("after\n");
  end
end


other_fcn.m:


function other_fcn
  continue
end


Output:


>> looper
before
before
before
before
before
>> continue
>> continue
>> continue
>> other_fcn
>> other_fcn
>>


Note that you can just call continue even if there's no for loop in the enclosing dynamic scope, and it does nothing.

Is this expected behavior? I saw it discussed over in https://savannah.gnu.org/bugs/?48665 related to a crash, but not mentioning that the behavior itself is odd.

Break doesn't behave the same way: it raises an error if you try to call it outside the lexical scope of a for loop.

call_break.m:

function call_break
  break
endfunction



>> break
parse error:

  break must appear in a loop in the same file as loop command

>>> break
        ^

>> call_break
parse error near line 2 of file /Users/janke/tmp/octave-continue/call_break.m

  break must appear in a loop in the same file as loop command

>>>   break
          ^

>>



Andrew Janke <apjanke>
Mon 25 Mar 2019 07:42:24 AM UTC, original submission:  

In Octave, you can call "continue" from within a function that does not itself contain a for loop, and it will either cause a continuation in a for loop in a calling function, or do nothing.

Example:

looper.m:


function looper
  for i = 1:5
    fprintf ("before\n");
    other_fcn ();
    fprintf ("after\n");
  end
end
+verbatim+

other_fcn.m:

+verbatim+
function other_fcn
  continue
end


Output:


>> looper
before
before
before
before
before
>> continue
>> continue
>> continue
>> other_fcn
>> other_fcn
>>


Note that you can just call continue even if there's no for loop in the enclosing dynamic scope, and it does nothing.

Is this expected behavior? I saw it discussed over in https://savannah.gnu.org/bugs/?48665 related to a crash, but not mentioning that the behavior itself is odd.

Break doesn't behave the same way: it raises an error if you try to call it outside the lexical scope of a for loop.

call_break.m:

function call_break
  break
endfunction



>> break
parse error:

  break must appear in a loop in the same file as loop command

>>> break
        ^

>> call_break
parse error near line 2 of file /Users/janke/tmp/octave-continue/call_break.m

  break must appear in a loop in the same file as loop command

>>>   break
          ^

>>



Andrew Janke <apjanke>

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:
   
   
Comment:
   

Attached Files
file #46639:  continue-diffs.txt added by jwe (1KiB - text/plain)

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by jwe (Updated the item)
  • -email is unavailable- added by rik5 (Posted a comment)
  • -email is unavailable- added by arb (Posted a comment)
  • -email is unavailable- added by apjanke (Submitted the item)
  •  

    There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

    Only group members can vote.

     

    Follow 5 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2019-03-29 rik5 Open/ClosedOpen Closed
    2019-03-26 rik5 StatusReady For Test Fixed
    2019-03-26 jwe StatusNone Ready For Test
        Release5.1.0 dev
    2019-03-26 jwe Attached File- Added continue-diffs.txt, #46639

    Back to the top

    Powered by Savane 3.13-4448.
    Corresponding source code