- •Contents
- •List of Figures
- •List of Tables
- •Welcome!
- •About the Forth Programming Language
- •About This Book
- •How to Use This Book
- •Reference Materials
- •How to Proceed
- •1. Introduction
- •1.1.1 Definitions of Terms
- •1.1.2 Dictionary
- •1.1.3 Data Stack
- •1.1.4 Return Stack
- •1.1.5 Text Interpreter
- •1.1.6 Numeric Input
- •1.1.7 Two-stack Virtual Machine
- •1.2 Forth Operating System Features
- •1.3 The Forth Assembler
- •1.3.1 Notational Differences
- •1.3.1.1 Instruction Mnemonics
- •1.3.1.2 Addressing Modes
- •1.3.1.3 Instruction Format
- •1.3.1.4 Labels, Branches, and Structures
- •1.3.2 Procedural Differences
- •1.3.2.1 Resident Assembler
- •1.3.2.2 Immediately Executable Code
- •1.3.2.3 Relationship to Other Routines
- •1.3.2.4 Register Usage
- •1.4 Documentation and Programmer Aids
- •1.4.1 Comments
- •1.4.2 Locating Command Source
- •1.4.3 Cross-references
- •1.4.4 Decompiler and Disassembler
- •1.5 Interactive Programming—An Example
- •2. Forth Fundamentals
- •2.1 Stack Operations
- •2.1.1 Stack Notation
- •2.1.2 Data Stack Manipulation Operations
- •2.1.3 Memory Stack Operations
- •2.1.4 Return Stack Manipulation Operations
- •2.1.5 Programmer Conveniences
- •2.2 Arithmetic and Logical Operations
- •2.2.1 Arithmetic and Shift Operators
- •Single-Precision Operations
- •Double-precision Operations
- •Mixed-precision Operations
- •2.2.2 Logical and Relational Operations
- •Single-Precision Logical Operations
- •Double-Precision Logical Operations
- •2.2.3 Comparison and Testing Operations
- •2.3 Character and String Operations
- •2.3.1 The PAD—Scratch Storage for Strings
- •2.3.2 Single-Character Reference Words
- •2.3.3 String Management Operations
- •2.3.4 Comparing Character Strings
- •2.4 Numeric Output Words
- •2.4.1 Standard Numeric Output Words
- •2.4.2 Pictured Number Conversion
- •2.4.2.1 Using Pictured Numeric Output Words
- •2.4.2.2 Using Pictured Fill Characters
- •2.4.2.3 Processing Special Characters
- •2.5 Program Structures
- •2.5.1 Indefinite Loops
- •2.5.2 Counting (Finite) Loops
- •2.5.3 Conditionals
- •2.5.4 CASE Statement
- •2.5.5 Un-nesting Definitions
- •2.5.6 Vectored Execution
- •2.6 Exception Handling
- •3. System Functions
- •3.1 Vectored Routines
- •3.2 System Environment
- •3.3 Serial I/O
- •3.3.1 Terminal Input
- •3.3.2 Terminal Output
- •3.3.3 Support of Special Terminal Features
- •3.4 Block-Based Disk Access
- •3.4.1 Overview
- •3.4.2 Block-Management Fundamentals
- •3.4.3 Loading Forth Source Blocks
- •3.4.3.1 The LOAD Operation
- •3.4.3.2 Named Program Blocks
- •3.4.3.3 Block-based Programmer Aids and Utilities
- •3.5 File-Based Disk Access
- •3.5.1 Overview
- •3.5.2 Global File Operations
- •3.5.3 File Reading and Writing
- •3.5.4 File Support Words
- •3.6 Time and Timing Functions
- •3.7 Dynamic Memory Management
- •3.8 Floating Point
- •3.8.1 Floating-Point System Guidelines
- •3.8.2 Input Number Conversion
- •3.8.3 Output Formats
- •3.8.4 Floating-Point Constants, Variables, and Literals
- •3.8.5 Memory Access
- •3.8.6 Floating-Point Stack Operators
- •3.8.7 Floating-Point Arithmetic
- •3.8.8 Floating-Point Conditionals
- •3.8.9 Logarithmic and Trigonometric Functions
- •3.8.10 Address Management
- •3.8.11 Custom I/O
- •4. The Forth Interpreter and Compiler
- •4.1 The Text Interpreter
- •4.1.1 Input Sources
- •4.1.2 Source Selection and Parsing
- •4.1.3 Dictionary Searches
- •4.1.4 Input Number Conversion
- •4.1.5 Character String Processing
- •4.1.5.1 Scanning Characters to a Delimiter
- •4.1.5.2 Compiling and Interpreting Strings
- •4.1.6 Text Interpreter Directives
- •4.2 Defining Words
- •4.2.1 Creating a Dictionary Entry
- •4.2.2 Variables
- •4.2.3 CONSTANTs and VALUEs
- •4.2.4 Colon Definitions
- •4.2.5 Code Definitions
- •4.2.6 Custom Defining Words
- •4.2.6.1 Basic Principles of Defining Words
- •4.2.6.2 High-level Defining Words
- •4.3 Compiling Words and Literals
- •4.3.1 ALLOTing Space in the Dictionary
- •4.3.2 Use of , and C, to Compile Values
- •4.3.3 The Forth Compiler
- •4.3.4 Use of Literals and Constants in : Definitions
- •4.3.5 Explicit Literals
- •4.3.6 Use of ['] to Compile Literal Addresses
- •4.3.7 Compiling Strings
- •4.4 Compiler Directives
- •4.4.1 Making Compiler Directives
- •4.5 Overlays
- •4.6 Word Lists
- •4.6.1 Basic Principles
- •4.6.2 Managing Word Lists
- •4.6.3 Sealed Word Lists
- •5. The Assembler
- •5.1 Code Definitions
- •5.2 Code Endings
- •5.3 Assembler Instructions
- •5.4 Notational Conventions
- •5.5 Use of the Stack in Code
- •5.6 Addressing Modes
- •5.7 Macros
- •5.8 Program Structures
- •5.9 Literals
- •5.10 Device Handlers
- •5.11 Interrupts
- •5.12 Example
- •6.1 Guidelines for BLOCK-based source
- •6.1.1 Stack Effects
- •6.1.2 General Comments
- •6.1.3 Spacing Within Source
- •6.2.1 Typographic Conventions
- •6.2.2 Use of Spaces
- •6.2.3 Conditional Structures
- •6.2.4 do…loop Structures
- •6.2.5 begin…while…repeat Structures
- •6.2.6 begin…until…again Structures
- •6.2.7 Block Comments
- •6.2.8 Stack Comments
- •6.2.9 Return Stack Comments
- •6.2.10 Numbers
- •6.3 Wong’s Rules for Readable Forth
- •6.3.1 Example: Magic Numbers
- •6.3.2 Example: Factoring
- •6.3.3 Example: Simplicity
- •6.3.4 Example: Testing Assumptions
- •6.3.5 Example: IF Avoidance
- •6.3.6 Example: Stack Music
- •6.3.7 Summary
- •6.4 Naming Conventions
- •Appendix A: Bibliography
- •Appendix B: Glossary & Notation
- •B.1 Abbreviations
- •B.2 Glossary
- •B.3 Data Types in Stack Notation
- •B.4 Flags and IOR Codes
- •B.5 Forth Glossary Notation
- •Appendix C: Index to Forth Words
- •General Index
|
|
|
Forth Programmer’s Handbook |
|
|
|
|
Glossary |
|
|
|
BLOCK |
( u — addr ) |
Block |
Return the address of a buffer containing a copy of the contents of block u, having read it from disk, if necessary. If a read occurred, the previous contents of the buffer is first written to disk, if it has been marked as updated.
BUFFER ( u — addr ) Block
Return the address of a buffer marked to contain block u, having written previous contents to disk, if necessary (does not perform any read operation).
UPDATE ( — ) Block
Mark the most recently referenced buffer as having been updated. The contents of a buffer that has been marked in this way will be written to disk when its buffer is needed for a different block.
FLUSH |
( — ) |
Block |
Ensure that all updated buffers are written to disk, and free all the buffers. |
||
SAVE-BUFFERS |
( — ) |
Block |
Write all updated buffers to disk, leaving them in the buffers but with their |
||
UPDATE flags cleared. |
|
|
EMPTY-BUFFERS |
( — ) |
Block Ext |
Erase all block buffers without saving them. EMPTY-BUFFERS works by clearing the update bits in all buffers and performing a FLUSH to free the buffers.
3.4.3 Loading Forth Source Blocks
Most compiled languages require a three-step process to construct executable programs:
1.Compile the program to an object file on disk.
2.Link this program to other previously compiled and/or assembled routines.
3.Load the result into memory.
This often-lengthy procedure has a negative effect on a programmer’s effectiveness. Forth supports fully interactive programming by shortening this
System Functions 91
Forth Programmer’s Handbook
cycle to a single, fast operation: compiling from source to executable form in memory. This process is accomplished by the word LOAD.
3.4.3.1 The LOAD Operation
LOAD specifies the interpretation of source text from a disk block. LOAD expects on top of the stack the block number of the Forth block to be LOADed:
<number> LOAD
This block number is also stored in the variable BLK, used by Forth’s text interpreter. If BLK contains zero, the source is not a block, and usually is the terminal. When BLK is zero, the word SOURCE-ID returns a value indicating the input source (zero if it is the user input device or terminal, -1 if it is a character string passed by evaluate, and optionally a file-identifier if the input is a text file—see Section 3.5).
When LOAD is encountered, interpretation of text from the current input source is suspended and input is taken from the specified disk block. The text interpreter starts at the beginning and processes each word until it reaches the end of the block after 1024 characters. On some systems, if the word EXIT is encountered interpretively in the block, it will cause processing to terminate at once.
When all processing specified by the disk block is complete (assuming no errors were encountered while processing the block), execution resumes with input from the source that was in control when the LOAD was encountered.
If a block contains definitions, the result of a LOAD operation will be to process them via the text interpreter and compile them into the dictionary. The process of LOADing disk blocks is identical to processing the same information entered from the terminal or text file, but all information in a single disk block is processed as a single string (i.e., there will be no embedded carriage returns).
The block to be LOADed may itself contain a LOAD command, at which point the LOADing of the first block is suspended. When this occurs, the block number of the current block, the current text interpreter pointers are saved on the return stack, pending loading of the requested block. This nested LOADing process may continue indefinitely, subject to return stack size.
A group of blocks to be LOADed should be specified by LOAD commands con-
92 System Functions
Forth Programmer’s Handbook
tained in a single block, called a load block, as opposed to serial nesting (i.e., having each block load the next block in sequence). From a management viewpoint, loading groups of related blocks from a single load block aids readability and maintainability.
The command THRU can load a group of sequential blocks. For example, if blocks 260 through 270 need to be loaded, THRU could be used:
260 270 THRU
A LOAD operation may also be compiled in a definition, in which case the requested LOAD is done when the definition is executed. Following the LOAD, execution will resume at the word immediately after LOAD.
If an error is detected during the LOADing process, an error message is produced and all LOADing ceases. Both the return stack and the data stack are cleared, and Forth reverts to terminal input.
During loading, all text interpreter input is taken from the specified disk block. All output, however, proceeds to its normal destination. Thus, . (“dot”) or other output commands will send output to the terminal of the task executing the LOAD.
Glossary |
|
|
BLK |
( — a-addr ) |
Block |
|
Return a-addr, the address of a cell containing the number of the mass-storage |
|
|
block being interpreted, or zero if the current input source is not a block. “B-L-K” |
|
LOAD |
( i*x u — j*x ) |
Block |
|
Save the current input source specification in a system-specific manner. Store |
|
|
u in the variable BLK, thus making block u the input source. Set the input |
|
|
buffer to contain the contents of block u. Set the buffer pointer >IN to zero and |
|
|
interpret the buffer contents. When the parse area is exhausted, restore the |
|
|
prior input specification. Any other stack effects are due to the words exe- |
|
|
cuted as a result of the LOAD. |
|
THRU |
( i*x u1 u2 — j*x ) |
Block Ext |
Execute LOAD in sequence for each of the blocks numbered u1 through u2. Any other stack effects are due to the words executed as a result of the LOADs.
System Functions 93
Forth Programmer’s Handbook
References EXIT, Section 2.5.5
Input source identification, Section 4.1.1
Text file identifiers, Section 3.5.1
3.4.3.2 Named Program Blocks
The defining word CONSTANT may be used to give names to important blocks, such as load blocks, which load other blocks to form a utility or application. For example, define:
120 CONSTANT OBSERVING
which will be used as:
OBSERVING LOAD
The above has the effect of loading block 120 and executing any other LOAD instructions specified in that block.
CONSTANT is particularly appropriate when you want to use the name in other ways, such as:
OBSERVING LIST
We recommend the use of a key block for each major section of an application. The key block should primarily load other associated blocks, specified numerically or through CONSTANTS; it may also contain other brief, application-wide definitions. Then you can see at a glance which of your application blocks are loaded, and in what order.
This technique is much safer than chaining blocks (i.e., serial nesting), which can cause a return-stack overflow. Generally, a single block names all the key blocks in that system, and is LOADed immediately after booting.
A convenient side effect of named blocks is that they can be successfully
!LOADed when in any number conversion base. But, for this reason, named key blocks should have a DECIMAL command in the first line to guard against incorrect loading of subsidiary blocks due to an unexpected current base.
94 System Functions