bugGforth - Bugs: bug #63268, throw|catch behavior: unexpected...

 
 

bug #63268: throw|catch behavior: unexpected items at data stack

Submitter:  Stephan Rudlof <hartrock>
Submitted:  Mon 24 Oct 2022 08:49:30 PM UTC
   
 
Category:  None Severity:  1 - Wish
Item Group:  None Status:  Invalid
Privacy:  Public Assigned to:  None
Open/Closed:  Closed
* Mandatory Fields

Add a New Comment Rich Markup
   

Jump to the original submission

Sun 30 Oct 2022 11:50:36 PM UTC, comment #6: 

BTW:
Recently definition

: then-endtry
    ]] then endtry [[
; immediate compile-only

has been useful; example:

    try
        o ^_peek separator-char? if
            ws ^$contents
            o ^spc-integer
            0
        else
            Ex_^spc-number_scan
        then
    then-endtry
    ws ^release \ cleanup
    throw


Stephan Rudlof <hartrock>
Sat 29 Oct 2022 03:18:06 PM UTC, comment #5: 

IIRC you can get similar effects with longjmp() in C.

As for where to discuss these things, some questions may be appropriate at forth-standard.org.  There is also a gforth mailing list for Gforth-specific questions, and the Usenet group comp.lang.forth (you may want to put a few participants of the latter in your killfile).


Anton Ertl <anton>
Group administrator
Tue 25 Oct 2022 11:40:05 AM UTC, comment #4: 

Hello Anton,

thanks for further explanation!

coming from a non-Forth experience - C, C++, Javascript, Smalltalk -, where stack effects are not managed by programmer, having access to unknown values there has been the trap which has catched me... (local vars at stack typically stay at their value).

BTW:
Do you think this is a good place for such discussions, or would it be better to use some discussion ML (or similar)?
Sharing some learning experience is not a bug report in the narrow sense... (but I like the discussion experience here!).

Some way to get wished stack behavior for the example below is to move arguments to throwing word inside try|endtry (all together suited for copy/paste):

sr@rs:~/Gforth$ cat throw_catch_problem3.fs
: run-thrower_no-arg ( -- )
    try
        77 throw
    restore
    endtry
    ~~
    ."   just before throw"
    throw
;
: run-thrower_arg ( c-addr u -- )
    2drop
    try
        77 throw
    restore
    endtry
    ~~
    ."   just before throw"
    throw
;

: trigger_problem
    s" arg" cr 2dup . .
    ~~
    ['] run-thrower_arg catch
    ~~
    ."   after catch: *why* 2 additional stack items at dstack after catching err throw here?"
    assert( 77 = )
;
: trigger_problem_not
    ~~
    ['] run-thrower_no-arg catch
    ~~
    ."   after catch: *no* 2 additional stack items at dstack after catching err throw here."
    assert( 77 = )
;

: trigger_problem_not_arg
    try
        s" arg" cr 2dup . .
        run-thrower_arg 0
    restore
    endtry
    ~~
    ."   after catch: *no* additional stack items at dstack after catching err throw here!"
    assert( 77 = )
;
sr@rs:~/Gforth$ gforth throw_catch_problem3.fs
Gforth 0.7.9_20221013
Authors: Anton Ertl, Bernd Paysan, Jens Wilke et al., for more type `authors'
Copyright © 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
Gforth comes with ABSOLUTELY NO WARRANTY; for details type `license'
Type `help' for basic help
trigger_problem_not_arg
3 139760105353056
throw_catch_problem3.fs:16:5:<1> #77
  just before throw
throw_catch_problem3.fs:43:5:<1> #77
  after catch: *no* additional stack items at dstack after catching err throw here! ok


Stephan Rudlof <hartrock>
Tue 25 Oct 2022 07:19:36 AM UTC, comment #3: 

Yes.  The depth effect is intended, and the values of stack items "pushed" by throw are arbitrary (apart from the ball).

The idea behind this is that the code that throws does in general not know the place that catches the throw, and does not know the stack depth in case of a non-throwing exit.  So it restores the stack depth to the depth on entry to the CATCH (or at the TRY), and the code after CATCH can then deal with the situation (it knows from the ball whether there was a non-throwing exit or a throwing exit).

How do you know which values on the stack may be nonsense? From the stack effect of the xt passed to catch (or the code between TRY and RESTORE).  If the stack effect is ( n1 n2 -- n3 n4 ), you know that the code can have taken n1 and n2 off the stack before throwing, so these two cells are arbitrary.

Anton Ertl <anton>
Group administrator
Mon 24 Oct 2022 11:44:09 PM UTC, comment #2: 

Conclusion (after learning something):

  • Observed behavior is a feature (no bug);
  • items are expected (their value depends...).
Stephan Rudlof <hartrock>
Mon 24 Oct 2022 09:28:57 PM UTC, comment #1: 

Trying an explanation; from
  https://gforth.org/manual/Exception-Handling.html
:



The Standard Forth way to catch exceptions is catch:

catch ( x1 .. xn xt – y1 .. ym 0 / z1 .. zn error  ) exception “catch”

Executes xt. If execution returns normally, catch pushes 0 on the stack. If execution returns through throw, all the stacks are reset to the depth on entry to catch, and the TOS (the xt position) is replaced with the throw code.


'All the stacks are reset to the depth on entry to catch'; so if there are args at stack before

['] run-thrower_arg catch

, stack depth thereafter reflects this.
But obviously - as shown below - these additional positons at stack are not restored to their values before...


Stephan Rudlof <hartrock>
Mon 24 Oct 2022 08:49:30 PM UTC, original submission:  

Unclear to me, why there are items left at data stack after executing trigger_problem.

Wrong understanding of throw|catch mechanism, bug, or (what) feature?


sr@rs:~/Gforth$ cat throw_catch_problem.fs
: run-thrower_no-arg ( -- )
    try
        77 throw
    restore
    endtry
    ~~
    ."   just before throw"
    throw
;
: run-thrower_arg ( c-addr u -- )
    2drop
    try
        77 throw
    restore
    endtry
    ~~
    ."   just before throw"
    throw
;

: trigger_problem
    s" arg"
    ~~
    ['] run-thrower_arg catch
    ~~
    ."   after catch: *why* 2 additonal stack items at dstack after catching err throw here?"
    assert( 77 = )
;
: trigger_problem_not
    ~~
    ['] run-thrower_no-arg catch
    ~~
    ."   after catch: *no* 2 additonal stack items at dstack after catching err throw here."
    assert( 77 = )
;
sr@rs:~/Gforth$ gforth throw_catch_problem.fs
Gforth 0.7.9_20221013
Authors: Anton Ertl, Bernd Paysan, Jens Wilke et al., for more type `authors'
Copyright © 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
Gforth comes with ABSOLUTELY NO WARRANTY; for details type `license'
Type `help' for basic help
trigger_problem_not
throw_catch_problem.fs:30:5:<0>

throw_catch_problem.fs:6:5:<1> #77
  just before throw
throw_catch_problem.fs:32:5:<1> #77
  after catch: *no* 2 additional stack items at dstack after catching err throw here. ok
.s <0>  ok
trigger_problem
throw_catch_problem.fs:23:5:<2> "arg"

throw_catch_problem.fs:16:5:<1> #77
  just before throw
throw_catch_problem.fs:25:5:<3> #77 $7F4A0C4D2F28 #77
  after catch: *why* 2 additional stack items at dstack after catching err throw here? ok 2
.s <2> 77 139956010692392  ok 2
\ Why?  ok 2


Stephan Rudlof <hartrock>

 

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

Attach Files:
   
   
Comment:
   

No files currently attached

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by anton (Posted a comment)
  • -email is unavailable- added by hartrock (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 logged-in users can vote.

     

    Follow 3 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2022-10-25 anton Severity3 - Normal 1 - Wish
        StatusNone Invalid
        Open/ClosedOpen Closed

    Back to the top

    Powered by Savane 3.13-f8d8.
    Corresponding source code