forth.cpp

Go to the documentation of this file.
00001 /*
00002 This program is distributed under the terms of the 'MIT license'. The text
00003 of this licence follows...
00004 
00005 Copyright (c) 2005 J.D.Medhurst (a.k.a. Tixy)
00006 
00007 Permission is hereby granted, free of charge, to any person obtaining a copy
00008 of this software and associated documentation files (the "Software"), to deal
00009 in the Software without restriction, including without limitation the rights
00010 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00011 copies of the Software, and to permit persons to whom the Software is
00012 furnished to do so, subject to the following conditions:
00013 
00014 The above copyright notice and this permission notice shall be included in
00015 all copies or substantial portions of the Software.
00016 
00017 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00018 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00019 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
00020 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00021 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00022 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00023 THE SOFTWARE.
00024 */
00025 
00055 #include "common.h"
00056 #include "forth.h"
00057 
00058 #if 1
00059 #define LITTLE_ENDIAN   
00060 #else
00061 #define BIG_ENDIAN      
00062 #endif
00063 
00068 #define CELLS(x)        ((CELL)(((CELL*)256)+(x))-(CELL)((CELL*)256))
00069 
00074 #define CHARS(x)        ((CELL)(((CHAR*)256)+(x))-(CELL)((CHAR*)256))
00075 
00080 #define SLASH_CELL(x)   ((CELL*)(256+(x))-((CELL*)256))
00081 
00086 #define SLASH_CHAR(x)   ((CHAR*)(256+(x))-((CHAR*)256))
00087 
00092 #define ALIGNED(x)      (((x)+CELLS(1)-1)&~(CELLS(1)-1))
00093 
00097 static const CELL BitsPerCell = BITS_PER_CHAR*CHARS_PER_CELL;
00098 
00103 static const CELL CellLoMask = ((CELL)1<<(BitsPerCell/2))-1;
00104 
00108 static const CELL SlashCountedString = 255;
00109 
00115 static const CELL NameLengthMask = 31;
00116 
00120 static const CELL NumberTIB = 80;
00121 
00125 static const CELL SlashPad = 84;
00126 
00131 static const CELL DictionaryOverhead = CHARS(SlashCountedString+2+SlashPad);
00132 
00136 static const CELL MaxWordlists = 16;
00137 
00141 static const CELL StackCells = 256;
00142 
00146 static const CELL ReturnStackCells = 256;
00147 
00148 
00152 class WordHeader
00153     {
00154 public:
00165     CELL Previous;
00166 
00171     CHAR NameLength;
00172 
00177     CHAR Name[1];
00178 
00183     enum WordFlags
00184         {
00185         Token       = 1<<5, 
00187         Immediate   = 1<<6, 
00188         Valid       = 1<<7  
00189         };
00190 
00191 public:
00196     inline CELL* CFA()
00197         { return (CELL*)ALIGNED((CELL)(Name+(NameLength&NameLengthMask))); }
00198     };
00199 
00200 
00204 enum Exception
00205     {
00206     DivideByZero = -10,
00207     ResultOutOfRange = -11,
00208     UndefinedWord = -13,
00209     ZeroLengthName = -16,
00210     PicturedStringOverflow = -17,
00211     ControlStructureMismatch = -22
00212     };
00213 
00214 
00218 struct Wordlist
00219     {
00223     CELL LastWord;
00224 
00228     CELL Previous;
00229 
00234     CELL Name;
00235     };
00236 
00237 
00241 enum ControlStackMarkers
00242     {
00243     ColonMagic = 12340, 
00244     OrigMagic  = 12341, 
00245     DestMagic  = 12342  
00246     };
00247 
00248 
00252 enum ForthXT
00253     {
00254     XT_STORE,               
00255     XT_NUMBER_SIGN,         
00256     XT_NUMBER_SIGN_GREATER, 
00257     XT_STAR,                
00258     XT_PLUS,                
00259     XT_PLUS_STORE,          
00260     XT_PAREN_PLUS_LOOP,     
00261     XT_COMMA,               
00262     XT_MINUS,               
00263     XT_0_LESS,              
00264     XT_0_EQUALS,            
00265     XT_1_PLUS,              
00266     XT_1_MINUS,             
00267     XT_2_STORE,             
00268     XT_2_STAR,              
00269     XT_2_SLASH,             
00270     XT_2_FETCH,             
00271     XT_2DROP,               
00272     XT_2DUP,                
00273     XT_2OVER,               
00274     XT_2SWAP,               
00275     XT_LESS_THAN,           
00276     XT_LESS_NUMBER_SIGN,    
00277     XT_EQUALS,              
00278     XT_GREATER_THAN,        
00279     XT_TO_IN,               
00280     XT_TO_NUMBER,           
00281     XT_TO_R,                
00282     XT_QUESTION_DUP,        
00283     XT_FETCH,               
00284     XT_ABS,                 
00285     XT_ACCEPT,              
00286     XT_ALIGN,               
00287     XT_ALIGNED,             
00288     XT_ALLOT,               
00289     XT_AND,                 
00290     XT_BASE,                
00291     XT_C_STORE,             
00292     XT_C_COMMA,             
00293     XT_C_FETCH,             
00294     XT_CELL_PLUS,           
00295     XT_CELLS,               
00296     XT_CHAR_PLUS,           
00297     XT_CHARS,               
00298     XT_PAREN_CONSTANT,      
00299     XT_COUNT,               
00300     XT_DEPTH,               
00301     XT_PAREN_DO,            
00302     XT_DROP,                
00303     XT_DUP,                 
00304     XT_PAREN_BRANCH,        
00305     XT_EMIT,                
00306     XT_EXECUTE,             
00307     XT_EXIT,                
00308     XT_FILL,                
00309     XT_HERE,                
00310     XT_HOLD,                
00311     XT_I,                   
00312     XT_PAREN_0BRANCH,       
00313     XT_INVERT,              
00314     XT_J,                   
00315     XT_KEY,                 
00316     XT_LEAVE,               
00317     XT_PAREN_LITERAL,       
00318     XT_PAREN_LOOP,          
00319     XT_LSHIFT,              
00320     XT_MAX,                 
00321     XT_MIN,                 
00322     XT_MOVE,                
00323     XT_NEGATE,              
00324     XT_OR,                  
00325     XT_OVER,                
00326     XT_R_FROM,              
00327     XT_R_FETCH,             
00328     XT_ROT,                 
00329     XT_RSHIFT,              
00330     XT_S_TO_D,              
00331     XT_SIGN,                
00332     XT_SPACE,               
00333     XT_STATE,               
00334     XT_SWAP,                
00335     XT_TYPE,                
00336     XT_U_LESS_THAN,         
00337     XT_UM_STAR,             
00338     XT_UNLOOP,              
00339     XT_XOR,                 
00340     XT_LEFT_BRACKET,        
00341     XT_RIGHT_BRACKET,       
00343     XT_0_NOT_EQUALS,        
00344     XT_0_GREATER,           
00345     XT_2_TO_R,              
00346     XT_2_R_FROM,            
00347     XT_2_R_FETCH,           
00348     XT_NOT_EQUALS,          
00349     XT_PAREN_QUESTION_DO,   
00350     XT_ERASE,               
00351     XT_FALSE,               
00352     XT_NIP,                 
00353     XT_PAD,                 
00354     XT_PARSE,               
00355     XT_PICK,                
00356     XT_ROLL,                
00357     XT_TRUE,                
00358     XT_TUCK,                
00359     XT_U_GREATER_THAN,      
00360     XT_UNUSED,              
00362     XT_D_PLUS,              
00363     XT_DABS,                
00364     XT_DNEGATE,             
00365     XT_M_PLUS,              
00367     XT_CATCH,               
00368     XT_THROW,               
00370     XT_CMOVE,               
00371     XT_CMOVE_UP,            
00373     XT_BREAKPOINT,
00374     XT_END,
00375     XT_CATCH_END,
00376     XT_EXCEPTION_MESSAGE,
00377     XT_CODE_EXECUTE,
00378 
00379     XT_UDM_SLASH_MOD,
00380     XT_RDROP,
00381 
00382     XT_EMPTYS,
00383     XT_EMPTYR,
00384     XT_TIB,
00385     XT_PAREN_SOURCE,
00386     XT_CONTEXT,
00387     XT_CURRENT,
00388     XT_LATEST,
00389     XT_FORTH_WORDLIST,
00390     XT_PARSE_WORD,
00391     XT_PAREN_SEARCH_WORDLIST,
00392     XT_TO_CFA,
00393     XT_PAREN_CR
00394     };
00395 
00402 #define XT_BRANCH(offset) XT_PAREN_BRANCH,CELLS(offset)
00403 
00410 #define XT_0BRANCH(offset) XT_PAREN_0BRANCH,CELLS(offset)
00411 
00417 #define LIT(x) XT_PAREN_LITERAL,(CELL)x
00418 
00419 
00425 static const CELL XT_NEST_CHECK[] =
00426     {
00427     XT_EQUALS, XT_0BRANCH(2), XT_EXIT,                      // = IF EXIT THEN
00428     LIT(ControlStructureMismatch), XT_THROW                 // -22 THROW
00429     };
00430 
00431 
00437 static const CELL XT_FORWARD_BRANCH_COMMA[] =
00438     {
00439     XT_COMMA, XT_HERE, XT_FALSE, XT_COMMA,                  // , HERE 0 ,
00440     LIT(OrigMagic), XT_EXIT                                 // OrigMagic
00441     };
00442 
00443 
00449 static const CELL XT_BACKWARD_BRANCH_COMMA[] =
00450     {
00451     XT_COMMA, LIT(DestMagic), (CELL)XT_NEST_CHECK,          // , DestMagic NEST-CHECK
00452     XT_HERE, XT_MINUS, XT_COMMA, XT_EXIT                    // HERE - ,
00453     };
00454 
00455 
00461 static const CELL XT_IF[] =
00462     {
00463     LIT(XT_PAREN_0BRANCH), (CELL)XT_FORWARD_BRANCH_COMMA,   // ['] (0branch) >BRANCH,
00464     XT_EXIT
00465     };
00466 
00467 
00473 static const CELL XT_AHEAD[] =
00474     {
00475     LIT(XT_PAREN_BRANCH), (CELL)XT_FORWARD_BRANCH_COMMA,    // ['] (branch) >BRANCH,
00476     XT_EXIT
00477     };
00478 
00479 
00486 static const CELL XT_THEN[] =
00487     {
00488     LIT(OrigMagic), (CELL)XT_NEST_CHECK,                    // OrigMagic NEST-CHECK
00489     XT_HERE, XT_OVER, XT_MINUS, XT_SWAP, XT_STORE, XT_EXIT  // HERE OVER - SWAP !
00490     };
00491 
00492 
00498 static const CELL XT_BEGIN[] =
00499     {
00500     XT_HERE, LIT(DestMagic), XT_EXIT                        // HERE DestMagic
00501     };
00502 
00503 
00509 static const CELL XT_AGAIN[] =
00510     {
00511     LIT(XT_PAREN_BRANCH), (CELL)XT_BACKWARD_BRANCH_COMMA,   // ['] (branch) <BRANCH,
00512     XT_EXIT
00513     };
00514 
00515 
00523 static const CELL XT_UM_SLASH_MOD[] =
00524     {
00525     XT_DUP, XT_0_EQUALS, XT_0BRANCH(4),                     // DUP 0= IF
00526     LIT(DivideByZero), XT_THROW,                            // -10 THROW THEN
00527     XT_UDM_SLASH_MOD, XT_0BRANCH(4),                        // UDM/MOD IF
00528     LIT(ResultOutOfRange), XT_THROW,                        // -11 THROW THEN
00529     XT_EXIT
00530     };
00531 
00532 
00539 static const CELL XT_CHECK_NEG[] =
00540     {
00541     XT_DUP, XT_0_GREATER, XT_0BRANCH(4),                    // DUP 0> IF
00542     LIT(ResultOutOfRange), XT_THROW, XT_EXIT                // -11 THROW THEN
00543     };
00544 
00545 
00552 static const CELL XT_CHECK_POS[] = // ( n -- n )
00553     {
00554     XT_DUP, XT_0_LESS, XT_0BRANCH(4),                       // DUP 0< IF
00555     LIT(ResultOutOfRange), XT_THROW, XT_EXIT                // -11 THROW THEN
00556     };
00557 
00558 
00572 static const CELL XT_SM_SLASH_REM[] =
00573     {
00574     XT_OVER, XT_TO_R, XT_2DUP, XT_XOR, XT_TO_R,             // OVER >R 2DUP XOR >R
00575     XT_ABS, XT_TO_R, XT_DABS, XT_R_FROM,                    // ABS >R DABS R>
00576     (CELL)XT_UM_SLASH_MOD,                                  // UM/MOD
00577     XT_R_FROM, XT_0_LESS, XT_0BRANCH(5),                    // R> 0< IF
00578     XT_NEGATE, (CELL)XT_CHECK_NEG, XT_BRANCH(2),            // NEGATE CHECK-NEG ELSE
00579     (CELL)XT_CHECK_POS,                                     // CHECK-POS THEN
00580     XT_SWAP, XT_R_FROM, XT_0_LESS, XT_0BRANCH(2),           // SWAP R> 0< IF
00581     XT_NEGATE, XT_SWAP, XT_EXIT                             // NEGATE THEN SWAP
00582     };
00583 
00584 
00599 static const CELL XT_FM_SLASH_MOD[] =
00600     {
00601     XT_DUP, XT_TO_R, XT_2DUP, XT_XOR, XT_TO_R,              // DUP >R 2DUP XOR >R
00602     XT_ABS, XT_TO_R, XT_DABS, XT_R_FROM,                    // ABS >R DABS R>
00603     (CELL)XT_UM_SLASH_MOD,                                  // UM/MOD
00604     XT_R_FROM, XT_0_LESS, XT_0BRANCH(15),                   // R> 0< IF
00605     XT_NEGATE, (CELL)XT_CHECK_NEG, XT_OVER, XT_0BRANCH(11), // NEGATE CHECK-NEG OVER IF
00606     XT_1_MINUS, (CELL)XT_CHECK_NEG, XT_R_FETCH, XT_ABS,     // 1- CHECK-NEG R@ ABS
00607     XT_ROT, XT_MINUS, XT_SWAP, XT_BRANCH(2),                // ROT - SWAP THEN ELSE
00608     (CELL)XT_CHECK_POS,                                     // CHECK-POS THEN
00609     XT_SWAP, XT_R_FROM, XT_0_LESS, XT_0BRANCH(2),           // SWAP R> 0< IF
00610     XT_NEGATE, XT_SWAP, XT_EXIT                             // NEGATE THEN SWAP
00611     };
00612 
00613 
00620 #define XT_M_SLASH_MOD (((-1)/2) ? (CELL)XT_FM_SLASH_MOD : (CELL)XT_SM_SLASH_REM)
00621 
00622 
00628 static const CELL XT_SLASH_MOD[] =
00629     {
00630     XT_TO_R, XT_S_TO_D, XT_R_FROM, XT_M_SLASH_MOD, XT_EXIT  // >R S>D R> M/MOD
00631     };
00632 
00633 
00640 static const CELL XT_M_STAR[] =
00641     {
00642     XT_2DUP, XT_XOR, XT_TO_R, XT_ABS, XT_SWAP, XT_ABS,      // 2DUP XOR >R ABS SWAP ABS
00643     XT_UM_STAR, XT_R_FROM, XT_0_LESS,                       // UM* R> 0<
00644     XT_0BRANCH(2), XT_DNEGATE, XT_EXIT                      // IF DNEGATE THEN
00645     };
00646 
00647 
00653 static const CELL XT_STAR_SLASH_MOD[] =
00654     {
00655     XT_TO_R, (CELL)XT_M_STAR, XT_R_FROM, XT_M_SLASH_MOD,    // >R M* R> M/MOD
00656     XT_EXIT
00657     };
00658 
00659 
00665 static const CELL XT_NUMBER_SIGN_S[] =
00666     {
00667     XT_NUMBER_SIGN, XT_2DUP, XT_OR, XT_0_EQUALS,            // BEGIN # 2DUP OR 0=
00668     XT_0BRANCH(-5), XT_EXIT                                 // UNTIL
00669     };
00670 
00671 
00679 static const CELL XT_D_DOT[] =
00680     {
00681     XT_LESS_NUMBER_SIGN, LIT(' '),                          // <# BL
00682     XT_HOLD, XT_DUP, XT_TO_R, XT_DABS,                      // HOLD DUP >R DABS
00683     (CELL)XT_NUMBER_SIGN_S, XT_R_FROM, XT_SIGN,             // #S R> SIGN
00684     XT_NUMBER_SIGN_GREATER, XT_TYPE, XT_EXIT                // #> TYPE
00685     };
00686 
00687 
00693 static const CELL XT_DOT[] =
00694     {
00695     XT_S_TO_D, (CELL)XT_D_DOT, XT_EXIT                      // S>D D.
00696     };
00697 
00698 
00704 static const CELL XT_CR[] =
00705     {
00706     XT_PAREN_CR, XT_TYPE, XT_EXIT                           // (cr) TYPE
00707     };
00708 
00709 
00730 static const CELL XT_CREATE_WORD[] =
00731     {
00732     XT_OVER, XT_0_NOT_EQUALS,                                   // OVER 0<>
00733     XT_OVER, XT_0_GREATER, XT_INVERT, XT_AND,                   // OVER 0> INVERT AND
00734     XT_0BRANCH(4), LIT(ZeroLengthName), XT_THROW,               // IF -16 THROW THEN
00735     LIT(NameLengthMask), XT_MIN,                                // NameLengthMask MIN
00736     XT_ALIGN, XT_HERE, XT_TO_R,                                 // ALIGN HERE >R
00737 
00738     XT_CURRENT, XT_FETCH,                                       // CURRENT @
00739     XT_DUP, XT_FETCH, XT_R_FETCH, XT_MINUS, XT_COMMA,           // DUP @ R@ - ,
00740     XT_R_FETCH, XT_SWAP, XT_STORE,                              // R@ SWAP !
00741 
00742     XT_DUP, XT_C_COMMA,                                         // DUP C,
00743     XT_DUP, XT_0BRANCH(10), XT_OVER, XT_C_FETCH, XT_C_COMMA,    // BEGIN DUP WHILE OVER C@ C,
00744     XT_SWAP, XT_CHAR_PLUS, XT_SWAP, XT_1_MINUS, XT_BRANCH(-11), // SWAP CHAR+ SWAP 1- REPEAT
00745     XT_2DROP, XT_ALIGN, XT_R_FROM, XT_LATEST, XT_STORE,         // 2DROP ALIGN R> LATEST ! ;
00746     XT_EXIT
00747     };
00748 
00749 
00757 static const CELL XT_VALIDATE[] =
00758     {
00759     LIT(WordHeader::Valid),                                 // WordValid
00760     XT_LATEST, XT_FETCH, XT_CELL_PLUS,                      // LATEST @ >FLAGS
00761     XT_TUCK, XT_C_FETCH,                                    // TUCK C@
00762     XT_OR, XT_SWAP, XT_C_STORE,                             // OR SWAP C!
00763     XT_EXIT
00764     };
00765 
00766 
00773 static const CELL XT_PAREN_CREATE[] =
00774     {
00775     XT_R_FROM, XT_EXIT                                      // R>
00776     };
00777 
00778 
00784 static const CELL XT_CREATE[] =
00785     {
00786     XT_PARSE_WORD, (CELL)XT_CREATE_WORD,                    // PARSE-WORD CREATE-WORD
00787     LIT(XT_PAREN_CREATE), XT_COMMA,                         // POSTPONE (create)
00788     (CELL)XT_VALIDATE, XT_EXIT                              // VALIDATE
00789     };
00790 
00791 
00798 static const CELL XT_PAREN_DOES[] =
00799     {
00800     XT_R_FROM, XT_LATEST, XT_FETCH, XT_TO_CFA, XT_STORE,    // R> LATEST @ >CFA !
00801     XT_EXIT
00802     };
00803 
00804 
00810 static const CELL XT_LITERAL[] =
00811     {
00812     LIT(XT_PAREN_LITERAL), XT_COMMA, XT_COMMA,              // ['] (literal) , ,
00813     XT_EXIT
00814     };
00815 
00816 
00824 static const CELL XT_PAREN_S_QUOTE[] =
00825     {
00826     XT_R_FETCH, XT_CELL_PLUS, XT_R_FROM, XT_FETCH,          // R@ CELL+ R> @
00827     XT_2DUP, XT_CHARS, XT_PLUS, XT_ALIGNED, XT_TO_R,        // 2DUP CHARS + ALIGNED >R
00828     XT_EXIT
00829     };
00830 
00831 
00840 static const CELL XT_S_QUOTE[] =
00841     {
00842     LIT('"'), XT_PARSE,                                     // [CHAR] " PARSE
00843     LIT(XT_PAREN_S_QUOTE), XT_COMMA,                        // POSTPONE (s")
00844     XT_DUP, XT_COMMA, XT_HERE, XT_SWAP,                     // DUP , HERE SWAP
00845     XT_DUP, XT_CHARS, XT_ALLOT, XT_ALIGN, XT_CMOVE, XT_EXIT // DUP CHARS ALLOT ALIGN CMOVE
00846     };
00847 
00848 
00854 static const CELL XT_CHAR[] =
00855     {
00856     XT_PARSE_WORD, XT_0BRANCH(3), XT_C_FETCH, XT_EXIT,      // PARSE-WORD IF C@ EXIT THEN
00857     XT_DROP, XT_FALSE, XT_EXIT                              // DROP FALSE
00858     };
00859 
00860 
00878 static const CELL XT_PAREN_FIND[] =
00879     {
00880     XT_CONTEXT, XT_FETCH, XT_FALSE,                         // CONTEXT @ 0
00881     XT_PAREN_QUESTION_DO, CELLS(15),                        // DO
00882     XT_CONTEXT, XT_I, XT_1_PLUS, XT_CELLS, XT_PLUS,         // CONTEXT I 1+ CELLS +
00883     XT_FETCH, XT_PAREN_SEARCH_WORDLIST,                     // @ (search-wordlist)
00884     XT_QUESTION_DUP, XT_0BRANCH(3), XT_UNLOOP, XT_EXIT,     // ?DUP IF UNLOOP EXIT THEN
00885     XT_PAREN_LOOP, CELLS(-13), XT_FALSE, XT_EXIT            // LOOP FALSE
00886     };
00887 
00888 
00894 static const CELL XT_THROW_QUOTE[] =
00895     {
00896     XT_TO_R, XT_EXCEPTION_MESSAGE, XT_2_STORE,
00897     XT_R_FROM, XT_THROW
00898     };
00899 
00900 
00906 static const CELL XT_PAREN_TICK[] =
00907     {
00908     XT_PARSE_WORD, (CELL)XT_PAREN_FIND,                     // PARSE-WORD (find)
00909     XT_0BRANCH(2), XT_EXIT,                                 // IF EXIT THEN
00910     LIT(UndefinedWord), (CELL)XT_THROW_QUOTE                // -13 THROW"
00911     };
00912 
00913 
00919 static const CELL XT_TICK[] =
00920     {
00921     (CELL)XT_PAREN_TICK, XT_DROP, XT_EXIT                   // (') DROP
00922     };
00923 
00924 
00937 static const CELL XT_TO_SIGN[] =
00938     {
00939     XT_DUP, XT_0_EQUALS, XT_0BRANCH(3), XT_FALSE, XT_EXIT,  // DUP 0= IF FALSE EXIT THEN
00940     XT_OVER, XT_C_FETCH, LIT('-'), XT_EQUALS,               // OVER C@ [CHAR] - =
00941     XT_0BRANCH(7), XT_SWAP, XT_CHAR_PLUS, XT_SWAP,          // IF SWAP CHAR+ SWAP
00942     XT_1_MINUS, XT_TRUE, XT_EXIT, XT_FALSE, XT_EXIT         // 1- TRUE EXIT THEN FALSE
00943     };
00944 
00945 
00964 static const CELL XT_NUMBER_QUERY[] =
00965     {
00966     (CELL)XT_TO_SIGN, XT_TO_R, XT_FALSE, XT_FALSE,          // >SIGN >R 0 0
00967     XT_2SWAP, XT_TO_NUMBER, XT_2SWAP,                       // 2SWAP >NUMBER 2SWAP
00968     XT_R_FROM, XT_0BRANCH(2), XT_DNEGATE,                   // R> IF DNEGATE THEN
00969     XT_2SWAP, XT_DUP, XT_0_EQUALS, XT_0BRANCH(6),           // 2SWAP DUP 0= IF
00970     XT_2DROP, XT_DROP, LIT(1), XT_EXIT,                     // 2DROP DROP 1 EXIT THEN
00971     LIT(1), XT_EQUALS, XT_SWAP,                             // 1 = SWAP
00972     XT_C_FETCH, LIT('.'), XT_EQUALS,    XT_AND,             // C@ [CHAR] . = AND
00973     XT_0BRANCH(4),  LIT(2), XT_EXIT,                        // IF 2 EXIT THEN
00974     XT_2DROP, XT_FALSE, XT_EXIT                             // 2DROP 0
00975     };
00976 
00977 
01000 static const CELL XT_INTERPRET_WORD[] =
01001     {
01002     (CELL)XT_PAREN_FIND,                                    // (find)
01003     XT_0BRANCH(4), XT_DROP, XT_EXECUTE, XT_EXIT,            // IF DROP EXECUTE EXIT THEN
01004     XT_2DUP, XT_2_TO_R, (CELL)XT_NUMBER_QUERY,              // 2DUP 2>R NUMBER?
01005     XT_0BRANCH(4), XT_RDROP, XT_RDROP, XT_EXIT,             // IF R> DROP R> DROP EXIT THEN
01006     XT_2_R_FROM,                                            // 2R>
01007     LIT(UndefinedWord), (CELL)XT_THROW_QUOTE                // -13 THROW"
01008     };
01009 
01010 
01040 static const CELL XT_COMPILE_WORD[] =
01041     {
01042     (CELL)XT_PAREN_FIND,                                    // (find)
01043     XT_0BRANCH(7), XT_0BRANCH(3), XT_EXECUTE, XT_EXIT,      // IF IF EXECUTE EXIT THEN
01044     XT_COMMA, XT_EXIT,                                      // , EXIT THEN
01045     XT_2DUP, XT_2_TO_R, (CELL)XT_NUMBER_QUERY, XT_DUP,      // 2DUP 2>R NUMBER? DUP
01046     XT_0BRANCH(10), XT_RDROP, XT_RDROP,                     // IF R> DROP R> DROP
01047     XT_1_MINUS, XT_0BRANCH(3), XT_SWAP, (CELL)XT_LITERAL,   // 1- IF SWAP POSTPONE LITERAL THEN
01048     (CELL)XT_LITERAL, XT_EXIT,                              // POSTPONE LITERAL EXIT THEN
01049     XT_2_R_FROM,                                            // 2R>
01050     LIT(UndefinedWord), (CELL)XT_THROW_QUOTE                // -13 THROW"
01051     };
01052 
01053 
01067 static const CELL XT_INTERPRET[] =
01068     {
01069     XT_PARSE_WORD, XT_DUP,                                  // BEGIN PARSE-WORD DUP
01070     XT_0BRANCH(11), XT_STATE, XT_FETCH,                     // WHILE STATE @
01071     XT_0BRANCH(4), (CELL)XT_COMPILE_WORD,                   // IF COMPILE-WORD
01072     XT_BRANCH(-10), (CELL)XT_INTERPRET_WORD, XT_BRANCH(-13),// ELSE INTERPRET-WORD THEN REPEAT
01073     XT_2DROP, XT_EXIT                                       // 2DROP
01074     };
01075 
01076 
01086 static const CELL XT_EVALUATE[] =
01087     {
01088     XT_PAREN_SOURCE, XT_2_FETCH, XT_2_TO_R,                 // (source) 2@ 2>R
01089     XT_TO_IN, XT_2_FETCH, XT_2_TO_R,                        // >IN 2@ 2>R
01090     XT_PAREN_SOURCE, XT_2_STORE,                            // (source) 2!
01091     XT_TRUE, XT_FALSE, XT_TO_IN, XT_2_STORE,                // -1 0 >IN 2!
01092     LIT(XT_INTERPRET), XT_CATCH,                            // ' INTERPRET CATCH
01093     XT_2_R_FROM, XT_TO_IN, XT_2_STORE,                      // 2R> >IN 2!
01094     XT_2_R_FROM, XT_PAREN_SOURCE, XT_2_STORE,               // 2R> (source) 2!
01095     XT_THROW, XT_EXIT                                       // THROW
01096     };
01097 
01098 
01110 static const CELL XT_REFILL_TIB[] =
01111     {
01112     XT_TIB, XT_DUP, LIT(NumberTIB), XT_ACCEPT,              // TIB DUP /TIB ACCEPT
01113     XT_SPACE, XT_PAREN_SOURCE, XT_2_STORE,                  // SPACE (source) 2!
01114     XT_FALSE, XT_TO_IN, XT_STORE, XT_TRUE, XT_EXIT          // 0 >IN ! TRUE
01115     };
01116 
01117 
01129 static const CELL XT_REFILL[] =
01130     {
01131     XT_TO_IN, XT_CELL_PLUS, XT_FETCH, XT_0_EQUALS,          // >IN CELL+ @ 0=
01132     XT_0BRANCH(3), (CELL)XT_REFILL_TIB, XT_EXIT,            // IF REFILL-TIB EXIT THEN
01133     XT_FALSE, XT_EXIT                                       // FALSE
01134     };
01135 
01136 
01151 static const CELL XT_DO_QUIT[] =
01152     {
01153     XT_FALSE, XT_TO_IN, XT_CELL_PLUS,                       // 0 >IN CELL+
01154     XT_STORE, XT_LEFT_BRACKET,                              // ! POSTPONE [
01155     (CELL)XT_REFILL, XT_0BRANCH(17), (CELL)XT_INTERPRET,    // BEGIN REFILL WHILE INTERPRET
01156     XT_STATE, XT_FETCH, XT_0_EQUALS, XT_0BRANCH(8),         // STATE @ 0= IF
01157     XT_SPACE, LIT('O'), XT_EMIT,                            // ."  OK"
01158     LIT('K'), XT_EMIT, (CELL)XT_CR,                         // THEN CR
01159     XT_BRANCH(-18), XT_EXIT                                 // REPEAT
01160     };
01161 
01162 
01163 static const CHAR AbortText[] = {'A','B','O','R','T'};
01164 static const CHAR ExceptionText[] = {'E','x','c','e','p','t','i','o','n'};
01165 
01180 const CELL XT_EXCEPTION_DOT[] =
01181     {
01182     XT_DUP, XT_TRUE, XT_EQUALS, XT_0BRANCH(7),              // DUP -1 = IF
01183     LIT(AbortText), LIT(5), XT_TYPE, XT_EXIT,               // ." ABORT" EXIT THEN
01184 
01185     XT_DUP, LIT(-2), XT_EQUALS, XT_0BRANCH(5),              // DUP -2 = IF
01186     XT_EXCEPTION_MESSAGE, XT_2_FETCH, XT_TYPE, XT_EXIT,     // EXCEPTION-STRING 2@ TYPE EXIT
01187 
01188     XT_DUP, LIT(-13), XT_EQUALS, XT_0BRANCH(9),             // DUP -13 = IF
01189     XT_EXCEPTION_MESSAGE, XT_2_FETCH, XT_TYPE, XT_SPACE,    // EXCEPTION-STRING 2@ TYPE SPACE
01190     LIT('?'), XT_EMIT, XT_EXIT,                             // [CHAR] ? EMIT EXIT THEN
01191 
01192     LIT(ExceptionText), LIT(10), XT_TYPE,                   // ." Exception"
01193     XT_DUP, (CELL)XT_DOT, XT_EXIT                           // DUP .
01194     };
01195 
01196 
01205 const CELL XT_QUIT[] =
01206     {
01207     XT_EMPTYR, LIT(XT_DO_QUIT), XT_CATCH,                   // BEGIN EMPTYR ['] DO-QUIT CATCH
01208     (CELL)XT_EXCEPTION_DOT, (CELL)XT_CR,                    // EXCEPTION. CR
01209     XT_EMPTYS, XT_BRANCH(-8)                                // EMPTYS AGAIN
01210     };
01211 
01212 
01213 // Macros for constructing word headers
01214 #define IMMEDIATE 0x8000
01215 #define TOKEN 0x4000
01216 #define LINK(n) CELLS(((n)+!!((n)&TOKEN))&~(IMMEDIATE|TOKEN))
01217 #define FLAGS(f) ((((f)&IMMEDIATE)?(UCELL)WordHeader::Immediate:0)|(((f)&TOKEN)?(UCELL)WordHeader::Token:0)|(UCELL)WordHeader::Valid)
01218 
01219 #define PREPEND_CHAR(x,c) ((((CELL)x)<<BITS_PER_CHAR)+((CELL)c))
01220 #ifdef LITTLE_ENDIAN
01221 #define C4(a,b,c,d) ((CELL)PREPEND_CHAR(PREPEND_CHAR(PREPEND_CHAR(d,c),b),a))
01222 #define C8(a,b,c,d,e,f,g,h) ((C4(e,f,g,h)<<(BITS_PER_CHAR*4))+C4(a,b,c,d))
01223 #endif
01224 #ifdef BIG_ENDIAN
01225 #define C4(a,b,c,d) ((CELL)PREPEND_CHAR(PREPEND_CHAR(PREPEND_CHAR(a,b),c),d))
01226 #define C8(a,b,c,d,e,f,g,h) ((C4(a,b,c,d)<<(BITS_PER_CHAR*4))+C4(e,f,g,h))
01227 #endif
01228 
01229 #if CHARS_PER_CELL==8
01230 
01231 #define H1(a,args)              LINK(2+(args)),C8(FLAGS(args)+1,a,0,0,0,0,0,0)
01232 #define H2(a,b,args)            LINK(2+(args)),C8(FLAGS(args)+2,a,b,0,0,0,0,0)
01233 #define H3(a,b,c,args)          LINK(2+(args)),C8(FLAGS(args)+3,a,b,c,0,0,0,0)
01234 #define H4(a,b,c,d,args)        LINK(2+(args)),C8(FLAGS(args)+4,a,b,c,d,0,0,0)
01235 #define H5(a,b,c,d,e,args)      LINK(2+(args)),C8(FLAGS(args)+5,a,b,c,d,e,0,0)
01236 #define H6(a,b,c,d,e,f,args)    LINK(2+(args)),C8(FLAGS(args)+6,a,b,c,d,e,f,0)
01237 #define H7(a,b,c,d,e,f,g,args)  LINK(2+(args)),C8(FLAGS(args)+7,a,b,c,d,e,f,g)
01238 #define H8(a,b,c,d,e,f,g,h,args)                LINK(3+(args)),C8(FLAGS(args)+8,a,b,c,d,e,f,g),C8(h,0,0,0,0,0,0,0)
01239 #define H9(a,b,c,d,e,f,g,h,i,args)              LINK(3+(args)),C8(FLAGS(args)+9,a,b,c,d,e,f,g),C8(h,i,0,0,0,0,0,0)
01240 #define H10(a,b,c,d,e,f,g,h,i,j,args)           LINK(3+(args)),C8(FLAGS(args)+10,a,b,c,d,e,f,g),C8(h,i,j,0,0,0,0,0)
01241 #define H11(a,b,c,d,e,f,g,h,i,j,k,args)         LINK(3+(args)),C8(FLAGS(args)+11,a,b,c,d,e,f,g),C8(h,i,j,k,0,0,0,0)
01242 #define H12(a,b,c,d,e,f,g,h,i,j,k,l,args)       LINK(3+(args)),C8(FLAGS(args)+12,a,b,c,d,e,f,g),C8(h,i,j,k,l,0,0,0)
01243 #define H13(a,b,c,d,e,f,g,h,i,j,k,l,m,args)     LINK(3+(args)),C8(FLAGS(args)+13,a,b,c,d,e,f,g),C8(h,i,j,k,l,m,0,0)
01244 #define H14(a,b,c,d,e,f,g,h,i,j,k,l,m,n,args)   LINK(3+(args)),C8(FLAGS(args)+14,a,b,c,d,e,f,g),C8(h,i,j,k,l,m,n,0)
01245 #define H15(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,args) LINK(3+(args)),C8(FLAGS(args)+15,a,b,c,d,e,f,g),C8(h,i,j,k,l,m,n,o)
01246 #define H16(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,args)       LINK(4+(args)),C8(FLAGS(args)+16,a,b,c,d,e,f,g),C8(h,i,j,k,l,m,n,o),C8(p,0,0,0,0,0,0,0)
01247 #define H17(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,args)     LINK(4+(args)),C8(FLAGS(args)+17,a,b,c,d,e,f,g),C8(h,i,j,k,l,m,n,o),C8(p,q,0,0,0,0,0,0)
01248 #define H18(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,args)   LINK(4+(args)),C8(FLAGS(args)+18,a,b,c,d,e,f,g),C8(h,i,j,k,l,m,n,o),C8(p,q,r,0,0,0,0,0)
01249 
01250 #elif CHARS_PER_CELL==4
01251 
01252 #define H1(a,args)      LINK(2+(args)),C4(FLAGS(args)+1,a,0,0)
01253 #define H2(a,b,args)    LINK(2+(args)),C4(FLAGS(args)+2,a,b,0)
01254 #define H3(a,b,c,args)  LINK(2+(args)),C4(FLAGS(args)+3,a,b,c)
01255 #define H4(a,b,c,d,args)        LINK(3+(args)),C4(FLAGS(args)+4,a,b,c),C4(d,0,0,0)
01256 #define H5(a,b,c,d,e,args)      LINK(3+(args)),C4(FLAGS(args)+5,a,b,c),C4(d,e,0,0)
01257 #define H6(a,b,c,d,e,f,args)    LINK(3+(args)),C4(FLAGS(args)+6,a,b,c),C4(d,e,f,0)
01258 #define H7(a,b,c,d,e,f,g,args)  LINK(3+(args)),C4(FLAGS(args)+7,a,b,c),C4(d,e,f,g)
01259 #define H8(a,b,c,d,e,f,g,h,args)        LINK(4+(args)),C4(FLAGS(args)+8,a,b,c),C4(d,e,f,g),C4(h,0,0,0)
01260 #define H9(a,b,c,d,e,f,g,h,i,args)      LINK(4+(args)),C4(FLAGS(args)+9,a,b,c),C4(d,e,f,g),C4(h,i,0,0)
01261 #define H10(a,b,c,d,e,f,g,h,i,j,args)   LINK(4+(args)),C4(FLAGS(args)+10,a,b,c),C4(d,e,f,g),C4(h,i,j,0)
01262 #define H11(a,b,c,d,e,f,g,h,i,j,k,args) LINK(4+(args)),C4(FLAGS(args)+11,a,b,c),C4(d,e,f,g),C4(h,i,j,k)
01263 #define H12(a,b,c,d,e,f,g,h,i,j,k,l,args)       LINK(5+(args)),C4(FLAGS(args)+12,a,b,c),C4(d,e,f,g),C4(h,i,j,k),C4(l,0,0,0)
01264 #define H13(a,b,c,d,e,f,g,h,i,j,k,l,m,args)     LINK(5+(args)),C4(FLAGS(args)+13,a,b,c),C4(d,e,f,g),C4(h,i,j,k),C4(l,m,0,0)
01265 #define H14(a,b,c,d,e,f,g,h,i,j,k,l,m,n,args)   LINK(5+(args)),C4(FLAGS(args)+14,a,b,c),C4(d,e,f,g),C4(h,i,j,k),C4(l,m,n,0)
01266 #define H15(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,args) LINK(5+(args)),C4(FLAGS(args)+15,a,b,c),C4(d,e,f,g),C4(h,i,j,k),C4(l,m,n,o)
01267 #define H16(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,args)       LINK(6+(args)),C4(FLAGS(args)+16,a,b,c),C4(d,e,f,g),C4(h,i,j,k),C4(l,m,n,o),C4(p,0,0,0)
01268 #define H17(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,args)     LINK(6+(args)),C4(FLAGS(args)+17,a,b,c),C4(d,e,f,g),C4(h,i,j,k),C4(l,m,n,o),C4(p,q,0,0)
01269 #define H18(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,args)   LINK(6+(args)),C4(FLAGS(args)+18,a,b,c),C4(d,e,f,g),C4(h,i,j,k),C4(l,m,n,o),C4(p,q,r,0)
01270 
01271 #else
01272 
01273 #error CHARS_PER_CELL value not supported
01274 
01275 #endif
01276 
01280 static const CELL ForthDictionary[] =
01281     {
01282     H1('!',TOKEN), XT_STORE,
01283     H1('#',TOKEN), XT_NUMBER_SIGN,
01284     H2('#','>',TOKEN), XT_NUMBER_SIGN_GREATER,
01285     H2('#','S',TOKEN), (CELL)XT_NUMBER_SIGN_S,
01286     H1('\'',TOKEN), (CELL)XT_TICK,
01287     H1('(',IMMEDIATE|5), LIT(')'),                          // : (   ( "ccc<paren>" -- )
01288         XT_PARSE, XT_2DROP, XT_EXIT,                        //   [CHAR] ) PARSE 2DROP ; IMMEDIATE
01289     H1('*',TOKEN), XT_STAR,
01290     H2('*','/',3),                                          // : * /   ( n1 n2 n3 -- n4 )
01291         (CELL)XT_STAR_SLASH_MOD, XT_NIP, XT_EXIT,           //   */MOD NIP ;
01292     H5('*','/','M','O','D',TOKEN), (CELL)XT_STAR_SLASH_MOD,
01293     H1('+',TOKEN), XT_PLUS,
01294     H2('+','!',TOKEN), XT_PLUS_STORE,
01295     H5('+','L','O','O','P',IMMEDIATE|5),                    // : +LOOP   ( C: do-sys -- )
01296         LIT(XT_PAREN_PLUS_LOOP),                            //   ['] (+loop)
01297         (CELL)XT_BACKWARD_BRANCH_COMMA, (CELL)XT_THEN,      //   <BRANCH, POSTPONE THEN
01298         XT_EXIT,                                            //   ; IMMEDIATE
01299     H1(',',TOKEN), XT_COMMA,
01300     H1('-',TOKEN), XT_MINUS,
01301     H1('.',TOKEN), (CELL)XT_DOT,
01302     H2('.','"',IMMEDIATE|5),                                // : ."   ( "ccc<quote>" -- )
01303         (CELL)XT_S_QUOTE, LIT(XT_TYPE), XT_COMMA, XT_EXIT,  //   POSTPONE S" POSTPONE TYPE ; IMMEDIATE
01304     H1('/',3),                                              // : /   ( n1 n2 -- n3 )
01305         (CELL)XT_SLASH_MOD, XT_NIP, XT_EXIT,                //   /MOD NIP ;
01306     H4('/','M','O','D',TOKEN), (CELL)XT_SLASH_MOD,
01307     H2('0','<',TOKEN), XT_0_LESS,
01308     H2('0','=',TOKEN), XT_0_EQUALS,
01309     H2('1','+',TOKEN), XT_1_PLUS,
01310     H2('1','-',TOKEN), XT_1_MINUS,
01311     H2('2','!',TOKEN), XT_2_STORE,
01312     H2('2','*',TOKEN), XT_2_STAR,
01313     H2('2','/',TOKEN), XT_2_SLASH,
01314     H2('2','@',TOKEN), XT_2_FETCH,
01315     H5('2','D','R','O','P',TOKEN), XT_2DROP,
01316     H4('2','D','U','P',TOKEN), XT_2DUP,
01317     H5('2','O','V','E','R',TOKEN), XT_2OVER,
01318     H5('2','S','W','A','P',TOKEN), XT_2SWAP,
01319     H1(':',7),                                              // : :   ( C: "<spaces>name" -- colon-sys )
01320         XT_PARSE_WORD, (CELL)XT_CREATE_WORD,                //   PARSE-WORD CREATE-WORD
01321         XT_FALSE, LIT(ColonMagic), XT_RIGHT_BRACKET,        //   0 COLON-MAGIC ]
01322         XT_EXIT,
01323     H1(';',IMMEDIATE|14),                                   // : ;   ( C: colon-sys -- )
01324         XT_LEFT_BRACKET,                                    //   [
01325         LIT(ColonMagic), (CELL)XT_NEST_CHECK,               //   COLON-MAGIC NEST-CHECK
01326         LIT(XT_EXIT), XT_COMMA, XT_DUP, XT_0_EQUALS,        //   ['] EXIT , DUP 0=
01327         XT_0BRANCH(2), XT_DROP, (CELL)XT_VALIDATE, XT_EXIT, //   IF DROP VALIDATE THEN ; IMMEDIATE
01328     H1('<',TOKEN), XT_LESS_THAN,
01329     H2('<','#',TOKEN), XT_LESS_NUMBER_SIGN,
01330     H1('=',TOKEN), XT_EQUALS,
01331     H1('>',TOKEN), XT_GREATER_THAN,
01332     H5('>','B','O','D','Y',TOKEN), XT_CELL_PLUS,
01333     H3('>','I','N',TOKEN), XT_TO_IN,
01334     H7('>','N','U','M','B','E','R',TOKEN), XT_TO_NUMBER,
01335     H2('>','R',TOKEN), XT_TO_R,
01336     H4('?','D','U','P',TOKEN), XT_QUESTION_DUP,
01337     H1('@',TOKEN), XT_FETCH,
01338     H5('A','B','O','R','T',2), XT_TRUE, XT_THROW,           // : ABORT -1 THROW ;
01339     H6('A','B','O','R','T','"',IMMEDIATE|10),               // : ABORT"   ( "ccc<quote>" -- )
01340         (CELL)XT_IF, (CELL)XT_S_QUOTE,                      //   POSTPONE IF POSTPONE S"
01341         LIT(-2), (CELL)XT_LITERAL,                          //   -2 POSTPONE LITERAL
01342         LIT(XT_THROW_QUOTE), XT_COMMA,                      //   POSTPONE THROW-QUOTE
01343         (CELL)XT_THEN, XT_EXIT,                             //   POSTPONE THEN ; IMMEDIATE
01344     H3('A','B','S',TOKEN), XT_ABS,
01345     H6('A','C','C','E','P','T',TOKEN), XT_ACCEPT,
01346     H5('A','L','I','G','N',TOKEN), XT_ALIGN,
01347     H7('A','L','I','G','N','E','D',TOKEN), XT_ALIGNED,
01348     H5('A','L','L','O','T',TOKEN), XT_ALLOT,
01349     H3('A','N','D',TOKEN), XT_AND,
01350     H4('B','A','S','E',TOKEN), XT_BASE,
01351     H5('B','E','G','I','N',IMMEDIATE|TOKEN), (CELL)XT_BEGIN,
01352     H2('B','L',2),                                          // 32 CONSTANT BL
01353         XT_PAREN_CONSTANT, 32,
01354     H2('C','!',TOKEN), XT_C_STORE,
01355     H2('C',',',TOKEN), XT_C_COMMA,
01356     H2('C','@',TOKEN), XT_C_FETCH,
01357     H5('C','E','L','L','+',TOKEN), XT_CELL_PLUS,
01358     H5('C','E','L','L','S',TOKEN), XT_CELLS,
01359     H4('C','H','A','R',TOKEN), (CELL)XT_CHAR,
01360     H5('C','H','A','R','+',TOKEN), XT_CHAR_PLUS,
01361     H5('C','H','A','R','S',TOKEN), XT_CHARS,
01362     H8('C','O','N','S','T','A','N','T',8),                  // : CONSTANT   ( x "<spaces>name" -- )
01363         XT_PARSE_WORD, (CELL)XT_CREATE_WORD,                //   PARSE-WORD CREATE-WORD
01364         LIT(XT_PAREN_CONSTANT), XT_COMMA, XT_COMMA,         //   POSTPONE (constant) ,
01365         (CELL)XT_VALIDATE, XT_EXIT,                         //   VALIDATE ;
01366     H5('C','O','U','N','T',TOKEN), XT_COUNT,
01367     H2('C','R',TOKEN), (CELL)XT_CR,
01368     H6('C','R','E','A','T','E',TOKEN), (CELL)XT_CREATE,
01369     H7('D','E','C','I','M','A','L',5),                      // : DECIMAL   ( -- )
01370         LIT(10), XT_BASE, XT_STORE, XT_EXIT,                //   10 BASE ! ;
01371     H5('D','E','P','T','H',TOKEN), XT_DEPTH,
01372     H2('D','O',IMMEDIATE|5),                                // : DO   ( C: -- do-sys )
01373         LIT(XT_PAREN_DO), (CELL)XT_FORWARD_BRANCH_COMMA,    //   ['] (do) >BRANCH,
01374         (CELL)XT_BEGIN, XT_EXIT,                            //   POSTPONE BEGIN ; IMMEDIATE
01375     H5('D','O','E','S','>',IMMEDIATE|7),                    // : DOES>   ( C: colon-sys1 -- colon-sys2 )
01376         LIT(XT_PAREN_DOES), XT_COMMA,                       //   POSTPONE (does)
01377         LIT(XT_R_FROM), XT_COMMA, XT_EXIT,                  //   POSTPONE R> ;
01378     H4('D','R','O','P',TOKEN), XT_DROP,
01379     H3('D','U','P',TOKEN), XT_DUP,
01380     H4('E','L','S','E',IMMEDIATE|4),                        // : ELSE   ( C: orig1 -- orig2 )
01381         (CELL)XT_AHEAD, XT_2SWAP, (CELL)XT_THEN, XT_EXIT,   //   POSTPONE AHEAD 2SWAP POSTPONE THEN ; IMMEDIATE
01382     H4('E','M','I','T',TOKEN), XT_EMIT,
01383     H12('E','N','V','I','R','O','N','M','E','N','T','?',13),// : ENVIRONMENT?   ( c-addr u -- false | i*x true )
01384         XT_FORTH_WORDLIST, XT_CELL_PLUS, XT_FETCH,          //   ENVIRONMENT-WORDLIST
01385         XT_PAREN_SEARCH_WORDLIST, XT_NIP,                   //   (search-wordlist) NIP
01386         XT_0BRANCH(4), XT_EXECUTE, XT_TRUE, XT_EXIT,        //   IF EXECUTE TRUE EXIT THEN
01387         XT_DROP, XT_FALSE, XT_EXIT,                         //   DROP FALSE ;
01388     H8('E','V','A','L','U','A','T','E',TOKEN), (CELL)XT_EVALUATE,
01389     H7('E','X','E','C','U','T','E',TOKEN), XT_EXECUTE,
01390     H4('E','X','I','T',TOKEN), XT_EXIT,
01391     H4('F','I','L','L',TOKEN), XT_FILL,
01392     H4('F','I','N','D',17),                                 // : FIND   ( c-addr -- c-addr 0  |  xt 1  |  xt -1 )
01393         XT_COUNT, (CELL)XT_PAREN_FIND, XT_0BRANCH(8),       //   COUNT (find) IF
01394         XT_0BRANCH(4), LIT(1), XT_EXIT, XT_TRUE, XT_EXIT,   //   IF 1 EXIT THEN -1 EXIT
01395         XT_DROP, LIT(CHARS(1)), XT_MINUS, XT_FALSE, XT_EXIT,//   THEN DROP 1 CHARS - 0 THEN ;
01396     H6('F','M','/','M','O','D',TOKEN), (CELL)XT_FM_SLASH_MOD,
01397     H4('H','E','R','E',TOKEN), XT_HERE,
01398     H4('H','O','L','D',TOKEN), XT_HOLD,
01399     H1('I',TOKEN), XT_I,
01400     H2('I','F',IMMEDIATE|TOKEN), (CELL)XT_IF,
01401     H9('I','M','M','E','D','I','A','T','E',4),              // : IMMEDIATE   ( -- )
01402         LIT(WordHeader::Immediate), (CELL)(XT_VALIDATE+2),  //   1 SET-WORD-FLAG ;
01403         XT_EXIT,
01404     H6('I','N','V','E','R','T',TOKEN), XT_INVERT,
01405     H1('J',TOKEN), XT_J,
01406     H3('K','E','Y',TOKEN), XT_KEY,
01407     H5('L','E','A','V','E',TOKEN), XT_LEAVE,
01408     H7('L','I','T','E','R','A','L',IMMEDIATE|TOKEN), (CELL)XT_LITERAL,
01409     H4('L','O','O','P',IMMEDIATE|5),                        // : LOOP   ( C: do-sys -- )
01410         LIT(XT_PAREN_LOOP), (CELL)XT_BACKWARD_BRANCH_COMMA, //   ['] (loop) <BRANCH,
01411         (CELL)XT_THEN, XT_EXIT,                             //   POSTPONE THEN ; IMMEDIATE
01412     H6('L','S','H','I','F','T',TOKEN), XT_LSHIFT,
01413     H2('M','*',TOKEN), (CELL)XT_M_STAR,
01414     H3('M','A','X',TOKEN), XT_MAX,
01415     H3('M','I','N',TOKEN), XT_MIN,
01416     H3('M','O','D',3),                                      // : MOD   ( n1 n2 -- n3 )
01417         (CELL)XT_SLASH_MOD, XT_DROP, XT_EXIT,               //   /MOD DROP ;
01418     H4('M','O','V','E',TOKEN), XT_MOVE,
01419     H6('N','E','G','A','T','E',TOKEN), XT_NEGATE,
01420     H2('O','R',TOKEN), XT_OR,
01421     H4('O','V','E','R',TOKEN), XT_OVER,
01422     H8('P','O','S','T','P','O','N','E',IMMEDIATE|10),       // : POSTPONE   ( "<spaces>name" -- )
01423         (CELL)XT_PAREN_TICK,                                //   (')
01424         XT_0BRANCH(3), XT_COMMA, XT_EXIT,                   //   IF , EXIT THEN
01425         (CELL)XT_LITERAL, LIT(XT_COMMA), XT_COMMA, XT_EXIT, //   POSTPONE LITERAL POSTPONE , ; IMMEDIATE
01426     H4('Q','U','I','T',TOKEN), (CELL)XT_QUIT,
01427     H2('R','>',TOKEN), XT_R_FROM,
01428     H2('R','@',TOKEN), XT_R_FETCH,
01429     H7('R','E','C','U','R','S','E',IMMEDIATE|5),            // : RECURSE   ( -- )
01430         XT_LATEST, XT_FETCH, XT_TO_CFA, XT_COMMA, XT_EXIT,  //   LATEST @ >CFA , ;
01431     H6('R','E','P','E','A','T',IMMEDIATE|3),                // : REPEAT   ( C: orig dest -- )
01432         (CELL)XT_AGAIN, (CELL)XT_THEN, XT_EXIT,             //   POSTPONE AGAIN POSTPONE THEN ; IMMEDIATE
01433     H3('R','O','T',TOKEN), XT_ROT,
01434     H6('R','S','H','I','F','T',TOKEN), XT_RSHIFT,
01435     H2('S','"',IMMEDIATE|TOKEN), (CELL)XT_S_QUOTE,
01436     H3('S','>','D',TOKEN), XT_S_TO_D,
01437     H4('S','I','G','N',TOKEN), XT_SIGN,
01438     H6('S','M','/','R','E','M',TOKEN), (CELL)XT_SM_SLASH_REM,
01439     H6('S','O','U','R','C','E',3),                          // : SOURCE   ( -- c-addr u )
01440         XT_PAREN_SOURCE, XT_2_FETCH, XT_EXIT,               //   (source) 2@ ;
01441     H5('S','P','A','C','E',TOKEN), XT_SPACE,
01442     H6('S','P','A','C','E','S',10),                         // : SPACES   ( n -- )
01443         XT_DUP, XT_0_GREATER, XT_0BRANCH(5),                //   BEGIN DUP 0> WHILE
01444         XT_SPACE, XT_1_MINUS, XT_BRANCH(-7), XT_DROP,       //   SPACE 1- REPEAT DROP
01445         XT_EXIT,                                            //   ;
01446     H5('S','T','A','T','E',TOKEN), XT_STATE,
01447     H4('S','W','A','P',TOKEN), XT_SWAP,
01448     H4('T','H','E','N',IMMEDIATE|TOKEN), (CELL)XT_THEN,
01449     H4('T','Y','P','E',TOKEN), XT_TYPE,
01450     H2('U','.',3),                                          // : U.   ( u -- )
01451         XT_FALSE, (CELL)XT_D_DOT, XT_EXIT,                  //   0 D. ;
01452     H2('U','<',TOKEN), XT_U_LESS_THAN,
01453     H3('U','M','*',TOKEN), XT_UM_STAR,
01454     H6('U','M','/','M','O','D',TOKEN), (CELL)XT_UM_SLASH_MOD,
01455     H6('U','N','L','O','O','P',TOKEN), XT_UNLOOP,
01456     H5('U','N','T','I','L',IMMEDIATE|4),                    // : UNTIL   ( C: dest -- )
01457         LIT(XT_PAREN_0BRANCH),                              //   ['] (0branch)
01458         (CELL)XT_BACKWARD_BRANCH_COMMA, XT_EXIT,            //   <BRANCH, ; IMMEDIATE
01459     H8('V','A','R','I','A','B','L','E',4),                  // : VARIABLE   ( "<spaces>name" -- )
01460         (CELL)XT_CREATE, XT_FALSE, XT_COMMA, XT_EXIT,       //   CREATE 0 , ;
01461     H5('W','H','I','L','E',IMMEDIATE|3),                    // : WHILE   ( C: dest -- orig dest )
01462         (CELL)XT_IF, XT_2SWAP, XT_EXIT,                     //   POSTPONE IF 2SWAP ; IMMEDIATE
01463     H4('W','O','R','D',14),                                 // : WORD   ( char "<chars>ccc<char>" -- c-addr )
01464         XT_INVERT, XT_PARSE, LIT(SlashCountedString),       //   INVERT PARSE /COUNTED-STRING
01465         XT_MIN, XT_DUP, XT_HERE, XT_C_STORE, XT_HERE,       //   MIN DUP HERE C! HERE
01466         XT_CHAR_PLUS, XT_SWAP, XT_CMOVE, XT_HERE, XT_EXIT,  //   CHAR+ SWAP CMOVE HERE ;
01467     H3('X','O','R',TOKEN), XT_XOR,
01468     H1('[',IMMEDIATE|TOKEN), XT_LEFT_BRACKET,
01469     H3('[','\'',']',IMMEDIATE|3),                           // : [']   ( "<spaces>name" -- )
01470         (CELL)XT_TICK, (CELL)XT_LITERAL, XT_EXIT,           //   ' POSTPONE LITERAL ; IMMEDIATE
01471     H6('[','C','H','A','R',']',IMMEDIATE|3),                // : [CHAR]   ( "<spaces>name" -- )
01472         (CELL)XT_CHAR, (CELL)XT_LITERAL, XT_EXIT,           //   CHAR POSTPONE LITERAL ; IMMEDIATE
01473     H1(']',TOKEN), XT_RIGHT_BRACKET,
01474 
01475     //
01476     // CORE EXT
01477     //
01478 
01479     H3('0','<','>',TOKEN), XT_0_NOT_EQUALS,
01480     H2('0','>',TOKEN), XT_0_GREATER,
01481     H3('2','>','R',TOKEN), XT_2_TO_R,
01482     H3('2','R','>',TOKEN), XT_2_R_FROM,
01483     H3('2','R','@',TOKEN), XT_2_R_FETCH,
01484     H7(':','N','O','N','A','M','E',8),                      // : :NONAME   ( C:  -- colon-sys )  ( S:  -- xt )
01485         XT_FALSE, XT_FALSE, (CELL)XT_CREATE_WORD,           //   0 0 CREATE-WORD
01486         XT_HERE, LIT(ColonMagic), XT_RIGHT_BRACKET,     //   HERE COLON-MAGIC ] ;
01487         XT_EXIT,
01488     H2('<','>',TOKEN), XT_NOT_EQUALS,
01489     H3('?','D','O',IMMEDIATE|5),                            // : ?DO   ( C: -- do-sys )
01490         LIT(XT_PAREN_QUESTION_DO),                          //   ['] (?do)
01491         (CELL)XT_FORWARD_BRANCH_COMMA, (CELL)XT_BEGIN,      //   >BRANCH, POSTPONE BEGIN
01492         XT_EXIT,                                            // ; IMMEDIATE
01493     H5('A','G','A','I','N',IMMEDIATE|TOKEN), (CELL)XT_AGAIN,
01494     H8('C','O','M','P','I','L','E',',',TOKEN), XT_COMMA,
01495     H5('E','R','A','S','E',TOKEN), XT_ERASE,
01496     H5('F','A','L','S','E',TOKEN), XT_FALSE,
01497     H3('H','E','X',5),                                      // : HEX   ( -- )
01498         LIT(16), XT_BASE, XT_STORE, XT_EXIT,                //   16 BASE ! ;
01499     H3('N','I','P',TOKEN), XT_NIP,
01500     H3('P','A','D',TOKEN), XT_PAD,
01501     H5('P','A','R','S','E',TOKEN), XT_PARSE,
01502     H4('P','I','C','K',TOKEN), XT_PICK,
01503     H4('R','O','L','L',TOKEN), XT_ROLL,
01504     H4('T','R','U','E',TOKEN), XT_TRUE,
01505     H4('T','U','C','K',TOKEN), XT_TUCK,
01506     H2('U','>',TOKEN), XT_U_GREATER_THAN,
01507     H6('U','N','U','S','E','D',TOKEN), XT_UNUSED,
01508     H1('\\',IMMEDIATE|8),                                   // : \   ( "ccc<eol>"-- )
01509         XT_PAREN_CR, XT_1_MINUS, XT_CHARS, XT_PLUS,         //   (cr) 1- CHARS +
01510         XT_C_FETCH, XT_PARSE, XT_2DROP, XT_EXIT,            //   C@ PARSE 2DROP ; IMMEDIATE
01511 
01512     //
01513     // DOUBLE
01514     //
01515 
01516     H2('D','+',TOKEN), XT_D_PLUS,
01517     H2('D','.',TOKEN), (CELL)XT_D_DOT,
01518     H4('D','A','B','S',TOKEN), XT_DABS,
01519     H7('D','N','E','G','A','T','E',TOKEN), XT_DNEGATE,
01520     H2('M','+',TOKEN), XT_M_PLUS,
01521 
01522     //
01523     // EXCEPTION
01524     //
01525 
01526     H5('C','A','T','C','H',TOKEN), XT_CATCH,
01527     H5('T','H','R','O','W',TOKEN), XT_THROW,
01528 
01529     //
01530     // SEARCH
01531     //
01532 
01533     H14('F','O','R','T','H','-','W','O','R','D','L','I','S','T',TOKEN), XT_FORTH_WORDLIST, // : FORTH-WORDLIST   ( -- wid )
01534     H15('S','E','A','R','C','H','-','W','O','R','D','L','I','S','T',13), // : SEARCH-WORDLIST   ( c-addr u wid -- 0 | xt 1 | xt -1 )
01535         XT_PAREN_SEARCH_WORDLIST, XT_0BRANCH(8),            //   (SEARCH-WORDLIST) IF
01536         XT_0BRANCH(4), LIT(1), XT_EXIT, XT_TRUE, XT_EXIT,   //   IF 1 EXIT THEN -1 EXIT
01537         XT_2DROP, XT_FALSE, XT_EXIT,                        //   2DROP FALSE ;
01538 
01539     //
01540     // STRING
01541     //
01542 
01543     H5('C','M','O','V','E',TOKEN), XT_CMOVE,
01544     H6('C','M','O','V','E','>',TOKEN), XT_CMOVE_UP,
01545 
01546     //
01547     // TOOLS
01548     //
01549 
01550     H2('.','S',18),                                         // : .S   ( -- )
01551         (CELL)XT_CR, XT_DEPTH, LIT(StackCells), XT_MIN,     //   CR DEPTH STACK-CELLS MIN
01552         XT_FALSE, XT_MAX, XT_DUP, XT_0BRANCH(7),            //   0 MAX BEGIN DUP WHILE
01553         XT_DUP, XT_PICK, (CELL)XT_DOT, XT_1_MINUS,          //   DUP PICK . 1-
01554         XT_BRANCH(-8), XT_DROP, XT_EXIT,                    //   REPEAT DROP ;
01555     H5('A','H','E','A','D',TOKEN), (CELL)XT_AHEAD,
01556     H3('B','Y','E',TOKEN), XT_END,                          // : BYE   ( -- )   END ;
01557 
01558     //
01559     // NOT ANS
01560     //
01561 
01562     H7('C','O','N','T','E','X','T',TOKEN), XT_CONTEXT,      // : CONTEXT   ( -- a-addr )
01563     H7('C','U','R','R','E','N','T',TOKEN), XT_CURRENT,      // : CURRENT   ( -- a-addr )
01564     H6('L','A','T','E','S','T',TOKEN), XT_LATEST,           // : LATEST   ( -- a-addr )
01565     H8('(','s','o','u','r','c','e',')',TOKEN), XT_PAREN_SOURCE, // : (source)   ( -- a-addr )
01566     H9('I','N','T','E','R','P','R','E','T',TOKEN), (CELL)XT_INTERPRET, // : INTERPRET   ( i*x -- j*x )
01567     H10('B','R','E','A','K','P','O','I','N','T',TOKEN), XT_BREAKPOINT, // : BREAKPOINT   ( -- )
01568 
01569     0
01570     };
01571 
01572 
01576 static const CELL EnvironmentDictionary[] =
01577     {
01578     H15('/','C','O','U','N','T','E','D','-','S','T','R','I','N','G',2), XT_PAREN_CONSTANT, SlashCountedString,
01579     H5('/','H','O','L','D',2), XT_PAREN_CONSTANT, SlashCountedString,
01580     H4('/','P','A','D',2), XT_PAREN_CONSTANT, SlashPad,
01581     H17('A','D','D','R','E','S','S','-','U','N','I','T','-','B','I','T','S',2), XT_PAREN_CONSTANT, BITS_PER_CHAR/CHARS(1),
01582     H4('C','O','R','E',TOKEN), XT_TRUE,
01583     H7('F','L','O','O','R','E','D',2), XT_PAREN_CONSTANT, ((-1)/2),
01584     H8('M','A','X','-','C','H','A','R',2), XT_PAREN_CONSTANT, (1<<BITS_PER_CHAR)-1,
01585     H5('M','A','X','-','U',TOKEN), XT_TRUE,
01586     H5('M','A','X','-','D',4), XT_TRUE, LIT((CELL)(((UCELL)(~0))>>1)), XT_EXIT,
01587     H5('M','A','X','-','N',2), XT_PAREN_CONSTANT, (CELL)(((UCELL)(~0))>>1),
01588     H6('M','A','X','-','U','D',3), XT_TRUE, XT_TRUE, XT_EXIT,
01589     H18('R','E','T','U','R','N','-','S','T','A','C','K','-','C','E','L','L','S',2), XT_PAREN_CONSTANT, ReturnStackCells,
01590     H11('S','T','A','C','K','-','C','E','L','L','S',2), XT_PAREN_CONSTANT, StackCells,
01591     0
01592     };
01593 
01594 
01598 class ForthVM : public Forth
01599     {
01600 private:
01602     bool DoReset();
01603 
01605     CELL DoQuit();
01606 
01608     CELL DoExecute(CELL xt);
01609 
01611     CELL DoEvaluate(const CHAR* text,unsigned textLength);
01612 
01614     void DoPush(const CELL* cells, unsigned numCells);
01615 
01617     const CELL* DoPop(unsigned numCells);
01618 private:
01624     CELL Run(const CELL* ip);
01625 
01631     CELL UncaughtException(CELL exceptionNumber);
01632 private:
01636     ForthIo*    Io;
01637 
01641     CELL*       Sp0;
01642 
01646     CELL*       Rp0;
01647 
01652     CELL*       MemoryEnd;
01653 
01658     CELL*       Sp;
01659 
01664     CELL*       Rp;
01665 
01669     CHAR*       Dp;
01670 
01674     UCELL       DpLimit;
01675 
01679     UCELL       SourceSize;
01680 
01685     CELL        SourceBase;
01686 
01690     UCELL       SourceOffset;
01691 
01696     CELL        SourceId;
01697 
01703     CELL        Context[MaxWordlists+1];
01704 
01709     CELL        Current;
01710 
01715     CELL        Latest;
01716 
01720     CELL        State;
01721 
01725     CELL        Base;
01726 
01730     CELL*       ExceptionFrame;
01731 
01741     CELL        ExceptionMessage[2];
01742 
01746     Wordlist    ForthWordlist;
01747 
01751     Wordlist    EnvironmentWordlist;
01752 
01753     static void MultiplyPrimitive(CELL* sp);
01754     static void DividePrimitive(CELL* sp);
01755     static void ToNumber(CELL* sp,UCELL base);
01756     void ParsePrimitive(CELL* sp,CELL delimiter);
01757     CELL FindPrimitive(CELL* sp,CELL wordlist);
01758     CELL Accept(CHAR* buffer, CELL maxLen);
01759 
01760     friend class Forth;
01761     };
01762 
01763 
01764 bool ForthVM::DoReset()
01765     {
01766     // clear all memory
01767     CELL* end = MemoryEnd;
01768     CELL* ptr = (CELL*)(&this->MemoryEnd+1);
01769     while(ptr<end) *ptr++=0;
01770 
01771     // make space for TIB at end of memory
01772     end -= (NumberTIB*sizeof(CHAR)+(sizeof(CELL)-1))/sizeof(CELL);
01773 
01774     // initialise stacks
01775     Rp0 = end;
01776     Rp = end;
01777     end -= ReturnStackCells;
01778 
01779     Sp0 = end;
01780     Sp = end;
01781     end -= StackCells;
01782 
01783     // initialse user variables
01784     DpLimit = (UCELL)end-DictionaryOverhead;
01785     Dp = (CHAR*)(this+1);
01786     if((UCELL)Dp>=DpLimit)
01787         return false;
01788     Base = 10;
01789 
01790     // initialise dictionary
01791     ForthWordlist.LastWord = (CELL)ForthDictionary;
01792     ForthWordlist.Previous = (CELL)&EnvironmentWordlist;
01793     EnvironmentWordlist.LastWord = (CELL)EnvironmentDictionary;
01794 
01795     Context[0] = 2;
01796     Context[1] = (CELL)&ForthWordlist;
01797     Context[2] = (CELL)&EnvironmentWordlist;
01798     Current = (CELL)&ForthWordlist;
01799 
01800     return true;
01801     }
01802 
01803 
01804 inline CELL ForthVM::DoExecute(CELL xt)
01805     {
01806     CELL execute[2];
01807     execute[0] = xt;
01808     execute[1] = XT_END;
01809     return ((ForthVM*)this)->Run(execute);
01810     }
01811 
01812 
01813 inline CELL ForthVM::DoQuit()
01814     {
01815     return DoExecute((CELL)XT_QUIT);
01816     }
01817 
01818 
01819 inline CELL ForthVM::DoEvaluate(const CHAR* text,unsigned textLength)
01820     {
01821     SourceBase = (CELL)text;
01822     SourceSize = textLength;
01823     SourceOffset = 0;
01824     SourceId = -2;
01825     return Execute((CELL)XT_INTERPRET);
01826     }
01827 
01828 
01829 inline const CELL* ForthVM::DoPop(unsigned numCells)
01830     {
01831     CELL* cells = Sp;
01832     Sp+=numCells;
01833     return cells;
01834     }
01835 
01836 
01837 inline void ForthVM::DoPush(const CELL* cells, unsigned numCells)
01838     {
01839     CELL* sp = Sp-numCells;
01840     Sp = sp;
01841     while(numCells--)
01842         *sp++ = *cells++;
01843     }
01844 
01845 
01846 #define NEXT            goto next
01847 #define BRANCH          ip = (CELL*)((CELL)ip+(CELL)ip[0]); NEXT
01848 #define THROW(a)        { t=a; goto exception; }
01849 #define CALL(a)         { xt=(CELL)(a); goto call; }
01850 
01851 #define PUSH(a)         { *--sp=(CELL)(a); }
01852 #define POP(a)          { (a)=*sp++; }
01853 #define RPUSH(a)        { *--rp=(CELL)(a); }
01854 #define RPOP(cast,a)    { (a)=(cast)*rp++; }
01855 
01856 CELL ForthVM::Run(const CELL* ip)
01857     {
01858     CELL*   sp = Sp;
01859     CELL*   rp = Rp;
01860     CELL    t = *sp++;
01861     CELL    x = 0;
01862     CELL    xt;
01863     goto next;
01864 call:
01865     RPUSH(ip);
01866     ip=(CELL*)xt;
01867 next:
01868     xt = *ip++;
01869 execute:
01870     switch(xt)
01871         {
01872     case XT_BREAKPOINT:             BREAKPOINT; NEXT;
01873     case XT_END:                    PUSH(t); Sp = sp; Rp = rp; return 0;
01874 
01875     case XT_CATCH:                  RPUSH(ip); RPUSH(sp); RPUSH(XT_CATCH_END); ip = rp;
01876                                     RPUSH(ExceptionFrame); ExceptionFrame = rp;
01877                                     // fall through to EXECUTE...
01878     case XT_EXECUTE:                xt=t; POP(t); goto execute;
01879 
01880     case XT_CATCH_END:              RPOP(CELL*,ExceptionFrame); ++rp; ++rp; PUSH(t); t=0;
01881                                     // fall through to EXIT...
01882     case XT_EXIT:                   RPOP(CELL*,ip); NEXT;
01883 
01884     case XT_THROW:                  if(!t) { POP(t); NEXT; }
01885                         exception:  rp=ExceptionFrame;
01886                                     if(rp)
01887                                         {
01888                                         RPOP(CELL*,ExceptionFrame); ++rp; RPOP(CELL*,sp); RPOP(CELL*,ip); NEXT;
01889                                         }
01890                                     Sp = sp; Rp = rp; return UncaughtException(t);
01891 
01892     case XT_EXCEPTION_MESSAGE:      PUSH(t); t=(CELL)ExceptionMessage; NEXT;
01893 
01894     case XT_CODE_EXECUTE:           sp=((CELL*(*)(CELL*))t)(sp); POP(t); NEXT;
01895     case XT_PAREN_0BRANCH:          x=t; POP(t); if(x) { ++ip; NEXT; } // fall through to BRANCH...
01896     case XT_PAREN_BRANCH:           BRANCH;
01897     case XT_PAREN_LITERAL:          PUSH(t); t=*ip++; NEXT;
01898     case XT_PAREN_CONSTANT:         PUSH(t); t=*ip; RPOP(CELL*,ip); NEXT;
01899 
01900     // Looping
01901     case XT_PAREN_QUESTION_DO:      if(t==*sp) { t = sp[1]; sp+=2; BRANCH; } // fall through to (DO)...
01902     case XT_PAREN_DO:               RPUSH(ip++); POP(x); RPUSH(x); RPUSH(t); POP(t); NEXT;
01903     case XT_LEAVE:                  rp+=2; RPOP(CELL*,ip); BRANCH;
01904     case XT_PAREN_LOOP:             x=*rp+1; *rp=x; if(x!=rp[1]) { BRANCH; } ++ip; // fall through to UNLOOP...
01905     case XT_UNLOOP:                 rp+=3; NEXT;
01906     case XT_J:                      PUSH(t); t=rp[3]; NEXT;
01907     case XT_PAREN_PLUS_LOOP:    {   x = rp[0]; t+=x; rp[0]=t; CELL lim=rp[1];
01908                                     if(( ((x-lim)&(lim-1-t)) | ((t-lim)&(lim-1-x)) )>=0)
01909                                         { POP(t); BRANCH; }
01910                                     POP(t); ip++; rp += 3; NEXT; }
01911 
01912     // Arithmetic
01913     case XT_PLUS:                   POP(x); t=x+t; NEXT;
01914     case XT_MINUS:                  POP(x); t=x-t; NEXT;
01915     case XT_STAR:                   POP(x); t=x*t; NEXT;
01916     case XT_UM_STAR:                PUSH(t); MultiplyPrimitive(sp); POP(t); NEXT;
01917     case XT_UDM_SLASH_MOD:          PUSH(t); if(!t) THROW(DivideByZero); DividePrimitive(sp); POP(t); NEXT;
01918     case XT_AND:                    POP(x); t=x&t; NEXT;
01919     case XT_OR:                     POP(x); t=x|t; NEXT;
01920     case XT_XOR:                    POP(x); t=x^t; NEXT;
01921     case XT_LSHIFT:                 POP(x); t=x<<t; NEXT;
01922     case XT_RSHIFT:                 POP(x); t=(UCELL)x>>t; NEXT;
01923     case XT_INVERT:                 t = ~t; NEXT;
01924     case XT_ABS:                    if(t>=0) NEXT; // fall through to NEGATE...
01925     case XT_NEGATE:                 t=-t; NEXT;
01926     case XT_1_PLUS:                 ++t; NEXT;
01927     case XT_1_MINUS:                --t; NEXT;
01928     case XT_2_STAR:                 t<<=1; NEXT;
01929     case XT_2_SLASH:                t>>=1; NEXT;
01930     case XT_MIN:                    POP(x); if(x<t) t=x; NEXT;
01931     case XT_MAX:                    POP(x); if(x>t) t=x; NEXT;
01932 
01933     case XT_DABS:                   if(t>=0) NEXT; // fall through to DNEGATE...
01934     case XT_DNEGATE:                x=*sp; *sp=-x; if(x) t=~t; else t=-t; NEXT;
01935     case XT_M_PLUS:                 PUSH(t); t>>=(BitsPerCell-1); // fall through to D+...
01936     case XT_D_PLUS:                 sp[2]+=sp[0]; if((UCELL)sp[2]<(UCELL)sp[0]) ++t; t+=sp[1]; sp+=2; NEXT;
01937 
01938     // Memory access
01939     case XT_CELLS:                  t=CELLS(t); NEXT;
01940     case XT_CHARS:                  t=CHARS(t); NEXT;
01941     case XT_CELL_PLUS:              t = (CELL)((CELL*)t+1); NEXT;
01942     case XT_CHAR_PLUS:              t = (CELL)((CHAR*)t+1); NEXT;
01943     case XT_ALIGNED:                t=ALIGNED(t); NEXT;
01944     case XT_2_FETCH:                PUSH(((CELL*)t)[1]); // fall through to @
01945     case XT_FETCH:                  t=*(CELL*)t; NEXT;
01946     case XT_STORE:                  POP(x); *(CELL*)t=x; POP(t); NEXT;
01947     case XT_C_FETCH:                t=*(CHAR*)t; NEXT;
01948     case XT_C_STORE:                POP(x); *(CHAR*)t=x; POP(t); NEXT;
01949     case XT_2_STORE:                POP(x); *((CELL*)t)=x; POP(x); ((CELL*)t)[1]=x; POP(t); NEXT;
01950     case XT_PLUS_STORE:             POP(x); *(CELL*)t+=x; POP(t); NEXT;
01951     case XT_COUNT:                  t = (CELL)((CHAR*)t+1); PUSH(t); t=((CHAR*)t)[-1]; NEXT;
01952 
01953     case XT_MOVE:                   t=SLASH_CHAR(t);
01954                                     if((UCELL)(sp[0]-sp[1])<(UCELL)CHARS(t)) goto cmove_up;
01955                                     // fall through to CMOVE...
01956 
01957     case XT_CMOVE:                  {   POP(x); CHAR* d=(CHAR*)x; POP(x); CHAR* s=(CHAR*)x; CHAR* lim=s+t;
01958                                         while(s<lim) *d++=*s++; POP(t); NEXT; }
01959 
01960     case XT_CMOVE_UP:               cmove_up:
01961                                     {   POP(x); CHAR* d=(CHAR*)x+t; POP(x); CHAR* lim=(CHAR*)x; CHAR* s=lim+t;
01962                                         while(s>lim) *--d=*--s; POP(t); NEXT; }
01963 
01964     case XT_ERASE:                  t=SLASH_CHAR(t); PUSH(t); t=0; // fall through to FILL...
01965 
01966     case XT_FILL:                   {   POP(x); CHAR* lim=(CHAR*)x; POP(x); CHAR* d=(CHAR*)x;
01967                                         if((CELL)lim>0)
01968                                             { lim=d+(CELL)lim; while(d<lim) *d++=t; }
01969                                         POP(t); NEXT; }
01970 
01971     // Stack maniputation
01972     case XT_QUESTION_DUP:           if(!t) NEXT; // fall through to DUP
01973     case XT_DUP:                    PUSH(t); NEXT;
01974     case XT_2DROP:                  ++sp; // fall through to DROP...
01975     case XT_DROP:                   POP(t); NEXT;
01976     case XT_SWAP:                   x=*sp; *sp=t; t=x; NEXT;
01977     case XT_OVER:                   PUSH(t); t=sp[1]; NEXT;
01978     case XT_ROT:                    x=sp[1]; sp[1]=sp[0]; sp[0]=t; t=x; NEXT;
01979     case XT_NIP:                    ++sp; NEXT;
01980     case XT_TUCK:                   x=*sp; *sp=t; PUSH(x); NEXT;
01981     case XT_2_TO_R:                 POP(x); RPUSH(x); // fall through to >R
01982     case XT_TO_R:                   RPUSH(t); POP(t); NEXT;
01983     case XT_R_FROM:                 PUSH(t); RPOP(CELL,t); NEXT;
01984     case XT_I:                      PUSH(t); t=*rp; NEXT;
01985     case XT_R_FETCH:                PUSH(t); t=*rp; NEXT;
01986     case XT_2DUP:                   x=*sp; PUSH(t); PUSH(x); NEXT;
01987     case XT_2SWAP:                  x=sp[1]; sp[1]=t; t=x; x=sp[2]; sp[2]=sp[0]; sp[0]=x; NEXT;
01988     case XT_2OVER:                  PUSH(t); t=sp[3]; PUSH(t); t=sp[3]; NEXT;
01989     case XT_2_R_FROM:               PUSH(t); RPOP(CELL,t); RPOP(CELL,x); PUSH(x); NEXT;
01990     case XT_2_R_FETCH:              PUSH(t); t=rp[0]; x=rp[1]; PUSH(x); NEXT;
01991     case XT_RDROP:                  ++rp; NEXT;
01992     case XT_PICK:                   t=sp[t]; NEXT;
01993     case XT_ROLL:                   x = sp[t]; while(t) { sp[t]=sp[t-1]; --t; } t=x; ++sp; NEXT;
01994     case XT_DEPTH:                  PUSH(t); t=(CELL*)Sp0-sp; NEXT;
01995     case XT_EMPTYS:                 sp=Sp0+1; NEXT;
01996     case XT_EMPTYR:                 ExceptionFrame=0; rp=Rp0; NEXT;
01997 
01998     // Comparison operation
01999     case XT_0_EQUALS:               if(t==0) t=~0; else t=0; NEXT;
02000     case XT_0_NOT_EQUALS:           if(t!=0) t=~0; NEXT;
02001     case XT_S_TO_D:                 PUSH(t); // fall through to 0< ...
02002     case XT_0_LESS:                 t>>=(BitsPerCell-1); NEXT;
02003     case XT_0_GREATER:              if(t>0) t=~0; else t=0; NEXT;
02004     case XT_EQUALS:                 POP(x); if(x==t) t=~0; else t=0; NEXT;
02005     case XT_NOT_EQUALS:             POP(x); if(x!=t) t=~0; else t=0; NEXT;
02006     case XT_LESS_THAN:              POP(x); if(x<t) t=~0; else t=0; NEXT;
02007     case XT_GREATER_THAN:           POP(x); if(x>t) t=~0; else t=0; NEXT;
02008     case XT_U_LESS_THAN:            POP(x); if((UCELL)x<(UCELL)t) t=~0; else t=0; NEXT;
02009     case XT_U_GREATER_THAN:         POP(x); if((UCELL)x>(UCELL)t) t=~0; else t=0; NEXT;
02010     case XT_TRUE:                   PUSH(t); t=~0; NEXT;
02011     case XT_FALSE:                  PUSH(t); t=0; NEXT;
02012 
02013     // Dictionary manipulation
02014     case XT_HERE:                   PUSH(t); t=(CELL)Dp; NEXT;
02015     case XT_ALLOT:                  x=(CELL)Dp; x=(CELL)((CHAR*)x+t); Dp=(CHAR*)x; POP(t); NEXT;
02016     case XT_ALIGN:                  x=(CELL)Dp; x=ALIGNED(x); Dp=(CHAR*)x; NEXT;
02017     case XT_COMMA:                  { CELL* p=(CELL*)Dp; *p++=t; Dp=(CHAR*)p; } POP(t); NEXT;
02018     case XT_C_COMMA:                *((CHAR*&)Dp)++=t; POP(t); NEXT;
02019     case XT_UNUSED:                 PUSH(t); t=DpLimit-(UCELL)Dp; NEXT;
02020     case XT_PAD:                    PUSH(t); t=(CELL)Dp+CHARS(SlashCountedString+2); NEXT;
02021 
02022     // Input parsing
02023     case XT_PAREN_SOURCE:           PUSH(t); t=(CELL)&SourceSize; NEXT;
02024     case XT_TO_IN:                  PUSH(t); t=(CELL)&SourceOffset; NEXT;
02025     case XT_PARSE_WORD:             PUSH(t); t=~' '; // fall through to PARSE...
02026     case XT_PARSE:                  ParsePrimitive(sp,t); --sp; t=sp[-1]; NEXT;
02027     case XT_TO_NUMBER:              PUSH(t); ToNumber(sp,Base); POP(t); NEXT;
02028 
02029     // Dictionary search
02030     case XT_CONTEXT:                PUSH(t); t=(CELL)&Context; NEXT;
02031     case XT_CURRENT:                PUSH(t); t=(CELL)&Current; NEXT;
02032     case XT_LATEST:                 PUSH(t); t=(CELL)&Latest; NEXT;
02033     case XT_FORTH_WORDLIST:         PUSH(t); t=(CELL)&ForthWordlist; NEXT;
02034     case XT_PAREN_SEARCH_WORDLIST:  t=FindPrimitive(sp,t); NEXT;
02035     case XT_TO_CFA:                 t=(CELL)((WordHeader*)t)->CFA(); NEXT;
02036 
02037     // Compilation state
02038     case XT_STATE:                  PUSH(t); t=(CELL)&State; NEXT;
02039     case XT_LEFT_BRACKET:           State=0; NEXT;
02040     case XT_RIGHT_BRACKET:          State=~0; NEXT;
02041 
02042     // Console i/o
02043     case XT_SPACE:                  PUSH(t); t=' '; // fall through to EMIT...
02044     case XT_EMIT:                   x = (CELL)((CHAR*)rp-1); *(CHAR*)x=(CHAR)t; PUSH(x); t=1; // Fall through to type...
02045     case XT_TYPE:                   Io->ConsoleOut((CHAR*)*sp++,t); POP(t); NEXT;
02046     case XT_KEY:                    PUSH(t); do t=Io->ConsoleIn(); while((UCELL)t>255); NEXT;
02047     case XT_ACCEPT:                 POP(x); t=Accept((CHAR*)x,t); NEXT;
02048     case XT_PAREN_CR:               PUSH(t); PUSH(&Io->NewLine[1]); t=(CELL)Io->NewLine[0]; NEXT;
02049     case XT_TIB:                    PUSH(t); t=(CELL)Rp0; NEXT;
02050 
02051     // Number conversion
02052     case XT_BASE:                   PUSH(t); t=(CELL)&Base; NEXT;
02053     case XT_LESS_NUMBER_SIGN:       *Dp=SlashCountedString; NEXT;
02054 
02055     case XT_NUMBER_SIGN_GREATER:    t=(CELL)(SlashCountedString-*Dp);
02056                                     sp[0]=(CELL)(Dp+(SlashCountedString+1-t)); NEXT;
02057 
02058     case XT_SIGN:                   if(t>=0) { POP(t); NEXT; } t='-'; goto hold;
02059 
02060     case XT_NUMBER_SIGN:            PUSH(t); sp[-1]=Base; DividePrimitive(sp-1);
02061                                     t=sp[1]; sp[1]=sp[0]; sp[0]=sp[-1];
02062                                     t+='0'; if(t>'9') t+='A'-'9'-1; // fall through to HOLD...
02063 
02064     case XT_HOLD:           hold:   if(*Dp==0) THROW(-17);
02065                                     Dp[*Dp]=(CHAR)t; --Dp[0]; POP(t); NEXT;
02066 
02067     default:
02068         goto call;
02069     }
02070 }
02071 
02072 
02073 CELL ForthVM::UncaughtException(CELL exceptionNumber)
02074     {
02075     Io->ConsoleOut((const CHAR*)ExceptionMessage[1],ExceptionMessage[0]);
02076     if(exceptionNumber==-13)
02077         {
02078         CHAR c = ' ';
02079         Io->ConsoleOut(&c,1);
02080         c = '?';
02081         Io->ConsoleOut(&c,1);
02082         }
02083     {
02084     CHAR* source = (CHAR*)SourceBase+SourceOffset;
02085     *(volatile CHAR*)source; // to avoid warning about 'source' being unused
02086     BREAKPOINT;
02087     }
02088     State = 0;
02089     return exceptionNumber;
02090     }
02091 
02092 
02093 void ForthVM::MultiplyPrimitive(CELL* sp) // (u1 u2 -- ud )
02094     {
02095     UCELL a = (UCELL)sp[0];
02096     UCELL b = (UCELL)sp[1];
02097 
02098     UCELL lo = (a&CellLoMask)*(b&CellLoMask);
02099     UCELL hi = (a>>(BitsPerCell/2))*(b>>(BitsPerCell/2));
02100     UCELL i1 = (a&CellLoMask)*(b>>(BitsPerCell/2));
02101     UCELL i2 = (a>>(BitsPerCell/2))*(b&CellLoMask);
02102 
02103     i1 += i2;
02104     if(i1<i2)
02105         hi += (CELL)(UCELL)1<<(BitsPerCell/2);
02106     hi += i1>>(BitsPerCell/2);
02107     i1 <<= (BitsPerCell/2);
02108     lo += i1;
02109     if(lo<i1)
02110         hi++;
02111 
02112     sp[0] = hi;
02113     sp[1] = lo;
02114     }
02115 
02116 
02117 void ForthVM::DividePrimitive(CELL* sp) // (ud1 u1 -- u2[remainder] ud2[quotient])
02118     {
02119     UCELL d  = sp[0];
02120     UCELL r  = 0;
02121     UCELL qh = sp[1];
02122     UCELL ql = sp[2];
02123     int n  = 2*BitsPerCell;
02124 
02125     if(qh<d)
02126         {
02127         r = qh;
02128         qh = ql;
02129         ql = 0;
02130         n -= BitsPerCell;
02131         }
02132 
02133     UCELL c  = 0;
02134     do
02135         {
02136         UCELL sub = r>>(BitsPerCell-1);
02137 
02138         r  = (r<<1)+(qh>>(BitsPerCell-1));
02139         qh = (qh<<1)+(ql>>(BitsPerCell-1));
02140         ql = (ql<<1)+c;
02141 
02142         if(r>=d) sub = 1;
02143         c = sub;
02144         if(sub)
02145             r -= d;
02146         }
02147     while(--n);
02148 
02149     qh = (qh<<1)+(ql>>(BitsPerCell-1));
02150     ql = (ql<<1)+c;
02151 
02152     sp[0] = qh;
02153     sp[1] = ql;
02154     sp[2] = r;
02155     }
02156 
02157 
02158 void ForthVM::ToNumber(CELL* sp,UCELL base) // ( d1 c-addr2 u2 -- d2 c-addr2 u2 )
02159     {
02160     UCELL count = sp[0];
02161     CHAR* ptr = (CHAR*)sp[1];
02162     UCELL hi = sp[2];
02163     UCELL lo = sp[3];
02164 
02165     while(count)
02166         {
02167         UCELL c=ptr[0];
02168         if(c>='a')
02169             c -= 'a'-'A';
02170         c -= '0';
02171         if(c>=10)
02172             {
02173             c -= 'A'-'9'-1;
02174             if(c<10)
02175                 break;
02176             }
02177         if(c>=base)
02178             break;
02179 
02180         UCELL mid = lo>>(BitsPerCell/2);
02181         lo &= CellLoMask;
02182         lo = lo*base+c;
02183         mid *= base;
02184         hi *= base;
02185         hi += mid>>(BitsPerCell/2);
02186         mid = mid<<(BitsPerCell/2);
02187         lo = lo+mid;
02188         if(lo<mid)
02189             ++hi;
02190 
02191         ++ptr;
02192         --count;
02193         }
02194 
02195     sp[0] = count;
02196     sp[1] = (CELL)ptr;
02197     sp[2] = hi;
02198     sp[3] = lo;
02199     }
02200 
02201 
02202 void ForthVM::ParsePrimitive(CELL* sp,CELL delimiter) // ( -- c-addr u )
02203     {
02204     CHAR* base = (CHAR*)SourceBase;
02205     CHAR* end = base+SourceSize;
02206     CHAR* in = base+SourceOffset;
02207     CHAR* start;
02208 
02209     CELL skipLeading = delimiter>>(BitsPerCell-1);
02210     if(skipLeading)
02211         delimiter = ~delimiter;
02212 
02213     if(delimiter==' ')
02214         {
02215         if(skipLeading)
02216             while(in<end && *in<=' ')
02217                 ++in;
02218         start = in;
02219         while(in<end)
02220             if(*in++<=' ')
02221                 goto delimited;
02222         }
02223     else
02224         {
02225         if(skipLeading)
02226             while(in<end && *in==delimiter)
02227                 ++in;
02228         start = in;
02229         while(in<end)
02230             if(*in++==delimiter)
02231                 goto delimited;
02232         }
02233 
02234     sp[-1] = (CELL)start;
02235     sp[-2] = in-start;
02236     SourceOffset = in-base;
02237     return;
02238 
02239 delimited:
02240     sp[-1] = (CELL)start;
02241     sp[-2] = in-start-1;
02242     SourceOffset = in-base;
02243     }
02244 
02245 
02246 inline bool MatchChars(CELL a, CELL b)
02247     {
02248     if(a>='a' && a<='z')
02249         a -= 'a'-'A';
02250     if(b>='a' && b<='z')
02251         b -= 'a'-'A';
02252     return a==b;
02253     }
02254 
02255 
02256 CELL ForthVM::FindPrimitive(CELL* sp,CELL wordlist) // (c-addr u -- c-addr u 0 | xt immed header )
02257     {
02258     UCELL nameLength = (UCELL)sp[0];
02259     if(nameLength>(UCELL)NameLengthMask)
02260         nameLength=NameLengthMask;
02261     CHAR* name = (CHAR*)sp[1];
02262 
02263     WordHeader* word=*(WordHeader**)wordlist;
02264     while(word->Previous)
02265         {
02266         UCELL i;
02267         if((UCELL)(word->NameLength&NameLengthMask)!=nameLength)
02268             goto next;
02269         for(i=0; i<nameLength; i++)
02270             if(!MatchChars(word->Name[i],name[i]))
02271                 goto next;
02272         if(word->NameLength&WordHeader::Valid)
02273             {
02274             CELL xt = (CELL)word->CFA();
02275             if(word->NameLength&WordHeader::Token)
02276                 xt = *(CELL*)xt;
02277 
02278             sp[1] = xt;
02279             sp[0] = word->NameLength&WordHeader::Immediate ? ~0 : 0;
02280             return (CELL)word;
02281             }
02282 next:
02283         word=(WordHeader*)((CELL)word+word->Previous);
02284         }
02285     return 0;
02286     }
02287 
02288 
02289 CELL ForthVM::Accept(CHAR* buffer, CELL maxLen)
02290     {
02291     CELL len=0;
02292     for(;;)
02293         {
02294         CELL c=Io->ConsoleIn();
02295         if(c==0x0a || c==0x0d) // LF or CR
02296             return len;
02297         if(c==0x08 || c==0x7f) // BS or DEL
02298             {
02299             if(!len)
02300                 continue;
02301             --len;
02302             static const CHAR bs[] = {8,' ',8};
02303             Io->ConsoleOut(bs,3);
02304             }
02305         else
02306             {
02307             if(len>=maxLen)
02308                 continue;
02309             buffer[len] = c;
02310             Io->ConsoleOut(&buffer[len],1);
02311             len++;
02312             }
02313         }
02314     }
02315 
02316  // End of group
02318 
02319 //
02320 // Definition of the public Forth class members follow...
02321 //
02322 
02323 Forth* Forth::Construct(void* memoryStart,size_t memorySize,ForthIo* ioHandler)
02324     {
02325     if(memorySize<sizeof(ForthVM))
02326         return 0;
02327     ForthVM* forth = (ForthVM*)memoryStart;
02328     forth->MemoryEnd = (CELL*)memoryStart+memorySize/sizeof(CELL);
02329     forth->Io = ioHandler;
02330     if(!forth->DoReset())
02331         return 0;
02332     return forth;
02333     }
02334 
02335 
02336 void Forth::Reset()
02337     {
02338     ((ForthVM*)this)->DoReset();
02339     }
02340 
02341 
02342 CELL Forth::Quit()
02343     {
02344     return ((ForthVM*)this)->DoQuit();
02345     }
02346 
02347 
02348 CELL Forth::Execute(CELL xt)
02349     {
02350     return ((ForthVM*)this)->DoExecute(xt);
02351     }
02352 
02353 
02354 CELL Forth::Evaluate(const CHAR* text,unsigned textLength)
02355     {
02356     return ((ForthVM*)this)->DoEvaluate(text,textLength);
02357     }
02358 
02359 
02360 const CELL* Forth::Pop(unsigned numCells)
02361     {
02362     return ((ForthVM*)this)->DoPop(numCells);
02363     }
02364 
02365 
02366 void Forth::Push(const CELL* cells, unsigned numCells)
02367     {
02368     ((ForthVM*)this)->DoPush(cells,numCells);
02369     }
02370 
02371 

Generated by  doxygen 1.6.1