rtforth 0.6.8

Forth implemented in Rust for realtime application
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
( -*- forth -*- )

( this is adapted from Bill Muench's x86 eForth.. original copyright notice:

---
Copyright Bill Muench All rights reserved.
Permission is granted for non-commercial use, provided this notice is included.
Contact Bill Muench concerning commercial use.
---

contains some adaptations to make it work on the purrr kernel. i
converted everything to lower case. aestetics i guess..

)



( ============================================================ )

: noop ( -- ) ( 0x7b ) ;

( system variables )

: _var ( -- a ) ( 0xb9 ) r> ; compile-only
: _con ( -- n ) ( 0xba ) r> @ ; compile-only

create '?key ( input device vector )
  ' ?rx ,
create 'emit ( output device vector )
  ' tx! ,

variable base ( numeric radix ) ( 6.1.0750 )( 0xa0 )
variable dpl  ( numeric input decimal place )
variable hld  ( numeric output string pointer )

variable >in ( input buffer offset ) ( 6.1.0560 )
create #in   ( input buffer count )
  2 cells allot ( input buffer address )

variable csp ( save stack pointer )

create state ( interpret/compile flag ) ( 6.1.2250 )( 0xdc )
  2 cells allot ( interpret/compile vector )

create dp ( dictionary pointer )
  2 cells allot

create sup ( -- tid )
  =rp , ( return stack )
  =sp , ( data stack )

=bl constant bl ( -- c ) ( 6.1.0770 )( 0xa9 )

( common functions )

: hex ( -- ) ( 6.2.1660 ) 16 base ! ;
: decimal ( -- ) ( 6.1.1170 ) 10 base ! ;

: rot ( n1 n2 n3 -- n2 n3 n1 ) ( 6.1.2160 )( 0x4a ) >r swap r> swap ;
: nip ( n1 n2 -- n2 ) ( 6.2.1930 )( 0x4d ) swap drop ;
: 2drop ( n n -- ) ( 6.1.0370 )( 0x52 ) drop drop ;
: 2dup ( n1 n2 -- n1 n2 n1 n2 ) ( 6.1.0380 )( 0x53 ) over over ;
: ?dup ( n -- n n | 0 ) ( 6.1.0630 )( 0x50 ) dup if dup then ;

: + ( n n -- n ) ( 6.1.0120 )( 0x1e ) um+ drop ;
: d+ ( d d -- d ) ( 8.6.1.1040 )( 0xd8 ) >r  swap >r  um+  r> +  r> + ;

: invert ( n -- n ) ( 6.1.1720 )( 0x26 ) -1 xor ;

: negate ( n -- n ) ( 6.1.1910 )( 0x2c ) invert 1 + ;
: dnegate ( d -- d ) ( 8.6.1.1230 ) invert >r invert 1 um+ r> + ;

: s>d ( n -- d ) ( 6.1.2170 ) dup 0< ;
: abs ( n -- u ) ( 6.1.0690 )( 0x2d ) dup 0< if negate then ;
: dabs ( d -- ud ) ( 8.6.1.1160 ) dup 0< if dnegate then ;

: - ( n n -- n ) ( 6.1.0160 )( 0x1f ) negate + ;

: pick ( n -- n ) ( 6.2.2030 )( 0x50 )
  ?dup if swap >r 1 - recurse r> swap exit then dup ;

( comparison )

: 0= ( n -- f ) ( 6.1.0270 )( 0x34 ) if 0 exit then -1 ;
: = ( n n -- f ) ( 6.1.0530 )( 0x3c ) xor 0= ;

: u< ( u u -- f ) ( 6.1.2340 )( 0x40 ) 2dup xor 0< if  nip 0< exit then - 0< ;
:  < ( n n -- f ) ( 6.1.0480 )( 0x3a ) 2dup xor 0< if drop 0< exit then - 0< ;

: max ( n n -- n ) ( 6.1.1870 )( 0x2f ) 2dup      < if swap then drop ;
: min ( n n -- n ) ( 6.1.1880 )( 0x2e ) 2dup swap < if swap then drop ;

