Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

ABORT" alternatives

82 views
Skip to first unread message

Julian Fondren

unread,
Apr 22, 2017, 4:28:53 AM4/22/17
to
Hello clf,

Consider the following code:

: check1 ( x1 dim1 -- x1 ) over u> not abort" *** array index 1 out of bounds ***" ;
: check2 ( x2 dim2 -- x2 ) over u> not abort" *** array index 2 out of bounds ***" ;
: check3 ( x3 dim3 -- x3 ) over u> not abort" *** array index 3 out of bounds ***" ;
: check4 ( x4 dim4 -- x4 ) over u> not abort" *** array index 4 out of bounds ***" ;
: check5 ( x5 dim4 -- x5 ) over u> not abort" *** array index 5 out of bounds ***" ;
: check6 ( x6 dim4 -- x6 ) over u> not abort" *** array index 6 out of bounds ***" ;

Yes, that's six definitions that differ only by a single character.

Is this just foolishness? Well, ABORT" is the only standard way of
getting a custom message into the exception system. If this code
prints a message arbitrarily, it will be printed even if caught. If
instead of ABORT" a custom throw-code is used and the message stored
somewhere, the top-level needs to be aware of that throw-code and
aware of the custom location of the message. So, three libraries,
potentially three separate message locations? Three sets of throw
codes, possibly overlapping?

So, it's not just foolishness, if you want nice error messages. You
would have to use EXECUTE-PARSING or EVALUATE to deal with the
repetition above. And what about messages with double quotes in them?

Or, you could use your Forth system's custom solution to this problem.

gforth: provide a message, get a throw-code back.

s" a custom message" EXCEPTION constant my-exception

my-exception throw
:3: a custom message
my-exception >>>throw<<<
Backtrace:

gforth: set a variable and throw ABORT"

: x c" a custom message" "error ! -2 throw ;

x
:11: a custom message
>>>x<<<
Backtrace:
$7F0A17CE1270 throw

SwiftForth: provide a message, get a throw-code back (while working a
little bit more with the system)

THROW#
s" a custom message" >THROW enum my-exception
TO THROW#

my-exception throw a custom message

SwiftForth: set a static buffer and throw ABORT"

: x s" a custom message" ERRMSG place -2 throw ;

x a custom message

VFX: provide a (parsed) message, get a throw-code constant:

ErrDef my-exception "a custom message" ok
my-exception throw
Err# 501 a custom message
-> my-exception throw
^

VFX: set a variable and throw ABORT"

: x c" a custom message" 'AbortText ! -2 throw ; ok
x a custom message
-> x
^

iForth: provide a message as if to ABORT"

FORTH> c" a custom message" $throw
**** RETURN STACK DUMP ****
Error -2
a custom message ?


I checked ciforth and it doesn't implement ABORT" with THROW , so the
message can't be prevented with CATCH and none of this really applies
-- instead of ABORT" you can just print out the message you like and
then ABORT

How do other forths look? Is there variation not seen above?

As it is a "provide message, get throw-code" word would work across
most systems and a "provide message, get throwing word" would work
across more - at the cost of not being able to differentiate between
that precise failure and others. But that's how it is with ABORT"
anyway.

Such a word:

THROWER ( c-addr u "name" -- )

s" a custom message" THROWER my-bad

my-bad \ <-- throws. if not caught, 'a custom message' is the error.

With definitions:

\ gforth
: thrower ( c-addr u "name" -- )
exception create , does> @ throw ;

\ SwiftForth
: thrower ( c-addr u "name" -- )
THROW# -rot >THROW create dup , 1+ TO THROW#
does> @ throw ;

\ VFX
: thrower ( c-addr u "name" -- )
here -rot here over 1+ allot place
align create , does> @ 'AbortText ! -2 throw ;

\ iForth
: thrower ( c-addr u "name" -- )
here -rot here over 1+ allot pack drop
create , does> @ $throw ;


This assumes though that it's enough for error messages to vary at
compile time. That's the case for the code above, but oftentimes you
want to say "I had a failure opening <this exact file>". But speaking
of files, their names can be quite long--easily longer than 255
characters. Probably at this point you'd rather have a serious
Log4j-style logging solution rather than exception handling.

Mark Wills

