00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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,
00428 LIT(ControlStructureMismatch), XT_THROW
00429 };
00430
00431
00437 static const CELL XT_FORWARD_BRANCH_COMMA[] =
00438 {
00439 XT_COMMA, XT_HERE, XT_FALSE, XT_COMMA,
00440 LIT(OrigMagic), XT_EXIT
00441 };
00442
00443
00449 static const CELL XT_BACKWARD_BRANCH_COMMA[] =
00450 {
00451 XT_COMMA, LIT(DestMagic), (CELL)XT_NEST_CHECK,
00452 XT_HERE, XT_MINUS, XT_COMMA, XT_EXIT
00453 };
00454
00455
00461 static const CELL XT_IF[] =
00462 {
00463 LIT(XT_PAREN_0BRANCH), (CELL)XT_FORWARD_BRANCH_COMMA,
00464 XT_EXIT
00465 };
00466
00467
00473 static const CELL XT_AHEAD[] =
00474 {
00475 LIT(XT_PAREN_BRANCH), (CELL)XT_FORWARD_BRANCH_COMMA,
00476 XT_EXIT
00477 };
00478
00479
00486 static const CELL XT_THEN[] =
00487 {
00488 LIT(OrigMagic), (CELL)XT_NEST_CHECK,
00489 XT_HERE, XT_OVER, XT_MINUS, XT_SWAP, XT_STORE, XT_EXIT
00490 };
00491
00492
00498 static const CELL XT_BEGIN[] =
00499 {
00500 XT_HERE, LIT(DestMagic), XT_EXIT
00501 };
00502
00503
00509 static const CELL XT_AGAIN[] =
00510 {
00511 LIT(XT_PAREN_BRANCH), (CELL)XT_BACKWARD_BRANCH_COMMA,
00512 XT_EXIT
00513 };
00514
00515
00523 static const CELL XT_UM_SLASH_MOD[] =
00524 {
00525 XT_DUP, XT_0_EQUALS, XT_0BRANCH(4),
00526 LIT(DivideByZero), XT_THROW,
00527 XT_UDM_SLASH_MOD, XT_0BRANCH(4),
00528 LIT(ResultOutOfRange), XT_THROW,
00529 XT_EXIT
00530 };
00531
00532
00539 static const CELL XT_CHECK_NEG[] =
00540 {
00541 XT_DUP, XT_0_GREATER, XT_0BRANCH(4),
00542 LIT(ResultOutOfRange), XT_THROW, XT_EXIT
00543 };
00544
00545
00552 static const CELL XT_CHECK_POS[] =
00553 {
00554 XT_DUP, XT_0_LESS, XT_0BRANCH(4),
00555 LIT(ResultOutOfRange), XT_THROW, XT_EXIT
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,
00575 XT_ABS, XT_TO_R, XT_DABS, XT_R_FROM,
00576 (CELL)XT_UM_SLASH_MOD,
00577 XT_R_FROM, XT_0_LESS, XT_0BRANCH(5),
00578 XT_NEGATE, (CELL)XT_CHECK_NEG, XT_BRANCH(2),
00579 (CELL)XT_CHECK_POS,
00580 XT_SWAP, XT_R_FROM, XT_0_LESS, XT_0BRANCH(2),
00581 XT_NEGATE, XT_SWAP, XT_EXIT
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,
00602 XT_ABS, XT_TO_R, XT_DABS, XT_R_FROM,
00603 (CELL)XT_UM_SLASH_MOD,
00604 XT_R_FROM, XT_0_LESS, XT_0BRANCH(15),
00605 XT_NEGATE, (CELL)XT_CHECK_NEG, XT_OVER, XT_0BRANCH(11),
00606 XT_1_MINUS, (CELL)XT_CHECK_NEG, XT_R_FETCH, XT_ABS,
00607 XT_ROT, XT_MINUS, XT_SWAP, XT_BRANCH(2),
00608 (CELL)XT_CHECK_POS,
00609 XT_SWAP, XT_R_FROM, XT_0_LESS, XT_0BRANCH(2),
00610 XT_NEGATE, XT_SWAP, XT_EXIT
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
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,
00643 XT_UM_STAR, XT_R_FROM, XT_0_LESS,
00644 XT_0BRANCH(2), XT_DNEGATE, XT_EXIT
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,
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,
00668 XT_0BRANCH(-5), XT_EXIT
00669 };
00670
00671
00679 static const CELL XT_D_DOT[] =
00680 {
00681 XT_LESS_NUMBER_SIGN, LIT(' '),
00682 XT_HOLD, XT_DUP, XT_TO_R, XT_DABS,
00683 (CELL)XT_NUMBER_SIGN_S, XT_R_FROM, XT_SIGN,
00684 XT_NUMBER_SIGN_GREATER, XT_TYPE, XT_EXIT
00685 };
00686
00687
00693 static const CELL XT_DOT[] =
00694 {
00695 XT_S_TO_D, (CELL)XT_D_DOT, XT_EXIT
00696 };
00697
00698
00704 static const CELL XT_CR[] =
00705 {
00706 XT_PAREN_CR, XT_TYPE, XT_EXIT
00707 };
00708
00709
00730 static const CELL XT_CREATE_WORD[] =
00731 {
00732 XT_OVER, XT_0_NOT_EQUALS,
00733 XT_OVER, XT_0_GREATER, XT_INVERT, XT_AND,
00734 XT_0BRANCH(4), LIT(ZeroLengthName), XT_THROW,
00735 LIT(NameLengthMask), XT_MIN,
00736 XT_ALIGN, XT_HERE, XT_TO_R,
00737
00738 XT_CURRENT, XT_FETCH,
00739 XT_DUP, XT_FETCH, XT_R_FETCH, XT_MINUS, XT_COMMA,
00740 XT_R_FETCH, XT_SWAP, XT_STORE,
00741
00742 XT_DUP, XT_C_COMMA,
00743 XT_DUP, XT_0BRANCH(10), XT_OVER, XT_C_FETCH, XT_C_COMMA,
00744 XT_SWAP, XT_CHAR_PLUS, XT_SWAP, XT_1_MINUS, XT_BRANCH(-11),
00745 XT_2DROP, XT_ALIGN, XT_R_FROM, XT_LATEST, XT_STORE,
00746 XT_EXIT
00747 };
00748
00749
00757 static const CELL XT_VALIDATE[] =
00758 {
00759 LIT(WordHeader::Valid),
00760 XT_LATEST, XT_FETCH, XT_CELL_PLUS,
00761 XT_TUCK, XT_C_FETCH,
00762 XT_OR, XT_SWAP, XT_C_STORE,
00763 XT_EXIT
00764 };
00765
00766
00773 static const CELL XT_PAREN_CREATE[] =
00774 {
00775 XT_R_FROM, XT_EXIT
00776 };
00777
00778
00784 static const CELL XT_CREATE[] =
00785 {
00786 XT_PARSE_WORD, (CELL)XT_CREATE_WORD,
00787 LIT(XT_PAREN_CREATE), XT_COMMA,
00788 (CELL)XT_VALIDATE, XT_EXIT
00789 };
00790
00791
00798 static const CELL XT_PAREN_DOES[] =
00799 {
00800 XT_R_FROM, XT_LATEST, XT_FETCH, XT_TO_CFA, XT_STORE,
00801 XT_EXIT
00802 };
00803
00804
00810 static const CELL XT_LITERAL[] =
00811 {
00812 LIT(XT_PAREN_LITERAL), XT_COMMA, XT_COMMA,
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,
00827 XT_2DUP, XT_CHARS, XT_PLUS, XT_ALIGNED, XT_TO_R,
00828 XT_EXIT
00829 };
00830
00831
00840 static const CELL XT_S_QUOTE[] =
00841 {
00842 LIT('"'), XT_PARSE,
00843 LIT(XT_PAREN_S_QUOTE), XT_COMMA,
00844 XT_DUP, XT_COMMA, XT_HERE, XT_SWAP,
00845 XT_DUP, XT_CHARS, XT_ALLOT, XT_ALIGN, XT_CMOVE, XT_EXIT
00846 };
00847
00848
00854 static const CELL XT_CHAR[] =
00855 {
00856 XT_PARSE_WORD, XT_0BRANCH(3), XT_C_FETCH, XT_EXIT,
00857 XT_DROP, XT_FALSE, XT_EXIT
00858 };
00859
00860
00878 static const CELL XT_PAREN_FIND[] =
00879 {
00880 XT_CONTEXT, XT_FETCH, XT_FALSE,
00881 XT_PAREN_QUESTION_DO, CELLS(15),
00882 XT_CONTEXT, XT_I, XT_1_PLUS, XT_CELLS, XT_PLUS,
00883 XT_FETCH, XT_PAREN_SEARCH_WORDLIST,
00884 XT_QUESTION_DUP, XT_0BRANCH(3), XT_UNLOOP, XT_EXIT,
00885 XT_PAREN_LOOP, CELLS(-13), XT_FALSE, XT_EXIT
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,
00909 XT_0BRANCH(2), XT_EXIT,
00910 LIT(UndefinedWord), (CELL)XT_THROW_QUOTE
00911 };
00912
00913
00919 static const CELL XT_TICK[] =
00920 {
00921 (CELL)XT_PAREN_TICK, XT_DROP, XT_EXIT
00922 };
00923
00924
00937 static const CELL XT_TO_SIGN[] =
00938 {
00939 XT_DUP, XT_0_EQUALS, XT_0BRANCH(3), XT_FALSE, XT_EXIT,
00940 XT_OVER, XT_C_FETCH, LIT('-'), XT_EQUALS,
00941 XT_0BRANCH(7), XT_SWAP, XT_CHAR_PLUS, XT_SWAP,
00942 XT_1_MINUS, XT_TRUE, XT_EXIT, XT_FALSE, XT_EXIT
00943 };
00944
00945
00964 static const CELL XT_NUMBER_QUERY[] =
00965 {
00966 (CELL)XT_TO_SIGN, XT_TO_R, XT_FALSE, XT_FALSE,
00967 XT_2SWAP, XT_TO_NUMBER, XT_2SWAP,
00968 XT_R_FROM, XT_0BRANCH(2), XT_DNEGATE,
00969 XT_2SWAP, XT_DUP, XT_0_EQUALS, XT_0BRANCH(6),
00970 XT_2DROP, XT_DROP, LIT(1), XT_EXIT,
00971 LIT(1), XT_EQUALS, XT_SWAP,
00972 XT_C_FETCH, LIT('.'), XT_EQUALS, XT_AND,
00973 XT_0BRANCH(4), LIT(2), XT_EXIT,
00974 XT_2DROP, XT_FALSE, XT_EXIT
00975 };
00976
00977
01000 static const CELL XT_INTERPRET_WORD[] =
01001 {
01002 (CELL)XT_PAREN_FIND,
01003 XT_0BRANCH(4), XT_DROP, XT_EXECUTE, XT_EXIT,
01004 XT_2DUP, XT_2_TO_R, (CELL)XT_NUMBER_QUERY,
01005 XT_0BRANCH(4), XT_RDROP, XT_RDROP, XT_EXIT,
01006 XT_2_R_FROM,
01007 LIT(UndefinedWord), (CELL)XT_THROW_QUOTE
01008 };
01009
01010
01040 static const CELL XT_COMPILE_WORD[] =
01041 {
01042 (CELL)XT_PAREN_FIND,
01043 XT_0BRANCH(7), XT_0BRANCH(3), XT_EXECUTE, XT_EXIT,
01044 XT_COMMA, XT_EXIT,
01045 XT_2DUP, XT_2_TO_R, (CELL)XT_NUMBER_QUERY, XT_DUP,
01046 XT_0BRANCH(10), XT_RDROP, XT_RDROP,
01047 XT_1_MINUS, XT_0BRANCH(3), XT_SWAP, (CELL)XT_LITERAL,
01048 (CELL)XT_LITERAL, XT_EXIT,
01049 XT_2_R_FROM,
01050 LIT(UndefinedWord), (CELL)XT_THROW_QUOTE
01051 };
01052
01053
01067 static const CELL XT_INTERPRET[] =
01068 {
01069 XT_PARSE_WORD, XT_DUP,
01070 XT_0BRANCH(11), XT_STATE, XT_FETCH,
01071 XT_0BRANCH(4), (CELL)XT_COMPILE_WORD,
01072 XT_BRANCH(-10), (CELL)XT_INTERPRET_WORD, XT_BRANCH(-13),
01073 XT_2DROP, XT_EXIT
01074 };
01075
01076
01086 static const CELL XT_EVALUATE[] =
01087 {
01088 XT_PAREN_SOURCE, XT_2_FETCH, XT_2_TO_R,
01089 XT_TO_IN, XT_2_FETCH, XT_2_TO_R,
01090 XT_PAREN_SOURCE, XT_2_STORE,
01091 XT_TRUE, XT_FALSE, XT_TO_IN, XT_2_STORE,
01092 LIT(XT_INTERPRET), XT_CATCH,
01093 XT_2_R_FROM, XT_TO_IN, XT_2_STORE,
01094 XT_2_R_FROM, XT_PAREN_SOURCE, XT_2_STORE,
01095 XT_THROW, XT_EXIT
01096 };
01097
01098
01110 static const CELL XT_REFILL_TIB[] =
01111 {
01112 XT_TIB, XT_DUP, LIT(NumberTIB), XT_ACCEPT,
01113 XT_SPACE, XT_PAREN_SOURCE, XT_2_STORE,
01114 XT_FALSE, XT_TO_IN, XT_STORE, XT_TRUE, XT_EXIT
01115 };
01116
01117
01129 static const CELL XT_REFILL[] =
01130 {
01131 XT_TO_IN, XT_CELL_PLUS, XT_FETCH, XT_0_EQUALS,
01132 XT_0BRANCH(3), (CELL)XT_REFILL_TIB, XT_EXIT,
01133 XT_FALSE, XT_EXIT
01134 };
01135
01136
01151 static const CELL XT_DO_QUIT[] =
01152 {
01153 XT_FALSE, XT_TO_IN, XT_CELL_PLUS,
01154 XT_STORE, XT_LEFT_BRACKET,
01155 (CELL)XT_REFILL, XT_0BRANCH(17), (CELL)XT_INTERPRET,
01156 XT_STATE, XT_FETCH, XT_0_EQUALS, XT_0BRANCH(8),
01157 XT_SPACE, LIT('O'), XT_EMIT,
01158 LIT('K'), XT_EMIT, (CELL)XT_CR,
01159 XT_BRANCH(-18), XT_EXIT
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),
01183 LIT(AbortText), LIT(5), XT_TYPE, XT_EXIT,
01184
01185 XT_DUP, LIT(-2), XT_EQUALS, XT_0BRANCH(5),
01186 XT_EXCEPTION_MESSAGE, XT_2_FETCH, XT_TYPE, XT_EXIT,
01187
01188 XT_DUP, LIT(-13), XT_EQUALS, XT_0BRANCH(9),
01189 XT_EXCEPTION_MESSAGE, XT_2_FETCH, XT_TYPE, XT_SPACE,
01190 LIT('?'), XT_EMIT, XT_EXIT,
01191
01192 LIT(ExceptionText), LIT(10), XT_TYPE,
01193 XT_DUP, (CELL)XT_DOT, XT_EXIT
01194 };
01195
01196
01205 const CELL XT_QUIT[] =
01206 {
01207 XT_EMPTYR, LIT(XT_DO_QUIT), XT_CATCH,
01208 (CELL)XT_EXCEPTION_DOT, (CELL)XT_CR,
01209 XT_EMPTYS, XT_BRANCH(-8)
01210 };
01211
01212
01213
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(')'),
01288 XT_PARSE, XT_2DROP, XT_EXIT,
01289 H1('*',TOKEN), XT_STAR,
01290 H2('*','/',3),
01291 (CELL)XT_STAR_SLASH_MOD, XT_NIP, XT_EXIT,
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),
01296 LIT(XT_PAREN_PLUS_LOOP),
01297 (CELL)XT_BACKWARD_BRANCH_COMMA, (CELL)XT_THEN,
01298 XT_EXIT,
01299 H1(',',TOKEN), XT_COMMA,
01300 H1('-',TOKEN), XT_MINUS,
01301 H1('.',TOKEN), (CELL)XT_DOT,
01302 H2('.','"',IMMEDIATE|5),
01303 (CELL)XT_S_QUOTE, LIT(XT_TYPE), XT_COMMA, XT_EXIT,
01304 H1('/',3),
01305 (CELL)XT_SLASH_MOD, XT_NIP, XT_EXIT,
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),
01320 XT_PARSE_WORD, (CELL)XT_CREATE_WORD,
01321 XT_FALSE, LIT(ColonMagic), XT_RIGHT_BRACKET,
01322 XT_EXIT,
01323 H1(';',IMMEDIATE|14),
01324 XT_LEFT_BRACKET,
01325 LIT(ColonMagic), (CELL)XT_NEST_CHECK,
01326 LIT(XT_EXIT), XT_COMMA, XT_DUP, XT_0_EQUALS,
01327 XT_0BRANCH(2), XT_DROP, (CELL)XT_VALIDATE, XT_EXIT,
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,
01339 H6('A','B','O','R','T','"',IMMEDIATE|10),
01340 (CELL)XT_IF, (CELL)XT_S_QUOTE,
01341 LIT(-2), (CELL)XT_LITERAL,
01342 LIT(XT_THROW_QUOTE), XT_COMMA,
01343 (CELL)XT_THEN, XT_EXIT,
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),
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),
01363 XT_PARSE_WORD, (CELL)XT_CREATE_WORD,
01364 LIT(XT_PAREN_CONSTANT), XT_COMMA, XT_COMMA,
01365 (CELL)XT_VALIDATE, XT_EXIT,
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),
01370 LIT(10), XT_BASE, XT_STORE, XT_EXIT,
01371 H5('D','E','P','T','H',TOKEN), XT_DEPTH,
01372 H2('D','O',IMMEDIATE|5),
01373 LIT(XT_PAREN_DO), (CELL)XT_FORWARD_BRANCH_COMMA,
01374 (CELL)XT_BEGIN, XT_EXIT,
01375 H5('D','O','E','S','>',IMMEDIATE|7),
01376 LIT(XT_PAREN_DOES), XT_COMMA,
01377 LIT(XT_R_FROM), XT_COMMA, XT_EXIT,
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),
01381 (CELL)XT_AHEAD, XT_2SWAP, (CELL)XT_THEN, XT_EXIT,
01382 H4('E','M','I','T',TOKEN), XT_EMIT,
01383 H12('E','N','V','I','R','O','N','M','E','N','T','?',13),
01384 XT_FORTH_WORDLIST, XT_CELL_PLUS, XT_FETCH,
01385 XT_PAREN_SEARCH_WORDLIST, XT_NIP,
01386 XT_0BRANCH(4), XT_EXECUTE, XT_TRUE, XT_EXIT,
01387 XT_DROP, XT_FALSE, XT_EXIT,
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),
01393 XT_COUNT, (CELL)XT_PAREN_FIND, XT_0BRANCH(8),
01394 XT_0BRANCH(4), LIT(1), XT_EXIT, XT_TRUE, XT_EXIT,
01395 XT_DROP, LIT(CHARS(1)), XT_MINUS, XT_FALSE, XT_EXIT,
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),
01402 LIT(WordHeader::Immediate), (CELL)(XT_VALIDATE+2),
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),
01410 LIT(XT_PAREN_LOOP), (CELL)XT_BACKWARD_BRANCH_COMMA,
01411 (CELL)XT_THEN, XT_EXIT,
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),
01417 (CELL)XT_SLASH_MOD, XT_DROP, XT_EXIT,
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),
01423 (CELL)XT_PAREN_TICK,
01424 XT_0BRANCH(3), XT_COMMA, XT_EXIT,
01425 (CELL)XT_LITERAL, LIT(XT_COMMA), XT_COMMA, XT_EXIT,
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),
01430 XT_LATEST, XT_FETCH, XT_TO_CFA, XT_COMMA, XT_EXIT,
01431 H6('R','E','P','E','A','T',IMMEDIATE|3),
01432 (CELL)XT_AGAIN, (CELL)XT_THEN, XT_EXIT,
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),
01440 XT_PAREN_SOURCE, XT_2_FETCH, XT_EXIT,
01441 H5('S','P','A','C','E',TOKEN), XT_SPACE,
01442 H6('S','P','A','C','E','S',10),
01443 XT_DUP, XT_0_GREATER, XT_0BRANCH(5),
01444 XT_SPACE, XT_1_MINUS, XT_BRANCH(-7), XT_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),
01451 XT_FALSE, (CELL)XT_D_DOT, XT_EXIT,
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),
01457 LIT(XT_PAREN_0BRANCH),
01458 (CELL)XT_BACKWARD_BRANCH_COMMA, XT_EXIT,
01459 H8('V','A','R','I','A','B','L','E',4),
01460 (CELL)XT_CREATE, XT_FALSE, XT_COMMA, XT_EXIT,
01461 H5('W','H','I','L','E',IMMEDIATE|3),
01462 (CELL)XT_IF, XT_2SWAP, XT_EXIT,
01463 H4('W','O','R','D',14),
01464 XT_INVERT, XT_PARSE, LIT(SlashCountedString),
01465 XT_MIN, XT_DUP, XT_HERE, XT_C_STORE, XT_HERE,
01466 XT_CHAR_PLUS, XT_SWAP, XT_CMOVE, XT_HERE, XT_EXIT,
01467 H3('X','O','R',TOKEN), XT_XOR,
01468 H1('[',IMMEDIATE|TOKEN), XT_LEFT_BRACKET,
01469 H3('[','\'',']',IMMEDIATE|3),
01470 (CELL)XT_TICK, (CELL)XT_LITERAL, XT_EXIT,
01471 H6('[','C','H','A','R',']',IMMEDIATE|3),
01472 (CELL)XT_CHAR, (CELL)XT_LITERAL, XT_EXIT,
01473 H1(']',TOKEN), XT_RIGHT_BRACKET,
01474
01475
01476
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),
01485 XT_FALSE, XT_FALSE, (CELL)XT_CREATE_WORD,
01486 XT_HERE, LIT(ColonMagic), XT_RIGHT_BRACKET,
01487 XT_EXIT,
01488 H2('<','>',TOKEN), XT_NOT_EQUALS,
01489 H3('?','D','O',IMMEDIATE|5),
01490 LIT(XT_PAREN_QUESTION_DO),
01491 (CELL)XT_FORWARD_BRANCH_COMMA, (CELL)XT_BEGIN,
01492 XT_EXIT,
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),
01498 LIT(16), XT_BASE, XT_STORE, XT_EXIT,
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),
01509 XT_PAREN_CR, XT_1_MINUS, XT_CHARS, XT_PLUS,
01510 XT_C_FETCH, XT_PARSE, XT_2DROP, XT_EXIT,
01511
01512
01513
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
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
01531
01532
01533 H14('F','O','R','T','H','-','W','O','R','D','L','I','S','T',TOKEN), XT_FORTH_WORDLIST,
01534 H15('S','E','A','R','C','H','-','W','O','R','D','L','I','S','T',13),
01535 XT_PAREN_SEARCH_WORDLIST, XT_0BRANCH(8),
01536 XT_0BRANCH(4), LIT(1), XT_EXIT, XT_TRUE, XT_EXIT,
01537 XT_2DROP, XT_FALSE, XT_EXIT,
01538
01539
01540
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
01548
01549
01550 H2('.','S',18),
01551 (CELL)XT_CR, XT_DEPTH, LIT(StackCells), XT_MIN,
01552 XT_FALSE, XT_MAX, XT_DUP, XT_0BRANCH(7),
01553 XT_DUP, XT_PICK, (CELL)XT_DOT, XT_1_MINUS,
01554 XT_BRANCH(-8), XT_DROP, XT_EXIT,
01555 H5('A','H','E','A','D',TOKEN), (CELL)XT_AHEAD,
01556 H3('B','Y','E',TOKEN), XT_END,
01557
01558
01559
01560
01561
01562 H7('C','O','N','T','E','X','T',TOKEN), XT_CONTEXT,
01563 H7('C','U','R','R','E','N','T',TOKEN), XT_CURRENT,
01564 H6('L','A','T','E','S','T',TOKEN), XT_LATEST,
01565 H8('(','s','o','u','r','c','e',')',TOKEN), XT_PAREN_SOURCE,
01566 H9('I','N','T','E','R','P','R','E','T',TOKEN), (CELL)XT_INTERPRET,
01567 H10('B','R','E','A','K','P','O','I','N','T',TOKEN), XT_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
01767 CELL* end = MemoryEnd;
01768 CELL* ptr = (CELL*)(&this->MemoryEnd+1);
01769 while(ptr<end) *ptr++=0;
01770
01771
01772 end -= (NumberTIB*sizeof(CHAR)+(sizeof(CELL)-1))/sizeof(CELL);
01773
01774
01775 Rp0 = end;
01776 Rp = end;
01777 end -= ReturnStackCells;
01778
01779 Sp0 = end;
01780 Sp = end;
01781 end -= StackCells;
01782
01783
01784 DpLimit = (UCELL)end-DictionaryOverhead;
01785 Dp = (CHAR*)(this+1);
01786 if((UCELL)Dp>=DpLimit)
01787 return false;
01788 Base = 10;
01789
01790
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
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
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; }
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
01901 case XT_PAREN_QUESTION_DO: if(t==*sp) { t = sp[1]; sp+=2; BRANCH; }
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;
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
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;
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;
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);
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
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]);
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
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;
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
01972 case XT_QUESTION_DUP: if(!t) NEXT;
01973 case XT_DUP: PUSH(t); NEXT;
01974 case XT_2DROP: ++sp;
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);
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
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);
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
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
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=~' ';
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
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
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
02043 case XT_SPACE: PUSH(t); t=' ';
02044 case XT_EMIT: x = (CELL)((CHAR*)rp-1); *(CHAR*)x=(CHAR)t; PUSH(x); t=1;
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
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;
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;
02086 BREAKPOINT;
02087 }
02088 State = 0;
02089 return exceptionNumber;
02090 }
02091
02092
02093 void ForthVM::MultiplyPrimitive(CELL* sp)
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)
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)
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)
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)
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)
02296 return len;
02297 if(c==0x08 || c==0x7f)
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
02318
02319
02320
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