: within ( u ul uh -- f ) ( 6.2.2440 )( 0x45 ) over - >r - r> u< ;

( multiply )

: lshift ( u n -- u ) ( 6.1.1805 )( 0x27 )
  begin dup
  while >r  dup +  r> 1 -
  repeat drop ;

: um* ( u u -- ud ) ( 6.1.2360 )( 0xd4 )
  0 swap  [ #bits ] literal
  begin dup
  while >r  dup um+ >r >r  dup um+ r> + r>
    if >r over um+ r> + then  r> 1 -
  repeat drop >r  nip r> ;

: * ( n n -- n ) ( 6.1.0090 )( 0x20 ) um* drop ;

( divide )

: rshift ( u n -- u ) ( 6.1.2162 )( 0x28 )
  0 swap  [ #bits ] literal swap -
  begin dup
  while >r  2dup d+  r> 1 -
  repeat drop  nip ;

: um/mod ( ud u -- ur uq ) ( 6.1.2370 )( 0xd5 )
  2dup u<
  if negate  [ #bits ] literal
    begin dup
    while >r  >r  dup um+ >r >r  dup um+ r> +
      dup r> r@ swap >r um+  r> or
      if >r drop 1 + r> else drop then r>  r> 1 -
    repeat 2drop swap exit
  then drop 2drop  -1 dup ;

: sm/rem ( d n -- r q ) ( 6.1.2214 ) ( symmetric )
  over >r >r  dabs r@ abs um/mod
  r> r@ xor 0< if negate then  r> 0< if >r negate r> then ;

: fm/mod ( d n -- r q ) ( 6.1.1561 ) ( floored )
  dup 0<  dup >r if negate >r dnegate r> then
  >r dup 0< if r@ + then r> um/mod r> if >r negate r> then ;

: /mod ( n n -- r q ) ( 6.1.0240 )( 0x2a ) over 0< swap  fm/mod ; ( or sm/rem )

: mod ( n n -- r ) ( 6.1.1890 )( 0x22 ) /mod drop ;
: / ( n n -- q ) ( 6.1.0230 )( 0x21 ) /mod nip ;

( memory access )

: +! ( n a -- ) ( 6.1.0130 )( 0x6c ) dup >r @ + r> ! ;
: count ( a -- a c ) ( 6.1.0980 )( 0x84 ) dup char+ swap c@ ;
: bounds ( a n -- a+n a ) ( 0xac ) over + swap ;
: /string ( a u n -- a+n u-n ) ( 17.6.1.0245 ) dup >r - swap r> chars + swap ;
: aligned ( a -- a ) ( 6.1.0706 )( 0xae ) ( depends on 2's comp and 2^n cell si
ze )
  [ 1 cells 1 - dup ] literal + [ invert ] literal and ;

: 2! ( u u a -- ) ( 6.1.0310 )( 0x77 ) swap over ! cell+ ! ;
: 2@ ( a -- u u ) ( 6.1.0350 )( 0x76 ) dup cell+ @ swap @ ;

: move ( a a u -- ) ( 6.1.1900 )( 0x78 )
  >r  2dup u<
  if
    begin r> dup
    while char- >r  over r@ + c@  over r@ + c!
    repeat drop  2drop exit
  then r> over + >r
  begin dup r@ xor
  while >r  dup c@ r@ c!  char+ r> char+
  repeat r> drop  2drop ;

: fill ( a u c -- ) ( 6.1.1540 )( 0x79 )
  >r  chars bounds
  begin 2dup xor
  while r@ over c!  char+
  repeat r> drop 2drop ;

: -trailing ( a u -- a u ) ( 17.6.1.0170 )
  begin dup
  while 1 -  2dup chars + c@  bl swap u<
  until 1 + then ;

: >adr ( xt -- a ) ; \ itc
: >body ( xt -- a ) ( 6.1.0550 )( 0x86 ) >adr cell+ cell+ ; \ itc

( multitask )

variable up ( current task pointer )
: _usr ( -- a ) up @ r> @ + ; compile-only

( u1\tf\tid\tos\status\follower\r>--<s  order is important )
1 cells ( init offset )
  cell- dup user follower ( address of next task's status )
  cell- dup user status   ( pass or wake )
  cell- dup user tos      ( top of stack )
  cell- dup user tid      ( back link tid )
  cell- dup user tf       ( throw frame )
  cell- dup user u1       ( free )
drop ( cleanup )

: 's ( tid a -- a ) ( index another task's local variable )
  follower  cell+ - swap @ + ;

: _pass ( -- ) ( hilevel absolute branch )
  r> @ >r ; compile-only
' _pass constant pass

: _wake ( -- ) ( restore follower )
  r> up !  tos @ sp! rp! ; compile-only
' _wake constant wake

: pause ( -- ) ( allow another task to execute )
  rp@  sp@ tos !  follower @ >r ;

: stop ( -- ) ( sleep current task )
  pass status ! pause ; compile-only

: get ( semaphore -- )
  pause ( remember your manners )
  dup @ status xor ( owner ? )
  if begin dup @ while pause repeat ( no, wait for release )
    status swap ! ( lock ) exit
  then drop ;

: release ( semaphore -- )
  dup @ status xor if drop exit then  0 swap ! ( unlock ) ;

: sleep ( tid -- ) ( sleep another task )
  pass swap status 's ! ;

: awake ( tid -- ) ( wake another task )
  wake swap status 's ! ;

: activate ( tid -- )
  dup 2@        ( tid sp rp )
  r> over !     ( save entry at rp )
  over !        ( save rp at sp )
  over tos 's ! ( save sp in tos )
  awake ; compile-only

: build ( tid -- )
  dup sleep                     ( sleep new task )
  follower @ over follower 's ! ( link new task )
  dup status 's follower !      ( link old task )
  dup tid 's ! ;                ( link to tid )

( numeric input )

: digit? ( c base -- u f ) ( 0xa3 )
  >r [char] 0 - 9 over <
  if 7 - dup 10 < or then dup r> u< ;

: >number ( ud a u -- ud a u ) ( 6.1.0570 )
  begin dup
  while >r  dup >r c@ base @ digit?
  while swap base @ um* drop rot base @ um* d+ r> char+ r> 1 -
  repeat drop r> r> then ;

: number? ( a u -- d -1 | a u 0 )
  over c@ [char] - = dup >r if 1 /string then
  >r >r  0 dup  r> r>  -1 dpl !
  begin >number dup
  while over c@ [char] . xor
    if rot drop rot r> 2drop  0 exit
    then 1 - dpl !  char+  dpl @
  repeat 2drop r> if dnegate then -1 ;

( numeric output )

: here ( -- a ) ( 6.1.1650 )( 0xad ) dp @ ;
: pad ( -- a ) ( 6.2.2000 ) here [ #pad chars ] literal + ;

: <# ( -- ) ( 6.1.0490 )( 0x96 ) pad hld ! ;
: digit ( u -- c ) 9 over < 7 and + [char] 0 + ;
: hold ( c -- ) ( 6.1.1670 )( 0x95 ) hld @ char- dup hld ! c! ;

: # ( d -- d ) ( 6.1.0030 )( 0xc7 )
  0 base @ um/mod >r base @ um/mod swap digit hold r> ;

: #s ( d -- d ) ( 6.1.0050 )( 0xc8 ) begin # 2dup or 0= until ;
: #> ( d -- a u ) ( 6.1.0040 )( 0xc9 ) 2drop hld @ pad over - ;

: sign ( n -- ) ( 6.1.2210 )( 0x98 ) 0< if [char] - hold then ;

( error handling )

: catch ( xt -- 0 | err ) ( 9.6.1.0875 )( 0x217 )
  sp@ >r  tf @ >r  rp@ tf !  execute  r> tf !  r> drop  0 ;

: throw ( 0 | err -- | err ) ( r: i*x i*y -- i*x i*y | i*x ) ( 9.6.1.2275 )( 0x
218 )
  ?dup if tf @ rp!  r> tf !  r> swap >r sp! drop r> then ;

: abort ( i*n -- ) ( r: i*x i*y -- i*x ) ( 9.6.2.0670 )( 0x216 ) -1 throw ;

( basic i/o )

: ?key ( -- c -1 | 0 )  pause  '?key @ execute ;
: key ( -- c ) ( 6.1.1750 )( 0x8e ) begin ?key until ;
: nuf? ( -- f ) ?key dup if 2drop key [ =cr ] literal = then ;

: emit ( c -- ) ( 6.1.1320 )( 0x8f ) 'emit @ execute ;
: space ( -- ) ( 6.1.2220 ) bl emit ; ,c" coyote"

: emits ( n c -- )
  swap 0 max begin dup while over emit 1 - repeat 2drop ;
: spaces ( n -- ) ( 6.1.2230 ) bl emits ;

: type ( a u -- ) ( 6.1.2310 )( 0x90 )
  chars bounds begin 2dup xor while count emit repeat 2drop ;
: cr ( -- ) ( 6.1.0990 )( 0x92 ) [ =cr ] literal emit [ =lf ] literal emit ;

: _" ( -- a )
  r> r> dup count chars + aligned >r swap >r ; compile-only

: _s" ( -- a u ) _" count ; compile-only
: _." ( -- ) ( 0x12 ) _" count type ; compile-only
: _abort" ( i*n f -- i*n | ) ( r: i*x i*y -- i*x i*y | i*x )
  if _" csp ! -2 throw then _" drop ; compile-only

: s.r ( a u n -- ) over - spaces type ;
: d.r ( d n -- ) ( 8.6.1.1070 ) >r dup >r dabs <# #s r> sign #> r> s.r ;
: u.r ( u n -- ) ( 6.2.2330 )( 0x9c ) 0 swap d.r ;
: .r ( n n -- ) ( 6.2.0210 )( 0x9e ) >r s>d r> d.r ;

: d. ( d -- ) ( 8.6.1.1060 ) 0 d.r space ;
: u. ( u -- ) ( 6.1.2320 )( 0x9b ) 0 d. ;
: . ( n -- ) ( 6.1.0180 )( 0x9d ) base @ 10 xor if u. exit then s>d d. ;
: ? ( a -- ) ( 15.6.1.0600 ) @ . ;

( bits & bytes )

: pack ( a1 u a2 -- a2 ) ( 0x83 )
  over 256 u<
  if dup >r  over >r  char+ swap chars move  r> r@ c!  r> exit
  then -18 throw ;

: depth ( -- n ) ( 6.1.1200 )( 0x51 )
  sp@  tid @ cell+ @  swap - [ 1 cells ] literal / ;
: ?stack ( -- ) depth 0< abort" depth?" ;

( terminal )

: accept ( a u -- u ) ( 6.1.0695 )
  over + over ( bot eot cur )
  begin key
    dup [ =cr ] literal xor ( carrage return ? )
  while
    dup [ =bs ] literal = ( backspace ? )
    if ( destructive backspace )
      drop  >r over r@ < dup ( any chars ? )
      if [ =bs ] literal dup emit  bl emit  emit
      then r> +
    else ( printable )
      >r  2dup xor ( more ? )
      if r@ over c!  char+  r@ emit
      then r> drop
    then
  repeat drop  nip  swap - ;

( interpreter )

: same? ( a a u -- f ) \ ???faster chars
  swap >r
  begin dup
  while char-  2dup + c@  over r@ + c@  xor
  until r> drop 2drop  0 exit ( no match )
  then r> drop 2drop  -1 ; ( found )

: _delimit ( a u -- a u delta ) \ ???chars
  bounds  dup >r  char-
  begin char+  2dup xor ( skip leading bl )
  while bl over c@ <
  until swap over ( save first non blank addr )
    begin char+  2dup xor ( scan trailing bl )
    while dup c@  bl 1 +  <
    until nip  dup char+ ( found )
    else drop dup ( not found )
    then >r  over -  r>
  else drop 0 over ( all bl )
  then r> - ;

: _parse ( a1 u1 c -- a1 u2 delta ) \ ???chars
  >r  over +  over char- ( save char, adjust addr )
  begin char+  2dup xor ( inc addr ? )
  while dup c@ r@ = ( match ? )
  until swap r> 2drop  over -  dup 1 + exit ( found )
  then  swap r> 2drop  over -  dup ; ( not found )

: name> ( a -- xt ) count chars + char+ aligned ;

: wid? ( a u wid -- xt lex -1 | a u 0 ) \ ???chars
  swap >r  @ ( address of last word )
  begin dup ( last word ? )
  while count r@ = ( count ? )
    if 2dup r@ same? ( match )
      if swap r> 2drop char-
        dup name>  swap count chars + c@  -1 exit ( found )
      then
    then char-  cell- @ ( link )
  repeat drop r>  0 ; ( no match )

create context ( search order )
  #vocs 1 + cells allot ( wids )

: sfind ( a u -- xt lex -1 | a u 0 )
  context cell- >r ( setup )
  begin r> cell+ dup >r @ dup ( wid | 0 )
  while wid? ( found ? )
  until -1 then r> drop ;

: _[ ( a u -- ) ( the forth interpreter )
  sfind ( search dictionary )
  if [ =comp ] literal and abort" compile?"
    execute ?stack exit
  then
  number? ( unknown symbol, try to convert a number )
  if dpl @ 0< ( single? )
    if drop then exit
  then -13 throw ; compile-only
: [ ( -- ) ( 6.1.2500 ) ['] _[  0  state 2! ; immediate

: source ( -- a u ) ( 6.1.2216 ) #in 2@ ;
: parse-word ( "ccc" -- a u ) source >in @ /string _delimit >in +! ;

: evaluate ( a u -- ) ( 6.1.1360 )( 0xcd )
  >in @ >r  0 >in !  source >r >r  #in 2!
  begin parse-word dup
  while state cell+ @ execute
  repeat 2drop  r> r> #in 2!  r> >in ! ;

( redirect input ms-dos only =============================== )

: asciiz ( a u a -- a )
  dup >r  swap chars  2dup + 0 swap c!  move  r> ;

: stdin ( a u -- )
  here asciiz redirect abort" file?" ; compile-only

: from ( "ccc" -- ) ( chain not nest )
  parse-word stdin  source >in ! drop ;

( ========================================================== )

create 'ok ( prompt options )
  ' noop , ( typically .s )
: quit ( -- ) ( r: i*x -- ) ( 6.1.2050 )
  sup @ rp!         ( reset return stack )
  [ ' [ compile, ]  ( reset interpret state )
  s" con" stdin     ( reset console i/o, ms-dos only )
  begin
    begin
      [ =tib ] literal  ( input buffer )
      dup [ #tib ] literal accept space ( user input )
      ['] evaluate catch dup ( error ? )
      if dup -1 xor      ( abort  = -1 )
        if cr dup -2 xor ( abort" = -2 )
          if source drop ( undefined error )
            >in @ -trailing type ."  ?(" 0 .r ." )"
          else csp @ count type
          then space
        then
        sup cell+ @ sp! ( reset data stack )
        recurse         ( restart )
      then cr state @ = ( 0 from catch )
    until 'ok @ execute ." ok " ( prompt )
  again ;

( compiler )

: align ( -- ) ( 6.1.0705 ) here aligned dp ! ;

: allot ( n -- ) ( 6.1.0710 ) dp +! ;
: s, ( a u -- ) here  over chars char+ allot  pack drop ;
: c, ( n -- ) ( 6.1.0860 )( 0xd0 ) here  [ 1 chars ] literal allot  c! ;
: , ( n -- ) ( 6.1.0150 )( 0xd3 ) here  [ 1 cells ] literal allot  ! ;

: compile, ( xt -- ) ( 6.2.0945 )( 0xdd ) , ;
: literal ( n -- ) ( 6.1.1780 ) ['] _lit compile, , ; immediate

: char ( "ccc" -- c ) ( 6.1.0895 ) parse-word drop c@ ;
: [char] ( "ccc" -- ) ( 6.1.2520 ) char  [ ' literal compile, ] ; immediate

: ' ( "name" -- xt ) ( 6.1.0070 ) parse-word sfind if drop exit then -13 thr
ow ;
: ['] ( "name" -- ) ( 6.1.2510 ) '  [ ' literal compile, ] ; immediate

: parse ( c "ccc" -- a u ) ( 6.2.2008 ) \ ???move
  >r source >in @ /string r> _parse >in +! ;

: ( ( "comment" -- ) ( 6.2.0200 ) [char] ) parse type ; immediate
: ( ( "comment" -- ) ( 6.1.0080 ) [char] ) parse 2drop ; immediate
: \ ( "comment" -- ) ( 6.2.2535 ) source >in ! drop ; immediate

: sliteral ( a u -- ) ( -- a u ) ( 17.6.1.2212 )
  ['] _s" compile, s, align ; immediate compile-only

: ,c" ( "ccc" -- ) [char] " parse s, align ;

: s" ( "ccc" -- ) ( 6.1.2165 ) ['] _s" compile, ,c" ; immediate compile-only
: ." ( "ccc" -- ) ( 6.1.0190 ) ['] _." compile, ,c" ; immediate compile-only

: abort" ( "ccc" -- ) ( 6.1.0680 )
  ['] _abort" compile, ,c" ; immediate compile-only

: _] ( a u -- ) ( the forth compiler )
  sfind ( search dictionary )
  if [ =imed ] literal and
    if execute ?stack exit ( immediate )
    then compile, exit
  then
  number? ( unknown symbol, try to convert a number )
  if dpl @ 0<
    if drop ( single )
    else swap  [ ' literal compile, ] ( double )
    then  [ ' literal compile, ] exit
  then -13 throw ; compile-only
: ] ( -- ) ( 6.1.2540 ) align ['] _] -1 state 2! ;

create forth-wordlist ( -- wid ) ( 16.6.1.1595 )
  0 , ( na, of last definition, linked )
  0 , ( wid|0, next or last wordlist in chain )
  0 , ( na, wordlist name pointer )

create last ( -- a )
  1 cells allot ( na, of last definition, unlinked )
  1 cells allot ( wid, current wordlist for linking )
label =token
  1 cells allot ( xt, of last definition )

create current ( -- a )
  forth-wordlist , ( wid, new definitions )
  forth-wordlist , ( wid, head of chain )

: get-current ( -- wid ) ( 16.6.1.1643 ) current @ ;
: set-current ( wid -- ) ( 16.6.1.2195 ) current ! ;
: definitions ( -- ) ( 16.6.1.1180 ) context @ set-current ;

: ?unique ( a u -- a u )
  2dup  get-current wid?
  if 2drop cr ." redef " 2dup type exit then 2drop ;

: head, ( "name" -- ) \ ???fix ( xt "name" -- )
  parse-word  dup
  if ?unique ( warn if redefined )
    align
    get-current  dup @ ,  here last 2! ( link )
    dup c, ( save count )
    here swap  dup allot  move ( build name )
    0 c, ( build attribute byte )
    exit
  then -16 throw ; ( attempt to use zero-length string )

| : lex! ( u -- ) last @ count chars + dup >r c@ or r> c! ;
: immediate ( -- ) ( 6.1.1710 ) [ =imed ] literal  lex! ;
: compile-only ( -- ) [ =comp ] literal  lex! ;

: reveal ( -- ) last 2@ swap ! [ ' [ compile, ] ;
: recurse ( -- ) ( 6.1.2120 ) [ =token ] literal @ compile, ; immediate

: postpone ( "name" -- ) ( 6.1.2033 )
  parse-word sfind
  if [ =imed ] literal and if compile, exit then
    [ ' literal compile, ]  ['] compile, compile,  exit
  then -13 throw ; immediate

( defining words )

: code ( "name" -- ) ( 15.6.2.0930 ) \ itc
  head, align here cell+ , reveal ;

: next, ( -- ) \ itc 80x86 only
  [ next1 ] literal  h# e9 c,  here 2 + - , ;

: :noname ( -- xt ) ( 6.2.0455 ) \ itc
  align here  dup [ =token ] literal !  [ list1 ] literal , ] ;

: : ( "name" -- ) ( 6.1.0450 ) head, :noname drop ;
: ; ( -- ) ( 6.1.0460 ) ['] exit compile, reveal ; immediate compile-only

: _does> ( -- ) ( link child )
\  align ( child ) \ ???why
  r>  [ =token ] literal @  cell+ ( itc )  ! ; compile-only

: does> ( -- ) ( 6.1.1250 ) ( build parent )
  ['] _does> compile, ( link child )
  :noname drop  ['] r> compile, ( begin child )
; immediate compile-only

: create ( "name" -- ) ( 6.1.1000 ) ['] _var  : reveal compile, ;
: variable ( "name" -- ) ( 6.1.2410 ) create 0 , ;
: constant ( n "name" -- ) ( 6.1.0950 ) ['] _con  : reveal compile,  , ;

: user ( n "name" -- ) ['] _usr  : reveal compile,  , ;

: hat ( u s r "name" -- ) ( -- tid )
  create + swap [ 7 cells ] literal + ( tf\tid\tos\status\follower\r>--<s )
  dup here + ( rp0 ) , + dup here + ( sp0 ) , allot ;

: wordlist ( -- wid ) ( 16.6.1.2460 )
  align here 0 ,  dup current cell+  dup @ ,  !  0 , ;

: order@ ( a -- u*wid u )
  dup @ dup if >r cell+  recurse  r> swap 1 + exit then nip ;
: get-order ( -- u*wid u ) ( 16.6.1.1647 ) context order@ ;

: set-order ( u*wid n -- ) ( 16.6.1.2197 )
  dup -1 = if drop forth-wordlist 1 then ( default ? )
  [ #vocs ] literal over u< if -46 throw then ( range ? )
  context swap
  begin dup
  while >r  swap over !  cell+  r> 1 -
  repeat  ( 0 ) swap ! ;

\ ============================================================
: _marker ( -- ) ( r: dfa -- ) \ ???
  r> 2@ ( * ) dup @ follower !  dup context
  begin >r cell+ dup @ dup r@ ! while r> cell+ repeat ( search order )
  cell+ dup 2@ current 2!  cell+ dup @ ( cur wid & head )
  begin >r  cell+ dup @ r@ !  r> cell+ @ ?dup 0= until ( wid last na's )
  r> 2drop ( * ) dp 2! ; compile-only

: marker ( "name" -- ) \ ???
  align dp 2@ ( * ) follower @ ,  context
  begin dup @ dup , while cell+ repeat  drop ( search order )
  current 2@ , dup , ( cur wid & head )
  begin dup @ , cell+ @ ?dup 0= until ( wid last na's )
  ['] _marker : reveal compile, ( * ) , , ;
\ ============================================================

( control flow )

: begin ( -- a ) ( 6.1.0760 ) here ; immediate
: then ( a -- ) ( 6.1.2270 ) [ ' begin compile, ] ( over - ) swap ! ; immediate

: resolve ( a -- ) ( [ ' begin compile, ] - ) , ;
: mark ( -- a ) here [ ' begin compile, ] resolve ;

: if ( -- a ) ( 6.1.1700 ) ['] _if compile, mark ; immediate
: ahead ( -- a ) ( 15.6.2.0702 ) ['] _else compile, mark ; immediate
: else ( a -- a ) ( 6.1.1310 ) [ ' ahead compile, ] swap [ ' then compile, ] ;
immediate
: while ( a -- a a ) ( 6.1.2430 ) [ ' if compile, ] swap ; immediate

: until ( a -- ) ( 6.1.2390 ) ['] _if compile, resolve ; immediate
: again ( a -- ) ( 6.2.0700 ) ['] _else compile, resolve ; immediate
: repeat ( a a -- ) ( 6.1.2140 ) [ ' again compile, ' then compile, ] ; immedia
te

( tools )

: .s ( -- ) ( 15.6.1.0220 )( 0x9f )
  ?stack depth begin ?dup while dup pick . 1 - repeat ;

: !csp ( -- ) sp@ csp ! ;
: ?csp ( -- ) sp@ csp @ xor abort" csp?" ;

: >char ( c -- c )
  h# 7f and dup 127 bl within if drop [char] _ then ;

: _type ( a u -- ) ( alpha dump )
  chars bounds begin 2dup xor while count >char emit repeat 2drop ;

: _dump ( a u -- ) ( numeric dump )
  chars bounds begin 2dup xor while count 3 u.r repeat 2drop ;

: dump ( a u -- ) ( 15.6.1.1280 )
  base @ >r hex  chars bounds
  begin 2dup swap u< while ( range? )
    cr dup 0 <#  # # # #  #> type ( address )
    space [ #dump ] literal  2dup _dump ( numeric )
    space space  2dup _type ( alpha )
    chars +  nuf? ( user? )
  until then 2drop  r> base ! ;

: .id ( a -- ) count _type ;

: widwords ( a u wid -- a u )
  swap >r  dup
  if cr dup ." wid=" u. cr
    begin @ dup ( last name ? )
    while 2dup char+ r@ same? ( match ? )
      if dup .id space then cell-  nuf?
    until then
  then drop r> ;
: words ( "ccc" -- )
  bl parse  dup
  if current begin cell+ @ ?dup while dup >r widwords r> repeat ( all wid )
  else context @ widwords
  then 2drop ;

: named? ( aa -- na | 0 )
  current ( all wid )
  begin cell+ @ dup ( last link ? )
  while dup >r
    begin @ ?dup ( zero link ? )
    while 2dup name> >adr = ( match ? )
       if swap r> 2drop exit ( found )
       then cell-
    repeat r>
  repeat nip ( not found ) ;

: ssee ( a u -- ) ( simple decompiler )
  cells bounds
  begin 2dup xor ( done? )
  while dup named? ?dup if cr .id cr then
    space dup @ >adr named? ?dup
    if .id ( display named token )
    else dup @ 0 u.r ( unnamed token )
    then cell+  nuf?
  until then 2drop ;
: see ( "name" -- ) ( 15.6.1.2194 ) ' >adr -1 ssee ;

( software reset )

: cold ( -- )
  sup 2@ rp! sp! ( init stacks )
  sup @ cell- ( follower ) up ! ( init user pointer )
  status follower !  sup tid !  sup awake ( init tasks )
  0 !io ( init i/o device )
  hex  -1 set-order definitions
  cr [ =version ] literal count type
  cr [ =(c) ] literal count type
  cr quit ;

code bye ( -- ) ( 15.6.2.0830 )
  h# 20 int ( terminate process )
end-code

proc vcold             ( cold start entry )
  cli                  ( disable interrupt for old 808x cpu bug )
  cs ax mov  ax ds mov ( ds=cs )
  ax ss mov            ( ss=cs )
  sup ## bp mov        ( system user pointer )
  1 cells bp [] sp mov ( init sp )
  0 cells bp [] bp mov ( init rp )
  sti                  ( enable interrrupts )
\ =====================
  reset ## dx mov      ( ^c on output ms-dos only )
  h# 2523 ## ax mov    ( set ^c interrupt int23 )
  h# 21 int
\ =====================
  cld                  ( direction flag, increment )
  ' cold ## di mov     ( first word to execute ) \ itc
  0 di [] jmp          ( start eforth )
end-code

cr ( metacompile end ) ]meta

references

   1. mailto:<forth@(www.)calcentral.com>bill muench?subject=eforth license