Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Heilman C.Pocket Forth manual.V0.6

.5.txt
Скачиваний:
12
Добавлен:
22.08.2013
Размер:
60.34 Кб
Скачать
Pocket Forth, version 0.6.5 by Chris Heilman 9/30/95

Introduction

Forth is a beautiful language. It is easily spoken and source code looks like
poetry. Oh yes, Forth produces fast compact code. Pocket Forth is a small
Forth system for the Macintosh computer, founded on well documented
principals(1,2,3). Although Forth is being standardized, Pocket Forth has
evolved independently of the standard.

Pocket Forth is based on Flint by G. Yates Fletcher(4), figFORTH(5,6) and the
Forth described in Starting FORTH by Leo Brodie(7). I wrote Pocket Forth to
experiment with the Macintosh toolbox and Apple Events. Pocket Forth can
produce applications that run under any system version.

Programs are easily modified and you are encouraged to adapt Pocket Forth into
your own program. Toward this end, you own your copies of Pocket Forth.
Programs may be distributed with no royalties, homage, or other restrictions,
even if the Forth system is available to the end user.

NOTE С Pocket Forth is not warranted for any particular purpose. That means
you assume all of the responsibilities in the use of Pocket Forth.

I have attempted to make Pocket Forth free of bugs, but low level languages,
such as Forth, allow you access to the operating system. Therefore, use Pocket
Forth with care in conjunction with other programs or files. This is
especially true when writing programs that access the disk, or when
experimenting while using other programs that do. Always open a backup of any
file you may want to keep, including Pocket Forth itself. Never run originals!

If you are new to Forth, read Starting FORTH to learn the language. The
Starting folder (inside of the Extensions folder) has more information on
using Pocket Forth with Starting FORTH to learn the language.

Preparation

To use Pocket Forth, follow this procedure:

Ґ Back up Pocket Forth before running it. Put the original away and make a
working copy. Be sure to run the working copies only.
Ґ Double click the program's icon. If everything is ok, a window will appear
and say so. The 'ok' prompt and cursor indicate that Pocket Forth is ready for
input.

Use other programming utilities, such as resource editors, to provide a rich
programming environment.


About Pocket Forth

Pocket Forth has a simple interpreter that can execute code or compile it into
a dictionary for later execution. Source code text is typed from the keyboard,
pasted from the clipboard or loaded from a file. The text is interpreted one
line at a time. When the line is completed an 'ok' prompt appears and the
input sequence restarts.

The text interpreter parses tokens from the input line (also called the input
stream). Tokens are any group of characters, excluding space, tab and carriage
return. Individual tokens are separated from each other by one or more spaces.
Carriage return signals the end of the line.

Each token of a line is looked up in a dictionary. The dictionary is a list of
named subroutines, called words. Each of these words does a part of the
program in a reusable subroutine. Words can be called by the interpreter or
compiled into larger words.

In executing mode, the word's subroutine is run and the interpreter continues
with the next token. Tokens not found in the dictionary are converted to a
value. If the token is not a valid integer or floating point number, an error
is signaled by printing a question mark and the unrecognized token.

Some words place the interpreter into compile mode. When in compile mode, new
words are defined. Words are written into the dictionary as machine language
subroutines. Thus, Pocket Forth produces subroutine threaded code. A program
is built by factoring an algorithm into its parts, then defining words that
assemble those parts into code. (12)

Here is the structure of the interpreter:

[figure 1]

Text Files

Typing into the Pocket Forth window supplies text to be interpreted. None of
what is typed is saved, so write programs with an editor.

Pocket Forth does not use Forth's traditional block input, rather it
interprets normal text files. This allows program source files to be prepared
with your favorite text editor and tools. Which editor you choose will depend
on memory available and personal preference.

On Macintoshes with MultiFinder or System 7, the Pocket Forth application runs
in multitasking mode. A 64K byte segment is the minimum, but 128K bytes or can
be used. This allows Pocket Forth to run simultaneously with an editor.
Accessory editors can be used with Pocket Forth on even the smallest
Macintosh.

Text from a file can be interpreted by Pocket Forth from the clipboard via
copy and paste, or directly from the file. You may select and copy text from a
source file and paste it into the Pocket Forth window. The pasted text is
printed and interpreted just as if it had been typed in. The 'ok' prompt
returns when the paste is complete.

Files are also interpreted directly. The basic file loading word is "-->"
(pronounced "load"). Follow "-->" with the name of the file. If the file is in
a folder, a path name must be used in the following manner:

--> diskName:folderName:fileName

This will load the file called 'fileName' in the folder 'folderName' from the
disk 'diskName'. If the file to be loaded is in the default folder or on the
top level of the startup disk, then only the file name is necessary. Launch a
Pocket Forth from a folder to make it the default folder.

File, folder and disk names that are to be used with "-->" must not contain
any spaces because the text interpreter stops at spaces, causing the entire
name not to be found. This or other disk errors print an error message and
return control to the keyboard. See the error section for more information.

The word "open" presents a standard file open dialog to peruse. Use it to
select a file to interpret. There are no restrictions on the filename or
location when "open" is used. The File menu has the OpenЙ command available on
it, which calls "open".

If System 7 is being used, files can be loaded by dragging the file icon to
the Pocket Forth icon in the Finder. Release the file icon when Pocket Forth
becomes selected. This causes Pocket Forth to start up if it is not already
running and the file to be loaded.

Files should be saved from the editor prior to pasting or loading into Pocket
Forth. Text files require a carriage return (ASCII: $0D) at the end of each
line. Lines longer than 80 characters choke the interpreter.

A file stack is maintained so that files can load other files. Files can
'nest' up to five levels deep. When a file is finished interpreting, the input
stream returns to the previous file and begins with the line after the "-->"
was encountered. When all levels have been completed, control returns to the
keyboard. If more than 5 files are nested, an error will result.

The text of the current file and all pending files is kept in memory. While
files can be any size, the memory available will limit how large a file will
load. Use short files that deal with single aspects of a program. Reusable
code in small files can be loaded by other files. Simplify source code by
loading a list of modular files and code that is specific to a particular
program.

Comments document a program within the source code. Create comments by
enclosing text within parenthesis or preceding the comment with a backСslash.
Two main types of comments are stack comments and general comments, however
their different structure is by convention only.

