![]() ![]() | ![]() |
Changed format to Gforth2x (0.4 or greater)
1: \ CROSS.FS The Cross-Compiler 06oct92py 2: \ Idea and implementation: Bernd Paysan (py) 3: 4: \ Copyright (C) 1995,1996,1997,1998 Free Software Foundation, Inc. 5: 6: \ This file is part of Gforth. 7: 8: \ Gforth is free software; you can redistribute it and/or 9: \ modify it under the terms of the GNU General Public License 10: \ as published by the Free Software Foundation; either version 2 11: \ of the License, or (at your option) any later version. 12: 13: \ This program is distributed in the hope that it will be useful, 14: \ but WITHOUT ANY WARRANTY; without even the implied warranty of 15: \ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16: \ GNU General Public License for more details. 17: 18: \ You should have received a copy of the GNU General Public License 19: \ along with this program; if not, write to the Free Software 20: \ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21: 22: \ Log: 23: \ changed in ; [ to state off 12may93jaw 24: \ included place +place 12may93jaw 25: \ for a created word (variable, constant...) 26: \ is now an alias in the target voabulary. 27: \ this means it is no longer necessary to 28: \ switch between vocabularies for variable 29: \ initialization 12may93jaw 30: \ discovered error in DOES> 31: \ replaced !does with (;code) 16may93jaw 32: \ made complete redesign and 33: \ introduced two vocs method 34: \ to be asure that the right words 35: \ are found 08jun93jaw 36: \ btw: ! works not with 16 bit 37: \ targets 09jun93jaw 38: \ added: 2user and value 11jun93jaw 39: 40: \ needed? works better now!!! 01mar97jaw 41: \ mach file is only loaded into target 42: \ cell corrected 43: \ romable extansions 27apr97-5jun97jaw 44: \ environmental query support 01sep97jaw 45: \ added own [IF] ... [ELSE] ... [THEN] 14sep97jaw 46: \ extra resolver for doers 20sep97jaw 47: \ added killref for DOES> 20sep97jaw 48: 49: 50: hex \ the defualt base for the cross-compiler is hex !! 51: Warnings off 52: 53: \ words that are generaly useful 54: 55: : KB 400 * ; 56: : >wordlist ( vocabulary-xt -- wordlist-struct ) 57: also execute get-order swap >r 1- set-order r> ; 58: 59: : umax 2dup u< IF swap THEN drop ; 60: : umin 2dup u> IF swap THEN drop ; 61: 62: : string, ( c-addr u -- ) 63: \ puts down string as cstring 64: dup c, here swap chars dup allot move ; 65: 66: : SetValue ( n -- <name> ) 67: \G Same behaviour as "Value" if the <name> is not defined 68: \G Same behaviour as "to" if <name> is defined 69: \G SetValue searches in the current vocabulary 70: save-input bl word >r restore-input throw r> count 71: get-current search-wordlist 72: IF ['] to execute ELSE Value THEN ; 73: 74: : DefaultValue ( n -- <name> ) 75: \G Same behaviour as "Value" if the <name> is not defined 76: \G DefaultValue searches in the current vocabulary 77: save-input bl word >r restore-input throw r> count 78: get-current search-wordlist 79: IF bl word drop 2drop ELSE Value THEN ; 80: 81: hex 82: 83: Vocabulary Cross 84: Vocabulary Target 85: Vocabulary Ghosts 86: VOCABULARY Minimal 87: only Forth also Target also also 88: definitions Forth 89: 90: : T previous Cross also Target ; immediate 91: : G Ghosts ; immediate 92: : H previous Forth also Cross ; immediate 93: 94: forth definitions 95: 96: : T previous Cross also Target ; immediate 97: : G Ghosts ; immediate 98: 99: : >cross also Cross definitions previous ; 100: : >target also Target definitions previous ; 101: : >minimal also Minimal definitions previous ; 102: 103: H 104: 105: >CROSS 106: 107: \ 1 Constant Cross-Flag \ to check whether assembler compiler plug-ins are 108: \ for cross-compiling 109: \ No! we use "[IFUNDEF]" there to find out whether we are target compiling!!! 110: 111: : comment? ( c-addr u -- c-addr u ) 112: 2dup s" (" compare 0= 113: IF postpone ( 114: ELSE 2dup s" \" compare 0= IF postpone \ THEN 115: THEN ; 116: 117: \ Begin CROSS COMPILER: 118: 119: 120: 121: \ \ -------------------- Error Handling 05aug97jaw 122: 123: \ Flags 124: 125: also forth definitions \ these values may be predefined before 126: \ the cross-compiler is loaded 127: 128: false DefaultValue stack-warn \ check on empty stack at any definition 129: false DefaultValue create-forward-warn \ warn on forward declaration of created words 130: 131: [IFUNDEF] DebugMaskSrouce Variable DebugMaskSource 0 DebugMaskSource ! [THEN] 132: [IFUNDEF] DebugMaskCross Variable DebugMaskCross 0 DebugMaskCross ! [THEN] 133: 134: previous >CROSS 135: 136: : .dec 137: base @ decimal swap . base ! ; 138: 139: : .sourcepos 140: cr sourcefilename type ." :" 141: sourceline# .dec ; 142: 143: : warnhead 144: \G display error-message head 145: \G perhaps with linenumber and filename 146: .sourcepos ." Warning: " ; 147: 148: : empty? depth IF .sourcepos ." Stack not empty!" THEN ; 149: 150: stack-warn [IF] 151: : defempty? empty? ; 152: [ELSE] 153: : defempty? ; immediate 154: [THEN] 155: 156: 157: 158: \ \ GhostNames Ghosts 9may93jaw 159: 160: \ second name source to search trough list 161: 162: VARIABLE GhostNames 163: 0 GhostNames ! 164: 165: : GhostName ( -- addr ) 166: here GhostNames @ , GhostNames ! here 0 , 167: bl word count 168: \ 2dup type space 169: string, \ !! cfalign ? 170: align ; 171: 172: \ Ghost Builder 06oct92py 173: 174: \ <T T> new version with temp variable 10may93jaw 175: 176: VARIABLE VocTemp 177: 178: : <T get-current VocTemp ! also Ghosts definitions ; 179: : T> previous VocTemp @ set-current ; 180: 181: hex 182: 4711 Constant <fwd> 4712 Constant <res> 183: 4713 Constant <imm> 4714 Constant <do:> 184: 185: \ iForth makes only immediate directly after create 186: \ make atonce trick! ? 187: 188: Variable atonce atonce off 189: 190: : NoExec true ABORT" CROSS: Don't execute ghost" ; 191: 192: : GhostHeader <fwd> , 0 , ['] NoExec , ; 193: 194: : >magic ; \ type of ghost 195: : >link cell+ ; \ pointer where ghost is in target, or if unresolved 196: \ points to the where we have to resolve (linked-list) 197: : >exec cell+ cell+ ; \ execution symantics (while target compiling) of ghost 198: : >end 3 cells + ; \ room for additional tags 199: \ for builder (create, variable...) words the 200: \ execution symantics of words built are placed here 201: 202: Variable executed-ghost \ last executed ghost, needed in tcreate and gdoes> 203: Variable last-ghost \ last ghost that is created 204: Variable last-header-ghost \ last ghost definitions with header 205: 206: : Make-Ghost ( "name" -- ghost ) 207: >in @ GhostName swap >in ! 208: <T Create atonce @ IF immediate atonce off THEN 209: here tuck swap ! ghostheader T> 210: dup last-ghost ! 211: DOES> dup executed-ghost ! >exec @ execute ; 212: 213: \ ghost words 14oct92py 214: \ changed: 10may93py/jaw 215: 216: : gfind ( string -- ghost true/1 / string false ) 217: \ searches for string in word-list ghosts 218: dup count [ ' ghosts >wordlist ] ALiteral search-wordlist 219: dup IF >r >body nip r> THEN ; 220: 221: : gdiscover ( xt -- ghost true | xt false ) 222: GhostNames 223: BEGIN @ dup 224: WHILE 2dup 225: cell+ @ dup >magic @ <fwd> <> 226: >r >link @ = r> and 227: IF cell+ @ nip true EXIT THEN 228: REPEAT 229: drop false ; 230: 231: VARIABLE Already 232: 233: : ghost ( "name" -- ghost ) 234: Already off 235: >in @ bl word gfind IF Already on nip EXIT THEN 236: drop >in ! Make-Ghost ; 237: 238: : >ghostname ( ghost -- adr len ) 239: GhostNames 240: BEGIN @ dup 241: WHILE 2dup cell+ @ = 242: UNTIL nip 2 cells + count 243: ELSE 2drop 244: \ true abort" CROSS: Ghostnames inconsistent" 245: s" ?!?!?!" 246: THEN ; 247: 248: ' >ghostname ALIAS @name 249: 250: : forward? ( ghost -- flag ) 251: >magic @ <fwd> = ; 252: 253: \ Predefined ghosts 12dec92py 254: 255: ghost 0= drop 256: ghost branch ghost ?branch 2drop 257: ghost (do) ghost (?do) 2drop 258: ghost (for) drop 259: ghost (loop) ghost (+loop) 2drop 260: ghost (next) drop 261: ghost unloop ghost ;S 2drop 262: ghost lit ghost (compile) ghost ! 2drop drop 263: ghost (does>) ghost noop 2drop 264: ghost (.") ghost (S") ghost (ABORT") 2drop drop 265: ghost ' drop 266: ghost :docol ghost :doesjump ghost :dodoes 2drop drop 267: ghost :dovar drop 268: ghost over ghost = ghost drop 2drop drop 269: ghost - drop 270: ghost 2drop drop 271: ghost 2dup drop 272: 273: \ \ Parameter for target systems 06oct92py 274: 275: \ we define it ans like... 276: wordlist Constant target-environment 277: 278: VARIABLE env-current \ save information of current dictionary to restore with environ> 279: 280: : >ENVIRON get-current env-current ! target-environment set-current ; 281: : ENVIRON> env-current @ set-current ; 282: 283: >TARGET 284: 285: : environment? 286: target-environment search-wordlist 287: IF execute true ELSE false THEN ; 288: 289: : e? name T environment? H 0= ABORT" environment variable not defined!" ; 290: 291: : has? name T environment? H 292: IF \ environment variable is present, return its value 293: ELSE \ environment variable is not present, return false 294: \ !! JAW abort is just for testing 295: false true ABORT" arg" 296: THEN ; 297: 298: : $has? T environment? H IF ELSE false THEN ; 299: 300: >ENVIRON get-order get-current swap 1+ set-order 301: true SetValue compiler 302: true SetValue cross 303: true SetValue standard-threading 304: >TARGET previous 305: 306: 307: mach-file count included hex 308: 309: >ENVIRON 310: 311: T has? ec H 312: [IF] 313: false DefaultValue relocate 314: false DefaultValue file 315: false DefaultValue OS 316: false DefaultValue prims 317: false DefaultValue floating 318: false DefaultValue glocals 319: false DefaultValue dcomps 320: false DefaultValue hash 321: false DefaultValue xconds 322: false DefaultValue header 323: [THEN] 324: 325: true DefaultValue interpreter 326: true DefaultValue ITC 327: false DefaultValue rom 328: 329: >TARGET 330: s" relocate" T environment? H 331: [IF] SetValue NIL 332: [ELSE] >ENVIRON T NIL H SetValue relocate 333: [THEN] 334: 335: >CROSS 336: 337: \ \ Create additional parameters 19jan95py 338: 339: 1 8 lshift Constant maxbyte 340: T 341: NIL Constant TNIL 342: cell Constant tcell 343: cell<< Constant tcell<< 344: cell>bit Constant tcell>bit 345: bits/byte Constant tbits/byte 346: bits/byte 8 / Constant tchar 347: float Constant tfloat 348: 1 bits/byte lshift Constant tmaxbyte 349: H 350: 351: \ Variables 06oct92py 352: 353: Variable image 354: Variable tlast TNIL tlast ! \ Last name field 355: Variable tlastcfa \ Last code field 356: Variable tdoes \ Resolve does> calls 357: Variable bit$ 358: 359: \ statistics 10jun97jaw 360: 361: Variable headers-named 0 headers-named ! 362: Variable user-vars 0 user-vars ! 363: 364: \ Memory initialisation 05dec92py 365: 366: [IFDEF] Memory \ Memory is a bigFORTH feature 367: also Memory 368: : initmem ( var len -- ) 369: 2dup swap handle! >r @ r> erase ; 370: toss 371: [ELSE] 372: : initmem ( var len -- ) 373: tuck allocate abort" CROSS: No memory for target" 374: ( len var adr ) dup rot ! 375: ( len adr ) swap erase ; 376: [THEN] 377: 378: \ MakeKernal 12dec92py 379: 380: : makekernel ( targetsize -- targetsize ) 381: bit$ over 1- tcell>bit rshift 1+ initmem 382: image over initmem ; 383: 384: >MINIMAL 385: : makekernel makekernel ; 386: 387: 388: >CROSS 389: 390: \ \ memregion.fs 391: 392: 393: Variable last-defined-region \ pointer to last defined region 394: Variable region-link \ linked list with all regions 395: Variable mirrored-link \ linked list for mirrored regions 396: 0 dup mirrored-link ! region-link ! 397: 398: 399: : >rdp 2 cells + ; 400: : >rlen cell+ ; 401: : >rstart ; 402: 403: 404: : region ( addr len -- ) \G create a new region 405: \ check whether predefined region exists 406: save-input bl word find >r >r restore-input throw r> r> 0= 407: IF \ make region 408: drop 409: save-input create restore-input throw 410: here last-defined-region ! 411: over ( startaddr ) , ( length ) , ( dp ) , 412: region-link linked name string, 413: ELSE \ store new parameters in region 414: bl word drop 415: >body >r r@ last-defined-region ! 416: r@ cell+ ! dup r@ ! r> 2 cells + ! 417: THEN ; 418: 419: : borders ( region -- startaddr endaddr ) \G returns lower and upper region border 420: dup @ swap cell+ @ over + ; 421: 422: : extent ( region -- startaddr len ) \G returns the really used area 423: dup @ swap 2 cells + @ over - ; 424: 425: : area ( region -- startaddr totallen ) \G returns the total area 426: dup @ swap cell+ @ ; 427: 428: : mirrored \G mark a region as mirrored 429: mirrored-link 430: linked last-defined-region @ , ; 431: 432: : .addr 433: base @ >r hex 434: tcell 2 u> 435: IF s>d <# # # # # '. hold # # # # #> type 436: ELSE s>d <# # # # # # #> type 437: THEN r> base ! ; 438: 439: : .regions \G display region statistic 440: 441: \ we want to list the regions in the right order 442: \ so first collect all regions on stack 443: 0 region-link @ 444: BEGIN dup WHILE dup @ REPEAT drop 445: BEGIN dup 446: WHILE cr 3 cells - >r 447: r@ 4 cells + count tuck type 448: 12 swap - 0 max spaces space 449: ." Start: " r@ @ dup .addr space 450: ." End: " r@ 1 cells + @ + .addr space 451: ." DP: " r> 2 cells + @ .addr 452: REPEAT drop 453: s" rom" T $has? H 0= ?EXIT 454: cr ." Mirrored:" 455: mirrored-link @ 456: BEGIN dup 457: WHILE space dup cell+ @ 4 cells + count type @ 458: REPEAT drop cr 459: ; 460: 461: \ -------- predefined regions 462: 463: 0 0 region address-space 464: \ total memory addressed and used by the target system 465: 466: 0 0 region dictionary 467: \ rom area for the compiler 468: 469: T has? rom H 470: [IF] 471: 0 0 region ram-dictionary mirrored 472: \ ram area for the compiler 473: [ELSE] 474: ' dictionary ALIAS ram-dictionary 475: [THEN] 476: 477: 0 0 region return-stack 478: 479: 0 0 region data-stack 480: 481: 0 0 region tib-region 482: 483: ' dictionary ALIAS rom-dictionary 484: 485: 486: : setup-target ( -- ) \G initialize targets memory space 487: s" rom" T $has? H 488: IF \ check for ram and rom... 489: address-space area nip 490: ram-dictionary area nip 491: rom-dictionary area nip 492: and and 0= 493: ABORT" CROSS: define address-space, rom- , ram-dictionary, with rom-support!" 494: THEN 495: address-space area nip 496: IF 497: address-space area 498: ELSE 499: dictionary area 500: THEN 501: dup 0= 502: ABORT" CROSS: define at least address-space or dictionary!!" 503: + makekernel drop ; 504: 505: \ \ switched tdp for rom support 03jun97jaw 506: 507: \ second value is here to store some maximal value for statistics 508: \ tempdp is also embedded here but has nothing to do with rom support 509: \ (needs switched dp) 510: 511: variable tempdp 0 , \ temporary dp for resolving 512: variable tempdp-save 513: 514: 0 [IF] 515: variable romdp 0 , \ Dictionary-Pointer for ramarea 516: variable ramdp 0 , \ Dictionary-Pointer for romarea 517: 518: \ 519: variable sramdp \ start of ram-area for forth 520: variable sromdp \ start of rom-area for forth 521: 522: [THEN] 523: 524: 525: 0 value tdp 526: variable fixed \ flag: true: no automatic switching 527: \ false: switching is done automatically 528: 529: \ Switch-Policy: 530: \ 531: \ a header is always compiled into rom 532: \ after a created word (create and variable) compilation goes to ram 533: \ 534: \ Be careful: If you want to make the data behind create into rom 535: \ you have to put >rom before create! 536: 537: variable constflag constflag off 538: 539: : (switchram) 540: fixed @ ?EXIT s" rom" T $has? H 0= ?EXIT 541: ram-dictionary >rdp to tdp ; 542: 543: : switchram 544: constflag @ 545: IF constflag off ELSE (switchram) THEN ; 546: 547: : switchrom 548: fixed @ ?EXIT rom-dictionary >rdp to tdp ; 549: 550: : >tempdp ( addr -- ) 551: tdp tempdp-save ! tempdp to tdp tdp ! ; 552: : tempdp> ( -- ) 553: tempdp-save @ to tdp ; 554: 555: : >ram fixed off (switchram) fixed on ; 556: : >rom fixed off switchrom fixed on ; 557: : >auto fixed off switchrom ; 558: 559: 560: 561: \ : romstart dup sromdp ! romdp ! ; 562: \ : ramstart dup sramdp ! ramdp ! ; 563: 564: \ default compilation goed to rom 565: \ when romable support is off, only the rom switch is used (!!) 566: >auto 567: 568: : there tdp @ ; 569: 570: >TARGET 571: 572: \ \ Target Memory Handling 573: 574: \ Byte ordering and cell size 06oct92py 575: 576: : cell+ tcell + ; 577: : cells tcell<< lshift ; 578: : chars ; 579: : char+ 1 + ; 580: : floats tfloat * ; 581: 582: >CROSS 583: : cell/ tcell<< rshift ; 584: >TARGET 585: 20 CONSTANT bl 586: \ TNIL Constant NIL 587: 588: >CROSS 589: 590: bigendian 591: [IF] 592: : S! ( n addr -- ) >r s>d r> tcell bounds swap 1- 593: DO maxbyte ud/mod rot I c! -1 +LOOP 2drop ; 594: : S@ ( addr -- n ) >r 0 0 r> tcell bounds 595: DO maxbyte * swap maxbyte um* rot + swap I c@ + swap LOOP d>s ; 596: : Sc! ( n addr -- ) >r s>d r> tchar bounds swap 1- 597: DO maxbyte ud/mod rot I c! -1 +LOOP 2drop ; 598: : Sc@ ( addr -- n ) >r 0 0 r> tchar bounds 599: DO maxbyte * swap maxbyte um* rot + swap I c@ + swap LOOP d>s ; 600: [ELSE] 601: : S! ( n addr -- ) >r s>d r> tcell bounds 602: DO maxbyte ud/mod rot I c! LOOP 2drop ; 603: : S@ ( addr -- n ) >r 0 0 r> tcell bounds swap 1- 604: DO maxbyte * swap maxbyte um* rot + swap I c@ + swap -1 +LOOP d>s ; 605: : Sc! ( n addr -- ) >r s>d r> tchar bounds 606: DO maxbyte ud/mod rot I c! LOOP 2drop ; 607: : Sc@ ( addr -- n ) >r 0 0 r> tchar bounds swap 1- 608: DO maxbyte * swap maxbyte um* rot + swap I c@ + swap -1 +LOOP d>s ; 609: [THEN] 610: 611: >CROSS 612: \ Bit string manipulation 06oct92py 613: \ 9may93jaw 614: CREATE Bittable 80 c, 40 c, 20 c, 10 c, 8 c, 4 c, 2 c, 1 c, 615: : bits ( n -- n ) chars Bittable + c@ ; 616: 617: : >bit ( addr n -- c-addr mask ) 8 /mod rot + swap bits ; 618: : +bit ( addr n -- ) >bit over c@ or swap c! ; 619: : -bit ( addr n -- ) >bit invert over c@ and swap c! ; 620: : relon ( taddr -- ) bit$ @ swap cell/ +bit ; 621: : reloff ( taddr -- ) bit$ @ swap cell/ -bit ; 622: 623: \ Target memory access 06oct92py 624: 625: : align+ ( taddr -- rest ) 626: tcell tuck 1- and - [ tcell 1- ] Literal and ; 627: : cfalign+ ( taddr -- rest ) 628: \ see kernel.fs:cfaligned 629: /maxalign tuck 1- and - [ /maxalign 1- ] Literal and ; 630: 631: >TARGET 632: : aligned ( taddr -- ta-addr ) dup align+ + ; 633: \ assumes cell alignment granularity (as GNU C) 634: 635: : cfaligned ( taddr1 -- taddr2 ) 636: \ see kernel.fs 637: dup cfalign+ + ; 638: 639: >CROSS 640: : >image ( taddr -- absaddr ) image @ + ; 641: >TARGET 642: : @ ( taddr -- w ) >image S@ ; 643: : ! ( w taddr -- ) >image S! ; 644: : c@ ( taddr -- char ) >image Sc@ ; 645: : c! ( char taddr -- ) >image Sc! ; 646: : 2@ ( taddr -- x1 x2 ) T dup cell+ @ swap @ H ; 647: : 2! ( x1 x2 taddr -- ) T swap over ! cell+ ! H ; 648: 649: \ Target compilation primitives 06oct92py 650: \ included A! 16may93jaw 651: 652: : here ( -- there ) there ; 653: : allot ( n -- ) tdp +! ; 654: : , ( w -- ) T here H tcell T allot ! H T here drop H ; 655: : c, ( char -- ) T here tchar allot c! H ; 656: : align ( -- ) T here H align+ 0 ?DO bl T c, H LOOP ; 657: : cfalign ( -- ) 658: T here H cfalign+ 0 ?DO bl T c, tchar H +LOOP ; 659: 660: : >address dup 0>= IF tchar / THEN ; 661: : A! swap >address swap dup relon T ! H ; 662: : A, ( w -- ) >address T here H relon T , H ; 663: 664: >CROSS 665: 666: : tcmove ( source dest len -- ) 667: \G cmove in target memory 668: tchar * bounds 669: ?DO dup T c@ H I T c! H 1+ 670: tchar +LOOP drop ; 671: 672: >TARGET 673: H also Forth definitions \ ." asm: " order 674: 675: : X also target bl word find 676: IF state @ IF compile, 677: ELSE execute THEN 678: ELSE previous ABORT" Cross: access method not supported!" 679: THEN 680: previous ; immediate 681: 682: [IFDEF] asm-include asm-include [THEN] hex 683: 684: previous 685: >CROSS H 686: 687: \ \ -------------------- Compiler Plug Ins 01aug97jaw 688: 689: \ Compiler States 690: 691: Variable comp-state 692: 0 Constant interpreting 693: 1 Constant compiling 694: 2 Constant resolving 695: 3 Constant assembling 696: 697: Defer lit, ( n -- ) 698: Defer alit, ( n -- ) 699: 700: Defer branch, ( target-addr -- ) \ compiles a branch 701: Defer ?branch, ( target-addr -- ) \ compiles a ?branch 702: Defer branchmark, ( -- branch-addr ) \ reserves room for a branch 703: Defer ?branchmark, ( -- branch-addr ) \ reserves room for a ?branch 704: Defer ?domark, ( -- branch-addr ) \ reserves room for a ?do branch 705: Defer branchto, ( -- ) \ actual program position is target of a branch (do e.g. alignment) 706: Defer branchtoresolve, ( branch-addr -- ) \ resolves a forward reference from branchmark 707: Defer branchfrom, ( -- ) \ ?! 708: Defer branchtomark, ( -- target-addr ) \ marks a branch destination 709: 710: Defer colon, ( tcfa -- ) \ compiles call to tcfa at current position 711: Defer colonmark, ( -- addr ) \ marks a colon call 712: Defer colon-resolve ( tcfa addr -- ) 713: 714: Defer addr-resolve ( target-addr addr -- ) 715: Defer doer-resolve ( ghost res-pnt target-addr addr -- ghost res-pnt ) 716: 717: Defer do, ( -- do-token ) 718: Defer ?do, ( -- ?do-token ) 719: Defer for, ( -- for-token ) 720: Defer loop, ( do-token / ?do-token -- ) 721: Defer +loop, ( do-token / ?do-token -- ) 722: Defer next, ( for-token ) 723: 724: [IFUNDEF] ca>native 725: defer ca>native 726: [THEN] 727: 728: >TARGET 729: DEFER >body \ we need the system >body 730: \ and the target >body 731: >CROSS 732: T 2 cells H VALUE xt>body 733: DEFER doprim, \ compiles start of a primitive 734: DEFER docol, \ compiles start of a colon definition 735: DEFER doer, 736: DEFER fini, \ compiles end of definition ;s 737: DEFER doeshandler, 738: DEFER dodoes, 739: 740: DEFER ]comp \ starts compilation 741: DEFER comp[ \ ends compilation 742: 743: : (cc) T a, H ; ' (cc) IS colon, 744: 745: : (cr) >tempdp ]comp colon, comp[ tempdp> ; ' (cr) IS colon-resolve 746: : (ar) T ! H ; ' (ar) IS addr-resolve 747: : (dr) ( ghost res-pnt target-addr addr ) 748: >tempdp drop over 749: dup >magic @ <do:> = 750: IF doer, 751: ELSE dodoes, 752: THEN 753: tempdp> ; ' (dr) IS doer-resolve 754: 755: : (cm) ( -- addr ) 756: T here align H 757: -1 colon, ; ' (cm) IS colonmark, 758: 759: >TARGET 760: : compile, colon, ; 761: >CROSS 762: 763: \ file loading 764: 765: : >fl-id 1 cells + ; 766: : >fl-name 2 cells + ; 767: 768: Variable filelist 0 filelist ! 769: 0 Value filemem 770: : loadfile filemem >fl-name ; 771: 772: 1 [IF] \ !! JAW WIP 773: 774: : add-included-file ( adr len -- ) 775: dup char+ >fl-name allocate throw >r 776: r@ >fl-name place 777: filelist @ r@ ! 778: r> dup filelist ! to FileMem 779: ; 780: 781: : included? ( c-addr u -- f ) 782: filelist 783: BEGIN @ dup 784: WHILE >r r@ 1 cells + count compare 0= 785: IF rdrop 2drop true EXIT THEN 786: r> 787: REPEAT 788: 2drop drop false ; 789: 790: : included 791: \ cr ." Including: " 2dup type ." ..." 792: FileMem >r 793: 2dup add-included-file included 794: r> to FileMem ; 795: 796: : include bl word count included ; 797: 798: : require bl word count included ; 799: 800: [THEN] 801: 802: \ resolve structure 803: 804: : >next ; \ link to next field 805: : >tag cell+ ; \ indecates type of reference: 0: call, 1: address, 2: doer 806: : >taddr cell+ cell+ ; 807: : >ghost 3 cells + ; 808: : >file 4 cells + ; 809: : >line 5 cells + ; 810: 811: : (refered) ( ghost addr tag -- ) 812: \G creates a reference to ghost at address taddr 813: rot >r here r@ >link @ , r> >link ! 814: ( taddr tag ) , 815: ( taddr ) , 816: last-header-ghost @ , 817: loadfile , 818: sourceline# , 819: ; 820: 821: : refered ( ghost tag -- ) 822: \G creates a resolve structure 823: T here aligned H swap (refered) 824: ; 825: 826: : killref ( addr ghost -- ) 827: \G kills a forward reference to ghost at position addr 828: \G this is used to eleminate a :dovar refence after making a DOES> 829: dup >magic @ <fwd> <> IF 2drop EXIT THEN 830: swap >r >link 831: BEGIN dup @ dup ( addr last this ) 832: WHILE dup >taddr @ r@ = 833: IF @ over ! 834: ELSE nip THEN 835: REPEAT rdrop 2drop 836: ; 837: 838: Defer resolve-warning 839: 840: : reswarn-test ( ghost res-struct -- ghost res-struct ) 841: over cr ." Resolving " >ghostname type dup ." in " >ghost @ >ghostname type ; 842: 843: : reswarn-forward ( ghost res-struct -- ghost res-struct ) 844: over warnhead >ghostname type dup ." is referenced in " 845: >ghost @ >ghostname type ; 846: 847: \ ' reswarn-test IS resolve-warning 848: 849: \ resolve 14oct92py 850: 851: : resolve-loop ( ghost resolve-list tcfa -- ) 852: >r 853: BEGIN dup WHILE 854: \ dup >tag @ 2 = IF reswarn-forward THEN 855: resolve-warning 856: r@ over >taddr @ 857: 2 pick >tag @ 858: CASE 0 OF colon-resolve ENDOF 859: 1 OF addr-resolve ENDOF 860: 2 OF doer-resolve ENDOF 861: ENDCASE 862: @ \ next list element 863: REPEAT 2drop rdrop 864: ; 865: 866: \ : resolve-loop ( ghost tcfa -- ghost tcfa ) 867: \ >r dup >link @ 868: \ BEGIN dup WHILE dup T @ H r@ rot T ! H REPEAT drop r> ; 869: 870: \ exists 9may93jaw 871: 872: Variable TWarnings 873: TWarnings on 874: Variable Exists-Warnings 875: Exists-Warnings on 876: 877: : exists ( ghost tcfa -- ) 878: over GhostNames 879: BEGIN @ dup 880: WHILE 2dup cell+ @ = 881: UNTIL 882: 2 cells + count 883: TWarnings @ Exists-Warnings @ and 884: IF warnhead type ." exists" 885: ELSE 2drop THEN 886: drop swap >link ! 887: ELSE true abort" CROSS: Ghostnames inconsistent " 888: THEN ; 889: 890: : resolve ( ghost tcfa -- ) 891: \G resolve referencies to ghost with tcfa 892: \ is ghost resolved?, second resolve means another definition with the 893: \ same name 894: over forward? 0= IF exists EXIT THEN 895: \ get linked-list 896: swap >r r@ >link @ swap \ ( list tcfa R: ghost ) 897: \ mark ghost as resolved 898: dup r@ >link ! <res> r@ >magic ! 899: \ loop through forward referencies 900: r> -rot 901: comp-state @ >r Resolving comp-state ! 902: resolve-loop 903: r> comp-state ! 904: 905: ['] noop IS resolve-warning 906: ; 907: 908: \ gexecute ghost, 01nov92py 909: 910: : is-forward ( ghost -- ) 911: colonmark, 0 (refered) ; \ compile space for call 912: 913: : is-resolved ( ghost -- ) 914: >link @ colon, ; \ compile-call 915: 916: : gexecute ( ghost -- ) 917: dup @ <fwd> = IF is-forward ELSE is-resolved THEN ; 918: 919: : addr, ( ghost -- ) 920: dup @ <fwd> = IF 1 refered 0 T a, H ELSE >link @ T a, H THEN ; 921: 922: \ !! : ghost, ghost gexecute ; 923: 924: \ .unresolved 11may93jaw 925: 926: variable ResolveFlag 927: 928: \ ?touched 11may93jaw 929: 930: : ?touched ( ghost -- flag ) dup forward? swap >link @ 931: 0 <> and ; 932: 933: : .forwarddefs ( ghost -- ) 934: ." appeared in:" 935: >link 936: BEGIN @ dup 937: WHILE cr 5 spaces 938: dup >ghost @ >ghostname type 939: ." file " dup >file @ ?dup IF count type ELSE ." CON" THEN 940: ." line " dup >line @ .dec 941: REPEAT 942: drop ; 943: 944: : ?resolved ( ghostname -- ) 945: dup cell+ @ ?touched 946: IF dup 947: cell+ cell+ count cr type ResolveFlag on 948: cell+ @ .forwarddefs 949: ELSE drop 950: THEN ; 951: 952: >MINIMAL 953: : .unresolved ( -- ) 954: ResolveFlag off cr ." Unresolved: " 955: Ghostnames 956: BEGIN @ dup 957: WHILE dup ?resolved 958: REPEAT drop ResolveFlag @ 959: IF 960: -1 abort" Unresolved words!" 961: ELSE 962: ." Nothing!" 963: THEN 964: cr ; 965: 966: : .stats 967: base @ >r decimal 968: cr ." named Headers: " headers-named @ . 969: r> base ! ; 970: 971: >CROSS 972: \ Header states 12dec92py 973: 974: : flag! ( 8b -- ) tlast @ dup >r T c@ xor r> c! H ; 975: 976: VARIABLE ^imm 977: 978: >TARGET 979: : immediate 40 flag! 980: ^imm @ @ dup <imm> = IF drop EXIT THEN 981: <res> <> ABORT" CROSS: Cannot immediate a unresolved word" 982: <imm> ^imm @ ! ; 983: : restrict 20 flag! ; 984: 985: : isdoer 986: \G define a forth word as doer, this makes obviously only sence on 987: \G forth processors such as the PSC1000 988: <do:> last-header-ghost @ >magic ! ; 989: >CROSS 990: 991: \ ALIAS2 ansforth conform alias 9may93jaw 992: 993: : ALIAS2 create here 0 , DOES> @ execute ; 994: \ usage: 995: \ ' <name> alias2 bla ! 996: 997: \ Target Header Creation 01nov92py 998: 999: >TARGET 1000: : string, ( addr count -- ) 1001: dup T c, H bounds ?DO I c@ T c, H LOOP ; 1002: : name, ( "name" -- ) bl word count T string, cfalign H ; 1003: : view, ( -- ) ( dummy ) ; 1004: >CROSS 1005: 1006: \ Target Document Creation (goes to crossdoc.fd) 05jul95py 1007: 1008: s" ./doc/crossdoc.fd" r/w create-file throw value doc-file-id 1009: \ contains the file-id of the documentation file 1010: 1011: : T-\G ( -- ) 1012: source >in @ /string doc-file-id write-line throw 1013: postpone \ ; 1014: 1015: Variable to-doc to-doc on 1016: 1017: : cross-doc-entry ( -- ) 1018: to-doc @ tlast @ 0<> and \ not an anonymous (i.e. noname) header 1019: IF 1020: s" " doc-file-id write-line throw 1021: s" make-doc " doc-file-id write-file throw 1022: tlast @ >image count $1F and doc-file-id write-file throw 1023: >in @ 1024: [char] ( parse 2drop 1025: [char] ) parse doc-file-id write-file throw 1026: s" )" doc-file-id write-file throw 1027: [char] \ parse 2drop 1028: T-\G 1029: >in ! 1030: THEN ; 1031: 1032: \ Target TAGS creation 1033: 1034: s" kernel.TAGS" r/w create-file throw value tag-file-id 1035: \ contains the file-id of the tags file 1036: 1037: Create tag-beg 2 c, 7F c, bl c, 1038: Create tag-end 2 c, bl c, 01 c, 1039: Create tag-bof 1 c, 0C c, 1040: 1041: 2variable last-loadfilename 0 0 last-loadfilename 2! 1042: 1043: : put-load-file-name ( -- ) 1044: loadfilename 2@ last-loadfilename 2@ d<> 1045: IF 1046: tag-bof count tag-file-id write-line throw 1047: sourcefilename 2dup 1048: tag-file-id write-file throw 1049: last-loadfilename 2! 1050: s" ,0" tag-file-id write-line throw 1051: THEN ; 1052: 1053: : cross-tag-entry ( -- ) 1054: tlast @ 0<> \ not an anonymous (i.e. noname) header 1055: IF 1056: put-load-file-name 1057: source >in @ min tag-file-id write-file throw 1058: tag-beg count tag-file-id write-file throw 1059: tlast @ >image count $1F and tag-file-id write-file throw 1060: tag-end count tag-file-id write-file throw 1061: base @ decimal sourceline# 0 <# #s #> tag-file-id write-file throw 1062: \ >in @ 0 <# #s [char] , hold #> tag-file-id write-line throw 1063: s" ,0" tag-file-id write-line throw 1064: base ! 1065: THEN ; 1066: 1067: \ Check for words 1068: 1069: Defer skip? ' false IS skip? 1070: 1071: : defined? ( -- flag ) \ name 1072: ghost forward? 0= ; 1073: 1074: : needed? ( -- flag ) \ name 1075: \G returns a false flag when 1076: \G a word is not defined 1077: \G a forward reference exists 1078: \G so the definition is not skipped! 1079: bl word gfind 1080: IF dup forward? 1081: nip 1082: 0= 1083: ELSE drop true THEN ; 1084: 1085: : doer? ( -- flag ) \ name 1086: ghost >magic @ <do:> = ; 1087: 1088: : skip-defs ( -- ) 1089: BEGIN refill WHILE source -trailing nip 0= UNTIL THEN ; 1090: 1091: \ Target header creation 1092: 1093: Variable CreateFlag 1094: CreateFlag off 1095: 1096: Variable NoHeaderFlag 1097: NoHeaderFlag off 1098: 1099: : 0.r ( n1 n2 -- ) 1100: base @ >r hex 1101: 0 swap <# 0 ?DO # LOOP #> type 1102: r> base ! ; 1103: : .sym 1104: bounds 1105: DO I c@ dup 1106: CASE '/ OF drop ." \/" ENDOF 1107: '\ OF drop ." \\" ENDOF 1108: dup OF emit ENDOF 1109: ENDCASE 1110: LOOP ; 1111: 1112: : (Theader ( "name" -- ghost ) 1113: \ >in @ bl word count type 2 spaces >in ! 1114: \ wordheaders will always be compiled to rom 1115: switchrom 1116: \ build header in target 1117: NoHeaderFlag @ 1118: IF NoHeaderFlag off 1119: ELSE 1120: T align H view, 1121: tlast @ dup 0> IF T 1 cells - H THEN T A, H there tlast ! 1122: 1 headers-named +! \ Statistic 1123: >in @ T name, H >in ! 1124: THEN 1125: T cfalign here H tlastcfa ! 1126: \ Symbol table 1127: \ >in @ cr ." sym:s/CFA=" there 4 0.r ." /" bl word count .sym ." /g" cr >in ! 1128: CreateFlag @ 1129: IF 1130: >in @ alias2 swap >in ! \ create alias in target 1131: >in @ ghost swap >in ! 1132: swap also ghosts ' previous swap ! \ tick ghost and store in alias 1133: CreateFlag off 1134: ELSE ghost 1135: THEN 1136: dup Last-Header-Ghost ! 1137: dup >magic ^imm ! \ a pointer for immediate 1138: Already @ 1139: IF dup >end tdoes ! 1140: ELSE 0 tdoes ! 1141: THEN 1142: 80 flag! 1143: cross-doc-entry cross-tag-entry ; 1144: 1145: VARIABLE ;Resolve 1 cells allot 1146: \ this is the resolver information from ":" 1147: \ resolving is done by ";" 1148: 1149: : Theader ( "name" -- ghost ) 1150: (THeader dup there resolve 0 ;Resolve ! ; 1151: 1152: >TARGET 1153: : Alias ( cfa -- ) \ name 1154: >in @ skip? IF 2drop EXIT THEN >in ! 1155: dup 0< s" prims" T $has? H 0= and 1156: IF 1157: .sourcepos ." needs prim: " >in @ bl word count type >in ! cr 1158: THEN 1159: (THeader over resolve T A, H 80 flag! ; 1160: : Alias: ( cfa -- ) \ name 1161: >in @ skip? IF 2drop EXIT THEN >in ! 1162: dup 0< s" prims" T $has? H 0= and 1163: IF 1164: .sourcepos ." needs doer: " >in @ bl word count type >in ! cr 1165: THEN 1166: ghost tuck swap resolve <do:> swap >magic ! ; 1167: >CROSS 1168: 1169: \ Conditionals and Comments 11may93jaw 1170: 1171: : ;Cond 1172: postpone ; 1173: swap ! ; immediate 1174: 1175: : Cond: ( -- ) \ name {code } ; 1176: atonce on 1177: ghost 1178: >exec 1179: :NONAME ; 1180: 1181: : restrict? ( -- ) 1182: \ aborts on interprete state - ae 1183: state @ 0= ABORT" CROSS: Restricted" ; 1184: 1185: : Comment ( -- ) 1186: >in @ atonce on ghost swap >in ! ' swap >exec ! ; 1187: 1188: Comment ( Comment \ 1189: 1190: \ compile 10may93jaw 1191: 1192: : compile ( -- ) \ name 1193: restrict? 1194: bl word gfind dup 0= ABORT" CROSS: Can't compile " 1195: 0> ( immediate? ) 1196: IF >exec @ compile, 1197: ELSE postpone literal postpone gexecute THEN ; 1198: immediate 1199: 1200: : [G'] 1201: \G ticks a ghost and returns its address 1202: bl word gfind 0= ABORT" CROSS: Ghost don't exists" 1203: state @ 1204: IF postpone literal 1205: THEN ; immediate 1206: 1207: : ghost>cfa 1208: dup forward? ABORT" CROSS: forward " >link @ ; 1209: 1210: >TARGET 1211: 1212: : ' ( -- cfa ) 1213: \ returns the target-cfa of a ghost 1214: bl word gfind 0= ABORT" CROSS: Ghost don't exists" 1215: ghost>cfa ; 1216: 1217: Cond: ['] T ' H alit, ;Cond 1218: 1219: >CROSS 1220: 1221: : [T'] 1222: \ returns the target-cfa of a ghost, or compiles it as literal 1223: postpone [G'] state @ IF postpone ghost>cfa ELSE ghost>cfa THEN ; immediate 1224: 1225: \ \ threading modell 13dec92py 1226: \ modularized 14jun97jaw 1227: 1228: : fillcfa ( usedcells -- ) 1229: T cells H xt>body swap - 0 ?DO 0 T c, tchar H +LOOP ; 1230: 1231: : (>body) ( cfa -- pfa ) xt>body + ; ' (>body) T IS >body H 1232: 1233: : (doer,) ( ghost -- ) ]comp gexecute comp[ 1 fillcfa ; ' (doer,) IS doer, 1234: 1235: : (docol,) ( -- ) [G'] :docol doer, ; ' (docol,) IS docol, 1236: 1237: : (doprim,) ( -- ) 1238: there xt>body + ca>native T a, H 1 fillcfa ; ' (doprim,) IS doprim, 1239: 1240: : (doeshandler,) ( -- ) 1241: T cfalign H compile :doesjump T 0 , H ; ' (doeshandler,) IS doeshandler, 1242: 1243: : (dodoes,) ( does-action-ghost -- ) 1244: ]comp [G'] :dodoes gexecute comp[ 1245: addr, 1246: T here H tcell - reloff 2 fillcfa ; ' (dodoes,) IS dodoes, 1247: 1248: : (lit,) ( n -- ) compile lit T , H ; ' (lit,) IS lit, 1249: 1250: : (alit,) ( n -- ) lit, T here cell - H relon ; ' (alit,) IS alit, 1251: 1252: : (fini,) compile ;s ; ' (fini,) IS fini, 1253: 1254: [IFUNDEF] (code) 1255: Defer (code) 1256: Defer (end-code) 1257: [THEN] 1258: 1259: >TARGET 1260: : Code 1261: defempty? 1262: (THeader there resolve 1263: [ T e? prims H 0= [IF] T e? ITC H [ELSE] true [THEN] ] [IF] 1264: doprim, 1265: [THEN] 1266: depth (code) ; 1267: 1268: : Code: 1269: defempty? 1270: ghost dup there ca>native resolve <do:> swap >magic ! 1271: depth (code) ; 1272: 1273: : end-code 1274: (end-code) 1275: depth ?dup IF 1- <> ABORT" CROSS: Stack changed" 1276: ELSE true ABORT" CROSS: Stack empty" THEN 1277: ; 1278: 1279: ( Cond ) : chars tchar * ; ( Cond ) 1280: 1281: >CROSS 1282: 1283: \ tLiteral 12dec92py 1284: 1285: >TARGET 1286: Cond: \G T-\G ;Cond 1287: 1288: Cond: Literal ( n -- ) restrict? lit, ;Cond 1289: Cond: ALiteral ( n -- ) restrict? alit, ;Cond 1290: 1291: : Char ( "<char>" -- ) bl word char+ c@ ; 1292: Cond: [Char] ( "<char>" -- ) restrict? Char lit, ;Cond 1293: 1294: \ some special literals 27jan97jaw 1295: 1296: \ !! Known Bug: Special Literals and plug-ins work only correct 1297: \ on 16 and 32 Bit Targets and 32 Bit Hosts! 1298: 1299: Cond: MAXU 1300: restrict? 1301: tcell 1 cells u> 1302: IF compile lit tcell 0 ?DO FF T c, H LOOP 1303: ELSE $ffffffff lit, THEN 1304: ;Cond 1305: 1306: Cond: MINI 1307: restrict? 1308: tcell 1 cells u> 1309: IF compile lit bigendian 1310: IF 80 T c, H tcell 1 ?DO 0 T c, H LOOP 1311: ELSE tcell 1 ?DO 0 T c, H LOOP 80 T c, H 1312: THEN 1313: ELSE tcell 2 = IF $8000 ELSE $80000000 THEN lit, THEN 1314: ;Cond 1315: 1316: Cond: MAXI 1317: restrict? 1318: tcell 1 cells u> 1319: IF compile lit bigendian 1320: IF 7F T c, H tcell 1 ?DO FF T c, H LOOP 1321: ELSE tcell 1 ?DO FF T c, H LOOP 7F T c, H 1322: THEN 1323: ELSE tcell 2 = IF $7fff ELSE $7fffffff THEN lit, THEN 1324: ;Cond 1325: 1326: >CROSS 1327: \ Target compiling loop 12dec92py 1328: \ ">tib trick thrown out 10may93jaw 1329: \ number? defined at the top 11may93jaw 1330: 1331: \ compiled word might leave items on stack! 1332: : tcom ( in name -- ) 1333: gfind ?dup IF 0> IF nip >exec @ execute 1334: ELSE nip gexecute THEN EXIT THEN 1335: number? dup IF 0> IF swap lit, THEN lit, drop 1336: ELSE 2drop >in ! 1337: ghost gexecute THEN ; 1338: 1339: >TARGET 1340: \ : ; DOES> 13dec92py 1341: \ ] 9may93py/jaw 1342: 1343: : ] state on 1344: Compiling comp-state ! 1345: BEGIN 1346: BEGIN >in @ bl word 1347: dup c@ 0= WHILE 2drop refill 0= 1348: ABORT" CROSS: End of file while target compiling" 1349: REPEAT 1350: tcom 1351: state @ 1352: 0= 1353: UNTIL ; 1354: 1355: \ by the way: defining a second interpreter (a compiler-)loop 1356: \ is not allowed if a system should be ans conform 1357: 1358: : : ( -- colon-sys ) \ Name 1359: defempty? 1360: constflag off \ don't let this flag work over colon defs 1361: \ just to go sure nothing unwanted happens 1362: >in @ skip? IF drop skip-defs EXIT THEN >in ! 1363: (THeader ;Resolve ! there ;Resolve cell+ ! 1364: docol, ]comp depth T ] H ; 1365: 1366: : :noname ( -- colon-sys ) 1367: T cfalign H there docol, 0 ;Resolve ! depth T ] H ; 1368: 1369: Cond: EXIT ( -- ) restrict? compile ;S ;Cond 1370: 1371: Cond: ?EXIT ( -- ) 1 abort" CROSS: using ?exit" ;Cond 1372: 1373: >CROSS 1374: : LastXT ;Resolve @ 0= abort" CROSS: no definition for LastXT" 1375: ;Resolve cell+ @ ; 1376: 1377: >TARGET 1378: 1379: Cond: recurse ( -- ) Last-Ghost @ gexecute ;Cond 1380: 1381: Cond: ; ( -- ) restrict? 1382: depth ?dup IF 1- <> ABORT" CROSS: Stack changed" 1383: ELSE true ABORT" CROSS: Stack empty" THEN 1384: fini, 1385: comp[ 1386: state off 1387: ;Resolve @ 1388: IF ;Resolve @ ;Resolve cell+ @ resolve THEN 1389: Interpreting comp-state ! 1390: ;Cond 1391: Cond: [ restrict? state off Interpreting comp-state ! ;Cond 1392: 1393: >CROSS 1394: 1395: Create GhostDummy ghostheader 1396: <res> GhostDummy >magic ! 1397: 1398: : !does ( does-action -- ) 1399: \ !! zusammenziehen und dodoes, machen! 1400: tlastcfa @ [G'] :dovar killref 1401: \ tlastcfa @ dup there >r tdp ! compile :dodoes r> tdp ! T cell+ ! H ; 1402: \ !! geht so nicht, da dodoes, ghost will! 1403: GhostDummy >link ! GhostDummy 1404: tlastcfa @ >tempdp dodoes, tempdp> ; 1405: 1406: >TARGET 1407: Cond: DOES> restrict? 1408: compile (does>) doeshandler, 1409: \ resolve words made by builders 1410: tdoes @ ?dup IF @ T here H resolve THEN 1411: ;Cond 1412: : DOES> switchrom doeshandler, T here H !does depth T ] H ; 1413: 1414: >CROSS 1415: \ Creation 01nov92py 1416: 1417: \ Builder 11may93jaw 1418: 1419: : Builder ( Create-xt do:-xt "name" -- ) 1420: \ builds up a builder in current vocabulary 1421: \ create-xt is executed when word is interpreted 1422: \ do:-xt is executet when the created word from builder is executed 1423: \ for do:-xt an additional entry after the normal ghost-enrys is used 1424: 1425: >in @ alias2 swap dup >in ! >r >r 1426: Make-Ghost 1427: rot swap >exec dup @ ['] NoExec <> 1428: IF 2drop ELSE ! THEN 1429: , 1430: r> r> >in ! 1431: also ghosts ' previous swap ! ; 1432: \ DOES> dup >exec @ execute ; 1433: 1434: : gdoes, ( ghost -- ) 1435: \ makes the codefield for a word that is built 1436: >end @ dup forward? 0= 1437: IF 1438: dup >magic @ <do:> = 1439: IF doer, 1440: ELSE dodoes, 1441: THEN 1442: EXIT 1443: THEN 1444: \ compile :dodoes gexecute 1445: \ T here H tcell - reloff 1446: 2 refered 1447: 0 fillcfa 1448: ; 1449: 1450: : TCreate ( <name> -- ) 1451: executed-ghost @ 1452: CreateFlag on 1453: create-forward-warn 1454: IF ['] reswarn-forward IS resolve-warning THEN 1455: Theader >r dup gdoes, 1456: \ stores execution symantic in the built word 1457: >end @ >exec @ r> >exec ! ; 1458: 1459: : RTCreate ( <name> -- ) 1460: \ creates a new word with code-field in ram 1461: executed-ghost @ 1462: CreateFlag on 1463: create-forward-warn 1464: IF ['] reswarn-forward IS resolve-warning THEN 1465: \ make Alias 1466: (THeader there 0 T a, H 80 flag! ( S executed-ghost new-ghost ) 1467: \ store poiter to code-field 1468: switchram T cfalign H 1469: there swap T ! H 1470: there tlastcfa ! 1471: dup there resolve 0 ;Resolve ! 1472: >r dup gdoes, 1473: >end @ >exec @ r> >exec ! ; 1474: 1475: : Build: ( -- [xt] [colon-sys] ) 1476: :noname postpone TCreate ; 1477: 1478: : BuildSmart: ( -- [xt] [colon-sys] ) 1479: :noname 1480: [ T has? rom H [IF] ] 1481: postpone RTCreate 1482: [ [ELSE] ] 1483: postpone TCreate 1484: [ [THEN] ] ; 1485: 1486: : gdoes> ( ghost -- addr flag ) 1487: executed-ghost @ 1488: state @ IF gexecute true EXIT THEN 1489: >link @ T >body H false ; 1490: 1491: \ DO: ;DO 11may93jaw 1492: \ changed to ?EXIT 10may93jaw 1493: 1494: : DO: ( -- addr [xt] [colon-sys] ) 1495: here ghostheader 1496: :noname postpone gdoes> postpone ?EXIT ; 1497: 1498: : by: ( -- addr [xt] [colon-sys] ) \ name 1499: ghost 1500: :noname postpone gdoes> postpone ?EXIT ; 1501: 1502: : ;DO ( addr [xt] [colon-sys] -- addr ) 1503: postpone ; ( S addr xt ) 1504: over >exec ! ; immediate 1505: 1506: : by ( -- addr ) \ Name 1507: ghost >end @ ; 1508: 1509: >TARGET 1510: \ Variables and Constants 05dec92py 1511: 1512: Build: ( n -- ) ; 1513: by: :docon ( ghost -- n ) T @ H ;DO 1514: Builder (Constant) 1515: 1516: Build: ( n -- ) T , H ; 1517: by (Constant) 1518: Builder Constant 1519: 1520: Build: ( n -- ) T A, H ; 1521: by (Constant) 1522: Builder AConstant 1523: 1524: Build: ( d -- ) T , , H ; 1525: DO: ( ghost -- d ) T dup cell+ @ swap @ H ;DO 1526: Builder 2Constant 1527: 1528: BuildSmart: ; 1529: by: :dovar ( ghost -- addr ) ;DO 1530: Builder Create 1531: 1532: T has? rom H [IF] 1533: Build: ( -- ) T here 0 , H switchram T align here swap ! 0 , H ( switchrom ) ; 1534: by (Constant) 1535: Builder Variable 1536: [ELSE] 1537: Build: T 0 , H ; 1538: by Create 1539: Builder Variable 1540: [THEN] 1541: 1542: T has? rom H [IF] 1543: Build: ( -- ) T here 0 , H switchram T align here swap ! 0 , 0 , H ( switchrom ) ; 1544: by (Constant) 1545: Builder 2Variable 1546: [ELSE] 1547: Build: T 0 , 0 , H ; 1548: by Create 1549: Builder 2Variable 1550: [THEN] 1551: 1552: T has? rom H [IF] 1553: Build: ( -- ) T here 0 , H switchram T align here swap ! 0 , H ( switchrom ) ; 1554: by (Constant) 1555: Builder AVariable 1556: [ELSE] 1557: Build: T 0 A, H ; 1558: by Create 1559: Builder AVariable 1560: [THEN] 1561: 1562: \ User variables 04may94py 1563: 1564: >CROSS 1565: Variable tup 0 tup ! 1566: Variable tudp 0 tudp ! 1567: : u, ( n -- udp ) 1568: tup @ tudp @ + T ! H 1569: tudp @ dup T cell+ H tudp ! ; 1570: : au, ( n -- udp ) 1571: tup @ tudp @ + T A! H 1572: tudp @ dup T cell+ H tudp ! ; 1573: >TARGET 1574: 1575: Build: T 0 u, , H ; 1576: by: :douser ( ghost -- up-addr ) T @ H tup @ + ;DO 1577: Builder User 1578: 1579: Build: T 0 u, , 0 u, drop H ; 1580: by User 1581: Builder 2User 1582: 1583: Build: T 0 au, , H ; 1584: by User 1585: Builder AUser 1586: 1587: BuildSmart: T , H ; 1588: by (Constant) 1589: Builder Value 1590: 1591: BuildSmart: T A, H ; 1592: by (Constant) 1593: Builder AValue 1594: 1595: BuildSmart: ( -- ) [T'] noop T A, H ; 1596: by: :dodefer ( ghost -- ) ABORT" CROSS: Don't execute" ;DO 1597: Builder Defer 1598: 1599: BuildSmart: ( inter comp -- ) swap T immediate A, A, H ; 1600: DO: ( ghost -- ) ABORT" CROSS: Don't execute" ;DO 1601: Builder interpret/compile: 1602: 1603: \ Sturctures 23feb95py 1604: 1605: >CROSS 1606: : nalign ( addr1 n -- addr2 ) 1607: \ addr2 is the aligned version of addr1 wrt the alignment size n 1608: 1- tuck + swap invert and ; 1609: >TARGET 1610: 1611: Build: ; 1612: by: :dofield T @ H + ;DO 1613: Builder (Field) 1614: 1615: Build: ( align1 offset1 align size "name" -- align2 offset2 ) 1616: rot dup T , H ( align1 align size offset1 ) 1617: + >r nalign r> ; 1618: by (Field) 1619: Builder Field 1620: 1621: : struct T 1 chars 0 H ; 1622: : end-struct T 2Constant H ; 1623: 1624: : cell% ( n -- size align ) 1625: T 1 cells H dup ; 1626: 1627: \ ' 2Constant Alias2 end-struct 1628: \ 0 1 T Chars H 2Constant struct 1629: 1630: \ structural conditionals 17dec92py 1631: 1632: >CROSS 1633: : ?struc ( flag -- ) ABORT" CROSS: unstructured " ; 1634: : sys? ( sys -- sys ) dup 0= ?struc ; 1635: : >mark ( -- sys ) T here ( dup ." M" hex. ) 0 , H ; 1636: 1637: : branchoffset ( src dest -- ) - tchar / ; 1638: 1639: : >resolve ( sys -- ) T here ( dup ." >" hex. ) over branchoffset swap ! H ; 1640: 1641: : <resolve ( sys -- ) T here ( dup ." <" hex. ) branchoffset , H ; 1642: 1643: :noname compile branch T here branchoffset , H ; 1644: IS branch, ( target-addr -- ) 1645: :noname compile ?branch T here branchoffset , H ; 1646: IS ?branch, ( target-addr -- ) 1647: :noname compile branch T here 0 , H ; 1648: IS branchmark, ( -- branchtoken ) 1649: :noname compile ?branch T here 0 , H ; 1650: IS ?branchmark, ( -- branchtoken ) 1651: :noname T here 0 , H ; 1652: IS ?domark, ( -- branchtoken ) 1653: :noname dup T @ H ?struc T here over branchoffset swap ! H ; 1654: IS branchtoresolve, ( branchtoken -- ) 1655: :noname branchto, T here H ; 1656: IS branchtomark, ( -- target-addr ) 1657: 1658: >TARGET 1659: 1660: \ Structural Conditionals 12dec92py 1661: 1662: Cond: BUT restrict? sys? swap ;Cond 1663: Cond: YET restrict? sys? dup ;Cond 1664: 1665: 0 [IF] 1666: >CROSS 1667: Variable tleavings 1668: >TARGET 1669: 1670: Cond: DONE ( addr -- ) restrict? tleavings @ 1671: BEGIN 2dup u> 0= WHILE dup T @ H swap >resolve REPEAT 1672: tleavings ! drop ;Cond 1673: 1674: >CROSS 1675: : (leave) T here H tleavings @ T , H tleavings ! ; 1676: >TARGET 1677: 1678: Cond: LEAVE restrict? compile branch (leave) ;Cond 1679: Cond: ?LEAVE restrict? compile 0= compile ?branch (leave) ;Cond 1680: 1681: [ELSE] 1682: \ !! This is WIP 1683: \ The problem is (?DO)! 1684: \ perhaps we need a plug-in for (?DO) 1685: 1686: >CROSS 1687: Variable tleavings 0 tleavings ! 1688: : (done) ( addr -- ) 1689: tleavings @ 1690: BEGIN dup 1691: WHILE 1692: >r dup r@ cell+ @ \ address of branch 1693: u> 0= \ lower than DO? 1694: WHILE 1695: r@ 2 cells + @ \ branch token 1696: branchtoresolve, 1697: r@ @ r> free throw 1698: REPEAT r> THEN 1699: tleavings ! drop ; 1700: 1701: >TARGET 1702: 1703: Cond: DONE ( addr -- ) restrict? (done) ;Cond 1704: 1705: >CROSS 1706: : (leave) ( branchtoken -- ) 1707: 3 cells allocate throw >r 1708: T here H r@ cell+ ! 1709: r@ 2 cells + ! 1710: tleavings @ r@ ! 1711: r> tleavings ! ; 1712: >TARGET 1713: 1714: Cond: LEAVE restrict? branchmark, (leave) ;Cond 1715: Cond: ?LEAVE restrict? compile 0= ?branchmark, (leave) ;Cond 1716: 1717: [THEN] 1718: 1719: >CROSS 1720: \ !!JW ToDo : Move to general tools section 1721: 1722: : to1 ( x1 x2 xn n -- addr ) 1723: \G packs n stack elements in a allocated memory region 1724: dup dup 1+ cells allocate throw dup >r swap 1+ 1725: 0 DO tuck ! cell+ LOOP 1726: drop r> ; 1727: : 1to ( addr -- x1 x2 xn ) 1728: \G unpacks the elements saved by to1 1729: dup @ swap over cells + swap 1730: 0 DO dup @ swap 1 cells - LOOP 1731: free throw ; 1732: 1733: : loop] branchto, dup <resolve tcell - (done) ; 1734: 1735: : skiploop] ?dup IF branchto, branchtoresolve, THEN ; 1736: 1737: >TARGET 1738: 1739: \ Structural Conditionals 12dec92py 1740: 1741: >TARGET 1742: Cond: AHEAD restrict? branchmark, ;Cond 1743: Cond: IF restrict? ?branchmark, ;Cond 1744: Cond: THEN restrict? sys? branchto, branchtoresolve, ;Cond 1745: Cond: ELSE restrict? sys? compile AHEAD swap compile THEN ;Cond 1746: 1747: Cond: BEGIN restrict? branchtomark, ;Cond 1748: Cond: WHILE restrict? sys? compile IF swap ;Cond 1749: Cond: AGAIN restrict? sys? branch, ;Cond 1750: Cond: UNTIL restrict? sys? ?branch, ;Cond 1751: Cond: REPEAT restrict? over 0= ?struc compile AGAIN compile THEN ;Cond 1752: 1753: Cond: CASE restrict? 0 ;Cond 1754: Cond: OF restrict? 1+ >r compile over compile = 1755: compile IF compile drop r> ;Cond 1756: Cond: ENDOF restrict? >r compile ELSE r> ;Cond 1757: Cond: ENDCASE restrict? compile drop 0 ?DO compile THEN LOOP ;Cond 1758: 1759: \ Structural Conditionals 12dec92py 1760: 1761: :noname 1762: 0 compile (do) 1763: branchtomark, 2 to1 ; 1764: IS do, ( -- target-addr ) 1765: 1766: \ :noname 1767: \ compile 2dup compile = compile IF 1768: \ compile 2drop compile ELSE 1769: \ compile (do) branchtomark, 2 to1 ; 1770: \ IS ?do, 1771: 1772: :noname 1773: 0 compile (?do) ?domark, (leave) 1774: branchtomark, 2 to1 ; 1775: IS ?do, ( -- target-addr ) 1776: :noname compile (for) branchtomark, ; 1777: IS for, ( -- target-addr ) 1778: :noname 1to compile (loop) loop] compile unloop skiploop] ; 1779: IS loop, ( target-addr -- ) 1780: :noname 1to compile (+loop) loop] compile unloop skiploop] ; 1781: IS +loop, ( target-addr -- ) 1782: :noname compile (next) loop] compile unloop ; 1783: IS next, ( target-addr -- ) 1784: 1785: Cond: DO restrict? do, ;Cond 1786: Cond: ?DO restrict? ?do, ;Cond 1787: Cond: FOR restrict? for, ;Cond 1788: 1789: Cond: LOOP restrict? sys? loop, ;Cond 1790: Cond: +LOOP restrict? sys? +loop, ;Cond 1791: Cond: NEXT restrict? sys? next, ;Cond 1792: 1793: \ String words 23feb93py 1794: 1795: : ," [char] " parse T string, align H ; 1796: 1797: Cond: ." restrict? compile (.") T ," H ;Cond 1798: Cond: S" restrict? compile (S") T ," H ;Cond 1799: Cond: ABORT" restrict? compile (ABORT") T ," H ;Cond 1800: 1801: Cond: IS T ' >body H compile ALiteral compile ! ;Cond 1802: : IS T ' >body ! H ; 1803: Cond: TO T ' >body H compile ALiteral compile ! ;Cond 1804: : TO T ' >body ! H ; 1805: 1806: Cond: defers T ' >body @ compile, H ;Cond 1807: : on T -1 swap ! H ; 1808: : off T 0 swap ! H ; 1809: 1810: \ LINKED ERR" ENV" 2ENV" 18may93jaw 1811: 1812: \ linked list primitive 1813: : linked T here over @ A, swap ! H ; 1814: : chained T linked A, H ; 1815: 1816: : err" s" ErrLink linked" evaluate T , H 1817: [char] " parse T string, align H ; 1818: 1819: : env" [char] " parse s" EnvLink linked" evaluate 1820: T string, align , H ; 1821: 1822: : 2env" [char] " parse s" EnvLink linked" evaluate 1823: here >r T string, align , , H 1824: r> dup T c@ H 80 and swap T c! H ; 1825: 1826: \ compile must be last 22feb93py 1827: 1828: Cond: compile ( -- ) restrict? \ name 1829: bl word gfind dup 0= ABORT" CROSS: Can't compile" 1830: 0> IF gexecute 1831: ELSE dup >magic @ <imm> = 1832: IF gexecute 1833: ELSE compile (compile) addr, THEN THEN ;Cond 1834: 1835: Cond: postpone ( -- ) restrict? \ name 1836: bl word gfind dup 0= ABORT" CROSS: Can't compile" 1837: 0> IF gexecute 1838: ELSE dup >magic @ <imm> = 1839: IF gexecute 1840: ELSE compile (compile) addr, THEN THEN ;Cond 1841: 1842: \ \ minimal definitions 1843: 1844: >MINIMAL 1845: also minimal 1846: \ Usefull words 13feb93py 1847: 1848: : KB 400 * ; 1849: 1850: \ \ [IF] [ELSE] [THEN] ... 14sep97jaw 1851: 1852: \ it is useful to define our own structures and not to rely 1853: \ on the words in the compiler 1854: \ The words in the compiler might be defined with vocabularies 1855: \ this doesn't work with our self-made compile-loop 1856: 1857: Create parsed 20 chars allot \ store word we parsed 1858: 1859: : upcase 1860: parsed count bounds 1861: ?DO I c@ toupper I c! LOOP ; 1862: 1863: : [ELSE] 1864: 1 BEGIN 1865: BEGIN bl word count dup WHILE 1866: comment? parsed place upcase parsed count 1867: 2dup s" [IF]" compare 0= >r 1868: 2dup s" [IFUNDEF]" compare 0= >r 1869: 2dup s" [IFDEF]" compare 0= r> or r> or 1870: IF 2drop 1+ 1871: ELSE 2dup s" [ELSE]" compare 0= 1872: IF 2drop 1- dup 1873: IF 1+ 1874: THEN 1875: ELSE 1876: 2dup s" [ENDIF]" compare 0= >r 1877: s" [THEN]" compare 0= r> or 1878: IF 1- THEN 1879: THEN 1880: THEN 1881: ?dup 0= ?EXIT 1882: REPEAT 1883: 2drop refill 0= 1884: UNTIL drop ; immediate 1885: 1886: : [THEN] ( -- ) ; immediate 1887: 1888: : [ENDIF] ( -- ) ; immediate 1889: 1890: : [IF] ( flag -- ) 1891: 0= IF postpone [ELSE] THEN ; immediate 1892: 1893: Cond: [IF] postpone [IF] ;Cond 1894: Cond: [THEN] postpone [THEN] ;Cond 1895: Cond: [ELSE] postpone [ELSE] ;Cond 1896: 1897: \ define new [IFDEF] and [IFUNDEF] 20may93jaw 1898: 1899: : defined? defined? ; 1900: : needed? needed? ; 1901: : doer? doer? ; 1902: 1903: \ we want to use IFDEF on compiler directives (e.g. E?) in the source, too 1904: 1905: : directive? 1906: bl word count [ ' target >wordlist ] aliteral search-wordlist 1907: dup IF nip THEN ; 1908: 1909: : [IFDEF] >in @ directive? swap >in ! 1910: 0= IF defined? ELSE name 2drop true THEN 1911: postpone [IF] ; 1912: 1913: : [IFUNDEF] defined? 0= postpone [IF] ; 1914: 1915: Cond: [IFDEF] postpone [IFDEF] ;Cond 1916: 1917: Cond: [IFUNDEF] postpone [IFUNDEF] ;Cond 1918: 1919: \ C: \- \+ Conditional Compiling 09jun93jaw 1920: 1921: : C: >in @ defined? 0= 1922: IF >in ! T : H 1923: ELSE drop 1924: BEGIN bl word dup c@ 1925: IF count comment? s" ;" compare 0= ?EXIT 1926: ELSE refill 0= ABORT" CROSS: Out of Input while C:" 1927: THEN 1928: AGAIN 1929: THEN ; 1930: 1931: also minimal 1932: 1933: \G doesn't skip line when bit is set in debugmask 1934: : \D name evaluate debugmasksource @ and 0= IF postpone \ THEN ; 1935: 1936: \G interprets the line if word is not defined 1937: : \- defined? IF postpone \ THEN ; 1938: 1939: \G interprets the line if word is defined 1940: : \+ defined? 0= IF postpone \ THEN ; 1941: 1942: Cond: \- \- ;Cond 1943: Cond: \+ \+ ;Cond 1944: Cond: \D \D ;Cond 1945: 1946: : ?? bl word find IF execute ELSE drop 0 THEN ; 1947: 1948: : needed: 1949: \G defines ghost for words that we want to be compiled 1950: BEGIN >in @ bl word c@ WHILE >in ! ghost drop REPEAT drop ; 1951: 1952: previous 1953: 1954: \ save-cross 17mar93py 1955: 1956: >CROSS 1957: Create magic s" Gforth2x" here over allot swap move 1958: 1959: bigendian 1960: tcell 1 = 0 and 1961: tcell 2 = 2 and or 1962: tcell 4 = 4 and or 1963: tcell 8 = 6 and or 1964: magic 7 + c! 1965: 1966: : save-cross ( "image-name" "binary-name" -- ) 1967: bl parse ." Saving to " 2dup type cr 1968: w/o bin create-file throw >r 1969: TNIL IF 1970: s" #! " r@ write-file throw 1971: bl parse r@ write-file throw 1972: s" -i" r@ write-file throw 1973: #lf r@ emit-file throw 1974: r@ dup file-position throw drop 8 mod 8 swap ( file-id limit index ) 1975: ?do 1976: bl over emit-file throw 1977: loop 1978: drop 1979: magic 8 r@ write-file throw \ write magic 1980: ELSE 1981: bl parse 2drop 1982: THEN 1983: image @ there 1984: r@ write-file throw \ write image 1985: TNIL IF 1986: bit$ @ there 1- tcell>bit rshift 1+ 1987: r@ write-file throw \ write tags 1988: THEN 1989: r> close-file throw ; 1990: 1991: : save-region ( addr len -- ) 1992: bl parse w/o bin create-file throw >r 1993: swap image @ + swap r@ write-file throw 1994: r> close-file throw ; 1995: 1996: \ words that should be in minimal 1997: 1998: create s-buffer 50 chars allot 1999: 2000: >MINIMAL 2001: also minimal 2002: 2003: bigendian Constant bigendian 2004: : here there ; 2005: 2006: \ compiler directives 2007: : >ram >ram ; 2008: : >rom >rom ; 2009: : >auto >auto ; 2010: : >tempdp >tempdp ; 2011: : tempdp> tempdp> ; 2012: : const constflag on ; 2013: : warnings name 3 = 0= twarnings ! drop ; 2014: : | ; 2015: \ : | NoHeaderFlag on ; \ This is broken (damages the last word) 2016: 2017: : save-cross save-cross ; 2018: : save-region save-region ; 2019: : tdump swap >image swap dump ; 2020: 2021: also forth 2022: [IFDEF] Label : Label defempty? Label ; [THEN] 2023: [IFDEF] start-macros : start-macros defempty? start-macros ; [THEN] 2024: [IFDEF] builttag : builttag builttag ; [THEN] 2025: previous 2026: 2027: : s" [char] " parse s-buffer place s-buffer count ; \ for environment? 2028: : + + ; 2029: : 1+ 1 + ; 2030: : 2+ 2 + ; 2031: : or or ; 2032: : 1- 1- ; 2033: : - - ; 2034: : and and ; 2035: : or or ; 2036: : 2* 2* ; 2037: : * * ; 2038: : / / ; 2039: : dup dup ; 2040: : over over ; 2041: : swap swap ; 2042: : rot rot ; 2043: : drop drop ; 2044: : = = ; 2045: : 0= 0= ; 2046: : lshift lshift ; 2047: : 2/ 2/ ; 2048: : . . ; 2049: 2050: : all-words ['] false IS skip? ; 2051: : needed-words ['] needed? IS skip? ; 2052: : undef-words ['] defined? IS skip? ; 2053: 2054: : \ postpone \ ; immediate 2055: : \G T-\G ; immediate 2056: : ( postpone ( ; immediate 2057: : include bl word count included ; 2058: : require require ; 2059: : .( [char] ) parse type ; 2060: : ." [char] " parse type ; 2061: : cr cr ; 2062: 2063: : times 0 ?DO dup T c, H LOOP drop ; \ used for space table creation 2064: only forth also minimal definitions 2065: 2066: \ cross-compiler words 2067: 2068: : decimal decimal ; 2069: : hex hex ; 2070: 2071: : tudp T tudp H ; 2072: : tup T tup H ; 2073: 2074: : doc-off false T to-doc H ! ; 2075: : doc-on true T to-doc H ! ; 2076: [IFDEF] dbg : dbg dbg ; [THEN] 2077: 2078: minimal 2079: 2080: \ for debugging... 2081: : order order ; 2082: : hwords words ; 2083: : words also ghosts words previous ; 2084: : .s .s ; 2085: : bye bye ; 2086: 2087: \ turnkey direction 2088: : H forth ; immediate 2089: : T minimal ; immediate 2090: : G ghosts ; immediate 2091: 2092: : turnkey 0 set-order also Target definitions 2093: also Minimal also ; 2094: 2095: \ these ones are pefered: 2096: 2097: : lock turnkey ; 2098: : unlock forth also cross ; 2099: 2100: : [[ also unlock ; 2101: : ]] previous previous ; 2102: 2103: unlock definitions also minimal 2104: : lock lock ; 2105: lock