aboutsummaryrefslogtreecommitdiffstats
path: root/forth/core.fth
blob: 8ec5b71972ed80d458c0a3e9d84b15abcdb8106f (plain)
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
: *        m* drop ;
: s>d      1 m* ;
: /        >r s>d r> _/ ;
: %        >r s>d r> _% ;
: um*      0 swap 0 _uma ;

: cell+    2 + ;
: cells    2 * ;

: .        0 sys ;
: emit     2 sys ;

: 1+       1 + ;
: 1-       1 - ;

: '        _' drop ;
: !        1 _! ;
: @        1 _@ ;
: +!       dup >r swap r> @ + swap ! ;

: base     0 ;
: here     1 cells @ ;
: allot    1 cells +! ;

: c!       0 _! ;
: c@       0 _@ ;
: c,       here c! 1 allot ;
: char+    1+ ;
: chars    ;

: _latest  2 cells ;
: imm      _latest @ dup @ 1 5 << | swap ! ;
: immediate imm ;
: state    3 cells ;
: _compxt  4 cells ;
: _source  5 cells ;
: _sourceu 6 cells ;
: >in      7 cells ;
: _begin   8 cells 80 chars + ;

: ,        here ! 1 cells allot ;

: [        0 state ! ; imm
: ]        1 state ! ;