A stack comment is a one line diagram of the effect of a word's execution on
the parameter stack. Stack comments may also show compile mode or the return
stack. The purpose of a stack comment is to unambiguously show the effect of a
word. See the stack section. A stack comment: ( before.parameter --
after.parameter ).

General comments tell what a word does, or why it has been defined. A short
explanation comment should accompany each word defined. Long definitions may
contain many comments. By commenting well, your program will be easier for
others to understand and easier for you to maintain. See the example files for
the use of both types of comments.


Memory

Pocket Forth uses memory in six ways. There are two stacks, variables, the
dictionary, free memory available to the dictionary and absolute addresses.

Stack addressing is implied, that is, you push and pop, and the stack
determines what address the actions access. Variable, dictionary, and free
memory addressing are all done with a 16 bit relative address. Absolute
addresses cover the entire addressing range of the 680x0 with a 32 bit double
number.

Understanding the use of relative and absolute addressing is vital to
programming Pocket Forth.

Absolute Addressing

An absolute address is the actual address as seen by the microprocessor.
Pocket Forth treats absolute addresses as double numbers. A double number is
two consecutive 16 bit numbers or a 32 bit number. The double number words
(such as "2swap", "d+" and "2@") can manipulate absolute addresses. Absolute
addressing allows access to any address whether 24 bit or 32 bit addressing
mode is used.

In addition to double number words, Pocket Forth has some words to deal
directly with absolute addresses. The words "l@", "dl@", "l!" and "dl!" read
and write absolute addresses outside of the relative address range.

See the glossary for the specifics of using double number and absolute
addressing words.

Relative Addressing

The addresses used within Pocket Forth are relative addresses, that is, 16 bit
numbers, relative to a base address. Pocket Forth can be anywhere in memory
and relative addresses will remain constant.

Relative addressing uses the 'indirect with displacement' addressing mode of
the 680x0. Addresses within ±32K bytes of the base address can be accessed
using a 16 bit relative address. Pocket Forth's dictionary starts at zero and
uses only positive relative addresses, so the maximum dictionary size is 32K
bytes.

Free memory, that is, memory available for dictionary expansion, is determined
with the word "room". Pocket Forth is distributed with the maximum amount of
free space available. The default amount can be changed by adjusting the
'freeSize' variable. Setting a size greater than 32 kbytes will cause a crash.

'Address' or the abbreviation 'addr' usually means a relative address.
Relative and absolute addresses can be converted from one to the other. The
word ">abs" converts a relative address to a double number absolute address.

The word ">rel" converts an absolute address to a relative address. Only
absolute addresses within the relative addressing space will be correctly
converted. Absolute addresses outside of this range are mapped into the
relative addressing space, causing the wrong address to be calculated.

Stacks

The stack data structure is used throughout the computer world, but most
languages hide their stacks. On the other hand, Forth stacks allow complete
access.

Like most Forths, Pocket Forth uses a parameter stack and a return stack. The
term 'the stack' used by itself usually means the parameter stack. In
contrast, 'the stack' in other languages means the system stack, which is
Pocket Forth's return stack.

The parameter stack, used to pass values to and from routines, is under your
full control. It holds up to 1024 sixteen bit numbers or about 200 floating
point numbers. See the error section about under- and overflow conditions.
К
[figure 2]

Because the return stack is the system stack, it is used for subroutine
threading by Pocket Forth and other programs, including the operating system.
Runtime threading by pushing and popping addresses to the return stack is
handled automatically by the processor.

The return stack can also be used explicitly to store temporary data and to
interface with toolbox routines. Used for data storage the return stack makes
definitions smaller and faster. Here are two versions of a word that returns a
product and a quotient:

: PANDQ ( n1 n2 n3 -- n1*n3 n2/n3 ) dup rot swap / rot rot * swap ;
: PANDQ ( n1 n2 n3 -- n1*n3 n2/n3 ) >r swap r * swap r> / ;

In the first definition, "pandq" is written using parameter stack manipulation
only. Holding n3 temporarily on the return stack makes the second definition
smaller. It is also faster because return stack words, such as "r", "r>" and
">r", compile inline, as two byte macro definitions, instead of subroutine
calls.

Used this way, the return stack must be carefully balanced between the
beginning and end of a routine. An unbalanced parameter stack can cause an
incorrect result, but a single number out of place on the return stack causes
an immediate or delayed crash.

Toolbox parameters and results are passed by pushing and popping the return
stack. In addition to the words ">r"and "r>", Pocket Forth adds the words
"2>r", "2r>" and "a>r" to facilitate calling toolbox routines. Like the
standard return stack words, these words must be balanced within a single
colon definition. Refer to the glossary, the example programs and the toolbox
section of this manual for further information on the use of these words.


Dictionary

Pocket Forth's dictionary is a linked list of subroutines, variables and other
objects. Each object in the dictionary is named so that it may be matched to a
token from the input stream. This makes the interpreter seem conversational.

A subroutine named "search" provides the ability to quickly locate any named
routine. Given a token, "search" returns the address of the routine.
Execution, compilation or some other action may be taken with the address.

Normally words that are typed (or loaded, or pasted) are executed immediately.
The interpreter can also be in compile mode. The word ":" (pronounced "colon")
engages the compiler to add a new definition to the dictionary.

NOTE: Actually the word "]" ("right bracket") enters compile mode by setting
the user variable 'fcolon' to 128. "Colon" creates the dictionary header, that
is, the name and link fields, then calls "]". Like "colon", ";" (pronounced
"semi-colon") isn't the actual word that leaves compile mode. The word "["
("left bracket") is called by "semi colon" to do that.

Anatomy of Dictionary Entries

"Colon" definitions consist of a name, a link address for searching and an
executable subroutine. The subroutine contains code compiled by the
interpreter. These definitions are themselves subroutines, therefore,
definitions can call other definitions, nested as deep as the size of the
return stack will allow.

This simple example program illustrates the dictionary's structure:

