Deutsch   English   Français   Italiano  
<100c51f$sfr3$1@dont-email.me>

View for Bookmarking (what is this?)
Look up another Usenet article

Path: news.eternal-september.org!eternal-september.org!.POSTED!not-for-mail
From: Ruvim <ruvim.pinka@gmail.com>
Newsgroups: comp.lang.forth
Subject: Re: QUIT and ABORT
Date: Sun, 18 May 2025 12:16:46 +0400
Organization: A noiseless patient Spider
Lines: 165
Message-ID: <100c51f$sfr3$1@dont-email.me>
References: <87bjtn2hct.fsf@gmail.com>
 <60caba147f217f0c677ddc6bf8a7492a3c69688b@i2pn2.org>
 <2025May6.091324@mips.complang.tuwien.ac.at>
 <f3783e59aec9762f3871cfb39f36c514dc05f214@i2pn2.org>
 <vvg6l5$12kee$1@dont-email.me>
 <35ba145b7baa62154479eac080a2f6995b24b8e8@i2pn2.org>
 <vvi9b5$1ogea$1@dont-email.me>
 <0c4bc1ac6f9595ebc81448f21aade5d54639ada9@i2pn2.org>
 <vvk6s9$2jjoh$1@dont-email.me>
 <5069a2ba51509e4f92ffa680982a4e353ec45ab8@i2pn2.org>
 <vvlke3$2neud$1@dont-email.me> <vvvlin$1rk75$1@dont-email.me>
 <696f4a3105690a7ea898d1778a37d345cbd4c598@i2pn2.org>
 <1001gaa$2b9mr$2@dont-email.me>
 <9d4eb41927bc7282d1568054a0d94b5a0f60056b@i2pn2.org>
 <1006jsi$3js21$1@dont-email.me>
 <e32f5681efc287a2089300a61fc8db21d04ff7d0@i2pn2.org>
 <10076jg$3nh2i$1@dont-email.me>
 <2a3f2365e393969d8de858651cc9486806e2ad12@i2pn2.org>
 <1009s09$c9ih$1@dont-email.me>
 <4481f037e7bf4a8d7faa59640a9dcfac01c42226@i2pn2.org>
 <100b23g$g4a6$1@dont-email.me>
 <5ddd51973a3f163595605432f497ac65a5ed1336@i2pn2.org>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
Injection-Date: Sun, 18 May 2025 10:16:49 +0200 (CEST)
Injection-Info: dont-email.me; posting-host="980cda412f4110b7b6c16b284a72d5ad";
	logging-data="933731"; mail-complaints-to="abuse@eternal-september.org";	posting-account="U2FsdGVkX18FSMyIgxSPdCyiypeDyLsJ"
User-Agent: Mozilla Thunderbird
Cancel-Lock: sha1:9DD1jmKdS5pXzBD6PMgzvizWRrs=
In-Reply-To: <5ddd51973a3f163595605432f497ac65a5ed1336@i2pn2.org>
Content-Language: en-US

On 2025-05-18 06:58, dxf wrote:
> On 18/05/2025 8:20 am, Ruvim wrote:
>> On 2025-05-17 17:28, dxf wrote:
>>> On 17/05/2025 9:30 pm, Ruvim wrote:
>>>> On 2025-05-17 06:56, dxf wrote:
>>>>> On 16/05/2025 9:12 pm, Ruvim wrote:
>>>>>>>> ...
>>>>>>>> What solution do you mean?
>>>>>>>
>>>>>>> Default behaviour of QUIT is Core QUIT.  THROW handles -56 by jumping to
>>>>>>> Core QUIT.
>>>>>>
>>>>>> If you make `throw` do this regardless of whether a user's exception frame exists in the exception stack, you make the `-56` error code uncatchable. So, the following test case will fail:
>>>>>>
>>>>>>      t{  [: -56 throw ;] catch -> -56 }t
>>>>>>
>>>>>> And what is the benefit?
>>>>>
>>>>> Why should it fail?
>>>>
>>>> You wrote: "THROW handles -56 by jumping to Core QUIT". Then the test should fail. But as you now show, you only meant the case where there is no user exception frame in the exception stack.
>>>>
>>>>
>>>>>
>>>>>      [: -56 throw ;] catch  ok  -56 <
>>>>>
>>>>>      [: -1 throw ;] catch  ok  -1 <
>>>>
>>>> Okay, these cases are compliant.
>>>>
>>>>
>>>>>
>>>>>      1 2 3 -56 throw
>>>>>        ok  1 2 3 <
>>>>>
>>>>>      1 2 3 -1 throw
>>>>>        ok
>>>>
>>>> This special handling of `-56` is inconsistent, not justified by practice, and complicates implementations.
>>>
>>
>> Well, at least you don't object to the arguments about inconsistency and impracticality.
> 
> I saw the pejoratives and was waiting for the arguments.