unread,
Apr 22, 2017, 4:59:31 AM4/22/17
to
Maybe just factor it a bit more rather than reaching for the guru code
(untested):

: badIndex? ( flag n -- ) swap not if . ." *** array index " . ." out of bounds ***" abort else drop then ;
: check1 ( x1 dim1 -- x1 ) over u> 1 badIndex? ;
: check2 ( x2 dim2 -- x2 ) over u> 2 badIndex? ;
: check3 ( x3 dim3 -- x3 ) over u> 3 badIndex? ;
: check4 ( x4 dim4 -- x4 ) over u> 4 badIndex? ;
: check5 ( x5 dim4 -- x5 ) over u> 5 badIndex? ;
: check6 ( x6 dim4 -- x6 ) over u> 6 badIndex? ;

KISS (respectfully) :-)

Julian Fondren

unread,
Apr 22, 2017, 5:33:28 AM4/22/17
to
On Saturday, April 22, 2017 at 3:59:31 AM UTC-5, Mark Wills wrote:>
> Maybe just factor it a bit more rather than reaching for the guru code
> (untested):
>
> : badIndex? ( flag n -- ) swap not if . ." *** array index " . ." out of bounds ***" abort else drop then ;
> : check1 ( x1 dim1 -- x1 ) over u> 1 badIndex? ;
> : check2 ( x2 dim2 -- x2 ) over u> 2 badIndex? ;
> : check3 ( x3 dim3 -- x3 ) over u> 3 badIndex? ;
> : check4 ( x4 dim4 -- x4 ) over u> 4 badIndex? ;
> : check5 ( x5 dim4 -- x5 ) over u> 5 badIndex? ;
> : check6 ( x6 dim4 -- x6 ) over u> 6 badIndex? ;
>
> KISS (respectfully) :-)

When ABORT" is implemented with THROW , it stops being the same thing
as IF ." ABORT THEN

: x abort" you don't see this" ;
: y if ." you do see this" abort then ;

true ' x catch drop ok
true ' y catch drop you do see this ok

HAA

unread,
Apr 22, 2017, 9:53:28 PM4/22/17
to
Usually ABORT" represents a fatal event that you want to display and abort.

SwiftForth has ?ABORT

: z s" nor will you see this" ?abort ; ok

true ' z catch drop ok

To use Mark's factoring you'll need to assemble the target string.



Anton Ertl

unread,
Apr 24, 2017, 12:54:20 PM4/24/17
to
Julian Fondren <julian....@gmail.com> writes:
>Or, you could use your Forth system's custom solution to this problem.
>
>gforth: provide a message, get a throw-code back.
>
> s" a custom message" EXCEPTION constant my-exception
>
> my-exception throw
> :3: a custom message
> my-exception >>>throw<<<
> Backtrace:
...
>SwiftForth: provide a message, get a throw-code back (while working a
>little bit more with the system)
>
> THROW#
> s" a custom message" >THROW enum my-exception
> TO THROW#
>
> my-exception throw a custom message
...
>VFX: provide a (parsed) message, get a throw-code constant:
>
> ErrDef my-exception "a custom message" ok
> my-exception throw
> Err# 501 a custom message
> -> my-exception throw
> ^

Hmm, it looks like there is a common need for defining new throw codes
(SwiftForth and VFX would never, ever add features speculatively), and
also common practice in doing it, only the syntax differs. Time to
turn <http://www.forth200x.org/exception.html> into an RfD.

> oftentimes you
>want to say "I had a failure opening <this exact file>".

Or more likely: "<this exact file>: <OS error message>", e.g.,:

"/etc/shadow: permission denied"

The problem is that this does not fit the THROW model well. However,
we already have a THROW-plus-string (ABORT"); we could extend the file
words such that, on error, they store the file name somewhere, and
when the ior is THROWn, the system's handler picks up the file name,
and finally prints the message. That works with the current
interfaces, so there is no need to standardize it. Systems could
already do this now, as part of their quality of implementation.

For what other cases do we need a composed string? If we need one, we
can have a variant of EXCEPTION:

xt-exception ( xt -- n )
where xt ( -- ) prints the error string

- anton
--
M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
New standard: http://www.forth200x.org/forth200x.html
EuroForth 2016: http://www.euroforth.org/ef16/
0 new messages