: HI ." HELLO" ; ( print "hello" on the screen )
: LINE hi 33 emit cr ; ( print hello! and go to next line )
: TEST BEGIN line ?terminal UNTIL ; ( continue 'til key press )

This figure shows the memory used in the example to illustrate how definitions
are constructed:

[figure 3]

The three fields common to all definitions can be seen, as well as some
special features in each one. Notice that dictionary memory is commonly used
in 2 byte groups. These groups are called cells (or sometimes words, but that
is confusing).


Name Field

The first part of a dictionary entry is its name field. A name field is four
bytes long: the first three characters of the name are preceded by the number
of characters in the name. Names such as "hi", with less than three
characters, are padded with zeros so the name field is always four bytes long.
Names with more than three characters are truncated.

Name collisions occur if the name field of two words is the same. For example,
a word called "lint" would have the same name field as the word "line". The
effect of a name collision is that references to the collided word are
interpreted as the later defined word. References already compiled are
executed normally. Redefining a word does not cause an error message because
the dictionary is not searched during compilation, so choose names carefully.
Many bugs can be traced to name collisions.

Link Field

After the name field is the link field. This two byte field holds the name
address of the word defined just prior to the current word. "Search" uses the
link address to scan through the dictionary from word to word. A dictionary
search starts with the last word defined, whose name field address is returned
by the word "latest".

Code Field

The code for a word begins at its code field address, usually referred to as
simply 'the address' of the word. The address of a word can be found with the
word " ' " (pronounced "tick"). Provided with the code address, the words
">name" and ">link" return the name and link addresses.

The code field consists of a subroutine, ending either with an RTS instruction
or a jump to another subroutine. Most words compile to the form: JSR d(BP),
where the displacement, d, is the relative address of the word.

Other features besides subroutine calls are found in the code field. Some
words write code into the dictionary, or take some other action while in
compile mode. These words are called immediate words, because they execute
instead of compile when used within definitions. Some uses of immediate words
are branching, literal numbers, strings and compiler control.

Immediate words used by Pocket Forth are identified in the glossary. To make a
new definition immediate, follow the definition with the word "immediate". To
compile an immediate word, precede it with the word "[compile]".

Strings, such as 'HELLO' in the example are compiled as ASCII characters
prefaced with a length byte. The routine (.") prints the string data, then
adjusts the return address to skip over the string. The immediate word
"dot-quote" compiles (.") and a string into the dictionary, but does not print
the string.

NOTE С Pocket Forth's "dot-quote" is not 'state smart'. Its behavior outside
of a definition is the same as its compiling behavior, that is "dot-quote"
compiles a call to (.") and the string data. To have a word that prints
interactively, define "dot-paren":

: .( 41 word here count type ;
.( This is a test) ( will print the enclosed text )

Numbers, when used in a definition, compile inline code that pushes the value
to the stack. Using the example from figure 3, in the word "line", the value
33 compiles as MOVE #33,-(PS) that is, push 33 to the parameter stack. The
effect of this code is to put 33 on the stack when the code runs. Numbers
entered into the interpreter are pushed to the stack, like an RPN calculator.

The word "literal" compiles a value as described above (known as a literal
value) from data on the stack rather than from the input stream. The word
"dliteral" works like "literal" but compiles a 32 bit push instruction from a
double number. Floating point numbers work like integers but occupy ten bytes
on the stack. "Fliteral" compiles five consecutive push instructions.

Branching is controlled by immediate words that place short test and branch
routines into the code. These branching structures are supported by Pocket
Forth:

BEGIN ... (flag) UNTIL loop until flag is true
BEGIN ... (flag) WHILE ... REPEAT two part loop until flag is false
BEGIN ... AGAIN loop forever ...

(flag) IF ... THEN do enclosed code if flag is true
(flag) IF ... ELSE ... THEN do 1st part if true, 2nd if false

(limit start) DO ... LEAVE ... LOOP do code (limit-start) times
(limit start) DO ... LEAVE ... (count) +LOOP '' ((limit-start)/count) times
("leave" is optional)

Between "do" and "loop" the 16 bit value on the return stack, returned by "r"
is the index of the loop. You can test or change the value of "r" within a
loop. "Leave" sets the index to the limit; this causes the loop to exit at the
next occurrence of "loop" or "+loop".

Branching words must be used in the correct combination; no compile time error
will occur if they are not, but a crash is likely to at runtime.

NOTE: Back branches, that is branches toward lower memory are done by the word
"back". "Back" will compile short branches if the displacement is less than
128 bytes, otherwise, long branches (four bytes) and compiled. Back is called
by "until", "repeat", "again", "loop" and "+loop" so you usually don't need to
call it yourself.

Macro Definitions

Another class of definition, similar to immediate words, are macro
definitions. A compiled subroutine is four bytes long, and the JSR/RTS
combination has a small, but noticeable time penalty. Routines that are only
two or four bytes long are defined as macros. Macros compile their code inline
rather than as subroutines. Inline words are the same size or smaller and
execute a faster than subroutine words (2,8). When not in compile mode, macro
words function as subroutines.

These words are defined as 2 byte macro definitions:
, 2* DUP >LINK 2/ LATEST >NAME 2>R
MON >R 2DROP NEGATE 0 2DUP R 1+ 2R>
R> 1- DNEGATE RP@ 2+ DROP SP@

And these are 4 byte macros:
!PEN CBLK OR + CSTATE OVER +MD D+
PMODE -TO DL! R0@ 2OVER DL@ S0@ AND
L! TIB BASE L@ XOR FDROP INTERPRET

You may also define your own macros. Declare a word to be a macro definition
by following the word's definition with the word "macro". A major caveat
applies to user defined macros. Definitions become very large if macros longer
than four bytes are used. This means that macros should be machine code only.
If speed or maintaining the return stack is a concern, macros may be made from
code longer than four bytes. See the Sieve file for an example of macros built
for speed.

Here are some useful macro definitions:

: 00>R ( rstack: -- 0 0 ) ( push a long zero to the return stack )
,$ 42A7 ; macro \ clr.l -(rs)
: 2R ( -- d ) ( rstack: d -- d ) ( get double from the return stack )
,$ 2D17 ; macro \ move.l (rs),-(ps)

Parameter Field

The parameter field is present in words defined using "variable", "create" or
other 'defining' words. Defining words build new words, called 'daughter'
words, using the next token from the input stream for the name. When the
daughter word later executes, it returns the address of its parameter field to
the stack. If the "does>" follows "create" in a definition, the daughter word
also executes the code after "does>".

In a definition, words that follow "create" build a data structure during
compilation. Words after "does>" operate on the data at runtime. Here is an
example:

: 4CONSTANT create , , , , ( stack at compile time: n1 n2 n3 n4 -- )
does> dup 2@ rot 4 + 2@ 2swap ; ( at run time: -- n1 n2 n3 n4 )
100 100 300 200 4constant LRECT ( create a 4 cell constant: "lrect" )
LRECT ( put 100, 100, 300, 200 on the stack )

[figure 4]

Variables are defined with the word "variable", "2variable", "fvariable" or
"create". Use "variable" to create data structures if "does>" is not needed.
Variables are smaller and faster than 'created' data structures. If larger
storage areas are needed than "variable" or "2variable" provide, use "allot"
which adds bytes to the parameter field.

Memory Management

In a Macintosh, certain conditions cause functional blocks of memory to move
around(9). This is called memory management and is done by the memory manager
in the ROM. (Brodie's fans: imagine a cartoon character for the manager.)
Because of this, Macintosh programs must run from any memory location.

Memory available for a new program is allocated above the dictionary. Do not
confuse this with addressable memory. Allocated memory is memory you are
allowed to use by the memory manager. Addressable memory can be accessed with
a relative address. Programs that alter memory should respect the limit of the
allocated memory when using relative addressing. Pocket Forth comes with 32K
(the maximum) allocated.

The dictionary is loaded from the disk as a 'DICT' resource. The entire
dictionary can be written back to the disk with the word "save", replacing the
previous DICT resource. This makes extensions and modifications a permanent
part of your copy of Pocket Forth. NOTE: "save" cannot be undone.

The memory map, with high memory at the top:

[figure 5]

Other programs that may be in memory are not shown in this diagram.

Errors

Three types of error are reported: stack errors, numeric conversion errors and
disk errors. All of these errors use the general purpose error word "abort".
"Abort" prints a question mark, clears the file, parameter and return stacks
and goes back to the prompt. A fourth type of error is not reported, the Apple
Event error. See the Apple Event section for more details.

Stack errors occur when items are removed from the parameter stack when it is
already empty. Since the parameter stack is often 'under flowed' this way, it
is buffered so that no harm will be done by this condition. A stack error
report looks like this: *?. Make a stack error happen by typing "drop" when
you know the stack is empty.

Stack overflow on the other hand is not reported nor buffered. A runaway loop
is the most often cause of stack overflow. The symptoms differ in each
occurrence from a bomb box to extreme graphics and rude noises. Check your
loops carefully.

Tokens not found in the dictionary are assumed to be numbers. If the
conversion routine, "number", finds any characters greater than the value of
"base", the token is not an integer either. Then the interpreter uses SANE to
determine if the token is a valid floating point number. Usually these are
numerals with a decimal point or an 'E', however, any undefined token
beginning with a number is converted. Unconverted tokens are reported by
printing the token in capital letters, then doing "abort". Type "xx" to see
this error.

Disk errors are reported by printing "Disk:" and the number of the error
encountered. Look up the error numbers in Inside Macintosh(10) or other text.
"Abort" is executed after the message is printed.

Common disk errors include:
-35 No such volume error: disk name is misspelled or disk is not mounted.
-36 General purpose I/O error: cause unknown.
-43 File not found: pathname is misspelled or includes a space.

Use "abort" to write error handlers. Type a message then call "abort" as in
this example:

: BASIC ( -- ) here 20 expect ( get a line of text )
." Syntax Error" abort ( report error and abort )
beep ; ( NOTE: this never happens )

Errors reported by some other Forth systems are not reported by Pocket Forth.
Compiler or branching security is not provided, nor is free space checked
before compiling. Multiple definitions of the same word are allowed. The lack
of these messages can sometimes cause mysterious problems.

If the dictionary runs out of free space while compiling, compilation
continues on, right into whatever is right after the DICT block in the heap.
This is likely to cause a crash, so you must be aware of the memory available
for your program. Remember to check free dictionary space with "room".


Toolbox

The toolbox is a collection of hundreds of routines within the ROM and System
file that create the Macintosh interface. Pocket Forth enables use of the
toolbox routines.

Toolbox routines are called by executing a 16 bit instruction called a trap
word. Each routine has its own trap word that executes and returns as if it
had been called as a subroutine. Compile trap words inline into Pocket Forth
code.

A word ",$" (pronounced "comma hex") compiles a 16 bit hexadecimal number into
the dictionary from the input stream. If the token after "comma hex" is not a
hex number, a number conversion error is signaled. Use "comma hex" to compile
trap words.

Most toolbox arguments are passed on the system stack. Because Pocket Forth's
return stack is the system stack, return stack words can be used to setup for
a toolbox call. The words ">r" and "2>r" move 16 and 32 bit values to the
return stack. "R>" and "2r>" move 16 and 32 bit numbers from the return stack
to the parameter stack. The word "a>r" performs a double duty: it converts a
relative address on the stack to an absolute address which it pushes to the
return stack.

To call a toolbox routine, setup the system stack with "a>r", ">r" and "2>r".
If the toolbox call is a function, push a zero (single or double, as
appropriate) to the return stack ahead of any arguments. Then compile the trap
word with "comma-hex". Get function results with "r>" or "2r>". Examples of
toolbox calls are in the example and extension programs and figure 6, below.

The operating system keeps information for its use in low memory global
variables. These globals can be accessed using absolute addressing with the
words "l@" and "dl@". See the definition of "ticks" in figure 6.

Machine Language

Machine code can be mixed with Forth code in definitions. Insert it as hex
data directly with the word "comma hex". Be sure that all words execute
correctly and end with an RTS instruction (use ";") or JMPs into another
word's code field.

Respect the contents of most of the 680x0's registers. Save and restore
registers that are used by Pocket Forth if you change them with machine code.
The following table describes the register use:

Register Comments
D0-D1/A0-A1 Used and changed by many words; use freely
D2-D5 Preserved by all words; restore if used
D6.W Name address of the last definition (see "latest")
D7.W Input character counter
A2 (DP) Start of free memory absolute address (see "here")
A3 (BP) Base absolute address (see ">rel" and ">abs")
A4 (IS) The input stream pointer absolute address
A5 Macintosh operating system use
A6 (PS) The parameter stack pointer absolute address
A7 (RS) The return (and system) stack absolute address

The word "mon" executes the trap word _Debugger. If a debugger, such as TMON
or MacsBug is installed, it is engaged, otherwise, the system bomb window
appears. If it does, click the "Continue" (or "Resume") button to quit the
application.

Here are examples of toolbox calls, global variables and machine language:

: 0>R ( return stack: -- 0 ) ( push a zero to the return stack )
,$ 4267 ; MACRO ( clr -[rs] )
: RANDOM ( -- u ) ( u is a random number, 0 to 65535 )
0>r ,$ A861 r> ; ( _Random )
: TICKS ( -- d ) ( double number = ticks since startup )
362 0 dl@ ; ( fetch double from absolute address 362 )
: CLS ( -- ) ( clear the window, leaving the cursor alone )
4 +md a>r ,$ A8A3 ; ( _EraseRect the window content rect )

And a memory diagram for these words:

[figure 6]

Events

Macintosh programs interact with users and other programs by means of
'events'. For example, clicking on a partially hidden window generates mouse
down, mouse up, activate, deactivate and update events in order to bring the
window to the front. Pocket Forth has default event handlers, so deal only
with those that are pertinent.

The (relative) addresses of the event handlers are kept in a large table of
unnamed variables. The addresses of the variables are calculated with the word
"+md", which adds the address of the table to an offset. Some of the variables
in the table hold other important data instead of handlers. You can customize
Pocket Forth by changing the value of these variables.

Here is a list of the available variables. The left column's variables contain
the addresses of routines. The right column contains handles, pointers, flags
and other data.

Handler routines: Offset Other data: Offset
Activate window 12 Window Pointer 0
Update window 14 WRect, pixels 4
Button down 16 WSize, pixels 8
Idle 20 Menus list 18
Close 22 Screen echo flag 28
Version 24 AppleMenuHandle 30
Start up 26 File Menu Handle 34
Event routines: 116 Edit Menu Handle 38
(Button down) 118 File stack 42
(Button up) 120 Event record 148
(Key down) 122 What event 148
(Key up) 124 Message 150
(AutoKey) 126 When 154
(Update) 128 Where 158
(Disk inserted) 130 Modify 162
(Activate) 132 Selected window 164
(Apple Event) 136 Multitasking flag 186
(Multitask) 146 Apple Event list 188
Clicks: 168 Key pressed flag 192
inDeskRgn 168 Quit selected flag 194
inMenuRgn 170 Open ready flag 196
inSystemRgn 172 Apple Event reply 198
inContentRgn 174 Apple Event record 202
inDragRgn 176
inGrowRgn 178
inCloseRgn 180
inZoomIn 182
inZoomOut 184
Apple Event error 190

Routines:

Ґ Activate expects a flag on the stack, true for window on, false for window
off. The default handler is the word "drop". Substitute handler should also
take a number off the stack.

Ґ Update draws invalidated portions of the window if automatically invalidated
by uncovering it or explicitly invalidated by a program. The default handler
draws an underscore at the current text cursor position, and has no stack
effect.

Ґ Button executes when the mouse button is pressed inside the window. The word
"beep" is the default handler. Handlers can make use of the words "@mouse" and
"?button" to create more complex mouse button actions. The button handler has
no stack effect.

Ґ Idle is executed as often as possible, at least every 30th of a second. The
default Idle handler does nothing, however, the idle routine is temporarily
used by some Apple Events.

Ґ Close executes in response to a click in the window's close box. The default
handler executes "bye" which quits Pocket Forth.

Ґ Version is a handler that identifies the version of the program running. The
default handler displays the AboutЙ box from the Apple menu.

Ґ Start up is executed when the program starts, after the window has been
drawn, and all the registers are set up.

Ґ Events is a list of first line handlers for the first 15 event types. These
handlers do the behind the scene housekeeping for Pocket Forth. They execute
the handlers described above and do not normally need to be modified. Apple
events are mapped onto event number 10, the defunct network event.

Ґ Clicks is a list of the various window part handlers. They handle desktop,
menubar, desk accessory, window content region, drag region, grow box, close
box, zoom in and zoom out region clicks. Modify these handlers to change the
way the Pocket Forth window responds to mouse clicks in regions other than the
content region.

Ґ Apple Event error is executed if the result code of AEProcessAppleEvent is
not zero. This allows other high level events to be handled. See the Apple
Event section.

Data:

Ґ Window contains a pointer to Pocket Forth's window. Get the window pointer
with "0 +md 2@".

Ґ WRect is the content rect of the window in local coordinates and WSize is
the last four bytes of the rect, the width and height of the window. The
values in wrect are used by "cr" and "page" and other routines.

Ґ Menus is a variable that holds the relative address of a list of menu lists.
See the menu section for an explanation.

Ґ Screen echo is a variable that contains a flag. If the flag is true then
text is shown when pasting or loading. If it's false then text display isn't
done and loading (or pasting) is much faster. If the source code contains
errors however, you will not be able to see where the error occurred unless
the code is echoed.

Ґ Apple Menu Handle, File Menu Handle and Edit Menu Handle are double
variables that hold menu handles (absolute addresses) for the three built in
menus.

Ґ File stack is the memory to implement the stacks required to allow programs
to load other programs. See the source code to discover the inner workings of
the file stack.

Ґ Event record holds the event record data. This is the record used by the
main event loop. Since the system puts necessary data here, you should not
modify these variables. Your event handlers should, however, test them.

Ґ Selected window holds a temporary window pointer. Update and other routines
use this variable, so it should not be changed.

Ґ Multitasking flag contains true (-1) if a multitasking operating system such
as System 7 or MultiFinder is in effect. A true flag indicates that trap
WaitNextEvent is available and will retrieve events, if the flag is false,
GetNextEvent is used instead.

Ґ Apple Event list is a linked list of relative address pointers to the
handlers for each apple event supported. The format of the list is: d.class
d.message handler next.entry. The list is terminated with a zero for the
next.entry field. Refer to the Apple Events section.

Ґ Key pressed flag is used by the event loop. You should use the words "key"
or "?terminal" to determine if a key is pressed.

Ґ When the quit flag is set to any non zero value, the event loop exits Pocket
Forth. Use the word "bye" to accomplish this.

Ґ Open ready is true if a file is ready to be opened. The filename should be
at 'pad' and a working directory number on the stack. This variable is used by
"open", the 'odoc' handler and opening from the menu, but not by "-->".

Ґ AEReply holds the handle to the reply Apple Event record, an empty apple
event that is returned to the sending application. See the Apple Events
section.

Ґ AEEventRecord contains the handle to the current Apple Event data record.
See the Apple Events section.

As mentioned above, none of these names are in the dictionary, but they can be
defined as constants. Here are examples of the use of these variables:

12 +md constant ACTIVATE
14 +md constant UPDATE
16 +md constant BUTTON
24 +md constant VERSION

: MYACT ( flag -- ) IF ." Hello again!" cr THEN ; ( type the string )
: MYUPD ( -- ) 4 0 DO 8 emit LOOP .ok ( back up and issue prompt )
[ update @ compile ] ; ( call the original update handler )
: MYBUT ( -- ) version @ execute ; ( show version )

' myact activate ! ( set activate to address of "myact" )
' myupd update ! ( set 'update' to address of "myupd" )
' mybut button ! ( set 'button' to address of "mybut" )

Now try clicking on the window, hiding the window behind others, and
re-selecting it.

More Variables

Other variables exist in the Pocket Forth dictionary, for use by the
interpreter and other internal parts of the Pocket Forth system. These
variables can also be used to patch Pocket Forth's actions. Unlike standard
Forth user variables, these are unnamed.

Here is a list of the 'user' variables, the offsets are bytes from "tib".

Name Offset Description
TermBuf 0 terminal input buffer
StackSize 82 the size of the parameter stack, in bytes
IntA7 84 initial value of the system's stack pointer
Rzero 88 address of the bottom of the return stack
Szero 92 address of the bottom of the parameter stack
Form 96 decform record for floating point numbers
Expand 100 address of 'grow' routine in the CODE 1 resource
FreePt 104 relative address of the initial end of the dictionary
FreeSz 106 amount of free space at startup
DictPt 108 name address of the last word in the dictionary
NBase 110 value of the current number base at startup
Held 112 address for the next character in a numeral
DoesAdr 114 parameter from a created word for "does>"
fcolon 118 flag indicating the interpreter state (see "cstate")
fimmed 119 flag indicating an immediate word
fneg 120 flag indicating a negative number
fint 121 flag indicating input source (see "cblk")
fmacro 122 flag indicating macro compiling mode
fbit5 123 reserved flag


Menus

Menus can be created and changed. Three menus are already setup, Apple, File
and Edit. You can add your own menus. Each menu (except the Apple Menu)
consists of four parts: 1) A menu ID number, 2) a menu handle, 3) a menu
handler list with an entry for each item in the menu and 4) a MENU resource.
The menu resource is optional, as you may define menus from strings as well.
MENU resources are much easier. See the Window&Menu example file.

Menu ID numbers apply to all of the application's menus. Menus are numbered 2
for the File menu and 3 for the Edit menu. Give new menus a number of 4 and
higher if any are added. Handles for the existing menus are in the unnamed
variables as shown in the table.

The order in the list of menu item handlers corresponds to the appearance of
the items in the menu. The addresses of the menu handler lists from each menu
(except the Apple menu) are kept in a list that looks like the menubar. This
list of menu lists is pointed to by the Menus list unnamed variable (18 +md).
Perhaps this picture of the menu handlers and pointers will clear things up:

[figure 7]

The Apple menu is handled separately because the only changeable item is
AboutЙ which can be accessed via the Version unnamed variable.

To alter an item's handler, change the value of the handler in the menu's list
to point to the word you want to run instead. To change an entire menu, change
its address in the list of menus to point to a new list. This example sets the
handler of the Clear item of the Edit menu to a word to clear the screen:

( Paste this example into Pocket Forth to try it out. )
18 +md @ ( get the contents of menus list variable )
2+ @ constant EMLIST ( address of the edit menu list )
: CLEAR ( -- ) page quit ; ( clear screen and reset interpreter )
' clear emlist 5 2 * + ! ( set item 5 {clear} to "clear" )

The menus included with Pocket Forth contain commands that facilitate
interactive program development. The menu commands are:

Apple Menu

About Pocket Forth ... runs the handler routine whose address is kept in the
variable at 24 +md. The default handler displays an alert box.

Desk accessories or Apple Menu Folder contents and the About item.

File Menu

Open ... presents a dialog box to choose a file to be opened. The chosen
file is then loaded.

Save Dictionary ... presents a dialog asking you to confirm your choice. It
does this because saving the dictionary cannot be undone. The dictionary is
saved if you confirm the choice.

Debugger ... enters a machine language monitor by executing the word "mon".
You must have a monitor program, such as TMON or MacsBug installed or the
program will crash.

Print ... does nothing useful (it beeps).

Quit executes "bye".

Edit Menu

Undo, Cut, Copy and Clear do nothing except beep. They are provided to
support desk accessories under ФsingleХ Finder. See the example above to add a
function to the Clear item.

Paste interprets the text on the clipboard.


Resources

Pocket Forth is entirely made out of resources. Here is a list of all of the
resources in Pocket Forth:

TYPE ID bytes
actb 257 48 about alert color table
actb 258 48 red alert color table
aete 0 84 info about supported Apple Events *
ALRT 257 14 about box
ALRT 258 14 red (memory low) alert
ALRT 259 14 save alert
BNDL 128 36 finder icon bundle
cicn 128 970 color icon from about box
CODE 0 24 launching code
CODE 1 182 more launching code
DICT 257 6492 dictionary code
DITL 257 66 about box items list
DITL 258 90 red alert items list
DITL 259 154 save alert items list
FREF 128 7 finder reference for Pocket Forth
FREF 129 7 finder reference for text files
hdlg 257 50 about alert help balloon *
hdlg 259 82 save alert help balloon *
hfdr -5696 32 finder icon help balloon *
hmnu 1 40 apple menu help balloon *
hmnu 2 148 file menu help balloon *
hmnu 3 140 edit menu help balloon *
hrct 128 32 window help balloon rect definition *
hwin 128 30 window help balloon *
icl4 128 512 16 color icon *
icl8 128 1024 256 color icon *
ICN# 128 256 black and white icon
ICON 128 128 b&w icon for about box
ics# 128 64 small black and white icon
ics4 128 128 small 16 color icon *
ics8 128 256 small 256 color icon *
MENU 1 48 apple menu
MENU 2 104 file menu
MENU 3 72 edit menu
p4TH 0 38 signature and string for Get Info
PICT 128 352 picture for the about dialog
SIZE 1 10 multitasking and System 7 info
STR# 1 2384 help balloon text *
WIND 128 32 the main window
* used by System 7 only

To use resources in a program, create and install them into a copy of Pocket
Forth. Use ResEdit or an equivalent program to do the resource surgery. The
Window&Menu example shows a method for creating resources on the fly. The file
::Extensions:Misc includes a definition of RES to get a resource from an open
file.

The DICT resource of Pocket Forth contains the dictionary code and data. A
resource was used for the dictionary because of the simplicity of saving and
modifying the data within it.

Floating Point Numbers

Pocket Forth can recognize and manipulate floating point numbers. While this
is not a standard Forth feature, the language is well served by this
implementation (14), especially if your Macintosh has floating point hardware.
The floating point routines will. however, run on any Macintosh.

Floating point numbers are implemented using the SANE software in the
Macintosh system. SANE routines are fast and accurate. An available floating
point chip is used by SANE automatically. This means, programs will benefit
from its inclusion without needing specialized code.

Indicate that a token is a floating point number by including a decimal point
or the letter 'e' in the number. The translator routine (part of SANE), is
quite lenient, however the token must be a recognizable decimal or scientific
notation number, ±INF or a NAN code as described by the Apple Numerics Manual
(11). Examples of valid floating point numbers are: 3.1415926 42 .
-0.0000012 6.626E-34 6.02e23 . BEWARE: Unknown tokens, such as 4U2 and -0X
that start with numeral characters are also converted.

SANE extended floating point numbers are 80 bits long, so they occupy 10 bytes
in memory, or 5 cells on the stack. Illustrate this by typing "1.0 . . . . .
".
К
[figure 8]

Words for working with floating point numbers are included. Many of these
words are similar to integer words prefixed by 'f'. Words to manipulate
floating point numbers on the stack ("fdrop", "fdup", "fswap", "fpick",
"fpack" and "froll") and in memory ("f@", "f!", "fliteral", "f,", "fconstant"
and "fvariable"), output them ("fix", "sci" and "f.") and convert them ("f>d",
"d>f" and "fnumber") are all provided.

The sixteen math words make up the rest of the floating point suite. They are
"f+", "f-", "f*", "f/", "frem", "f^", "fint", "fabs", "fsqrt", "fsin", "fcos",
"ftan", "fexp", "fln" and "fcompare". The SANE financial functions are not
included, but can be defined if needed. Refer to the glossary and the
extension file, fvgFloatingPoint for more information.

Here is an example that calculates the area of a circle of a given diameter:
3.14159265359 fconstant PI
: ACIRCLE ( f.diameter -- f.area )
2. f/ fdup f* ( square the radius )
pi f* ; ( multiply it by pi )
13.6 acircle f.

Apple Events

The four required events, 'oapp', 'odoc', 'pdoc' and 'quit' are supported and
installed at startup time. Your program may define additional event handlers,
or redefine the required events. New events are added to the list to be
installed the next time Pocket Forth is started.

To define an Apple Event, first put the event type and the event class double
numbers on the stack, with ",s". Then use "ae:" and ";ae" to begin and end the
definition. Write a procedure between them for the event handler. This process
will attach the new definition to the tail of the Apple Events list. The
defining word "ae:" handles the management of the Apple Event list so you do
not need to deal with it.

Unlike the menu list, entries in the Apple Events list are installed into the
system when the program starts up, and cannot be modified dynamically by your
program. To install a new Apple Event, define the event then "save" the
dictionary. (Be sure to use a copy of Pocket Forth!) Quit, then relaunch
Pocket Forth and the new event handler is automatically installed.

When Pocket Forth receives an Apple Event, the AppleEvent and the Reply record
addresses (absolute) are placed in the variables at "202 +md" and "198 +md".
These addresses are used to extract information from, and respond to Apple
Events. (10,13)

To see how this is done, check out the AppleEvents file and the HyperCard
stack, AETest. This file defines 'do script', 'evaluate' and 'paste' events.

Here is an even simpler example. Make a copy of Pocket Forth and paste this
in:

: whide ( -- ) 0 +md 2@ 2>r ,$ A916 ; ( _HideWindow )
,s clos ,s aevt ae: whide ;ae ( define the 'clos' handler )
( If this isn't a copy, Quit! )
key drop save bye ( hit key to continue )

Reopen Pocket Forth, then use the AETest stack to send 'clos' to your new
copy. The Pocket Forth window will disappear. You must Quit to reopen the
window.
While this may not be useful, you have added a new Apple Event handler.

Errors are posted when an Apple Event sent to Pocket Forth is not handled
properly. The error routine (address at "190 +md") is executed if an error
occurred, with the error number on the stack. "Drop" is the default handler
for the error routine. Install a sample error handler:

: AEERROR ( error.no -- ) ." Apple Event error:" . ;
' aeerror 190 +md ! ( install error handler, no need to save this )

Send Pocket Forth an 'eval' event from the AETest stack. The error code for
'handler not installed' will be printed in Pocket Forth's window.

Pocket Forth contains an aete resource to let scripting programs know about
the Apple Events it can handle.


Turnkey

In the Forth world, "turnkey" means to produce a stand alone program from the
interpreter. Because most commercial Forth interpreters are proprietary, a
side effect of turnkeying is that the interpreter is sealed off, and no longer
available to the program's user.

For many programs, this is preferable since the interpreter can be confusing
to many users. Pocket Forth can turnkey applications with or without this side
effect.

The essence of the turnkey process is the assignment of new values to Pocket
Forth's event and message handlers. Define a word with the correct actions,
then place the address of the word in the unnamed variable used by the
particular event or message. Use "save" to make the changes a permanent part
of the program once it is debugged.

The button, activate and update events, idle and menu messages should be set
as described in the events and menu sections.

The idle routine is run once each time through the event loop. As mentioned
above the idle routine is used (non-destructivly) to defer actions set by some
Apple Events, specifically the 'odoc' routine. See how to do that in the
AppleEvents file.

The start up handler is executed after everything is setup and just before the
interpreter loop is entered. You can write programs that do not give the user
access to the interpreter. Do this by entering an endless event loop in the
start up handler. Run time structures, such as data blocks, should be created
in the startup handler.

The close handler is run when the close box of the window is clicked. The
default close handler calls "bye" and returns, causing the application to quit
by 'falling through' to the launching program (usually the Finder).

Key down events are not ignored, rather the application is centered around
getting and handling key presses. The main event loop of Pocket Forth is
called by the words "expect", "key" and "?terminal". Write an event loop for
your program by embedding one of these words in a loop:

... EXPECT ... ( handle all events until a return is typed )
... BEGIN KEY .. handle key data .. AGAIN ... ( endless event loop )
or ... BEGIN ... ?TERMINAL UNTIL ... ( a one shot event loop )

Run non-key events in their handler routines. Key events are handled in the
event loop code. Here is the turnkey example:

( Handler demo application )
( Show the events as they are processed )
( The idle routine should only run once a second )
variable TLAST 0 tlast ! ( hold the last value of ticks here )
: TICKS ( -- n ) 364 0 l@ ; ( low word of 'ticks' system variable )
: ?1SEC ( -- flag ) ( true if >1 second has elapsed since last time )
ticks tlast @ - abs 60 > ; ( is time difference > 1 sec? )
: MYIDLE ( -- ) ?1sec IF ticks tlast ! ( update tlast )
." Idle" cr THEN ; ( wait 1 second between idle messages )
: MYACTIVATE ( flag -- ) IF ." Activated" ELSE ." Deactivated" THEN cr ;
: MYUPDATE ( -- ) ." Window updated" cr ;
: MYBUTTON ( -- ) ." Window clicked" cr ;
: MYKEY ( c -- ) emit space ." key pressed" cr ;
: MYCLOSE ( -- ) ." Closed" cr bye ;
: MYSTARTUP ( -- ) ." Hi There!" cr
BEGIN key ( "key" waits for a key press and runs event handlers )
mykey AGAIN ; ( Loop through the key handler indefinitely )
' mystartup 26 +md ! ( set the open handler )
' myclose 22 +md ! ( set the close handler )
' myidle 20 +md ! ( set the idle handler )
' mybutton 16 +md ! ( set the button handler )
' myupdate 14 +md ! ( set the update handler )
' myactivate 12 +md ! ; ( set activate handler )
page
( If this is not a copy, Quit! )
( ...Or hit a key to continue... ) key drop save bye

Once a turnkey program is finished, debugged, and all variables are
initialized, save the dictionary, replacing the one stored on the disk. Then
use ResEdit to change the resources such as the window title and the
application's icon (as well as BNDL, FREF and signature resource) and AboutЙ
item. Be sure to "save" only copies of Pocket Forth since the changes are
permanent and cannot be undone.

The ReadMe application is an example of a turnkey program. Recompile ReadMe by
using ResEdit to replace the DICT resource of (a copy of) ReadMe with a DICT
copied from Pocket Forth. Save and close ReadMe from ResEdit. Launch ReadMe,
which will open a Pocket Forth window. Load the file Reader by typing "open"
(don't use the menu) and the ReadMe application will be rebuilt. (Type "bye"
to quit.)

Versions

The Pocket Forth version number is a three part number written as: T.V.S. 'T'
is the program type, 'V' is the version within that type and 'S' is the
subversion, indicating corrections within a version. Type 0 is an application
with a sixteen bit stack and subroutine threading. The current version is
0.6.5.

Type 1 is a desk accessory. Version 1.6.5 is included with this release. Refer
to the Manual Addendum inside of the desk accessory folder for details on the
differences between the DA and the application.

Write to the author, Chris Heilman, if you have questions or comments.
Email: "heilman@pc.maricopa.edu"
CompuServe: [70566,1474] *
AOL: cheilman *
US Mail: PO box 8345
Phoenix, AZ 85066-8345

or visit the Pocket Forth site on the World Wide Web:
http://chemlab.pc.maricopa.edu/pocket.html

* CompuServe and AOL mail is read only sporadically.

Bibliographic Notes:

(1) Barnhart, Joe, "FORTH and the Motorola 68000", Dr. Dobbs Journal no. 83,
September 1983, Peoples Computer Company.

(2) Greene, Ronald, "Faster Forth", Byte v.9 no.6, June 1984, McGraw Hill
Publishing Co.

(3) Loeliger, R. G. Threaded Interpretive Languages, Byte Books, 1981.

(4) Fletcher, G. Yates, "A Mini Forth for the 68000", Dr. Dobb's Journal
no.123, January 1987, M&T Publishing, Inc. This article presents Flint, Forth
interpreter in 68000 assembly language. Pocket Forth owes much of its
structure and philosophy to Flint, and I thank Professor Fletcher and Dr.
Dobb's Journal for publishing Flint.

(5) Ragsdale, William F., et al. fig-FORTH Installation Manual, release 1,
Nov. 1980, Forth Interest Group. Includes Forth in Forth and source code for
figFORTH.

(6) Derick, Mitch and Linda Baker FORTH Encyclopedia, Second Edition,
Mountain View Press, Inc. 1982. This book shows the definitions of fig-FORTH
words.

(7) Brodie, Leo Starting FORTH, FORTH, Inc. / Prentice Hall, 1981. The FORTH
instruction manual and fun to read. You shouldn't learn Forth without this
book.

(8) Chavez, Lori, "A Fast Forth for the 68000", Dr. Dobb's Journal no. 132,
October 1987, M&T Publishing, Inc. This article describes how to implement
macros.

(9) Knaster, Scott How to write Macintosh Software, Hayden Book Co., 1986

(10) Apple Computer Inc. Inside Macintosh, volume I through volume VI and
X-Ref & Interapplication Communications, Addison Wesley, 1985-1993

(11) Apple Computer Inc. Apple Numerics Manual, Second Edition, Addison
Wesley, 1988. This book describes SANE.

(12) Brodie, Leo Thinking Forth, Prentice Hall, 1984. The elements of code
reusability are clearly explained, years before it became fashionable. Fun.

(13) Little, Gary & Tim Swihart, Programming for System 7, Addison Wesley,
1991 Geared toward C but useful none-the-less.

(14) Tracy, Martin, "Zen Floating Point", Dr. Dobb's Toolbook of Forth,
volume II, M&T Publishing, 1987. Philosophical support for using floating
point numbers on the stack.
Соседние файлы в предмете Проектирование электроприборов