: literal  [ ' _lit dup , , ] , , ; imm
: [']      ' [ ' literal , ] ; imm

: if       ['] _jmp0 , here 0 , ; imm
: then     here swap ! ; imm
: else     ['] _jmp , here 0 , swap here swap ! ; imm

: postpone _' dup 0 = if exit then
           1 = swap ['] _lit , , if ['] execute ,
           else ['] , , then ; imm

: over     1 pick ;
: rot      >r swap r> swap ;
: -rot     rot rot ;

: 2drop    drop drop ;
: 2dup     over over ;
: 2over    3 pick 3 pick ;
: 2swap    rot >r rot r> ;

: decimal  10 base ! ;

: 2r>      ['] r> , ['] r> , ['] swap , ; imm
: 2>r      ['] swap , ['] >r , ['] >r , ; imm
: r@       ['] r> , ['] dup , ['] >r , ; imm

: 2!       swap over ! cell+ ! ;
: 2@       dup cell+ @ swap @ ;

: 0=       0 = ;
: 0<       0 < ;
: <=       2dup < >r = r> | ;
: >        swap < ;
: <>       = 0= ;

: begin    0 here ; imm
: while    swap 1+ swap postpone if -rot ; imm
: repeat   ['] _jmp , , if postpone then then ; imm
: until    ['] _jmp0 , , drop ; imm

: do       ['] _lit , here 0 , ['] >r , postpone 2>r here ; imm
: unloop   postpone 2r> ['] 2drop , ['] r> , ['] drop , ; imm
: leave    postpone 2r> ['] 2drop , ['] exit , ; imm
: +loop    ['] r> , ['] 2dup , ['] + ,
           postpone r@ ['] swap , ['] >r ,
           ['] - , ['] 2dup , ['] + , ['] over , ['] ^ ,
           ['] rot , ['] rot , ['] ^ , ['] & , ['] _lit , 0 ,
           ['] < , ['] _jmp0 , ,
           postpone unloop here 1 cells - swap ! ; imm
: loop     postpone 2r> ['] 1+ , ['] 2dup ,
           postpone 2>r ['] = , ['] _jmp0 , ,
           postpone unloop here 1 cells - swap ! ; imm
: i        postpone r@ ; imm 
: j        postpone 2r> ['] r> , postpone r@ ['] swap ,
           ['] >r , ['] -rot , postpone 2>r ; imm

: aligned  dup 1 cells 1- swap over & if 1 cells swap - + else drop then ;
: align    here dup aligned swap - allot ;

: and      & ;
: or       | ;
: xor      ^ ;
: lshift   << ;
: rshift   >> ;
: invert   -1 ^ ;
: mod      % ;
: 2*       2 * ;
: _msb     1 1 cells 8 * 1- << ;
: 2/       dup 1 >> swap 0< if _msb or then ;

: /mod     2dup % -rot / ;
: */       >r m* r> _/ ;
: sm/rem   >r 2dup r@ _% -rot r> _/ ;
: */mod    >r m* r> sm/rem ;
: fm/mod   2dup dup >r ^ >r sm/rem swap dup
           if r> 0< if r> + swap 1- else swap r> drop then
           else swap 2r> 2drop then ;

: cr       10 emit ;
: bl       32 ;
: space    bl emit ;
: spaces   begin dup 0 > while space 1- repeat drop ;

: ?dup     dup if dup then ;

: negate   -1 * ;
: abs      dup 0< if negate then ;
: min      2dup <= if drop else swap drop then ;
: max      2dup <= if swap drop else drop then ;

: source   _source @ _sourceu @ ;
: key      _source @ >in @ +
           begin dup c@ 0 = while _in repeat
           c@ 1 >in +! ;
: key?     _source @ >in @ + c@ 0 <> ;
: word     begin key? if key else -1 then 2dup <> until
           key? 0= if 2drop 0 here c! here exit then
           here begin char+ swap over c! swap
           key? if key else dup then
           2dup <> while rot repeat
           2drop here - here c! here ;
: count    dup char+ swap c@ ;
: char     bl word char+ c@ ;
: [char]   char postpone literal ; imm

: (        begin [char] ) key <> while repeat ; imm

: type     begin dup 0 > while swap dup c@ emit char+ swap 1- repeat 2drop ;
: s"       state @ if ['] _jmp , here 0 , then
           [char] " word count
           state @ 0= if exit then
           dup cell+ allot
           rot here swap !
           swap postpone literal postpone literal ; imm
: ."       postpone s" state @ if ['] type , else type then ; imm

: :noname  here dup _compxt ! 0 , here swap ] ;

: create   : here 4 cells + postpone literal postpone ; 0 , ;
: >body    cell+ @ ;

: _does>   >r _latest @ dup @ 31 & + cell+ aligned 2 cells +
           ['] _jmp over ! cell+ r> cell+ swap ! ;

: does>    state @ if
           ['] _lit , here 2 cells + , ['] _does> , ['] exit , else
           here dup _does> dup _compxt ! 0 , ] then ; imm

: variable create 1 cells allot ;
: constant create , does> @ ;

: quit     begin _rdepth 1 > while r> drop repeat postpone [ ;
: abort    begin depth 0 > while drop repeat quit ;
: abort"   postpone s" ['] rot ,
           postpone if ['] type , ['] abort ,
           postpone else ['] 2drop , postpone then ; imm

: recurse  _compxt @ dup @ 31 & + cell+ aligned , ; imm

: move     dup 0 <= if drop 2drop exit then
           >r 2dup < r> swap if
           1- 0 swap do over i + c@ over i + c! -1 +loop
           else
           0 do over i + c@ over i + c! loop
           then 2drop ;
: fill     -rot begin dup 0 > while
           >r 2dup c! char+ r> 1- repeat
           2drop drop ;

: environment? 2drop 1 0= ;

: accept   over >r begin dup 0 > while
           key dup 32 < if 2drop 0
           else dup emit rot 2dup c! char+ swap drop swap 1- then
           repeat drop r> - 1 chars / ;

: evaluate _source @ >r _sourceu @ >r >in @ >r
           0 >in ! _sourceu ! _source ! _ev
           r> >in ! r> _sourceu ! r> _source ! ;

: _isdigit ( ch -- bch )
  dup [char] 0 over <= swap [char] 0 base @ 10 min 1- + <= and
  if drop [char] 0 exit then
  base @ 11 < if drop 0 exit then
  base @ 36 min 10 - >r
  dup [char] a over <= swap [char] a r@ + < and
  if r> 2drop [char] a 10 - exit then
  [char] A over <= swap [char] A r> + < and
  if [char] A 10 - else 0 then ;
: >number  begin dup 0 >
           dup if drop over c@ _isdigit then while
           >r dup c@ swap >r base @ swap
           dup _isdigit - _uma
           r> char+ r> 1- repeat ;

: <#       40 here c! ;
: #>       2drop here dup c@ + 40 here c@ - ;
: hold     -1 here +! here dup c@ + c! ;
: #        base @
           >r 0 i um/mod r> swap >r um/mod r>
           rot 9 over <
           if 7 + then 48 + hold ;
: #s       begin # 2dup or 0= until ;
: sign     0< if [char] - hold then ;

: u.       0 <# bl hold #s #> type ;