Pygmy Forth version 1.4 MANUAL Copyright 1989-1992 Frank C. Sergeant 809 W. San Antonio St. San Marcos, TX 78666 Pygmy Forth version 1.4 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 16K. 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 and Other Products 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 Was New With Version 1.3 Chapter 10 What Is New With Version 1.4 Chapter 11 Tips Chapter 12 How Files Work Chapter 13 The Assembler Chapter 14 The Editor Chapter 15 The Metacompiler Chapter 16 Vocabularies Chapter 17 Additional Information Chapter 18 Addresses Chapter 19 The Glossary & Index Chapter 20 Memory Map Chapter 21 Files Chapter 22 Direct Threaded Chapter 23 History & Philosophy Chapter 24 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.4 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 the excerpted source code 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. Please don't refrain from writing, regardless. Chapter 2 Bonuses I offer a Bonus Disk to encourage you to "register" for anyone sending me at least $15 (North America) or $20 (elsewhere) (U.S. funds, please; International Postal Money Orders in US dollars are ok): 1. Serial I/O routines with interrupt driven input. 2. Double (32-bit) and Quad (64-bit) number support with 128-bit intermediates. 3. Shadow file (PYGMY.DOW) commenting block by block on the PYGMY.SCR source code. 4. FILTER.SCR examples of creating filter programs to read, modify, and write from and to standard input and output. 5. Copies of various articles on metacompilers, introduction to Forth, help screens, 8 Queens in Forth, arbitrarily high precision math (e.g. 1000 decimal digits). 6. Some laser printer support code (HP Laser Jet II, etc.) 7. Forth assembler for the Motorola 68HC11 microprocessor than can be run from Pygmy on the IBM PC. You really ought to get this, for the shadow blocks if nothing else. Combined with the ability to switch back and forth between source and shadow while in the editor they provide a very useful on-line reference. and Other Products At the moment (October, 1992) I offer a Bare Bones EPROM Programmer Kit (kit or assembled) for sale. This lets you turn your PC into a programmer for 2716, 2764, 27128, and 27256 EPROMs. It is easy to build and easy to use and I'm selling it far too cheaply to be taken seriously. Please see the file FLIER.TXT for more information. Of course, everything is subject to change without notice, but don't worry: if you order and I've discontinued it I'll return your check. I toy with the idea of offering a Professional Pygmy that would include additions along the following lines: multi-tasking, vocabularies, ability to use C style object libraries, even faster compilation, perhaps a closer tracking of ANSI Forth, annual updates, etc. I also toy with the idea of offering Pygmy for other processors such as the 68HC11, 680xx, 6809, Z80 & derivatives, 8051 & derivatives, Z8 & Super8, etc. I have had preliminary versions running on the Super8 and RTX2001 and am not far from the Motorola processors. The problem with this paragraph and the preceding one is I haven't figured out how to make any money doing either! If you have "registered" Pygmy I'll probably send you a flier when and if any of these others becomes available. I don't much feel like leaving home for very long, but I am often available for consulting work for short assignments. 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." Many other people, especially Ian Watters, Greg Lisle, Brad Rodriguez, J.E. Thomas, and David Zethmayr have offered suggestions and encouragement (and prodding) that have helped make Pygmy as pretty as it is today. Thank you. 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 Metacompilation Pygmy includes 1. a fast screen oriented block editor 2. an 8088/8086 assembler 3. full source code 4. full metacompiler, even easier to use than previously 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. BIOS video calls for the best mix of speed and compatibility. 9. vectored I/O ( EMIT, KEY, KEY?, CR ) 10. documentation (this file) 11. _Starting Forth_ compatibility hints for people new to Forth 12. an experimental "compleat beginner's" tutorial 13. VIEW for rapidly locating the source code for a particular word 14. a relocatable dictionary 15. ability to selectively make words headerless 16. ability to load from textfiles with FLOAD and to mix and nest between LOAD and FLOAD as deeply as you like Chapter 5 What Is Pygmy? Pygmy is one step on my path toward a "perfect" Forth. It runs on 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 did not include an editor. Also, no assembler was needed because the NOVIX's assembly language is Forth (more or less). Pygmy Forth includes an editor & assembler and still only takes up about 16K bytes. The kernel (without editor and assembler) is less than 8K. Actually, you have quite a lot of control on just how big it is because you can customize the system just the way you like it. It comes with complete source code, including the metacompiler, so it can recompile itself. The metacompiler 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. And you can make words headerless to reduce the size or transparency of your final applications. Pygmy is direct threaded with top of stack kept in a register. It has a comfortable screen oriented block editor. You can move quickly from block to block with the PgDn & PgUp keys, search across blocks, insert blank blocks, and compress out blank blocks, and switch between related blocks (for shadows or for comparing different versions of an application). Pygmy allows 15 files open at one time. These are all accessible "simultaneously" at different block numbers. 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 at one time. 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 All of the source code for the system, both the kernel and the extensions, is in the block file PYGMY.SCR. The manual 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. Another block file, YOURFILE.SCR is provided for the source code you write. It starts out with 8 blank blocks and can be enlarged as much as you like with the Editor's F9 key. Of course, you are free to create and use additional block files, but you do not have to do so in order to use Pygmy. If you are reading this, you probably know everything you need in order 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. If you have the shadow blocks available, press Ctrl-A to switch between a source code block and its shadow. To get out of the editor press Esc. To get back in where you left off, type ED To skip to a particular block, press Esc to get out of the editor and then type n EDIT where n is the block you want to jump to. To see what files have been opened automatically, get out of the editor and type .FILES To see the source code for a particular word, type VIEW followed by the word's name, e.g. VIEW EXPECT or you can use the shorthand V. 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 a few files automatically, so this should rarely be a problem.) If your monitor works with DOS it should work with Pygmy. Version 1.4 of Pygmy no longer tries to set itself up to match a particular monitor. Instead, it accesses the video through BIOS calls. 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). 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 and non-intimidating enough that you have a chance to grasp it (4) metacompiling, 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 a reply). 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 VIEW is a great help. To examine the internals of a word or data structure, use DUMP or DU. Make heavy use of the source code and shadows. The stack comments are most helpful, showing what goes into a word and what comes out. You could even try the experimental tutorial I have included. Print it out so you can work from a hard copy. Chapter 8 What Was New With Version 1.2 Just the highlights: / does a signed division, truncating toward zero ( eg -3 2 / returns -1 ) rather than flooring. U/ does an unsigned divide. BOOT is DEFER'd to make it easy to customize ( e.g. ' MYAPP IS BOOT ). Fast DO LOOP are now available (courtesy of Robert Berkey). 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 this to TYPE$ ( a -). NUMBER now understands hexadecimal literals such as $8000 $FF and ascii character literals such as 'A 'B 'z. .S " 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$ ; Chapter 9 What Was 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. (but see additional changes in version 1.4, where the handle is used more often). 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. You can still say ' (KEY IS KEY if you prefer the double code for special keys. All the source code is now in a single (block) file. All the documentation is now in a single (text) file. Metacompiling is even easier. FILES now keeps track of the highest block # in the file. Neither the editor nor BLOCK will go outside actual file bounds. HOLES was 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 block number. (But Esc key will abort it.) THRU no longer uses the data stack, so multi-block definitions which pass arguments on the stack during compilation 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 prefers spelling this ?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 What Is New With Version 1.4 Some of the following words are optional extensions and are not PYGMY.COM until you LOAD them. See blocks 133-135 for information on loading these extensions. " can now be used outside definitions as well as within. FILE handling has changed and/or improved in several directions. Check _all_ your code for compatibility with the new file handling words. We can now open a file inside or outside of definitions with a string literal (or a named string as before) " FILE17.SCR" 4 OPEN which beats the cumbersome process of v1.3. Files are now opened by specifying the name and the unit number. The number of the first block of each file is the unit number times one thousand, e.g. 0, 1000, 2000, 3000, etc. The following words now take a handle instead of a unit#: LBLK >EOF >BOF FCLOSE POSITION@ >POSITION +POSITION FILE-READ FILE-WRITE MORE FILE-SIZE SET-FILE-SIZE FOPEN and FMAKE take an asciiz counted string and return a handle and flag, eg. " T1.TXT" FOPEN from inside or outside of a colon definition. The following words still take unit#: ?CLOSE ?OPEN OPEN? EXISTS? MAKE ?MAKE Thus there is no longer a need for HANDLE-WRITE, etc. I think this factoring is more flexible and will let us do anything we want to do with DOS files. The above form the basis for a textfile loading facility, which is optionally loaded, or not, at metacompile time. I'd like to please those who really want to be able to load source code from textfiles while not penalizing those who only want to load from blocks. The main words are READ-LINE ( - a #) FLOAD ( name -) e.g. " FILE3.TXT" FLOAD INCLUDE ( ( -) e.g. INCLUDE FILE3.TXT they use various auxiliary words such as FIB ( holds addr of file input buffer) #FIB ( holds length of text string in file input buffer) >FIN ( holds offset from start of textfile) FBLK ( holds handle number for active textfile) FIBH ( holds handle number that matches contents of FIB) This system allows unlimited (well, limited by size of return stack and number of handles allowed by DOS) nesting in any combination of block and textfile LOAD and FLOAD and INCLUDE. Restrictions on contents of textfiles: They are expected to contain lines of no more than 132 characters, which end in CRLF ($0D $0A). Single words may not cross line boundaries. Paren type comments ( such as this) would be fine as long as the parens are paired on the same line. However I am adding a slightly different definition of left paren (as an extension) which will allow multi-line comments, such as ( This is a multi-line comment because the ending paren is not on the same line as the beginning paren.) All control characters in the file buffer (after partitioning it by CRLF pairs) are converted to spaces. Thus, there is no special requirement as to whether the file ends in Ctrl-Z, etc. Even though lines are expected to end in CRLF pairs, there is no problem if the CRLF is missing from the final line of the file. There is now a #TIB which is analogous to #FIB. QUERY can be used to gather text to be WORD'd (a simple #TIB OFF at the end will keep INTERPRET happy; no more having to fool with SPAN and >IN) and now EXPECT can be used without disturbing INTERPRET since the #TIB function has been separated from SPAN, thus no need for $INPUT, but I have added #INPUT as an extension. Textfile loading does not involve the unit# table and neither does SAVEM or SAVE, so the need for UN-UNIT (or its newer name RELEASE) goes away as well (or so I think). I have improved TXT>BLK which _creates_ a block file from a textfile, and BLK>TXT which _appends_ a range of blocks to the end of an already existing textfile. (I think only one of the words was in version 1.3, and that it was much slower.) Conditional compilation: I have added .IF ... .ELSE ... .THEN and ?LOAD to the metacompiler for conditional compilation (e.g. to allow the constant TFILES to control whether to load the textfile words or just the plain block words). Don't nest the .IF etc. -1 CONSTANT TFILES ( true if textfiles are desired) TFILES .IF 71 LOAD .ELSE 70 LOAD .THEN View Fields and Headerless Words I've been going up and down and back and forth on this. At first I made view fields a metacompile-time option; once set the system always had view fields or never had view fields. I also allowed headerless words with Ian's suggested | symbol preceding the word to be made headerless, but only during metacompilation. I didn't want users burdened with view fields if they didn't want them, or if space was too tight. However, I decided if I was going to have headerless words at all then I hated not to be able to behead the various editor support words. So, I decided to allow headerless at anytime. That eases the burden that view fields might cause, as space can now be saved, if necessary, by making certain words headerless. I was torn over whether to use | which is compact but has to be used for every word you want headerless, or to use HEADERS OFF ... HEADERS ON to bracket an entire section that is to be made headerless. I finally compromised by allowing both. And, they can co-exist without trouble. If either HEADERS are OFF or if a word is preceded by | then the word will be headerless, otherwise headerful. This means we need PRUNE and { and } in the kernel, not just in the metacompiler. The two versions do different things. The alternate dictionary must be established before using headerless. Currently the word SET-EDGE sets up H' and remembers its initial value. EDGE refers to the edge of the world that the headerless words' headers fall off of. I'm open to suggestions for better names. Care to suggest a decent name for this? PRUNE resets H' from EDGE, and is included in SAVE, because an unpruned dictionary with headers over the EDGE would be useless if reloaded. NOTE: as shipped, EDGE is set to $C000. Be sure not to let the dictionary grow above this value if you have any unPRUNE'd headers present. (If you define any headerless words, do PRUNE before HERE gets to $C000, or do SET-EDGE to set the EDGE to a higher value.) Using this headerless feature has allowed most of the editor and assembler support words' headers to vanish. EMIT and video words v1.3 did direct video writes for speed. On occasion this caused problems on slightly non-IBM-compatible computers (such as the AT&T 6300 (or whatever number it was). v1.4 has changed to doing EMIT and related words with BIOS Int $10 calls. This should greatly increase compatibility and should still be fast (providing no TSRs such as NEWKEY get in the way and slow things down). As before, most of the I/O words are vectored, so you still can replace any routines with ones of your own. The need for system variables CUR, VID, and CRTC goes away. Also, these low level words such as (EMIT, (CR, (KEY now have any ending parenthesis removed, so as not to accidentally end comments. ATTR is still used, but with a difference. In v1.3, this value was merged with every character written to the screen. Also, the attribute byte was kept in the most significant byte of the variable ATTR (to make the merging simpler). Now ATTR holds the attribute in the least significant byte. So, if you had used $7100 ATTR ! to make a pretty dark blue on light blue screen, you will need to do $71 ATTR ! 2000 .ATTR or $71 ATTR ! CLS instead, with v1.4. Now the attribute is only combined with characters by the word .ATTR. See .ATTR below. Summary of video words: (AT ( row col -) positions the cursor. It is usually what AT uses. (CUR@ ( - row col) fetches current cursor position (so you can save it and later restore it). It is usually what CUR@ uses. (EMIT ( c -) Writes a byte to the screen at the current cursor position and advances the cursor, using a BIOS Int$10 teletype style video write. Scrolling is done automatically at bottom of the screen. AT@ ( - aacc) Reads the character and attribute byte of the character on screen at the current cursor location. The most significant byte is the attribute and the least significant is the character. Use 255 AND to isolate the character, or use 256 U/ to isolate the attribute. .ATTR ( # -) Writes the specified number of blanks to the screen, applying the value in ATTR to each one. This starts at the current position location but does not change the position of the cursor. For example, this is used by (CLS to clear the screen and set the attributes of all the screen positions at once. These attributes will remain in effect until changed again by .ATTR (or some word that uses it, such as (CLS ). So, if you want to write a field with a different attribute (e.g. blinking, or a different color), you first need to set ATTR to the new attribute value (e.g. $bbff ATTR !) and then write the text of the field, e.g. ATTR @ ( optionally save current attribute) $71 ATTR ! ( dark blue on light blue background) 25 .ATTR ( clear a field 25 characters wide) ." This is the new text" ( write as much new text as you wish) ATTR ! ( optionally restore previous attribute) (CLS ( -) Clears the screen by writing 2000 spaces, using the current attribute (in ATTR). Note, this could be changed if you have a larger or smaller screen than 80 x 25. It is usually what CLS uses. This set of BIOS video words is more than the bare minimum we might get by with. For example, CLS could be done with 25 carriage returns. Then we would not need .ATTR or AT@. (AT@ is used in (BOOT to set ATTR to whatever attribute is currently in use at position 0 0 when the v1.4 is invoked.) But, then, you could not change attributes and so could not underline or reverse fields, or change colors, etc. Also, AT is now in the kernel in v1.4 but was not in v1.3. In addition to these words, two more BIOS video words are included in the unloaded (extension) section: SCROLL-UP ( row col row col # attr -) (verify the order of the parameters). And its companion SCROLL-DOWN. These scroll the text the specified number of lines, and blank the new lines at either the top or bottom. All of this is done only in the window specified by the upper left row and col and the lower right row and column. I have added various additional words in the extension section, including COLORS. Load it, if it is not already in the .COM file I'm sending you, and try it out. You can set the color just by storing the correct numbers into ATTR, but you might want to use words such as BLUE ON-BLUE or RED ON-YELLOW or BLINK or UNDERLINE or REVERSE, etc. QUIT restores EMIT to whatever is in DEFAULT-EMIT. Pygmy no longer tries to guess what type of video display is present. When it wakes up it sets the cursor to top left, fetches whatever attribute byte is already there, and uses it thereafter unless you change it. So, if you have a color screen at the DOS prompt, and like those colors (or don't like them), they should be the same colors in Pygmy. If you don't like those colors, say $1F ATTR ! CLS or $71 ATTR ! CLS and see if you like those colors better. Also try the word COLORS that lets you step through various possibilities of foreground and background colors by pressing the F1 and F2 keys, as mentioned above. Miscellaneous CONDENSED (for use in printing blocks in SHOW2) is currently set for Epson. See the load blocks if you want to change this for other printers. To check its setting, just type SEE CONDENSED (as SEE now handles DEFER'd words). DUMP and DU save the base, display in HEX, then restore the base. As DU does multiple DUMPs, and I can give it a huge count and interrupt it with a keypress, I rarely need to follow DU with another DU or DUMP. So, DU no longer leaves the next address on the stack. BYE now does FLUSH before exiting. Constants set the data & return stack initial addresses, so if you want to change the sizes you only need to make the change in a single location. In addition, there is a constant STACKSEG which should ordinarily be set to either 0 or to 1. If STACKSEG is 0 then the data and return stacks will be in the same 64K segment that contains the rest of Pygmy. If STACKSEG is 1 then the data and return stacks will be in the 64K segment above the 64K segment which contains the rest of Pygmy. I've added the constant TOP so the location of the disk buffers & input buffers can be customized (for those attempting to minimize the RAM Pygmy occupies when running). Note that I have set up the data and return stacks to use their own segment and each has about 32K of room. If you switch back to using stacks in the same segment as the rest of Pygmy be sure to alter the stack offsets accordingly! All of this is now done easily by setting options at the beginning of PYGMY.SCR; see the load blocks. SEE now shows what DEFER'd words are deferred to, very handy! Now that we allow headerless words and are using RECOVER and have view fields (and if all else fails we have the search across blocks facility) the former SEE has been discontinued and the new SEE's only function is to show where a DEFER'd word is pointing. There may be other important changes that I can't think of at the moment. If anything bites you please let me know about it. The Editor v1.3's editor on pretty-thoroughly-IBM-compatible computers has been a joy for me to use. However, it has not been very easy to convert to other (dare I say "weird") hardware. So, I have re-written the editor slightly so it keeps its hands off the video except through properly DEFER'd words, rather than trying to write to the video memory directly. So, if you can make versions of CLS, AT, CUR@, and EMIT that work on your machine, and if your screen has enough rows and columns, you should be able to get the full screen editor working on your machine. ED and PgDn and PgUp no longer restore ins/overwrite to overwrite, thus the setting stays the way you left it, unless you say EDIT. The system variable CURSOR has been renamed to EBLK. It is used by the editor to keep track of the beginning address of the block buffer that holds the block being edited. I have added a shadow facility to the editor. Ctrl-A switches between related blocks. Alt-A sets the current block as one of the two base blocks. The default, if you do not set any base blocks with Alt-A (or if you set them both to the same block), is to consider that alternate thousands are related (0 and 1000, 1 and 1001, etc. or 2001 and 3001, 2002 and 3002). That's why I have moved YOURFILE.SCR to 2000, to leave room at 1000 for the Pygmy shadow blocks (see Bonus Disk) that match PYGMY.SCR at 0000. Do Alt-A on the two blocks you want to compare and then hold down Ctrl-A to see the difference ("flickering" as described by Dick Miller). NUMBER I want NUMBER ( a - n), which takes a counted string, to become NUMBER ( a # - n), which takes an address and count. I have compromised. I added (SNUMBER ( a # - u) and left SNUMBER and NUMBER as ( a - u). Textfiles They are nestable to any level and in any combination with LOAD. Use " " FLOAD for postfix or use INCLUDE for prefix. At the moment the length of any one textfile is limited to 64K. Setting a single constant in the metacompiler to true or false determines whether the textfile code or the non-textfile code will be used to gen the kernel. That way non-users of textfiles do not have to suffer the extra overhead. (Is this Burger King, or what?) (Well, there is some overhead as the system variables will still be present in both versions, but LOAD and SOURCE and WORD will not be slowed down in the non-textfile version.) EXPECT I fixed a bug in EXPECT that was pointed out by Steve Birrell, whereby it wouldn't let you type the full length if backspace deleted characters took up some of the room. EXPECT can now be used without concern for resetting SPAN or >IN as it no longer disturbs the terminal input buffer. See QUERY when you want to get some input and use WORD on it. MS v1.4 now has a (more or less) machine-independent timing word, MS, in the extensions. This reads Timer 0 to tell when it has killed approximately the requested number of milliseconds. Since loop speeds will still vary among different speed machines, there will still be some slight variation. Feel free to cusomize the count value to tune it exactly for your specific machine if you wish. >STD >DOS The BIOS video EMIT words cannot be redirected (via the command line). Unloaded optional words culminating in >STD and >DOS can be redirected, although they are slower for screen use than (EMIT etc. added FILE-SIZE ( unit# - ud) I switched code for 0< to that suggested by Andrew McKewan Fixed error pointed out by Greg Lisle in XREF (and made it prettier?). I put in a regular FORGET I added textfile INCLUDE (which uses textfile FLOAD) VIEW, HEADERS, and | Basically, as Ian Watters suggested, I have added VIEW fields and the capability of making headerless words. The word | preceding a definition marks that one word as headerless. Some posting on GEnie requested that words reading the input stream be factored so a version is available that takes a pfa (e.g : VIEW ( -) ' (VIEW ; ), however I have not done it that way. Instead, I've provided the word VFA so if a non-input stream version is needed, just ( pfa) VFA @ and then do whatever you want with the block number. If the view field is zero then the word was compiled from the keyboard (or a textfile). VIEW simply terminates in this case. You can uncomment the code to have it print an error message if you wish. More details: HEAD is factored out of CREATE, the "pfa" of a headerless word contains the magic byte $D6, which won't ever appear as a machine opcode, followed by the value of the real pfa. cmForth set the msb of the count byte. The magic byte method costs an extra byte for every headerless header, but saves time in (-FIND on every compare when traversing the dictionary). The headerless headers don't disappear until the word PRUNE is executed. The word | preceding a word's definition makes that one word headerless. Pygmy has always had the ability to compile utilities out of the way in higher memory and then use them to compile words into the lower dictionary area. However, it takes PRUNE to cut those high words out of the dictionary when you are through with them. The PRUNE version of the metacompiler will not work for this except when metacompiling, hence a new version for regular use. By the way, the $D6 magic byte comes from Ian as a byte that does not appear as an opcode in the '386 or lower. Looking in a '386 book it looks like we could also use $F1 or $82 for this purpose. I tried out a high-level -FIND and it was about 8 times slower than the code (-FIND. So, we'll stick with the code version for now! Now (-FIND has become -FIND (ie no longer DEFER'd); ditto for (WORD & WORD. RESET and reset in version 1.3 have now been consolidated into RESET. A one byte INT3, has been added to the extensions (for Ian Watters). At Greg Lisle's suggestion I have changed OPEN so it takes a unit number instead of a starting block number. Also, I have renamed F# which converts a block number to its corresponding unit# to >UNIT#. SHELL out to DOS and the ability to read command lines passed from DOS have been included as extensions. Chapter 11 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 when you press the key. DUMP ( a - a') and DU ( 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, dropping the final address. ?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). .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 words named ." one is in FORTH and the other is in COMPILER.) Similarly " can be used inside or outside definitions for creating a string literal. 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 12 How Files Work Pygmy can access a number of files "simultaneously." As shipped, it contains 15 slots or units for files, stored in the FILES array. I often refer to this as the unit# table. 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, but since 1000 blocks are reserved for each unit#, you couldn't use more than 64 block files at once. Before you can access a file (as a block file), it must be installed into one of the slots. This is done by the word OPEN or by the word UNIT. UNIT establishes the file's name (as it is known to DOS) and starting block number. This name can include the full path, including drive, for those cases where the file is not in the default directory. The parameters for OPEN or UNIT are the filename and the unit#. The unit# will then determine the starting block number. The starting block number will always be 1000 times the unit#. Thus the file in unit# 0 starts at block 0, the file in unit# 5 starts at block 5000, etc. The filename 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. Previously I used the word NAMEZ: which defined a word whose name is the string. For example, NAMEZ: YOURFILE.SCR but now I generally just use a string literal, e.g. " YOURFILE.SCR" 2000 OPEN Once you have installed the file with UNIT or with OPEN, you can open and close the file repeatedly just by using the unit#. To replace that file in a particular slot in the unit# table, just open another file at the same unit#. The file that was previously in that unit# will be closed automatically before the new file is opened. You might want to type FLUSH before opening the new file. As shipped, Pygmy version 1.4 has three files that are already installed in units 0, 1, and 2. These are PYGMY.SCR, which contains all the source code, PYGMY.DOW which contains the shadow blocks (see Bonuses), and YOURFILE.SCR, which contains 8 blank blocks. These are automatically opened for you and ready to go. YOURFILE.SCR is provided so the new user of Pygmy has a block file ready to hold 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). 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 (than 1.3) versions of Pygmy you could extend a file just by accessing a block past the end of file. In versions 1.3 and 1.4 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. For creating a new block file from within Pygmy, see NEWFILE in the extensions. Chapter 13 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] SHL, would shift only a single byte. To override this, use W-PTR e.g. 0 [BX] W-PTR SHL, ( shift word at 0[BX] based on count in reg CX) For the shifts & rotates, if an immediate operand precedes it, it shifts a single bit, e.g. 1 #, AX SHR, ( shift AX right one bit right) or even 300 #, AX SHR, ( shift AX right one bit, not 300 bits) 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 14 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 block. This is delightfully fast. 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 block 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 then use 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 block, overlaying the current line. The cut buffer is almost unlimited in size. It can be used to copy and move lines on the same block or to different blocks (even blocks in different files). Notice that the count of lines cut (on the status line) changes as you press F7 & F8. F9 inserts blank blocks after the current block. F10 does a search like F1, but across multiple blocks. 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). Ctrl-A switches between related blocks (usually shadow blocks, but see Alt-A below). Alt-A marks the current block as one of a pair. Do this on two separate blocks to mark the base block numbers for two related ranges so that Ctrl-A will then switch between them. To return to the default, where even and the the following odd thousands are related (e.g. 0000 and 1000, 0001 and 1001, etc. or 2000 and 3000, 2075 and 3075) just press Alt-A twice on the current block. 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 Warning, this will only eliminate the changes that have not yet been written back to disk. F9 is good for opening up a file in the middle or for extending a file at the end. As you move blocks around and delete them from where they used to be, you may accumulate a number of blank blocks. SETTLE (used outside of the editor) is used to let the heavy blocks sink to the bottom and let the light blocks float to the top. It only affects the range of blocks that you specify, e.g. 315 345 SETTLE will re-arrange those blocks so that any completely blank blocks are at the highest numbers and the non-blank blocks are at the lowest numbers. This compresses out blank blocks. A related word CHOP will truncate a file by chopping off all trailing blank blocks, e.g. 3 CHOP will chop the blank blocks off the end of the file whose unit# is 3. Chapter 15 The Metacompiler Pygmy includes a metacompiler. 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 block. This block number is usually noted on block #1 to make it easy to find. It will usually be block #5, e.g. 5 LOAD Look at block 5 to see how this works. Note that this is simpler than in previous versions. Having all the source code in a single file makes this easier. Plus, version 1.4 does a better job of allowing you to change options in a single place. You can edit the load blocks so they will include just what you want and then save the newly created Forth to the filename you specify. Metacompiling 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 filenames you save the new versions under. After you've done this once or twice you can begin changing the kernel, or extending it differently. Here is how the metacompiler works. First the load block (#1) loads the metacompiler. This renames some of the current Forth's words (so they can be found later) 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 metacompiler will use those values to compile the proper code in the target. Then, the load block loads the target's code. 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 metacompiler 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 metacompiling, 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 metacompiling, 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. 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.) 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 keep!) 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 metacompiler.) If you change the boot code, you may need to change the patch on block 96 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 metacompiling. Chapter 16 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 metacompiler. Chapter 17 ADDITIONAL INFORMATION For additional information, browse through all of PYGMY.SCR using the editor ( n EDIT ) and the PgDn & PgUp keys. Searching across blocks (using F10 in the editor, after setting up the search string with F3) is handy for finding a particular word's definition and where it is used. Use VIEW or its shorthand V to pop into the editor on the source code for a particular word. Then use Ctrl-A to switch to the corresponding shadow block (see Bonuses). Chapter 18 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 You may also be able to reach me via bitnet as fs07675@swtexas, although it's anyone's guess how long I'll have that account. for info on signing up with GEnie dial 1-800-638-9636 Join FIG, send $40 (USA & Canada) or $52 (other countries) to Forth Interest Group (510) 89-FORTH (voice) P.O. Box 2154 (510) 535-1295 (FAX) Oakland, CA 94621 FIG is a great source for Forth related publications. The $40 membership fee includes a subscription to _Forth Dimensions_ , in which I occasionally have an article. Tell 'em I sent you. Subscribe to _The Computer Journal_ (800) 424-8825 P.O. Box 535 (916) 645-1670 Lincoln, CA 95648-0535 Call or write for a trial subscription. They also publish an occasional article by me. Tell 'em I sent you. ACM SIGForth c/o ACM Box 12115 Church Street Station New York, NY 10249 (212) 869-7440 Chapter 19 The Glossary & Index The on-line availability of the system's complete source code, coupled with the search across function in the editor, plus VIEW, plus the editor's shadow block function (if you have the shadow file PYGMY.DOW) serve as the glossary and the index. You can look up anything and everything! Chapter 20 MEMORY MAP Pygmy can fit in one 64K segment or it can fit in two segments. As shipped, the stacks are placed in a separate segment from the rest of Pygmy. Follow the instructions on the load blocks if you want to change this so they all share a single segment. DOS loads Pygmy at offset $0100. CS@ will fetch the contents of CS (the code segment register), in case you need to know the absolute address of the program. The stacks are currently set to the segment above CS@, by the metacompiler constant STACKSEG. The dictionary grows up from low memory. The tib, fib, disk buffers, and optionally the stacks are in high memory (within the one segment). The metacompiler constant TOP allows you to say how high high-memory is. sample memory map, with 4 disk buffers and TOP = 65536. origin $0100 boot code $0100 1st word (null) $0113 system variables $0120 - $0159 dictionary continues $015A HERE $4130 ( perhaps, depending on what's loaded) FIB @ $EE00 ( FIB is below TIB -- for textfile loading) TIB @ $EF00 ( TIB is below the disk buffers) ( The highest disk buffer is 1K below TOP) 1st disk buffer $F000 2nd disk buffer $F400 3rd disk buffer $F800 4th disk buffer $FC00 metacompiler TOP $10000 ( ie 65536, to allow a full segment) stacks are in the segment above the rest of Pygmy: return stack pointer $FFFE ( grows down from FFFE) data stack pointer $7FFE ( grows down from 7FFE) Chapter 21 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 or OPEN. 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 unit# to use. Set it to 0, 1, 2, etc. The unit# you select determines the starting block number for that file. It is always 1000 times the unit#. Chapter 22 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 does not return the address of the input buffer, but the address of the address of the 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, and LITERAL are deferred. ( e.g. DEFER EMIT ' (EMIT IS EMIT ) Chapter 23 HISTORY & PHILOSOPHY Pygmy was based on cmFORTH by Charles Moore. cmFORTH was designed for the NOVIX Forth chip. cmFORTH didn't include an assembler as that wasn't needed for the NOVIX. Also, it didn't include an editor, as it was designed to be used with a host terminal or computer that supplied 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 comfortable. I want it small & fast, but I want it comfortable too. It has grown bigger because of the VIEW fields, but the ability to make words headerless compensates for that, I think. 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 tends to make a crowded & busy WORDS listing and forces assembler words to end in commas. Beheading the editor (etc.) auxiliary words eases this burden. DO/LOOP have not been included. If you miss them too much, load them (Robert Berkey's version) from PYGMY.SCR block #179. 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'). The cmFORTH TYPE worked on counted strings (i.e. a one byte count at the address, followed by the string). 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>. However, a number of people _have_ convinced me that _they_ see how to do it. So, it is a matter of opinion, and you are free to change them back if you wish. 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. With version 1.4 I am closer than ever to feeling I have found the "perfect" Forth in Pygmy. Close, but not (and probably never) there. Overall I am very pleased. 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 absolutely have to have. Many people wanted the ability to load from textfiles. Well, now they have it. At the same time, since it is a metacompiler option, block enthusiasts do not have to suffer textfile overhead. Pygmy is really a set of Forths. Pick the one you prefer. 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 for any purpose. In addition, as mentioned above, full textfile loading is available. I think a Forth system should come with its complete source code, and so Pygmy does. I would rank that as one of my highest requirements in choosing a Forth. I also think a Forth system should be fairly _small_. I am appalled by systems (Forth as well as the modern C and Pascal systems) that require many megabytes of a harddisk. It might appear that the current purpose of software, by being increasingly bloated and slow, is to use up hardware speed (& disk capacity increases) so the user will not have to suffer any net speed increase in his applications. Chapter 24 How to Print the Source Code SHOW prints source code blocks 3 per page. SHOW2 prints source code blocks 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 blocks 5 and 156 for more info. Once you have set CONDENSED correctly for your printer, type 0 191 SHOW ( for 3 blocks per page) or 0 191 SHOW2 ( for 6 blocks per page) or 0 191 1000 SHADOW ( for 6 blocks per page with shadows) 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 ), or you can use the included LJ-CONDENSED (i.e. ' LJ-CONDENSED IS CONDENSED ). **** The End ****