version 1.67, 2000/08/09 20:04:06
|
version 1.68, 2000/08/10 20:46:25
|
Line 4463 Execution token, same size as Cell
|
Line 4463 Execution token, same size as Cell
|
@item wid |
@item wid |
@cindex @code{wid}, stack item type |
@cindex @code{wid}, stack item type |
Word list ID, same size as Cell |
Word list ID, same size as Cell |
|
@item ior, wior |
|
@cindex ior type description |
|
@cindex wior type description |
|
I/O result code, cell-sized. In Gforth, you can @code{throw} iors. |
@item f83name |
@item f83name |
@cindex @code{f83name}, stack item type |
@cindex @code{f83name}, stack item type |
Pointer to a name structure |
Pointer to a name structure |
Line 4786 One particular problem with floating-poi
|
Line 4790 One particular problem with floating-poi
|
for equality often fails when you would expect it to succeed. For this |
for equality often fails when you would expect it to succeed. For this |
reason approximate equality is often preferred (but you still have to |
reason approximate equality is often preferred (but you still have to |
know what you are doing). Also note that IEEE NaNs may compare |
know what you are doing). Also note that IEEE NaNs may compare |
differently from you might expect. The comparison words are: |
differently from what you might expect. The comparison words are: |
|
|
doc-f~rel |
doc-f~rel |
doc-f~abs |
doc-f~abs |
doc-f= |
|
doc-f~ |
doc-f~ |
|
doc-f= |
doc-f<> |
doc-f<> |
|
|
doc-f< |
doc-f< |
Line 4981 because it is used for looking up names,
|
Line 4985 because it is used for looking up names,
|
conventional dictionary.}, the heap, and a number of system-allocated |
conventional dictionary.}, the heap, and a number of system-allocated |
buffers. |
buffers. |
|
|
|
@cindex address arithmetic restrictions, ANS vs. Gforth |
|
@cindex contiguous regions, ANS vs. Gforth |
In ANS Forth data space is also divided into contiguous regions. You |
In ANS Forth data space is also divided into contiguous regions. You |
can only use address arithmetic within a contiguous region, not between |
can only use address arithmetic within a contiguous region, not between |
them. Usually each allocation gives you one contiguous region, but the |
them. Usually each allocation gives you one contiguous region, but the |
Line 5006 Dictionary allocation is a stack-oriente
|
Line 5012 Dictionary allocation is a stack-oriente
|
you want to deallocate X, you also deallocate everything |
you want to deallocate X, you also deallocate everything |
allocated after X. |
allocated after X. |
|
|
|
@cindex contiguous regions in dictionary allocation |
The allocations using the words below are contiguous and grow the region |
The allocations using the words below are contiguous and grow the region |
towards increasing addresses. Other words that allocate dictionary |
towards increasing addresses. Other words that allocate dictionary |
memory of any kind (i.e., defining words including @code{:noname}) end |
memory of any kind (i.e., defining words including @code{:noname}) end |
Line 5054 doc-cfalign
|
Line 5061 doc-cfalign
|
@cindex dynamic allocation of memory |
@cindex dynamic allocation of memory |
@cindex memory-allocation word set |
@cindex memory-allocation word set |
|
|
|
@cindex contiguous regions and heap allocation |
Heap allocation supports deallocation of allocated memory in any |
Heap allocation supports deallocation of allocated memory in any |
order. Dictionary allocation is not affected by it (i.e., it does not |
order. Dictionary allocation is not affected by it (i.e., it does not |
end a contiguous region). In Gforth, these words are implemented using |
end a contiguous region). In Gforth, these words are implemented using |
the standard C library calls malloc(), free() and resize(). |
the standard C library calls malloc(), free() and resize(). |
|
|
|
The memory region produced by one invocation of @code{allocate} or |
|
@code{resize} is internally contiguous. There is no contiguity between |
|
such a region and any other region (including others allocated from the |
|
heap). |
|
|
doc-allocate |
doc-allocate |
doc-free |
doc-free |
doc-resize |
doc-resize |
Line 5068 doc-resize
|
Line 5081 doc-resize
|
@subsection Memory Access |
@subsection Memory Access |
@cindex memory access words |
@cindex memory access words |
|
|
|
|
doc-@ |
doc-@ |
doc-! |
doc-! |
doc-+! |
doc-+! |
Line 5083 doc-sf!
|
Line 5095 doc-sf!
|
doc-df@ |
doc-df@ |
doc-df! |
doc-df! |
|
|
|
|
@node Address arithmetic, Memory Blocks, Memory Access, Memory |
@node Address arithmetic, Memory Blocks, Memory Access, Memory |
@subsection Address arithmetic |
@subsection Address arithmetic |
@cindex address arithmetic words |
@cindex address arithmetic words |
Line 5091 Address arithmetic is the foundation on
|
Line 5104 Address arithmetic is the foundation on
|
structures like arrays, records (@pxref{Structures}) and objects |
structures like arrays, records (@pxref{Structures}) and objects |
(@pxref{Object-oriented Forth}). |
(@pxref{Object-oriented Forth}). |
|
|
|
@cindex address unit |
|
@cindex au (address unit) |
ANS Forth does not specify the sizes of the data types. Instead, it |
ANS Forth does not specify the sizes of the data types. Instead, it |
offers a number of words for computing sizes and doing address |
offers a number of words for computing sizes and doing address |
arithmetic. Address arithmetic is performed in terms of address units |
arithmetic. Address arithmetic is performed in terms of address units |
(aus); on most systems the address unit is one byte. Note that a |
(aus); on most systems the address unit is one byte. Note that a |
character may have more than one au, so @code{chars} is no noop (on |
character may have more than one au, so @code{chars} is no noop (on |
systems where it is a noop, it compiles to nothing). |
platforms where it is a noop, it compiles to nothing). |
|
|
The basic address arithmetic words are @code{+} and @code{-}. E.g., if |
The basic address arithmetic words are @code{+} and @code{-}. E.g., if |
you have the address of a cell, perform @code{1 cells +}, and you will |
you have the address of a cell, perform @code{1 cells +}, and you will |
have the address of the next cell. |
have the address of the next cell. |
|
|
|
@cindex contiguous regions and address arithmetic |
In ANS Forth you can perform address arithmetic only within a contiguous |
In ANS Forth you can perform address arithmetic only within a contiguous |
region, i.e., if you have an address into one region, you can only add |
region, i.e., if you have an address into one region, you can only add |
and subtract such that the result is still within the region; you can |
and subtract such that the result is still within the region; you can |
Line 5286 CASE
|
Line 5302 CASE
|
@i{n1} OF @i{code1} ENDOF |
@i{n1} OF @i{code1} ENDOF |
@i{n2} OF @i{code2} ENDOF |
@i{n2} OF @i{code2} ENDOF |
@dots{} |
@dots{} |
|
( n ) @i{default-code} ( n ) |
ENDCASE |
ENDCASE |
@end example |
@end example |
|
|
Executes the first @i{codei}, where the @i{ni} is equal to |
Executes the first @i{codei}, where the @i{ni} is equal to @i{n}. If no |
@i{n}. A default case can be added by simply writing the code after |
@i{ni} matches, the optional @i{default-code} is executed. The optional |
the last @code{ENDOF}. It may use @i{n}, which is on top of the stack, |
default case can be added by simply writing the code after the last |
but must not consume it. |
@code{ENDOF}. It may use @i{n}, which is on top of the stack, but must |
|
not consume it. |
|
|
@node Simple Loops, Counted Loops, Selection, Control Structures |
@node Simple Loops, Counted Loops, Selection, Control Structures |
@subsection Simple Loops |
@subsection Simple Loops |
Line 5433 prints @code{0 2}
|
Line 5451 prints @code{0 2}
|
@noindent |
@noindent |
prints @code{1 3} |
prints @code{1 3} |
|
|
|
@item |
@cindex negative increment for counted loops |
@cindex negative increment for counted loops |
@cindex counted loops with negative increment |
@cindex counted loops with negative increment |
The behaviour of @code{@i{n} +LOOP} is peculiar when @i{n} is negative: |
The behaviour of @code{@i{n} +LOOP} is peculiar when @i{n} is negative: |
Line 5686 doc-;s
|
Line 5704 doc-;s
|
@subsection Exception Handling |
@subsection Exception Handling |
@cindex exceptions |
@cindex exceptions |
|
|
If your program detects a fatal error condition, the simplest action |
@c quit is a very bad idea for error handling, |
that it can take is to @code{quit}. This resets the return stack and |
@c because it does not translate into a THROW |
restarts the text interpreter, but does not print any error message. |
@c it also does not belong into this chapter |
|
|
The next stage in severity is to execute @code{abort}, which has the |
If a word detects an error condition that it cannot handle, it can |
same effect as @code{quit}, with the addition that it resets the data |
@code{throw} an exception. In the simplest case, this will terminate |
stack. |
your program, and report an appropriate error. |
|
|
A slightly more sophisticated approach is use use @code{abort"}, which |
doc-throw |
compiles a string to be used as an error message and does a conditional |
|
@code{abort} at run-time. For example: |
|
|
|
@example |
@code{Throw} consumes a cell-sized error number on the stack; there are |
@kbd{: checker abort" That flag was true" ." A false flag" ;@key{RET}} ok |
some predefined error numbers (see @file{errors.fs}). In Gforth (and |
@kbd{0 checker@key{RET}} A false flag ok |
most other systems) you can use the iors produced by various words as |
@kbd{1 checker@key{RET}} |
error numbers (e.g., a typical use of @code{allocate} is @code{allocate |
:1: That flag was true |
throw}). Gforth also provides the word @code{exception} to define your |
1 checker |
own error numbers (with decent error reporting); an ANS Forth version of |
^^^^^^^ |
this word (but without the error messages) is available in |
$400D1648 throw |
@code{compat/except.fs}. And finally, you can use your own error |
$400E4660 |
numbers (anything outside the range -4095..0), but won't get nice error |
|
messages, only numbers. For example, try: |
|
|
|
@example |
|
-10 throw |
|
-267 throw |
|
s" my error" exception throw |
|
7 throw |
@end example |
@end example |
|
|
These simple techniques allow a program to react to a fatal error |
doc---exception-exception |
condition, but they are not exactly user-friendly. The ANS Forth |
|
Exception word set provides the pair of words @code{throw} and |
|
@code{catch}, which can be used to provide sophisticated error-handling. |
|
|
|
@code{catch} has a similar behaviour to @code{execute}, in that it takes |
Your program can catch exceptions and then either correct the problem, |
an @i{xt} as a parameter and starts execution of the xt. However, |
or clean up some data structures and just throw the exception to the |
before passing control to the xt, @code{catch} pushes an |
next exception handler. Note that @code{throw} always executes the |
@dfn{exception frame} onto the @dfn{exception stack}. This exception |
dynamically innermost exception handler; the system's exception handler |
frame is used to restore the system to a known state if a detected error |
is outermost, and just prints an error and restarts command-line |
occurs during the execution of the xt. A typical way to use @code{catch} |
interpretation (or, in batch mode (i.e., while processing the shell |
would be: |
command line), leaves Gforth). |
|
|
@example |
The ANS Forth way to catch exceptions is @code{catch}: |
... ['] foo catch IF ... |
|
@end example |
|
|
|
@c TOS is undefined. - anton |
doc-catch |
|
|
@c nac-> TODO -- I need to look at this example again. |
The most common use of exception handlers is to clean up the state when |
|
an error happens. E.g., |
|
|
|
@example |
|
base @ >r hex \ actually the hex should be inside foo, or we h |
|
['] foo catch ( nerror|0 ) |
|
r> base ! |
|
( nerror|0 ) throw \ throw on |
|
@end example |
|
|
Whilst @code{foo} executes, it can call other words to any level of |
A use of @code{catch} for handling an error might look like this: |
nesting, as usual. If @code{foo} (and all the words that it calls) |
|
execute successfully, control will ultimately pass to the word following |
|
the @code{catch}, and there will be a 0 at TOS. However, if any word |
|
detects an error, it can terminate the execution of @code{foo} by |
|
pushing a non-zero error code onto the stack and then performing a |
|
@code{throw}. The execution of @code{throw} will pass control to the |
|
word following the @code{catch}, but this time the TOS will hold the |
|
error code. Therefore, the @code{IF} in the example can be used to |
|
determine whether @code{foo} executed successfully. |
|
|
|
This simple example shows how you can use @code{throw} and @code{catch} |
|
to ``take over'' exception handling from the system: |
|
@example |
@example |
: my-div ['] / catch if ." DIVIDE ERROR" else ." OK.. " . then ; |
['] foo catch |
|
dup myerror = if \ an error we can do something about? |
|
... \ do something about it |
|
else |
|
throw \ if there is an error, throw it on |
|
endif |
@end example |
@end example |
|
|
The next example is more sophisticated and shows a multi-level |
Having to wrap the code into a separate word is often cumbersome, |
@code{throw} and @code{catch}. To understand this example, start at the |
therefore Gforth provides an alternative syntax: |
definition of @code{top-level} and work backwards: |
|
|
|
@example |
@example |
: lowest-level ( -- c ) |
try |
key dup 27 = if |
@i{code1} |
1 throw \ ESCAPE key pressed |
recover \ optional |
else |
@i{code2} \ optional |
." lowest-level successful" CR |
endtry |
then |
@end example |
; |
|
|
|
: lower-level ( -- c ) |
This performs @i{Code1}. If @i{code1} completes normally, execution |
lowest-level |
continues after the @code{endtry}. If @i{Code1} throws, the stacks are |
\ at this level consider a CTRL-U to be a fatal error |
reset to the state during @code{try}, the throw value is pushed on the |
dup 21 = if \ CTRL-U |
data stack, and execution constinues at @i{code2}, and finally falls |
2 throw |
through the @code{endtry} into the following code. If there is no |
else |
@code{recover} clause, this works like an empty recover clause. |
." lower-level successful" CR |
|
then |
|
; |
|
|
|
: low-level ( -- c ) |
doc-try |
['] lower-level catch |
doc-recover |
?dup if |
doc-endtry |
\ error occurred - do we recognise it? |
|
dup 1 = if |
|
\ ESCAPE key pressed.. pretend it was an E |
|
[char] E |
|
else throw \ propogate the error upwards |
|
then |
|
then |
|
." low-level successfull" CR |
|
; |
|
|
|
: top-level ( -- ) |
The cleanup example above in this syntax: |
CR ['] low-level catch \ CATCH is used like EXECUTE |
|
?dup if \ error occurred.. |
@example |
." Error " . ." occurred - contact your supplier" |
base @ >r try |
else |
hex foo \ now the hex is placed correctly |
." The '" emit ." ' key was pressed" CR |
0 \ value for throw |
then |
endtry |
; |
r> base ! throw |
@end example |
@end example |
|
|
The ANS Forth document assigns @code{throw} codes thus: |
And here's the error handling example |
|
|
@itemize @bullet |
@example |
@item |
try |
codes in the range -1 -- -255 are reserved to be assigned by the |
foo |
Standard. Assignments for codes in the range -1 -- -58 are currently |
recover |
documented in the Standard. In particular, @code{-1 throw} is equivalent |
dup myerror = if |
to @code{abort} and @code{-2 throw} is equivalent to @code{abort"}. |
... \ do something about it |
@item |
else |
codes in the range -256 -- -4095 are reserved to be assigned by the system. |
throw |
@item |
endif |
all other codes may be assigned by programs. |
endtry |
@end itemize |
@end example |
|
|
Gforth provides the word @code{exception} as a mechanism for assigning |
There are two alternatives to @code{throw}: @code{Abort"} is conditional |
system throw codes to applications. This allows multiple applications to |
and you can provide an error message. @code{Abort} just produces an |
co-exist in memory without any clash of @code{throw} codes. A definition |
``Aborted'' error. |
of @code{exception} in ANS Forth is provided in |
|
@file{compat/exception.fs}. |
|
|
|
|
The problem with these words is that exception handlers cannot |
|
differentiate between different @code{abort"}s; they just look like |
|
@code{-2 throw} to them (the error message cannot be accessed by |
|
standard programs). Similar @code{abort} looks like @code{-1 throw} to |
|
exception handlers. |
|
|
doc-quit |
|
doc-abort |
|
doc-abort" |
doc-abort" |
|
doc-abort |
doc-catch |
|
doc-throw |
|
doc---exception-exception |
|
|
|
|
|
|
|
Line 11504 These section lists the ANS Forth words
|
Line 11508 These section lists the ANS Forth words
|
elsewhere in this manual. Ultimately, they all need proper homes. |
elsewhere in this manual. Ultimately, they all need proper homes. |
|
|
doc-[compile] |
doc-[compile] |
|
doc-quit |
|
|
The following ANS Forth words are not currently supported by Gforth |
The following ANS Forth words are not currently supported by Gforth |
(@pxref{ANS conformance}): |
(@pxref{ANS conformance}): |
Line 12508 All files that are left via the exceptio
|
Line 12512 All files that are left via the exceptio
|
|
|
@item @i{ior} values and meaning: |
@item @i{ior} values and meaning: |
@cindex @i{ior} values and meaning |
@cindex @i{ior} values and meaning |
|
@cindex @i{wior} values and meaning |
The @i{ior}s returned by the file and memory allocation words are |
The @i{ior}s returned by the file and memory allocation words are |
intended as throw codes. They typically are in the range |
intended as throw codes. They typically are in the range |
-512@minus{}-2047 of OS errors. The mapping from OS error numbers to |
-512@minus{}-2047 of OS errors. The mapping from OS error numbers to |