Hope, I have given enough arguments now (see also below).

Re practice — the burden of proof (providing examples) lies with the one 
who asserts that it is useful in practice.



>>> Neither special nor complicated:
>>>
>>>     -1  of s0 @ sp! fs0 @ fsp ! (core-quit) then
>>>
>>>     -56 of (core-quit) then
>>
>> Why do you empty stacks especially for `-1`?  Don't you do the same for `-2`, `-3`, `-4`, etc?
> 
> The above was for explanatory purposes.  The actual code is here:
> 
> https://pastebin.com/FAmufbki

An excerpt:

: error ( n -- )  \ part of THROW
   -1 of (abort) then
   -2 of boot cell+ @ 0= if .error then
      space errmsg 2@ type (abort) then
   -56 of 1 ?return then
   ."  THROW #" @base decimal swap . !base (abort) ;

: THROW ( n -- )
   ?dup if catcher @ ?dup 0= if error then rp!
   r> catcher ! 2r> fsp ! swap >r sp! drop r>  then ;

: CATCH ( xt -- n | 0 )
   sp@ fsp @ 2>r catcher @ >r rp@ catcher !
   execute 0 r> catcher ! 2r> 2drop ;

End of excerpt.

Note that in `error` you don't transfer control to `(abort)` only in the 
case of `-56`. The other differences are only related to the different 
error messages and can be factored out. For example, an equivalent 
definition:

   : error ( S: n\0 -- never )
     dup print-error
     -56 = if 1 ?return ( S: never ) then
     (abort)  ( S: never )
   ;



Another question is how are `evaluate` and `included` implemented?

I assume they use `catch`. Then your Forth system probably shows the 
following behavior in its terminal:

   999 -56 throw
      ok  999 <

   s" 999 -56 throw" evaluate
      ok

Of course, the first case shows a non-standard behavior. But moreover, 
the second case means that your catchable `quit` will not keep the data 
stack when it is called from `evaluate` or `included` (or `load`).

And what is the use of this?

When you call `quit` you probably want to eventually have on the stack 
all the passed values regardless how deep in program your call it, and 
how many exceptions frame are in the exception stack.



> 
>> In many systems, the actions specified for `throw` when there is no user exception frame are implemented in `quit`:
>>
>>    : translate-input ( any -- any )
>>      begin refill while interpret ?ok repeat
>>    ;
>>    : quit ( i*x -- never )   \ point (1)
>>      rdepth rndrop \ empty the return stack and exception stack
>>      0 set-source-id
>>      begin
>>        0 state ! \ enter interpretation state
>>        ['] translate-input catch dup
>>      while ( i*x n\0 )   \ point (2)
>>        ['] print-error catch if 6 bye-status then
>>        depth ndrop \ empty the data stack (and control-flow stack)
>>        fdepth fndrop \ empty the floating-point stack
>>      repeat bye \ end of stdin
>>    ;
>>
>> (this is allowed as the programs are not affected)
>>
>> And the system enters `quit` right after startup. So `throw` does not call `(core-quit)`, but non-locally *returns* to `(core-quit)` according to the system's exception frame.
>>
>> This approach avoids the need to determine in `throw` whether a user exception frame exists, and allows to use `catch` in the words like `evaluate` and `included` to restore the input source. See an example implementation for `throw` in E.9.6.1.2275
>> <https://forth-standard.org/standard/implement#imp:exception:THROW>
>>
>>
>> The caveat/nuance is that the special handling of `-56` as in your example is not compatible with this approach at all.
>>
>> This handling cannot be implemented in `throw`, since some exception frame always exists when `throw` is executed. And this handling cannot be implemented in `quit` because in the point (2) the data stack depth is already restored and is the same as in the point (1) plus one.
>>
>> That's why I said this special handling of `-56` complicates implementations.
> 
> That's hardly my problem or ANS'.
> ANS made provision for a catchable QUIT.

Only reserving a throw code does not provide this provision.


> It happens I could easily add it.  Those that want it will find a way.
========== REMAINDER OF ARTICLE TRUNCATED ==========