Some dozens make a long dozen,
but they won't make thirteen.
Some wise guy
STRENGTH IN FORTH
part twelve
EXTENDED REMARKS ON ELEVEN PARTS
I decided to give part twelve of this FORTH-course the above
title after many deliberations. I thought it was getting time to
give you an overall view on the FORTH-system. That means we have
to put things together, which have been scattered all over the
course and we have to explain things we left in the darkness of
'coming soon'. This time we are going to discuss three smaller
subjects: a) how a FORTH-system could look like; b) how a word is
placed in the dictionary and c) how it is searched for. I hope, I
can manage to put it all into a First Word file of 32K. At the
end of this part you will find the solutions to part eleven, but
there will not be any new exercises, as the subject of this part
isn't fit for it.
FORTH IN DISGUISH
It may have occurred to you, that FORTH has many faces, although
you will recognise a FORTH-system at the moment you see one.
What I do not mean with the word "system" here, is what could be
better described as the "package" you get when you buy a FORTH or
when you get one of the many FORTHs, available in the Public
Domain. In this last department - as far as I know - are three
FORTH-packages which use a 16-bit stack. Those are COMFORTH
(september-87-version),VOLKSFORTH vs 3.8 and ST-FORTH. There
happens to be only one PD-FORTH which uses 32-bit stacks. This
FORTH is called UNIX-FORTH-83. It is not available in any PD-
library in the Kingdom of The Netherlands. This is due, I think,
to the fact that three files of the version which circulates
among ST-owners, are irrepairably damaged. These files can be
well left out and yet you will have a perfectly operating
FORTH. One of my FORTH pen-diskfriends - I don't own a modem - is
constantly working to enrich this UNIX-FORTH with new items. The
other day he has develloped a marvelous editor and he now is busy
all day programming a GEM-library. This 32-bit FORTH can be
obtained by modem-owners through the BBS ST HAARLEM phone 023-
340077. In the commercial war-zone there is a fight between at
least one (1 !) 16-bit and two (2 !) 32-bit FORTHs, which are
called ST-FORTH - same name as the one PD - 32-FORTH and 4*FORTH
respectivily. All FORTHs mentioned here are very well documented
except for the UNIX-FORTH. But I am working to overcome this
shortcomings. I've just finished a Glossary of all the words used
in the Kernel. This Glossary contains a description - in ASCII-
order - of the stackaction, the name of the word, the use and
further details of all( minus 6) Kernel words. As soon as I've
completed this huge task by adding all user-words of the Utility-
and Assembler-files, you will hear from me. I will - of course -
see to it, that this Glossary will be PD. Soon there will be a
pre-release to give some smarter guys than me an opportunity to
comment to that Glossary. It must be said, that a FORTH with a
32-bit stack does not quite match the 83-Standard. I think it a
minor difference for the user. Instead of using the optional
Double Number Set in the 16-bit configuration to handle larger
numbers (larger than 16 bit can hold), the 32-bit FORTH provides
facilities to meet with explicit 16-bit values. So, it is in some
respect the other way round. All these FORTHs provide a Kernel -
the naked system - some editing facilities and an Assembler. And
often much more !! But we are not really interested in these
elements. Here and now I will link your attention on the memory
allocation of FORTH when the system has been installed in your
ST. I will not mention absolute memory-addresses, as these may
vary widely, depending on the system in use, nor is it to you to
take the given description as a prescription to which a FORTH is
pinned down. At the end of my description of a FORTH-system, I
hope you'll be able to 'decode' any FORTH in the future.
AT L(E)AST: SOME ART !
First of all I'll better draw a memory-allocation map of a FORTH-
system, based on UNIX-FORTH-83. Just for illustrating a few
points, eh !!
? ?
/|\ /|\
| video ram |
_____________________________________________
| |
| Free Memory |
| ^ ^ |
|¯¯¯v¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯v¯¯¯|
|________^____________Pad____________^________|
| v v |
| |
| ^ Here ^ |
|¯¯¯¯¯¯¯¯v¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯v¯¯¯¯¯¯¯¯|
| |
| Applications Dictionary |
|¯ ¯ ¯ ¯ ¯ ¯ ¯ ¯ ¯ ¯ ¯ ¯ ¯ ¯ ¯ ¯ ¯ ¯ ¯ ¯ ¯ ¯ ¯|
|===================Fence=====================|
| |
| Kernel or Nucleus |
| Dictionary |
| |
|___________________Origin____________________|
| |
| |
|_up0___^___________User Area_________^___up0_|
| rp0 v Return Stack v rp0 |
| |
| |
|_'tib__^_______________Tib___________^__'tib_|
| sp0 v Parameter Stack v sp0 |
| |
| |
| |
| |
|_______________Next_Free_Memory______________|
| v v |
| Free Memory |
| |
|_____________________________________________|
| | | |
| v Used by GEM v |
| |
| |
I told you once, I could do some nice painting....Well....?!
To give you an idea about the amount of space my configuration of
this UNIX-FORTH uses to settle down, imagine HERE is at address
427152, ORIGIN at 327680 and SP0 at 326684. The v- and ^-signs
are to be considered as arrows, maybe pointing up, maybe down.
Let's begin where each carreer starts....at the bottom. And
secondly, let's give GEM, what it belongs: the memory-space in
the deep dungeons of your ST. All memory up to Next-Free-Memory,
not used by GEM, may be used by you. Climbing up our Social
Memory Staircase we arrive at Parameter Stack and Tib. On both
sides of these words are sp0 and 'tib. If we should investigate
these two little words, which we will, we are to discover
something strange. Both words are user-variables. They hold some
value, where variables are made for, and they both hold the same
value. That value is a memory-address. This address now indicates
the start of the Parameter Stack (hold by sp0), the so called
bottom of the stack, and the start of the Terminal Input Buffer
(hold by 'tib) as well. As you can see the arrows point down in
the stack area and up in the buffer area. The meaning of this is,
that putting values on the stack will cause the stack to grow
downwards. Every next value is put at a lower address than its
predecessor. This movement is closely watched by another pointer-
word {SP@). We used this word in one of the first issues of this
course. It will print the address of the next available
stackspace, when used as {SP@} {.}. If we were able to increase
the pointer, held in {SP@}, FORTH would think that the next value
was to be put at that higher address and would overwrite the
value already there. Putting values onto the stack and DROPping
them again is made possible by increasing and decreasing the
address held in that Stack Pointer. So, if you get the message
Stack Empty, then it is not to inform you that there are no
values in the address space of the Parameter Stack, but to tell
you that the Stack Pointer points to the bottom of the stack. In
the case of the Terminal Input Buffer the terminal input starts
at the bottom, called Tib and moves upwards. This buffer is only
a minor one. Mostly it is as large as 80 bytes. Still higher we
see a similar situation. This time the Return Stack and the User
Area are involved. The functions of the Return Stack have been
explained earlier. As you can see it grows downward to lower
memory-addresses. Starting at up0 and moving to higher memory is
the User-Area. Here live those mysterious user-variables. Now the
time has come to throw some light on those peculiar creatures,
which you met frequently, but which I nevertheless left
unexplained. A user-variable is a system variable. This means,
that the value linked to such a variable - a number or an address
- is of high importance for the welfare of the system. Many user-
variables are initialised on a cold start of the FORTH-system,
and should not be used for plain variables in an ordinary
application. Only if you intend to make system modifications, you
are allowed to modify user-variables or to create new ones. It
should be perfectly clear, that user-variables are specifically
not intended to be used and certainly not by the user In UNIX-
FORTH the User Area is exactly 1024 bytes high. That means
whereas for a 32-bit FORTH every value counts 4 bytes, that 256
different user-variables can be hold in this residence. That's
fair enough ! Let's look still closer by creating a fancy user-
variable. We need the word {NUSER}. 100 {NUSER} IPL OK . We
created a new word {IPL}. So {NUSER} is a defining word. Two
things happened. First: the name of the new user-variable was
placed in the DICTIONARY as usual. Secondly: space was allocated
(4 bytes), in a separate User Area, in which the value of {IPL}
will have to be stored at a later date. This value will not be
100, as you might have expected. It could be 100, but it will
never be that 100 we used to define the variable {IPL}. That 100
is an offset. Hundred times 4 bytes are added to the address held
in {UP0} - the start of the User Area - and then 4 bytes are
allocated to hold the value of {IPL}. This last value is not
initialised. If you execute {IPL}, you will get the address in
the User Area in which is stored the value of {IPL}. If you {IPL}
{?}, then the value at {IPL}'s address in the User Area is
displayed at your screen. At this moment it can be anything.
It is not said, that your system provides the word {NUSER}. I
used it from that UNIX-FORTH. Two more additional words may be
used to define a user-variable in that system: {USER} and
{TUSER}. The basic word is {USER}. {NUSER} and {TUSER} are
basically equivalent, but their names are chosen merely for the
sake of easy understanding. To get the same result with {USER} as
with {NUSER} I should have entered 100 {4*} {USER} IPL. May be
that 100 {USER} IPL will do in other systems. Some very common
user-variables are:
Name | contains Name | contains
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
UP0 start of User Area SP0 start of parameter stack
RP0 start of return stack DP first free dictionary byte
FENCE barrier for forgetting CONTEXT vocabulary searched first
CURRENT voc for definitions STATE compile or interprete ?
BASE for numeric in- output DPL numeric input punctuation
LAST nfa of latest def. HLD points to last char in PAD
and there are several more.
ABOUT STATIONS AND BARRIERS..AND SOME SCRATCHING !
The next station we will visit on our race to the top is
{ORIGIN}. Here is the start of the Kernel, the Nucleus, the Root.
All addresses in a FORTH-system are derived from {ORIGIN}, which
on execution gives the address of the beginning of FORTH's
precompiled portion of the dictionary. Going up we meet {FENCE}.
As you just saw, {FENCE} is a user-variable. Its value is an
address between {ORIGIN} and {HERE}, between start and finish of
all the code compiled in the dictionary, the Root as well as the
applications' part. This address acts like a barrier. When you
instruct {FORGET} to forget a word, {FORGET} will do the job, if
it can find that word between {FENCE} and {HERE}. If the word to
{FORGET} is situated beneath {FENCE}, there will be a message and
the system will {ABORT}. The dictionary part between {ORIGIN} and
{FENCE} is a restricted area for {FORGET}. You may change the
barrier-address in {FENCE} to a higher or a lower address: {HERE}
{FENCE} {!} will store the address of the first free space in the
dictionary in {FENCE}. As long as you will be programming in this
new configuration, only the words you will enter afterwards, can
be forgotten. This method is recommended if you want to add some
application to the dictionary for good. In this case you will
have to save this configuration to disk, of course. Most systems
provide words to do so: {SAVE-SYSTEM} or the like. Of course you
can act like this: {ORIGIN} {FENCE} {!} OK and then {FORGET}
{ORIGIN} OK. It won't harm anybody personally, except you ! If
you fully back-upped your system, then you may recover your
FORTH. Otherwise you are through and done !! As you can see,
{HERE} fluctuates. It can go up, it can go down on the rhythm of
adding to and deleting words from the dictionary. And with {HERE}
{PAD} moves up and down in the same rhythm. {PAD} is simply
defined as : PAD HERE 50 + ; in this UNIX-FORTH. {PAD} is
really a scratch-pad. It allows two different kinds of use. It
may be used as a scratch-pad for numeric output conversion. As a
numeric pad {PAD} stores its data downwards. If the scratching is
done with text, then {PAD} stores the data upwards. The FORTH-
dictionary may grow until the end of 'normal' memory is reached
and the video-ram begins. How much room there is left for your
own applications depends on the system you use. ( And the Atari
you can afford !!)
FORTH DID IT HIS WAY
The second item we were to discuss in this issue, was the item of
how FORTH places a word in the dictionary. I've told you
something about it, but not those very intimate details. So if
you are over eightteen, keep on reading, otherwise ask your dad
or mum. First lesson: every FORTH has his own way ! I told you so
in part 10 of this course. Then we were discussing the word
{MBUF}. So look back and read it again. It was said there, that
my magnificent 1STWORD-drawing of an dictionary-entry was not the
one and only permitted. Several differently constructed entry's
are possible. But there are always a number of elements which
can't be left out in any entry. Every word has to have a
christian name. Christianed or not. Some FORTH's have some
limitations on the length of the name: a maximum of 4 characters
e.g. Others don't care what length, as long as a particular name
doesn't exceed 31 characters. Some of those will place only a
limited amount of that 31 characters in the NAMEFIELD, others are
more tolerant and will take them all 31. So there has to be a
namefield. The startaddress of this field is shorthened to {NFA}.
In this namefield the first byte helds the number of characters
stored in the namefield. Secondly there has to be PARAMETERFIELD,
even if it hasn't been initialised. In this field data is
stored. The startingaddress of this area is shortened to {PFA}.
The data in the parameterfield can be a number ( all data are
numbers of course, but I mean a real number, a value), or they
can be addresses. The third field is called LINKFIELD. {LFA}
stands for the startaddress of this field. For the simple-minded
Dutch: not only is it a field that by means of an address stored
in that place links the whole dictionary together, but it is
really a "link" (for simple-minded English-speaking "tricky" )
field. More later !! The fourth (beautiful word !!) field is the
CODEFIELD or COMPILATIONFIELD. I prefer codefield, because I
can't type very fast. The short form for the startingaddress of
the codefield is {CFA}. This field holds a pointer to the start
of some code. To what code depends on the action, that a
particular word has to perform. Don't think that a computer -
even loaded with FORTH - has a basketful of such codes: NO !
FORTH has some words to switch from namefield to linkfield and
from codefield to parameterfield etc. A list is to be found at
SUMMARY.
This four fields are used to make a word and with many words
together a dictionary in each FORTH. In the middle of two fields,
or in the front of all four, or at the back will be inserted a
byte ! In this byte resides the immediate bit, or not, if the
word is not immediate. Which bit will be honoured with this task
is of no importance.(For instance in that UNIX-FORTH it is the
sixth one, but it could as well have been the fifth ).
Principally it is of no importance either, in which order those
four fields are grouped. In the WYCOVE-FORTH the linkfield is the
second one after the namefield has been set up, as it is FIG-
FORTH. In UNIX-FORTH the linkfield is the first field, standing
in front of the namefield. So we have a name, data and specific
code which can handle the data. As I said the most tricky field
is the linkfield. This field 'chains' the dictionary. But not in
the way you thought it would do. Suppose our dictionary has grown
to some extend of 1000 words and we want a particular word
executed. So
{."} Linkfield {"} Linkfield OK
will print out at your screen "Linkfield". It was done by the
word {."}. Before FORTH can execute that word, FORTH has to look
it up in the dictionary. And FORTH has to find the right word,
not some ' this will also do'-word. So FORTH has to investigate
the whole dictionary, if a word happens to be deep in FORTH's
dungeons ?? NO !! Perhaps you would, FORTH won't. In this respect
FORTH is a junk, he uses HASH. This HASH-function is that very
tricky way in which FORTH succeeds to minimalise the amount of
dictionary-words to find its way through, to come to the right
desired word and that beyond any doubt. It depends on the
'depth' of the HASH-function, but at any 'depth' it will save an
enormous amount of searching in the dictionary and thus time,
time and time again. Simply said, the hash-function divides all
words that will be entered in the dictionary into groups. How
many groups depends. My lovely UNIX-FORTH has four groups, but a
FORTH like 4*FORTH has some 16 (!). The forming of the groups is
simply done by looking at the first character of the word. And
{HASH} - in UNIX-FORTH - is a normal word. Or should better I say
spell ?
THE SECRET YOU SHARE WITH HASH
Problably the supersonic speed at which FORTH searches the
dictionary for a particular word, have struck you. Partly it's
the language's speed itself. For a (much greater) part it is - as
I described above - the {HASH}-trick that does it. This trick has
a double effect. At first it works when you enter a word,
afterwards - when there is a search for a word - it makes use of
the information that {HASH} provided and that was stored
in.....the LINKFIELD !! The dictionary is not really a simple
chain of words, one after another as they have been entered.
Actually the dictionary is splitted up in vocabularies ( See part
11). A vocabulary consists of a group of words that for some -
most logical - criterion has been brought together: the Editor,
the Assembler. But such a vocabulary itself isn't a compact list
of all the words belonging to itself too.
Vocabularies can be into two very different states. A vocabulary
can be the {CONTEXT} vocabulary. That means that the search for
words starts in this vocabulary. As all vocabularies are
connected - similar as the words are linked -, a search for a
word will continue in the next linked vocabulary, if a word can't
be found in the {CONTEXT} vocabulary. In the other situation the
vocabulary is indicated as {CURRENT}. It means that new
definitions are placed in that vocabulary. And as we mentioned
above, at the creation of new entries {HASH} gets the lead.
A TRICKY PART
So let's reveal {HASH}'s secret in the UNIX-FORTH. Assuming, that
EDITOR is the {CONTEXT} vocabulary, {EDITOR} {DEFINITIONS} will
make it the {CURRENT} one, in which new definitions can be
placed. Because {HASH} is part of {CREATE} (and that last one
part of the {:}-word), we can study the mechanism by which a new
word is placed in the {CURRENT} vocabulary best, by analysing
{CREATE}. First of all, {CREATE} has to accept a namestring. That
will be the name of the new word. This string will be moved then
to the buffer called {WORD}. {WORD} always leaves the
startingaddress of that string on the stack. This address is
going to be {DUP}ed first and one of the two stringaddresses will
be used to check if the name of the new word you want to create
already exists. If, then a message is given: .....isn't Unique or
the like. The next thing to do, is to 'even' the address of
{HERE}, then the address of {HERE} is put onto the stack.
Remember {HERE} is at the top of the dictionary !! At the address
of {HERE}, {CREATE} puts a zero. So {CREATE} keeps that place
occupied, because {CREATE} will use this place within a second or
less to store the linkaddress. What is to come now , is very
important for to understand what follows afterwards. You know,
yes you know, that when {CREATE} put that occupying zero at the
address of {HERE}, {HERE} was incremented ( with 4, as UNIX-
FORTH's numbers counts 4 bytes = 32 bits), to form a new-{HERE}.
This new-{HERE} is {DUP}ed, one is put onto the stack and with
the help of {!} the other one in {LAST}. This is done because in
this UNIX-FORTH the namefield comes after the linkfield and
{CREATE} is going to use this new-{HERE} as the {NFA}. So
recapitulating: on the stack are two items: on top the old-{HERE}
and beneath the {NFA} of the namestring of the new word. We say:
the new word is called {PIPO}. Now {CREATE} {SWAP}s the items on
the stack. The stringaddress is on top now. The use of {COUNT}
{HERE} takes care of a stack on which the items are well fit for
the work {PACK} has to do. This word is a character-moving word.
{PACK} gets the namestring - the countbyte as well - and puts it
on the address of new-{HERE} and in one go {PACK} places this
new-{HERE}-address on the stack.
_________________________________________________________________
NOW TAKE AN EASY CHAIR (PLAYGIRL ?!) AND A CUP OF VERY STRONG
COFFEE AND LEAN BACK FOR A WHILE. You earned it !!
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
On the stack are old-HERE - {LFA} - and new-HERE - {NFA}.
{CREATE} now puts the address of {CURRENT} on top of the stack.
The pointer to the vocabulary into we want to place the new word
PIPO is hided in that address. The stack shows {LFA} - {NFA} -
vocabulary-pointer, all prepared well for {HASH}. {HASH} takes
the voc-pointer and puts it into the D1-register van de 68000-mc.
The stringaddress goes to A0. This register - that is, the
address in the register - is incremented with one to jump over
the countbyte. You know, strings do have countbytes; they count
the characters of the string. We are at the first character of
the name of the word. It was getting time !! That first letter is
the 'p'. And this 'p' is bytemoved to register D0. As a register
counts 32 bits, the rest - 24 - has to be turned to zeroes. This
D0-register now looks like:
0 0 0 0 0 0 0 0- 0 0 0 0 0 0 0 0- 0 0 0 0 0 0 0 0-0 1 1 1 0 0 0 0
This configuration is ANDed with 3, binary 11. Three, because
UNIX-FORTH has four - 0 1 2 3 - threads. The meaning of the
thread-word will be explained in a moment. Let's take the
contents of register D0. We only take the right byte: 0 1 1 1 0 0
0 0. This is the binary code for lowercase 'p'. The other three
bytes on the left side are always zero. The rightmost byte
changes if the first letter of the new word changes. In this
rightmost byte the only important bits are those two rightmost
bits, as these bits are the ones that may be changed by ANDing
with 3. The number 3 itself also consists of 32 bits, but the 30
leftmost ones are always zero and in this context of no
importance. These two rightmost bits of the first letter of the
new word in register D0 can look like the following:
0 0 0 1 1 0 1 1
ANDing with 3 1 1 1 1 1 1 1 1
Result 0 0 0 1 1 0 1 1
The result in decimal: 0 1 2 or 3. Thus in D0 stands, depending
on the first letter 0 1 2 of 3. By adding D0 twice to itself,
the D0-register will show 0 4 8 of 12. All characters that can
serve as the first character of a FORTH-word are divided into
four groups in this simple way !! The characters d h l p are
part of the group of 0, a e i n in the contrary belongs to 4.
All characters belonging to the same group are called a THREAD.
So there can be 4 threads or 10 or 16. You should experiment with
the ANDing, to see how you will get 8 groups of characters. Let's
stick with 4 groups. The result of the ANDing is added then to
the voc-pointer. In the case of PIPO the result was 0 and
therefore the voc-pointer remains unchanged. Out of this
pointer is destilled an address. NOW THIS ADDRESS IS THE
LINKADDRESS OF a) THE PREVIOUS WORD THAT HAS BEEN DEFINED AND b)
THAT BELONGED TO THE SAME THREAD. So in voc-pointer+0 is the
linkaddress of the previous defined word beginning with d h l p
or another character of this thread. In voc-pointer+4 is the
linkaddress of the group of a.o. the characters a e i n .
Etcetera. After all that the address of old-HERE is placed into
this voc-pointer, so the following word of the 0-thread can use
it as a link. Remember: in the voc-pointer is always the
linkaddress of the latest word of a specific thread that has been
defined. We have the linkaddress of the previous word. This
address is put into the address of old-{HERE}, the {LFA} of
{PIPO}. As each vocabulary has its own {CONTEXT}-address, it also
has its own thread-addresses. How vocabularies are chained is in
relation to {CREATE} of no importance; that subject gets
important when a particular word has to be searched by {FIND}. At
last we have got so far, that we can gladly announce, that
{CREATE} has done the job it was hired for. The only remaining
thing for {CREATE} to do is to construct the immediate-byte. But
explaining that we would go to deep into the UNIX-FORTH. The
facts are that after the nfa of {PIPO} a so called flag-byte is
inserted and initialised to zero. Is an IMMEDIATE word involved,
then the word {IMMEDIATE} will set one of the bits into the flag-
byte. In all other cases all bits will be zero. At last the
codefield and the parameterfield are installed. And so dear
countrymen and lovers an entry has become something like this:
|¯¯¯¯¯¯¯¯¯¯¯¯¯¯|
| LFA |
| |
|¯¯¯¯¯¯¯¯¯¯¯¯¯¯|
| NFA |
| |
|¯¯¯¯¯¯¯¯¯¯¯¯¯¯|
| FLAG BYTE |
| |
|¯¯¯¯¯¯¯¯¯¯¯¯¯¯|
| CFA |
| |
|¯¯¯¯¯¯¯¯¯¯¯¯¯¯|
| PFA |
|______________|
We saw, how {CREATE} made use of {HASH} to build 4 little 'sub'-
vocabularies into a vocabulary. Each 'sub' is a linked list of
those words that have the two same rightmost bits of the first
character of their name in common state. As the words provided to
do the search- part of FORTH's job, make use of that same {HASH},
the word asked for can be found - in the most unfriendish
circumstances - by searching 25 % of ALL words. This increases
the searching speed with 300 % at worst conditions. And these
last seven sentences will have to form the third item of which I
promised to tell you about: searching the dictionary. But
Statistics gives Bytes 33K and that's too much. I hope things are
clear now, although I doubt it.
_________________________________________________________________
NOW TAKE TWO EASY CHAIRS, TWO (PAPER)PLAYGIRLS AND A WHOLE POT OF
VERY STRONG COFFEE !! AND HATE ME !!!!
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
With doubtful greetings !
SUMMARY
{N>LINK} changes nfa to lfa ******* {L>NAME} changes lfa to nfa
{NAME>} " nfa to cfa ******* {LINK>} " lfa to cfa
{BODY>} " pfa to cfa ******* {>BODY} " cfa to nfa
{>NAME} " cfa to nfa ******* {>LINK} " cfa to lfa
EXTRAS
This is going to be the most very special EXTRAS ever written in
this course, because somebody has to stop Richard Karsmakers for
going on and on about that booklet of mr. Tolkien, The Lord of
the Rings. I hope this will reach him before it's too late. Do me
a favour, dear Richard and read The Chronicals of Thomas
Covenant. There are six (6) volumes, over 2300 pages of the most
marvelous story I ever happened to read. The author's name is
Stephen Donaldson. The volumes are published by Ballantine Book,
U.S.A. The title of the first volume of the first episode is Lord
Foul's Bane. Every episode counts three volumes and there are two
episodes. Especially for Dutch readers it's be written here, that
the translation into Dutch of most volumes has been done by Max
Schuchart, who was honoured with the Nyhoffprijs for translation
( in magnificant DUTCH ) of The Lord Of The Rings. The Dutch
title of the first volume of 'De kronieken van Thomas Covenant'
is De Vloek van Heer Veil. Published by Sirius en Siderius, Den
Haag, ISBN 906441033x. If you liked The Lord Of The Rings, you
are going to swallow the epos of Thomas Covenant. And in the case
of you, Richard, it will purify your thoughts - nobody has been
named SAG in that epos. I can testify about the healing power of
this book, because I didn't SENT(!!) a very angry letter to ST
NEWS for two reasons. The first one is called Thomas Covenant.
The other one is, because I felt writing angry and ferocious
letters is the easiest thing a man can do not to solve the real
problem; if there is one. The last - milder - letter you wrote
about the SAG, was a wise decision. You, Stefan and all the
others involved in ST NEWS in which way whatsoever, you, - we -
have to write a better worldwide diskmagazine, not to fight a
personal local war. So read it (THEM books, I mean !!).
SOLUTIONS TO PART ELEVEN
1. As you might have expected, {:} is an immediate word. The
reason why ? Well {:} has to be executed immediately to
2. Each 'plain' defining word adds something specific to all
the words it defines. They become 'family' Each word entered
into a vocabulary gets some mark, one could say. If the word
{PIPO} has been marked as belonging to the {CLOWNS}-
vocabulary, it has something in common with all words entered
in that vocabulary. In this way there is some agreement.
3. In {PIPO}, of course. Just look 7 lines higher.
4. In that case only the {I-CRY}-word that had been defined
last, would have been used in other words, that would make
use of {I-CRY}. Only all the older words than that last {I-
CRY}, would make use of that first one.
5. This answer should be the opposite of the answer to exercise
4. If the two {YOU-CRY} had been defined into a different
vocabulary, each execution of {YOU-CRY} in the appropriate
vocabulary would result in a different response.
6. This definition is the usual definition of {WHILE}. There is
nothing special about it. Or it should be the simple fact,
that there is little or no difference between these two loop-
starting words.
�
Disclaimer
The text of the articles is identical to the originals like they appeared
in old ST NEWS issues. Please take into consideration that the author(s)
was (were) a lot younger and less responsible back then. So bad jokes,
bad English, youthful arrogance, insults, bravura, over-crediting and
tastelessness should be taken with at least a grain of salt. Any contact
and/or payment information, as well as deadlines/release dates of any
kind should be regarded as outdated. Due to the fact that these pages are
not actually contained in an Atari executable here, references to scroll
texts, featured demo screens and hidden articles may also be irrelevant.