Pygmy Forth version 1.3 MANUAL Copyright 1989, 1990 Frank C. Sergeant 809 W. San Antonio St. San Marcos, TX 78666 Pygmy Forth version 1.3 is a fast direct-threaded Forth for reasonably compatible MS-DOS & PC-DOS machines. It includes an editor, assembler, and metacompiler (so it can recompile itself) in only 14K. Up to 15 files can be open simultaneously. It comes with full source code and documentation. It is based loosely on Charles Moore's cmFORTH. TABLE of CONTENTS Chapter 1 Terms of use and distribution Chapter 2 Bonuses Chapter 3 Credit Where Credit is Due Chapter 4 "Why I Wrote Pygmy" Chapter 5 What Is Pygmy? Chapter 6 How To Run The Program Chapter 7 If You Are New to Forth Chapter 8 What Was New With Version 1.2 Chapter 9 What Is New With Version 1.3 Chapter 10 Tips Chapter 11 How Files Work Chapter 12 The Assembler Chapter 13 The Editor Chapter 14 The Meta Compiler Chapter 15 Vocabularies Chapter 16 Additional Information Chapter 17 Addresses Chapter 18 The Glossary Chapter 19 Memory Map Chapter 20 Files Chapter 21 Direct Threaded Chapter 22 History & Philosophy Chapter 23 How to Print the Source Code Chapter 1 Terms of use and distribution I hold the copyright to all of the documentation and source code and machine code included in the Pygmy Forth version 1.3 package, including the organization and presentation thereof, with the exception of the parts taken from public domain sources or contributed by others. Conditional upon recipients accepting full responsibility for any adverse consequences or damages, I grant to recipients of this package permission to further distribute it, to post it on computer bulletin boards, to use it for developing personal or commercial applications, and to use parts of it in building other Forth systems. I DO NOT GRANT permission to distribute printed copies of the source code or the documentation, or to publish the same in books, magazines, etc. If you wish to do something along these lines, please contact me. (I am excluding from this excerpted source code that you have incorporated into your own Forth system, and nothing here is intended to prevent you from printing out a hard copy of the source code and documentation for your own use.) Is This Shareware or What? Well, yes and no. You are welcome to use Pygmy. If you do, you assume all risk. Don't use it on anything important until and unless you have completely tested it. If Pygmy is valuable to you, feel free to send me some money. A gift of any amount will be appreciated. On the other hand, my "assistants" in this endeavor (my bulletin board buddies as mentioned below) certainly should not send money. Please don't refrain from writing, regardless. That reminds me of the old joke of the kid away at college who writes home "Dear Mom & Dad, please write often, even if it's only $5.00." Chapter 2 Bonuses There are some bonuses for anyone sending me at least two tens and a five: 1. Serial I/O routines with interrupt driven input. 2. Double (32-bit) and Quad (64-bit) number support. 3. Printed glossary, organized by categories, indexed to screen numbers. 4. Shadow file (PYGMY.DOW) commenting, screen by screen, on the meta-compiler and kernel source code. 5. Perhaps (don't count on this) 1 or 2 mini-applications to serve as a skeleton for your own work. Chapter 3 Credit Where Credit is Due Pygmy Forth was inspired by cmFORTH for the NOVIX, a public domain Forth written by Charles Moore. Much of the overall structure and some of the specific high level code reflect this influence! Some of the machine code, especially flag producing words, is tighter due to ideas suggested by Robert Berkey. In addition, the code for DO LOOP (in the Starting Forth compatibility section) was contributed by Robert. Wil Baden provided OF THENS. The initial approach to handling files was suggested by Dennis Ruffer by his description of files in Forth Inc's polyForth. Rob Chapman contributed the idea of (and how obvious when you think about it!) having FOR NEXT do the loop times instead of times. He also contributed a slogan that I've adopted: "It's so simple - it HAS to work." There may be other such specific contributions that escape my mind at the moment. In general, I would also like to thank the many people who, through the Forth bulletin board network, hounded, badgered, criticized, suggested, questioned, and otherwise encouraged me to think. They should be held completely responsible for any remaining errors. Chapter 4 "Why I Wrote Pygmy" Pygmy Forth's goals: 1. Faster, more comfortable editor. 2. Reduced sized and complexity. 3. Inclusion of certain cmFORTH ideas: a. PUSH POP (instead of >R R>) b. FOR NEXT c. no IMMEDIATE word (but it does have words that are immediate) d. simple Meta-Compilation Pygmy includes 1. a fast screen oriented block editor 2. an 8088/8086 assembler 3. full source code 4. full meta-compiler 5. up to 15 files open & accessible at one time 6. default set of files opened automatically 7. FOR/NEXT, PUSH, POP, \, COMPILER vocabulary, and other cmFORTH improvements 8. Direct screen writes for speed for monochrome & color 9. vectored I/O ( EMIT, KEY, KEY?, CR ) 10. documentation (this file) 11. *Starting Forth* compatibility hints for people new to Forth Chapter 5 What Is Pygmy? Pygmy is one step on my path toward a "perfect" Forth. It runs on the IBM PC/XT/AT and compatibles. It is based (more and more loosely) on Charles Moore's cmFORTH for the NOVIX Forth chip. I have made many changes to allow it to run on a PC, and other changes as well. cmFORTH was designed to run on a NOVIX connected by a serial line to a host terminal or computer that supplies editing and file storage services. Therefore, cmFORTH does not include an editor. Also, no assembler is needed because the NOVIX's assembly language is Forth (more or less). Pygmy Forth includes an editor & assembler and still only takes up about 14K bytes. The kernel (without editor and assembler) is less than 8K. It comes with complete source code, including a meta-compiler, so it can recompile itself. The meta-compiler can also be used for target compiling custom applications. In this case you can eliminate the parts (such as the editor & assembler & various utilities) that the final application will not need. Pygmy is direct threaded with top of stack kept in a register. It has (in my opinion) quite a comfortable screen oriented block editor. You can move quickly from screen to screen with the PgDn & PgUp keys, search across screens, insert blank screens, and compress out blank screens. Pygmy allows you to have 15 files open at one time. These are all accessible "simultaneously" at different block numbers (none of the OPEN/FROM as used in F83). Your default files are opened automatically and the defaults can be changed, of course, and additional files can be opened. .FILES shows you the defaults and the documentation shows examples of how to reset them. If you need more than 15 files open at one time, there is supplemental code that shows how to have over 200 files open simultaneously (untested). Chapter 6 How To Run The Program Make a backup copy of the distribution disk. If Pygmy is distributed in a ZIP file, unzip it. If you are going to run from a hard disk, set up a directory and copy all of the files to that directory as in the following example. C:\>md pyg C:\>cd pyg C:\PYG\>copy a:*.* Then bring up Pygmy by typing C:\PYG\>pygmy In previous versions, most of the documentation was in block files. Version 1.3 contains only 3 files other than the program itself. One is a block file, PYGMY.SCR, which contains all the source code. Another is a regular text file, PYGMY.TXT (the file you are currently reading), which is readable with TYPE or LIST or just about any text editor. The last file is YOURFILE.SCR and contains 8 blank blocks all ready for you to play with. If you are reading this, then you probably know everything you need to know to read PYGMY.TXT. To read the source code, bring up Pygmy and then use Pygmy's editor to browse through the block file PYGMY.SCR. To start at the beginning, make sure Caps Lock is on, then type 0 EDIT (end all commands by pressing ). Then just start browsing with the PgDn & PgUp keys. To get out of the editor press Esc. To get back in where you left off, type ED To skip to a particular screen, press Esc to get out of the editor and then type n EDIT where n is the screen you want to jump to. To see what files have been opened automatically, get out of the editor and type .FILES CONFIG.SYS file If you get error messages when you try to open files, it probably means that your CONFIG.SYS file is not allowing enough files. Change or add a "FILES=" statement to CONFIG.SYS so it says FILES=20 then reboot and try again. (As shipped PYGMY.COM tries to open only 2 files automatically, so this should rarely be a problem.) If You Have Trouble Using Pygmy With Your Monitor Version 1.3 (as did version 1.2) of Pygmy automatically sets itself up to match the monitor you are using. This should work with any MS-DOS or PC-DOS computer that uses video display memory at either $B0000 or $B8000 (like normal IBM PCs and compatibles do). Chapter 7 If You Are New to Forth Could/should this manual teach you Forth? I don't know. Probably only YOU can teach yourself Forth. Maybe something can be done to make your job easier. I think the very best way for you to do it is to work your way through the book Starting Forth by Leo Brodie. It should be available from the Forth Interest Group (see phone number below). It's not ready as I write this, but look for an upcoming book by Kent Peterson that will teach you Forth with examples written specifically for Pygmy. I didn't design Pygmy to be a teaching Forth, but it does have some advantages: (1) it doesn't cost you a fortune (2) the entire source code is included (3) it is small enough that you have a chance to grasp it - it shouldn't be too intimidating (4) meta-compiling, using Pygmy, is the easiest I have ever seen (5) I am available to answer questions via GEnie and, thereby, a number of other bulletin boards (or even via the U.S. Postal Service - in which case a SASE might facilitate assistance to beginners). If you want to try it without a book, then read all of the documentation and read the source code as well. Try out simple examples. Join FIG and read Forth Dimensions. Then get a book, like you should have done to begin with. Then read everything again and try out more examples. There is no substitute for doing your own experimenting. The word SEE may help. To examine the internals of a word or data structure, use DUMP or DU. Make heavy use of the glossary. The stack comments are most helpful, showing what goes into a word and what comes out. Chapter 8 What Was New With Version 1.2 Some bugs have been fixed. Specifically, < & > did not work in all cases but should now be fixed. Also, / was accidentally doing an unsigned divide because I had cleared register DX rather than sign extending register AX into it. Now / does a signed division, truncating toward zero ( eg -3 2 / returns -1 ) rather than flooring. I don't much care whether division is floored or truncated toward zero so I left it the way the 8088/8086 IDIV instruction does it. U/ has been added so there is still an unsigned divide available. The various MODs are still unsigned, but have been renamed to reflect that fact. The type of video display is determined automatically. BOOT is DEFER'd to make it easy to customize ( e.g. ' MYAPP IS BOOT ). Words that return flags are now smaller and faster - based on Robert Berkey's code. LMOVE has been renamed MOVEL. I have my doubts as to which is the better name. It still takes a word count rather than a byte count. I also have doubts about that and think a byte count would make more sense, but have not changed it yet. Fast DO LOOP are now available from Robert Berkey. (Ver. 1.3 note: ALL source code is now in PYGMY.SCR.) TYPE ( a # -) replaces the cmFORTH TYPE ( a - a'). I have also added COUNT and -TRAILING to support it. I like the cmFORTH TYPE ( a - a') but the ending address was only used in one or two places so I've changed it to TYPE$ ( a -). NUMBER now understands hexadecimal literals such as $8000 $FF and ascii character literals such as 'A 'B 'z. .S has been changed so it shows exactly what is on the stack, rather than showing 3 values regardless of how many are present. This is much prettier, although more expensive. The opening greeting also shows the default files that are open. I found the first thing I always did was type .FILES so I built that into the default (BOOT word. " has been added for in-line string literals. At compile time it compiles the following text up to the ending quote mark as a counted string. It then commas in a zero byte, which is not included in the count. The purpose of this is to make it easy to setup "asciiz" strings for DOS. E.g. : TST " this is a string " TYPE$ ; -FIND and CREATE are now DEFER'd words to make experimenting with these easier. See next paragraph. The file HASH.SCR (ver. 1.3 note: this code has been moved to PYGMY.SCR) contains code to do very rapid dictionary searches. This is not built into Pygmy. If you want to use it, you must load it. Then hashing is optional ( HASH-ON HASH-OFF). You can use it for development and then leave it off in the final application. It devotes the 64K segment above Pygmy's segment to the hash table. To find a word probably takes an average of less than two compares. Unfortunately this is not the only factor involved in compiling speed. My quick tests suggest that with HASH-ON the time it takes to load an application is approximately 1/3rd less than with HASH-OFF. The larger the dictionary the more time will be saved. Chapter 9 What Is New With Version 1.3 File handling has been overhauled. Everything is now done relative to the unit# of the file. See UNIT, SETTLE, CHOP, OPEN, ?CLOSE, etc. ABORT is now a DEFER'd word, to make customizing applications easier. For Leonard Morgenstern, NUMBER & LITERAL are now DEFER'd. (This also makes adding the double and quad number extensions easier!) (ONEKEY is the default for KEY. It returns a single value no matter what key is pressed, rather than a single value for some keys and two values for other keys, as DOS does. I MUCH prefer the consistency of a single value. All the source code is now in a single (block) file. All the documentation is now in a single (text) file. Meta-compiling is even easier. WORD no longer does BLOCK every time (for faster loading). SEE now handles abort" " etc. and recognizes non colon words. FILES now keeps track of the highest block # in the file. Neither the editor nor BLOCK will go outside actual file bounds anymore. HOLES added to editor (F9). SETTLE & CHOP make managing block files more convenient. Search across now always goes to end of file, no need to set the ending screen number. THRU no longer uses the data stack, so multi-screen definitions which pass arguments on the stack can now be loaded with THRU. Added N! ( n a - n) to store n into a, keeping a copy of n Changed FOR/NEXT so 0 FOR ... NEXT goes thru loop zero times & u FOR ... NEXT goes thru loop u times. Robert Berkey suggests spelling it ?FOR. ABORT" now includes the IF. Added +UNDER ( a b c - a+c b). Added NIP ( a b c - a c). Straightened out the redundant EXIT. Chapter 10 TIPS Set Caps Lock on. Most words must be typed in UPPER CASE. To abandon changes you have just made in the editor, use Esc to get out of the editor then type EMPTY-BUFFERS ?SCROLL is embedded in WORDS and DU to let you halt the display by pressing any key (except Esc). Press any key again to start it up again (except Esc). To bail out, whether you are scrolling or paused, press Esc. You can also put ?SCROLL into your own words. For my tastes, this is very much better than the common practice of aborting the display when you press the key. DUMP ( a - a') and DU ( a # - a') allow you to inspect memory. DUMP dumps one line and leaves the address of the next line ready for typing DUMP once more. DU repeats DUMP for a number of lines. ?SCROLL is built in, so feel free to type 0 2000 DU (you can get out of it with Esc, or pause with any key). You'll probably want to say HEX first. .FILES ( -) shows the files that are currently open and the block numbers associated with them. You can open ANY type of file; you are not limited to Forth style BLOCK files. The word ." works either inside or outside of colon definitions. There is no need for the abomination .( (Actually there are two ."s one is in FORTH and the other is in COMPILER.) Pygmy recognizes $xxxx as a hex number (e.g. $2000 or $1FFE) and it recognizes character literals as well (e.g. 'A 'B 'C 'z). The hex literals are a great convenience and allow us to stay in DECIMAL more of the time. The character literals allow us to avoid the ugly CHAR & [CHAR] or ASCII & [ASCII]. NOT in Pygmy inverts the truth value on the stack. It is equivalent to 0=. If you want to invert each bit individually, use -1 XOR Chapter 11 How Files Work There are some changes in version 1.3. I'll discuss the philosophy more in another place. Pygmy can access a number of files "simultaneously." As shipped, it contains 15 slots or units for files. This can be changed to a smaller number if you wish. If you must access more (perhaps over 200 files), that can be done also, and sample code is included in PYGMY.SCR. Before you can access a file, it must be installed into one of the slots. This is done by the word UNIT. UNIT establishes the file's starting block number and the file's name (as it is known to DOS). This name can include the full path, including drive, for those cases where the file is not in the default directory. The parameters for UNIT are starting-screen#, file-name, and unit#. The file-name is the address of a counted string that ends in a zero byte (for the DOS "asciiz" format). There are several ways to define the name. Most of the time I use the word NAMEZ: which defines a word whose name is the string. For example, NAMEZ: YOURFILE.SCR defines a Forth word YOURFILE.SCR that returns the address of the counted string "YOURFILE.SCR" with the required zero-byte following the name. Now that we've defined the file name, we can install it into unit# 7 and declare that its starting block number will be 3000 by typing 3000 YOURFILE.SCR 7 UNIT Note, that this does not open, create, check, or do anything with the actual file. Once a file name and starting block number are equated with a particular unit#, everything else we want to do to that file is done by referring to its unit#, in this case 7. To open the file, type 7 OPEN To create a new file, type 7 MAKE To close the file, type 7 ?CLOSE Once you have set up the name and number with UNIT, you can open and close the file repeatedly without using the word UNIT again. If you want to use that slot (unit) for a different file, just set up the new name and number with UNIT, by typing, for example, NAMEZ: MYFILE 4000 MYFILE 7 UNIT 7 OPEN The file that was previously in unit# 7 will be closed automatically before the new file is opened. The question mark on ?CLOSE indicates that it closes the file if it is open, but doesn't blow up if the file is not open. As shipped, Pygmy version 1.3 has two files that are already installed in units 0 & 1. These are PYGMY.SCR, which contains all the source code, and YOURFILE.SCR, which contains 8 blank screens. These are automatically opened for you and ready to go. YOURFILE.SCR is provided so the new user of Pygmy has a file ready to go for his own source code. Any time you want to see which files are installed in units, whether they are open, or what their starting block numbers are, type .FILES You are not limited to these files! Close them all down with RESET-FILES if you like, and open your own set. If you save that image of PYGMY (ie SAVE TST1.COM), whenever you bring up that image (by typing TST1 at the DOS prompt) your custom set of files will automatically be opened for you (and the list of names and starting block numbers will be displayed). When installing file names with UNIT, be sure to give each file a different starting block number, so the block numbers do not overlap. It's probably neater to set them up with ascending numbers. For example, unit 1 could start with block #0, unit 2 with #300, unit 3 with #600, etc. However, that is not necessary in version 1.3. All block numbers must be lower than 8192. Each block in the entire system of open files has its unique number. There is no need to use the F83 OPEN/FROM CONVEY. There is no need for OFFSET. To copy a range of blocks, whether to and from the same or different files, just say ( from to #) COPIES e.g. 17 300 50 COPIES to copy the 50 blocks starting at block 17 to the 50 blocks starting at block 300. It is an error if those blocks do not exist. In earlier versions of Pygmy you could extend a file just by accessing a block past the end of file. In version 1.3, the blocks must already exist. To extend a file, either use the word MORE or use F9 from within the editor. It does not work quite like the MORE of F83. If the file is not empty, the easy way to extend it is to get in the editor and move to the last block and use the F9 key (which does MORE for you). For copying a single block you can still use COPY. Chapter 12 The Assembler The 8088/8086 assembler in Pygmy is a regular Forth postfix assembler. For examples of how it is used, browse through PYGMY.SCR. Begin a code word with CODE and end it with END-CODE, e.g. CODE DUP BX PUSH, NXT, END-CODE Except in special cases (& then you know what you are doing) code words must perform next somehow. In Pygmy, this code is laid down in-line (by the word NXT,) rather than by a jump to a central next routine. If your routine disturbs CS, DS, BP, SP, SI, or BX it must restore it. The direction flag must be left clear. BP points to the return stack. SP points to the data stack. The top (data) stack item is kept in BX rather than on the actual stack. See example above for DUP. DS:SI is Forth's IP register. AX is Forth's W register, but you may use it freely without restoring it. The assembler words generally end in a comma, signaling they actively comma data into the dictionary. This is useful for another purpose: as the assembler words and the regular Forth words all sit in the same vocabulary (FORTH), the comma helps distinguish between similar words, e.g. THEN & THEN, It is a "structured" assembler with IF, XXXXXX ELSE, XXXXXX THEN, and XX #, CX MOV, BEGIN, XXXXX LOOP, etc. If it is not clear from the instruction whether the operand is a byte or a word, a byte is assumed. E.g. 0 [BX] PUSH, would push only a single byte. To override this, use W-PTR e.g. 0 [BX] W-PTR PUSH, For the shifts & rotates, if an immediate operand precedes it, it shifts a single bit, e.g. 1 #, AX SHR, ( shift AX one bit right) or even 300 #, AX SHR, ( shift AX one bit, not 300 bits, right) If you want it to shift based on the contents of CL, omit the immediate operand, e.g. 4 #, CX MOV, AX SHR, examples to shift right 1 bit: 1 #, SI SHR, 1 #, W-PTR 17 [BX] SHR, 1 #, AL SHR, examples to shift right the # of bits in CL SI SHR, AL SHR, 1300 ) SHR, 3752 W-PTR ) SHR, IN, & OUT, (reading & writing I/O ports) use port #, AL IN, or port #, AX IN, for 8 bit ports or AX IN, if the port number is the DX register. Do not use AL DX IN, as the DX is implied. JMP, & CALL, Long JMPs & long CALLs are "not supported at this time." The instruction that does a bit by bit complement is called NOT by Intel, but in THIS assembler it is called COM,. This assembler uses NOT, to invert the test at the beginning of an IF, e.g. CS, IF, ( do if carry set) THEN, or CS, NOT, IF, ( do if carry not set) THEN, The full source code for the assembler is present in the file PYGMY.SCR. Some examples are included along with the source code. In addition, you can browse the code for Pygmy's primitives for examples of how to use the assembler. The general rule is that the operand(s) come first followed by the opcode mnemonic (which ends in a comma). With two operands, the source comes first and the destination second, like god meant it to be. BX AX MOV, lays down a move instruction to copy the contents of register BX into register AX. Chapter 13 The Editor Editor commands: To enter the editor, type n EDIT. To get out of the editor, press the ESC key. When you are in the editor you can make changes by using the arrow keys to position the cursor and then just typing. Press the INS key to switch between the insert and the overwrite modes. The backspace key will delete characters to the left of the cursor and the Del key will delete the character the cursor is on. Inserts and deletes only occur on the current line. The PgUp & PgDn keys are used to move to the previous or next screen. This is delightfully fast compared to the editor in F83. If the cursor is at the beginning of the line already, Home moves to top of screen; otherwise, Home moves to beginning of current line. End moves past last character on current line. The very top line of the screen is a status line that shows the screen number and the file name and a brief reminder of some of the function keys' functions. It also shows an "i" if in the insert mode. It also shows a count of the lines in the cut buffer. F1 repeats a search. F2 repeats a replace. F3 sets up a search string and then searches. F4 sets up a replace string and immediately replaces with it. ( To repeatedly change CAT to DOG, use F3 to set up CAT ) ( & F4 to set up DOG and then press F1 F2 F1 F2 etc ). F5 deletes the current line. F6 joins the line below to the current line at the cursor. F7 "cuts" the current line to the cut buffer. This does not alter the current line. (See the "c= " on status line). F8 "pastes" the oldest line in the cut buffer to the current line on the screen, overlaying the current line. The cut buffer is almost unlimited in size. It can be used to copy and move lines on the same screen or to different screens (even screens in different files). Notice that the count of lines cut (on the status line) changes as you press F7 & F8. F9 inserts blank screens after the current screen. F10 does a search like F1, but across multiple screens. Esc exits from the editor. If you want to cancel the most recent changes, after pressing Esc, type EMPTY-BUFFERS. If you want your most recent changes to be applied to the disk immediately, after pressing Esc, type FLUSH. CR ends the current line, pushing anything to the right onto the following line and pushing the lines below it down. Home moves the cursor to the beginning of the current line. If already at the beginning, it moves the cursor to top left corner. End moves the cursor just past the end of text on the current line (which may be at the 1st position of the following line). Bksp If not at the far left of a line, it deletes the character to the left of the cursor. Del deletes the character the cursor is on. Ins toggles insert vs overwrite modes (see the "i" on status line). Note, the deletions and insertions only affect the current line. Oooops How do you exit from the editor without making any changes? (cancel your changes, that is)? Press Esc key to get out of the editor and then type EMPTY-BUFFERS F9 is good for opening up a file in the middle or for extending a file at the end. As you move screens around and delete them from where they used to be, you may accumulate a number of blank screens. SETTLE (used outside of the editor) is used to let the heavy screens sink to the bottom and let the light screens float to the top. It only affects the range of screens that you specify, e.g. 315 345 SETTLE will re-arrange those screens so that any completely blank screens are at the highest numbers and the non-blank screens are at the lowest numbers. This compresses out blank screens. A related word CHOP will truncate a file by chopping off all trailing blank screens, e.g. 3 CHOP will chop the blank screens off the end of the file whose unit# is 3. Chapter 14 The Meta Compiler Pygmy includes a meta-compiler. It is easy to use. To regenerate the kernel of Pygmy, edit the source code in the file PYGMY.SCR to include your changes. Then type 1 LOAD This will create a new version of the Pygmy kernel and save it to disk. Be sure to edit the file name you want it saved as on scr #1. Exit to DOS with BYE and bring up the new version you just created. It is the kernel only, without the editor or assembler or other extensions. However, it will have the file PYGMY.SCR already set up in unit# 0, and opened automatically. To extend it, just load the proper load screen. This screen number is usually noted on screen #1 to make it easy to find, e.g. 83 LOAD Look at screen 83 to see how this works. Note that this is simpler than in previous (to version 1.3) versions. Having all the source code in a single file makes this easier. Be sure to edit screen 83 (or whatever your load screen is) so it will include just what you want and so it will save the newly created Forth to the proper file name. Meta-compiling Pygmy is very easy, so don't put off trying it. It lets you fix all the aspects of Pygmy that you disagree with me about! Your first attempt should be to generate a version of Pygmy with no changes whatsoever, except possibly the file name you save the new versions under. Once you've done this once or twice you can begin changing the kernel, or extending it differently. Here is how the meta-compiler works. First the load screen (#1) loads the meta-compiler (on screens 3 through 13). This renames some of the current Forth's words (so they can still be found) and then redefines the defining words needed for the new Forth. Note a number of variables such as TLIT and TVAR etc. These will hold the addresses of the target's runtime routines (for LITERAL and VARIABLE etc.) as soon as those runtime routines have been defined in the target. The meta-compiler will use those values to compile the proper code in the target. Then, starting at screen 17, the target's code begins. The target is compiled starting at address $8000. H' holds the target's dictionary pointer (H holds the host's). Following H' is the relocation factor used for the target code. The curly braces switch between the target & host spaces, so that the regular host facilities, such as , HERE -FIND etc can be used for both purposes. The host does need some special meta-compiler words. When we are redefining a host word that we might need the original of, the original is renamed, so we will still have access to it under the synonym ( e.g. : :' : ; ). There are two ghost vocabularies used for the target. After our redefinitions, FORTH & COMPILER refer to the target and FORTH' & COMPILER' refer to the host. This is the secret that keeps everything straight. When interpreting, words are looked up and executed (as is normal) from the FORTH' (host) vocabulary. When compiling a colon definition, COMPILER' (host) is searched first. If found the word is executed immediately. If not found, FORTH (target) is searched. If found, the word is compiled into the new definition. If not found, it is converted to a number (or an error) and compiled as a literal into the new definition. So, when meta-compiling, target COMPILER words are never executed, leaving the host's free to operate. When not compiling, target FORTH words are never executed, leaving our regular host system free to operate. \ is redefined so when meta-compiling, the word is looked up in the target's COMPILER vocabulary and compiled into the new definition. All of this means that you do not have to "forget" any of the target words. (There may one or two that need to be forget'd. I can't remember at the moment, ha ha.) So what changes might you make? Changing the constant TMAX-FILES will let you specify just how many files to allow open at the same time. Changing TNB lets you change the number of file buffers that will be used. Currently TNB is 1, which allows 2 buffers. Note that the number of buffers must be a power of two (and greater than 1), so acceptable values for TNB are 1, 3, 7, 15, etc. (TNB and thus NB are set to 1 less than the number of buffers.) Suit yourself. So far I haven't had any trouble using just two. You can eliminate the excess and useless words that I've included which you see no need for. (Just don't eliminate any that are used in the definitions of other words that you do want to include!) For target applications, you can let the metacompiler do all of your CODE (assembly language) words so that you do not need to include the assembler in the final target application. (You might also eliminate the editor from the final application if it isn't needed, but, since it is loaded after the kernel has been created, that's not affected by the meta-compiler.) Currently the meta-compiler does not allow headless code. If you want to streamline the dictionary, you can unlink the auxiliary words that won't need to be looked up in the final application by using HIDE (see its definition in PYGMY.SCR). The heads won't show with WORDS and they won't be in the links to slow down the dictionary searches, but they'll still be taking up space. If you change the boot code, you may need to change the patch on screen 68 where the address of reset is patched into boot. If you are target compiling an application and want it to execute your code automatically (rather than coming up in Forth) just point the word BOOT at your application. Suppose you have named it YOUR-APPLICATION. Type ' YOUR-APPLICATION IS BOOT and then save it to disk with something like SAVE YOUR.COM Note that BOOT can be re-vectored as above at anytime, not just when meta-compiling. The source code in PYGMY.SCR is set up to choose between monochrome and color displays automatically. The word 'VIDEO supplies the two address used by RESET to setup the system variables CRTC and VID to the correct addresses for the monitor you are using. For a color monitor VID is set to $B800 and CRTC is set to $03D4 and for a monochrome monitor, VID is set to $B000 and CRTC is set $03B4. Thus, a single version of Pygmy, should run on either color or monochrome. I think Pygmy will now work on all MSDOS & PCDOS systems that have video display memory at either $B000 or at $B800. If you have any trouble with it on your system, please send me full details. Chapter 15 VOCABULARIES PYGMY, like cmFORTH, has two vocabularies: FORTH & COMPILER. Compiler words are immediate by virtue of being in the COMPILER vocabulary. INTERPRET only looks up words in FORTH. When compiling, COMPILER is searched first. A word found in COMPILER is executed immediately otherwise FORTH is searched and if the word is found it is compiled. To force compilation of a COMPILER word, precede it with a backslash ( \ ). This is used in place of the FORTH-83 word [COMPILE]. CONTEXT holds the number that represents which of the two vocabularies is active. Whichever it is, that is the vocabulary into which new words will be linked. FORTH & COMPILER set CONTEXT to the appropriate number. There are also has 2 "spare" vocabularies available for use by the meta-compiler. Chapter 16 ADDITIONAL INFORMATION For additional information, browse through all of PYGMY.SCR using the editor ( n EDIT ) and the PgDn & PgUp keys. Search across (F9 in the editor, after setting up the search string with F3) is handy for finding a particular word's definition or where it is used. Use search across as a substitute for VIEW, which is not available. Chapter 17 ADDRESSES I'm glad to hear your comments. I can be reached on GEnie as F.SERGEANT or via the post office: Frank Sergeant 809 W. San Antonio St. San Marcos, Texas 78666 for info on signing up with GEnie dial 1-800-638-9636 Join FIG, send $30 (in North America) to Forth Interest Group (408) 277-0668 P.O. Box 8231 San Jose, CA 95155 FIG is a great source for Forth related publications. East Coast Forth Board bulletin board (703) 442-8695 ACM SIGForth c/o ACM Box 12115 Church Street Station New York, NY 10249 (212) 869-7440 or George Shaw (415) 276-5953 Dan Miller (713) 363-3140 Chapter 18 The Glossary If you don't have the printed glossary, use the file PYGMY.SCR and the editor's PgUp, PgDn, and F3 F9 search across screens to find the words you want more info about. Chapter 19 MEMORY MAP Pygmy fits in one 64K segment. DOS loads it at offset $0100. CS@ will fetch the contents of CS (the code segment), in case you need to know the absolute address of the program. The dictionary grows up from low memory. The stacks & TIB and disk buffers are in high memory (within the one segment). origin $0100 boot code $0100 1st word (null) $010B system variables $0116 - $0147 dictionary continues $0148 HERE $29C5 ( perhaps, if assembler is not loaded) TIB @ $F300 ( TIB is $100 bytes below the 1st disk) ( buffer. The last disk buffer is ) ( always at $F800 ) 1st disk buffer $F400 2nd disk buffer $F800 data stack pointer $FE00 ( grows down from FE00) return stack pointer $FF00 ( grows down from FF00) It also has 2 "spare" vocabularies available for use by the meta-compiler. Chapter 20 FILES MAX-FILES may be open at once. If you want a different mix, use RESET-FILES and open a new set or re-setup the files one by one with UNIT. If you then save an image of Pygmy, next time you bring it up, those files will be opened for you automatically. To install a file, you must say what the starting block number should be. I usually set them up in 300 block increments, but you may choose whatever increment you wish. It is no longer important that they be in ascending order. If the third file opened was handled this way NAMEZ: DUMMY.BLK 600 DUMMY.BLK 2 UNIT 2 OPEN then the beginning of the file would be screen 600. Previous (to 1.3) versions allowed you to alter the block numbers with which you accessed a file by using the word UNIT which set OFFSET to some value. In version 1.3, there is no word OFFSET, and UNIT has an entirely different use! Now UNIT establishes which starting number and file name go with which "unit" number. Chapter 21 DIRECT THREADED Pygmy is direct threaded, with TOS kept in a register (BX) for speed. Constants are coded "in-line" rather than by jumping to a central constant routine. This costs 2 bytes per constant but saves 40 cycles (46 vs 86) on the 8088. System variables are really coded as constants. So this method helps speed up the system. Note that the system variable TIB returns the address of the address of the terminal input buffer, as in figForth. Variables don't seem to offer the same advantage and so they still use a central routine. DEFER/IS deferred words are supported. EMIT, KEY, KEY?, CR, BOOT, ABORT, NUMBER, LITERAL, -FIND, and CREATE are deferred. ( e.g. DEFER EMIT ' (EMIT) IS EMIT ) Chapter 22 HISTORY & PHILOSOPHY Pygmy was based on cmFORTH by Charles Moore. cmFORTH is designed for the NOVIX Forth chip. cmFORTH doesn't include an assembler as that's not needed for the NOVIX. Also, it doesn't include an editor, as it is designed to be used with a host terminal or computer that supplies the disk storage and editing facilities. A Forth for the IBM PC/XT etc., can't do without an assembler and editor, and so these have been included as part of Pygmy. The goal for Pygmy is not to copy cmFORTH exactly, but to use it as a starting point for a fast lean Forth that can be used for serious application development. I've added multiple files (up to 15, but you can change it to fewer if you like) open at the same time, and the default set are opened automatically. This was inspired by Dennis Ruffer's notes on GEnie about Forth Inc's PolyForth. If you want up to 200+ files open at once, see the supplemental code in PYGMY.SCR. The editor is fast and is so much more comfortable than the line editor in F83 that I'm satisfied for now. Still, I don't feel I've completely solved the problem of managing source code. The addition of "holes" SETTLE CHOP have helped. I want it small & fast, but I want it comfortable too. I worry that it has grown too big. I have not added vocabularies. I like the cmFORTH idea of marking immediate words by the fact that they are in the COMPILER vocabulary! Everything else is in FORTH. Is this a problem? I don't think so, for me, but it makes for a crowded & busy WORDS listing and forces assembler words to end in commas. The auxiliary words can be unlinked from the dictionary to speed up searches and to unclutter WORDS somewhat. See HIDE in the supplemental definitions. I don't, personally, use HIDE, but I've included it for you if want it. DO/LOOP have not been included. If you miss them too much, load them (Robert Berkey's version) from PYGMY.SCR screen #171. I've been enjoying using FOR/NEXT and have not missed DO/LOOP. I changed FOR/NEXT so it does the loop n times instead of n+1 times. This was suggested and inspired by Rob Chapman. I no longer use cmFORTH's TYPE ( a - a'). In cmFORTH it expects to find a count at the first byte of the address. Instead I use a regular TYPE ( a # -). In addition there is TYPE$ ( a -) which expects the address of a counted string. It does COUNT TYPE and does not leave an address on the stack. There are 3 name changes in cmFORTH (& Pygmy) that delight me: new names old names PUSH >R POP R> \ [COMPILE] I think I always get >R & R> right, but it gives me hell every time I have to think about which is which. PUSH & POP are so much better names, in my opinion, and so much easier to read. I don't see how you can try them and then go back to >R & R>. I also prefer \ to [COMPILE]. I like comments in parentheses, so do not mind losing \ for that purpose. Also it is shorter and clearer (I think) than [COMPILE] once you get used to it. The stack comment for cmFORTH's M/MOD is ( l h u - q r) but I have implemented it as the more familiar ( l h u - r q). Of course, there are extensive changes from cmFORTH because the primitives had to be coded in 8088/8086 machine language rather than NOVIX. I may have made other changes due to my failing to appreciate the beauty & simplicity of how CM did it. I hope anyone noticing such denseness on my part will point it out to me. I am far from satisfied that I have found the "perfect" Forth in Pygmy. Overall I am pleased. There are many areas where Pygmy "works, but isn't pretty." The compromise I like is where you give up something you don't want to get something you do want. When I see one of those it is an easy decision. The more common decision is where you give up something you do want for something you think you prefer but aren't quite sure, or where you give up something you really want for something you have to have. I think there is room for a number of different styles of Forth. Speed with lots of primitives in machine language versus ease of porting to other microprocessors by having a minimal number of primitives: I (more or less) went for the speed. I traded off some efficiency in disk access for a much more regular and comfortable file interface. I've supplied the hooks for sequential file access (see FILE-READ FILE-WRITE >POSITION >EOF >BOF etc.) primarily for accessing data files in various formats, rather than for loading source code from text files. Sometime I want to try for raw speed with "Forth owns the whole disk" but I haven't reconciled that with my need for co-existing with DOS, which I feel I have to do at this time. I've left out VIEW and substituted a search-across-screens in the editor. But, I've included a fairly complete SEE for colon definitions. The supplemental hashing dictionary search mechanism is something I use almost all the time (it can be thrown away for the target system). Chapter 23 How to Print the Source Code SHOW prints source code screens 3 per page. SHOW2 prints source code screens 6 per page (your printer must allow 132 character lines). These words are now included in PYGMY.COM, so you don't have to load anything. If you are using SHOW2, you must set up the word CONDENSED so it will work with your printer. See screens #83 and #150-155 for more info. Once you have CONDENSED set correctly for your printer, type 0 182 SHOW or 0 182 SHOW2 to print the entire contents of PYGMY.SCR. If you are using an HP LaserJet II, IIP, or III, (or many other printers) you can set the characters per inch from the front panel (internal font #10 on a II, for example) and just set CONDENSED to a NOP ( e.g. ' NOP IS CONDENSED ). **** The End ****