[gforth] / gforth / kernel / int.fs  

gforth: gforth/kernel/int.fs


1 : pazsan 1.1 \ definitions needed for interpreter only
2 :    
3 : anton 1.90 \ Copyright (C) 1995-2000 Free Software Foundation, Inc.
4 : anton 1.11
5 :     \ This file is part of Gforth.
6 :    
7 :     \ Gforth is free software; you can redistribute it and/or
8 :     \ modify it under the terms of the GNU General Public License
9 :     \ as published by the Free Software Foundation; either version 2
10 :     \ of the License, or (at your option) any later version.
11 :    
12 :     \ This program is distributed in the hope that it will be useful,
13 :     \ but WITHOUT ANY WARRANTY; without even the implied warranty of
14 :     \ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 :     \ GNU General Public License for more details.
16 :    
17 :     \ You should have received a copy of the GNU General Public License
18 :     \ along with this program; if not, write to the Free Software
19 : anton 1.63 \ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
20 : anton 1.11
21 : pazsan 1.1 \ \ Revision-Log
22 :    
23 :     \ put in seperate file 14sep97jaw
24 :    
25 :     \ \ input stream primitives 23feb93py
26 :    
27 : jwilke 1.33 require ./basics.fs \ bounds decimal hex ...
28 :     require ./io.fs \ type ...
29 :     require ./nio.fs \ . <# ...
30 :     require ./errore.fs \ .error ...
31 : anton 1.50 require kernel/version.fs \ version-string
32 : jwilke 1.33 require ./../chains.fs
33 :    
34 : pazsan 1.64 has? new-input 0= [IF]
35 : crook 1.43 : tib ( -- c-addr ) \ core-ext t-i-b
36 : crook 1.40 \G @i{c-addr} is the address of the Terminal Input Buffer.
37 : crook 1.29 \G OBSOLESCENT: @code{source} superceeds the function of this word.
38 : pazsan 1.1 >tib @ ;
39 :    
40 : crook 1.29 Defer source ( -- c-addr u ) \ core
41 : pazsan 1.1 \ used by dodefer:, must be defer
42 : crook 1.40 \G @i{c-addr} is the address of the input buffer and @i{u} is the
43 : crook 1.29 \G number of characters in it.
44 : pazsan 1.1
45 : crook 1.29 : (source) ( -- c-addr u )
46 : pazsan 1.1 tib #tib @ ;
47 :     ' (source) IS source
48 : pazsan 1.64 [THEN]
49 : pazsan 1.1
50 :     : (word) ( addr1 n1 char -- addr2 n2 )
51 :     dup >r skip 2dup r> scan nip - ;
52 :    
53 :     \ (word) should fold white spaces
54 :     \ this is what (parse-white) does
55 :    
56 :     \ word parse 23feb93py
57 :    
58 : crook 1.29 : sword ( char -- addr len ) \ gforth s-word
59 : crook 1.40 \G Parses like @code{word}, but the output is like @code{parse} output.
60 : anton 1.47 \G @xref{core-idef}.
61 : anton 1.3 \ this word was called PARSE-WORD until 0.3.0, but Open Firmware and
62 :     \ dpANS6 A.6.2.2008 have a word with that name that behaves
63 :     \ differently (like NAME).
64 : pazsan 1.1 source 2dup >r >r >in @ over min /string
65 :     rot dup bl = IF drop (parse-white) ELSE (word) THEN
66 :     2dup + r> - 1+ r> min >in ! ;
67 :    
68 : crook 1.29 : word ( char "<chars>ccc<char>-- c-addr ) \ core
69 : crook 1.40 \G Skip leading delimiters. Parse @i{ccc}, delimited by
70 :     \G @i{char}, in the parse area. @i{c-addr} is the address of a
71 : crook 1.29 \G transient region containing the parsed string in
72 : crook 1.40 \G counted-string format. If the parse area was empty or
73 : crook 1.29 \G contained no characters other than delimiters, the resulting
74 :     \G string has zero length. A program may replace characters within
75 :     \G the counted string. OBSOLESCENT: the counted string has a
76 :     \G trailing space that is not included in its length.
77 :     sword here place bl here count + c! here ;
78 :    
79 :     : parse ( char "ccc<char>" -- c-addr u ) \ core-ext
80 : anton 1.80 \G Parse @i{ccc}, delimited by @i{char}, in the parse
81 :     \G area. @i{c-addr u} specifies the parsed string within the
82 :     \G parse area. If the parse area was empty, @i{u} is 0.
83 : crook 1.29 >r source >in @ over min /string over swap r> scan >r
84 : anton 1.80 over - dup r> IF 1+ THEN >in +! ;
85 : pazsan 1.1
86 :     \ name 13feb93py
87 :    
88 :     [IFUNDEF] (name) \ name might be a primitive
89 :    
90 : crook 1.40 : (name) ( -- c-addr count ) \ gforth
91 : pazsan 1.1 source 2dup >r >r >in @ /string (parse-white)
92 :     2dup + r> - 1+ r> min >in ! ;
93 :     \ name count ;
94 :     [THEN]
95 :    
96 :     : name-too-short? ( c-addr u -- c-addr u )
97 :     dup 0= -&16 and throw ;
98 :    
99 :     : name-too-long? ( c-addr u -- c-addr u )
100 : anton 1.67 dup lcount-mask u> -&19 and throw ;
101 : pazsan 1.1
102 :     \ \ Number parsing 23feb93py
103 :    
104 :     \ number? number 23feb93py
105 :    
106 :     hex
107 :     const Create bases 10 , 2 , A , 100 ,
108 :     \ 16 2 10 character
109 :    
110 : anton 1.18 \ !! protect BASE saving wrapper against exceptions
111 : pazsan 1.1 : getbase ( addr u -- addr' u' )
112 :     over c@ [char] $ - dup 4 u<
113 :     IF
114 :     cells bases + @ base ! 1 /string
115 :     ELSE
116 :     drop
117 :     THEN ;
118 :    
119 : pazsan 1.20 : sign? ( addr u -- addr u flag )
120 : jwilke 1.33 over c@ [char] - = dup >r
121 : pazsan 1.1 IF
122 :     1 /string
123 :     THEN
124 : pazsan 1.20 r> ;
125 :    
126 :     : s>unumber? ( addr u -- ud flag )
127 : pazsan 1.21 base @ >r dpl on getbase
128 : pazsan 1.20 0. 2swap
129 : anton 1.18 BEGIN ( d addr len )
130 : pazsan 1.1 dup >r >number dup
131 : anton 1.18 WHILE \ there are characters left
132 : pazsan 1.1 dup r> -
133 : anton 1.18 WHILE \ the last >number parsed something
134 :     dup 1- dpl ! over c@ [char] . =
135 :     WHILE \ the current char is '.'
136 : pazsan 1.1 1 /string
137 : anton 1.18 REPEAT THEN \ there are unparseable characters left
138 : pazsan 1.21 2drop false
139 : pazsan 1.20 ELSE
140 :     rdrop 2drop true
141 : pazsan 1.21 THEN
142 :     r> base ! ;
143 : pazsan 1.20
144 :     \ ouch, this is complicated; there must be a simpler way - anton
145 :     : s>number? ( addr len -- d f )
146 :     \ converts string addr len into d, flag indicates success
147 : pazsan 1.21 sign? >r
148 : pazsan 1.20 s>unumber?
149 :     0= IF
150 : pazsan 1.21 rdrop false
151 : anton 1.18 ELSE \ no characters left, all ok
152 : pazsan 1.20 r>
153 : pazsan 1.1 IF
154 :     dnegate
155 :     THEN
156 : anton 1.18 true
157 : pazsan 1.21 THEN ;
158 : pazsan 1.1
159 : anton 1.18 : s>number ( addr len -- d )
160 :     \ don't use this, there is no way to tell success
161 :     s>number? drop ;
162 :    
163 : pazsan 1.1 : snumber? ( c-addr u -- 0 / n -1 / d 0> )
164 : anton 1.18 s>number? 0=
165 : pazsan 1.1 IF
166 :     2drop false EXIT
167 :     THEN
168 : anton 1.18 dpl @ dup 0< IF
169 : pazsan 1.1 nip
170 : anton 1.18 ELSE
171 :     1+
172 : pazsan 1.1 THEN ;
173 :    
174 :     : number? ( string -- string 0 / n -1 / d 0> )
175 :     dup >r count snumber? dup if
176 :     rdrop
177 :     else
178 :     r> swap
179 :     then ;
180 :    
181 :     : number ( string -- d )
182 :     number? ?dup 0= abort" ?" 0<
183 :     IF
184 :     s>d
185 :     THEN ;
186 :    
187 :     \ \ Comments ( \ \G
188 :    
189 : crook 1.29 : ( ( compilation 'ccc<close-paren>' -- ; run-time -- ) \ thisone- core,file paren
190 : crook 1.17 \G ** this will not get annotated. The alias in glocals.fs will instead **
191 : crook 1.29 \G It does not work to use "wordset-" prefix since this file is glossed
192 :     \G by cross.fs which doesn't have the same functionalty as makedoc.fs
193 : pazsan 1.1 [char] ) parse 2drop ; immediate
194 :    
195 : anton 1.51 : \ ( compilation 'ccc<newline>' -- ; run-time -- ) \ thisone- core-ext,block-ext backslash
196 : crook 1.29 \G ** this will not get annotated. The alias in glocals.fs will instead **
197 :     \G It does not work to use "wordset-" prefix since this file is glossed
198 :     \G by cross.fs which doesn't have the same functionalty as makedoc.fs
199 : pazsan 1.12 [ has? file [IF] ]
200 : pazsan 1.1 blk @
201 :     IF
202 :     >in @ c/l / 1+ c/l * >in !
203 :     EXIT
204 :     THEN
205 : pazsan 1.12 [ [THEN] ]
206 : pazsan 1.1 source >in ! drop ; immediate
207 :    
208 : anton 1.51 : \G ( compilation 'ccc<newline>' -- ; run-time -- ) \ gforth backslash-gee
209 : crook 1.19 \G Equivalent to @code{\} but used as a tag to annotate definition
210 :     \G comments into documentation.
211 : pazsan 1.1 POSTPONE \ ; immediate
212 :    
213 :     \ \ object oriented search list 17mar93py
214 :    
215 :     \ word list structure:
216 :    
217 :     struct
218 :     cell% field find-method \ xt: ( c_addr u wid -- nt )
219 :     cell% field reveal-method \ xt: ( nt wid -- ) \ used by dofield:, must be field
220 :     cell% field rehash-method \ xt: ( wid -- ) \ re-initializes a "search-data" (hashtables)
221 :     cell% field hash-method \ xt: ( wid -- ) \ initializes ""
222 :     \ \ !! what else
223 :     end-struct wordlist-map-struct
224 :    
225 :     struct
226 : pazsan 1.6 cell% field wordlist-map \ pointer to a wordlist-map-struct
227 : anton 1.13 cell% field wordlist-id \ linked list of words (for WORDS etc.)
228 : pazsan 1.1 cell% field wordlist-link \ link field to other wordlists
229 : anton 1.13 cell% field wordlist-extend \ wordlist extensions (eg bucket offset)
230 : pazsan 1.1 end-struct wordlist-struct
231 :    
232 : pazsan 1.103 has? f83headerstring [IF]
233 :     : f83find ( addr len wordlist -- nt / false )
234 :     wordlist-id @ (f83find) ;
235 :     [ELSE]
236 : pazsan 1.1 : f83find ( addr len wordlist -- nt / false )
237 : anton 1.67 wordlist-id @ (listlfind) ;
238 : pazsan 1.103 [THEN]
239 : pazsan 1.1
240 :     : initvoc ( wid -- )
241 :     dup wordlist-map @ hash-method perform ;
242 :    
243 :     \ Search list table: find reveal
244 :     Create f83search ( -- wordlist-map )
245 :     ' f83find A, ' drop A, ' drop A, ' drop A,
246 :    
247 : pazsan 1.6 here G f83search T A, NIL A, NIL A, NIL A,
248 : pazsan 1.1 AValue forth-wordlist \ variable, will be redefined by search.fs
249 :    
250 :     AVariable lookup forth-wordlist lookup !
251 :     \ !! last is user and lookup?! jaw
252 :     AVariable current ( -- addr ) \ gforth
253 : crook 1.43 \G @code{Variable} -- holds the @i{wid} of the compilation word list.
254 : pazsan 1.1 AVariable voclink forth-wordlist wordlist-link voclink !
255 : anton 1.38 \ lookup AValue context ( -- addr ) \ gforth
256 :     Defer context ( -- addr ) \ gforth
257 : crook 1.43 \G @code{context} @code{@@} is the @i{wid} of the word list at the
258 :     \G top of the search order.
259 : pazsan 1.1
260 : anton 1.38 ' lookup is context
261 : pazsan 1.1 forth-wordlist current !
262 :    
263 :     \ \ header, finding, ticks 17dec92py
264 :    
265 : pazsan 1.69 \ The constants are defined as 32 bits, but then erased
266 :     \ and overwritten by the right ones
267 : anton 1.67
268 : pazsan 1.103 has? f83headerstring [IF]
269 :     \ to save space, Gforth EC limits words to 31 characters
270 :     $80 constant alias-mask
271 :     $40 constant immediate-mask
272 :     $20 constant restrict-mask
273 :     $1f constant lcount-mask
274 :     [ELSE]
275 : anton 1.67 $80000000 constant alias-mask
276 : pazsan 1.69 1 bits/char 1 - lshift
277 :     -1 cells allot bigendian [IF] c, 0 1 cells 1- times
278 :     [ELSE] 0 1 cells 1- times c, [THEN]
279 : anton 1.67 $40000000 constant immediate-mask
280 : pazsan 1.69 1 bits/char 2 - lshift
281 :     -1 cells allot bigendian [IF] c, 0 1 cells 1- times
282 :     [ELSE] 0 1 cells 1- times c, [THEN]
283 : anton 1.67 $20000000 constant restrict-mask
284 : pazsan 1.69 1 bits/char 3 - lshift
285 :     -1 cells allot bigendian [IF] c, 0 1 cells 1- times
286 :     [ELSE] 0 1 cells 1- times c, [THEN]
287 : anton 1.67 $1fffffff constant lcount-mask
288 : pazsan 1.69 1 bits/char 3 - lshift 1 -
289 : pazsan 1.71 -1 cells allot bigendian [IF] c, -1 1 cells 1- times
290 :     [ELSE] -1 1 cells 1- times c, [THEN]
291 : pazsan 1.103 [THEN]
292 : pazsan 1.1
293 :     \ higher level parts of find
294 :    
295 :     : flag-sign ( f -- 1|-1 )
296 :     \ true becomes 1, false -1
297 :     0= 2* 1+ ;
298 :    
299 : anton 1.79 : ticking-compile-only-error ( ... -- )
300 :     -&2048 throw ;
301 : pazsan 1.1
302 : anton 1.93 : compile-only-error ( ... -- )
303 :     -&14 throw ;
304 :    
305 : pazsan 1.1 : (cfa>int) ( cfa -- xt )
306 :     [ has? compiler [IF] ]
307 :     dup interpret/compile?
308 :     if
309 :     interpret/compile-int @
310 :     then
311 :     [ [THEN] ] ;
312 :    
313 : anton 1.67 : (x>int) ( cfa w -- xt )
314 : pazsan 1.1 \ get interpretation semantics of name
315 :     restrict-mask and
316 :     if
317 : anton 1.93 drop ['] compile-only-error
318 : pazsan 1.1 else
319 :     (cfa>int)
320 :     then ;
321 :    
322 : pazsan 1.103 has? f83headerstring [IF]
323 :     : name>string ( nt -- addr count ) \ gforth head-to-string
324 :     \g @i{addr count} is the name of the word represented by @i{nt}.
325 :     cell+ count lcount-mask and ;
326 :    
327 :     : ((name>)) ( nfa -- cfa )
328 :     name>string + cfaligned ;
329 :    
330 :     : (name>x) ( nfa -- cfa w )
331 :     \ cfa is an intermediate cfa and w is the flags cell of nfa
332 :     dup ((name>))
333 :     swap cell+ c@ dup alias-mask and 0=
334 :     IF
335 :     swap @ swap
336 :     THEN ;
337 :     [ELSE]
338 : pazsan 1.1 : name>string ( nt -- addr count ) \ gforth head-to-string
339 : crook 1.40 \g @i{addr count} is the name of the word represented by @i{nt}.
340 : anton 1.67 cell+ dup cell+ swap @ lcount-mask and ;
341 : pazsan 1.1
342 :     : ((name>)) ( nfa -- cfa )
343 :     name>string + cfaligned ;
344 :    
345 : anton 1.67 : (name>x) ( nfa -- cfa w )
346 :     \ cfa is an intermediate cfa and w is the flags cell of nfa
347 : pazsan 1.1 dup ((name>))
348 : anton 1.67 swap cell+ @ dup alias-mask and 0=
349 : pazsan 1.1 IF
350 :     swap @ swap
351 :     THEN ;
352 : pazsan 1.103 [THEN]
353 : pazsan 1.1
354 :     : name>int ( nt -- xt ) \ gforth
355 : crook 1.31 \G @i{xt} represents the interpretation semantics of the word
356 :     \G @i{nt}. If @i{nt} has no interpretation semantics (i.e. is
357 :     \G @code{compile-only}), @i{xt} is the execution token for
358 : anton 1.79 \G @code{ticking-compile-only-error}, which performs @code{-2048 throw}.
359 : pazsan 1.1 (name>x) (x>int) ;
360 :    
361 :     : name?int ( nt -- xt ) \ gforth
362 : anton 1.79 \G Like @code{name>int}, but perform @code{-2048 throw} if @i{nt}
363 : crook 1.31 \G has no interpretation semantics.
364 : pazsan 1.1 (name>x) restrict-mask and
365 :     if
366 : anton 1.79 ticking-compile-only-error \ does not return
367 : pazsan 1.1 then
368 :     (cfa>int) ;
369 :    
370 :     : (name>comp) ( nt -- w +-1 ) \ gforth
371 : crook 1.31 \G @i{w xt} is the compilation token for the word @i{nt}.
372 : pazsan 1.1 (name>x) >r
373 :     [ has? compiler [IF] ]
374 :     dup interpret/compile?
375 :     if
376 :     interpret/compile-comp @
377 :     then
378 :     [ [THEN] ]
379 :     r> immediate-mask and flag-sign
380 :     ;
381 :    
382 :     : (name>intn) ( nfa -- xt +-1 )
383 : anton 1.67 (name>x) tuck (x>int) ( w xt )
384 : pazsan 1.1 swap immediate-mask and flag-sign ;
385 :    
386 : pazsan 1.72 const Create ??? 0 , 3 , char ? c, char ? c, char ? c,
387 : jwilke 1.30 \ ??? is used by dovar:, must be created/:dovar
388 :    
389 :     [IFDEF] forthstart
390 :     \ if we have a forthstart we can define head? with it
391 :     \ otherwise leave out the head? check
392 :    
393 : anton 1.14 : head? ( addr -- f )
394 : anton 1.82 \G heuristic check whether addr is a name token; may deliver false
395 :     \G positives; addr must be a valid address; returns 1 for
396 :     \G particularly unsafe positives
397 : anton 1.14 \ we follow the link fields and check for plausibility; two
398 :     \ iterations should catch most false addresses: on the first
399 :     \ iteration, we may get an xt, on the second a code address (or
400 :     \ some code), which is typically not in the dictionary.
401 : anton 1.82 \ we added a third iteration for working with code and ;code words.
402 :     3 0 do
403 : anton 1.41 dup dup aligned <> if \ protect @ against unaligned accesses
404 :     drop false unloop exit
405 :     then
406 : anton 1.14 dup @ dup
407 :     if ( addr addr1 )
408 :     dup rot forthstart within
409 :     if \ addr1 is outside forthstart..addr, not a head
410 :     drop false unloop exit
411 :     then ( addr1 )
412 :     else \ 0 in the link field, no further checks
413 : anton 1.81 2drop 1 unloop exit \ this is very unsure, so return 1
414 : anton 1.14 then
415 :     loop
416 :     \ in dubio pro:
417 :     drop true ;
418 :    
419 : anton 1.48 : >head-noprim ( cfa -- nt ) \ gforth to-head-noprim
420 : anton 1.97 \ also heuristic
421 :     dup forthstart - max-name-length @ float+ cell+ min cell max cell ?do ( cfa )
422 : pazsan 1.70 dup i - dup @ [ alias-mask lcount-mask or ] literal
423 :     [ 1 bits/char 3 - lshift 1 - 1 bits/char 1 - lshift or
424 : pazsan 1.71 -1 cells allot bigendian [IF] c, -1 1 cells 1- times
425 :     [ELSE] -1 1 cells 1- times c, [THEN] ]
426 : pazsan 1.70 and ( cfa len|alias )
427 : anton 1.97 swap + cell+ cfaligned over alias-mask + =
428 : anton 1.14 if ( cfa )
429 :     dup i - cell - dup head?
430 :     if
431 :     nip unloop exit
432 :     then
433 :     drop
434 :     then
435 :     cell +loop
436 :     drop ??? ( wouldn't 0 be better? ) ;
437 : pazsan 1.1
438 : jwilke 1.30 [ELSE]
439 :    
440 : anton 1.48 : >head-noprim ( cfa -- nt ) \ gforth to-head-noprim
441 : pazsan 1.45 $25 cell do ( cfa )
442 : pazsan 1.70 dup i - dup @ [ alias-mask lcount-mask or ] literal
443 :     [ 1 bits/char 3 - lshift 1 - 1 bits/char 1 - lshift or
444 : pazsan 1.71 -1 cells allot bigendian [IF] c, -1 1 cells 1- times
445 :     [ELSE] -1 1 cells 1- times c, [THEN] ]
446 : pazsan 1.70 and ( cfa len|alias )
447 : anton 1.67 swap + cell + cfaligned over alias-mask + =
448 : jwilke 1.30 if ( cfa ) i - cell - unloop exit
449 :     then
450 :     cell +loop
451 :     drop ??? ( wouldn't 0 be better? ) ;
452 :    
453 :     [THEN]
454 : pazsan 1.1
455 : anton 1.83 cell% 2* 0 0 field >body ( xt -- a_addr ) \ core
456 :     \G Get the address of the body of the word represented by @i{xt} (the
457 :     \G address of the word's data field).
458 :     drop drop
459 :    
460 :     cell% -2 * 0 0 field body> ( xt -- a_addr )
461 : anton 1.84 drop drop
462 :    
463 :     has? standardthreading has? compiler and [IF]
464 :    
465 :     ' @ alias >code-address ( xt -- c_addr ) \ gforth
466 :     \G @i{c-addr} is the code address of the word @i{xt}.
467 :    
468 :     : >does-code ( xt -- a_addr ) \ gforth
469 :     \G If @i{xt} is the execution token of a child of a @code{DOES>} word,
470 :     \G @i{a-addr} is the start of the Forth code after the @code{DOES>};
471 :     \G Otherwise @i{a-addr} is 0.
472 :     dup @ dodoes: = if
473 :     cell+ @
474 :     else
475 :     drop 0
476 :     endif ;
477 :    
478 : anton 1.85 ' ! alias code-address! ( c_addr xt -- ) \ gforth
479 :     \G Create a code field with code address @i{c-addr} at @i{xt}.
480 :    
481 :     : does-code! ( a_addr xt -- ) \ gforth
482 :     \G Create a code field at @i{xt} for a child of a @code{DOES>}-word;
483 :     \G @i{a-addr} is the start of the Forth code after @code{DOES>}.
484 :     dodoes: over ! cell+ ! ;
485 :    
486 : anton 1.86 ' drop alias does-handler! ( a_addr -- ) \ gforth
487 :     \G Create a @code{DOES>}-handler at address @i{a-addr}. Normally,
488 :     \G @i{a-addr} points just behind a @code{DOES>}.
489 :    
490 : anton 1.85 2 cells constant /does-handler ( -- n ) \ gforth
491 :     \G The size of a @code{DOES>}-handler (includes possible padding).
492 :    
493 : anton 1.84 [THEN]
494 : pazsan 1.1
495 : crook 1.31 : (search-wordlist) ( addr count wid -- nt | false )
496 : pazsan 1.1 dup wordlist-map @ find-method perform ;
497 :    
498 : crook 1.31 : search-wordlist ( c-addr count wid -- 0 | xt +-1 ) \ search
499 : anton 1.53 \G Search the word list identified by @i{wid} for the definition
500 :     \G named by the string at @i{c-addr count}. If the definition is
501 :     \G not found, return 0. If the definition is found return 1 (if
502 :     \G the definition is immediate) or -1 (if the definition is not
503 :     \G immediate) together with the @i{xt}. In Gforth, the @i{xt}
504 :     \G returned represents the interpretation semantics. ANS Forth
505 :     \G does not specify clearly what @i{xt} represents.
506 : pazsan 1.1 (search-wordlist) dup if
507 :     (name>intn)
508 :     then ;
509 :    
510 : crook 1.31 : find-name ( c-addr u -- nt | 0 ) \ gforth
511 :     \g Find the name @i{c-addr u} in the current search
512 :     \g order. Return its @i{nt}, if found, otherwise 0.
513 : pazsan 1.1 lookup @ (search-wordlist) ;
514 :    
515 :     : sfind ( c-addr u -- 0 / xt +-1 ) \ gforth-obsolete
516 :     find-name dup
517 :     if ( nt )
518 :     state @
519 :     if
520 :     (name>comp)
521 :     else
522 :     (name>intn)
523 :     then
524 :     then ;
525 :    
526 : crook 1.31 : find ( c-addr -- xt +-1 | c-addr 0 ) \ core,search
527 : anton 1.53 \G Search all word lists in the current search order for the
528 :     \G definition named by the counted string at @i{c-addr}. If the
529 :     \G definition is not found, return 0. If the definition is found
530 :     \G return 1 (if the definition has non-default compilation
531 :     \G semantics) or -1 (if the definition has default compilation
532 :     \G semantics). The @i{xt} returned in interpret state represents
533 :     \G the interpretation semantics. The @i{xt} returned in compile
534 :     \G state represented either the compilation semantics (for
535 :     \G non-default compilation semantics) or the run-time semantics
536 :     \G that the compilation semantics would @code{compile,} (for
537 :     \G default compilation semantics). The ANS Forth standard does
538 :     \G not specify clearly what the returned @i{xt} represents (and
539 :     \G also talks about immediacy instead of non-default compilation
540 :     \G semantics), so this word is questionable in portable programs.
541 :     \G If non-portability is ok, @code{find-name} and friends are
542 :     \G better (@pxref{Name token}).
543 : pazsan 1.1 dup count sfind dup
544 :     if
545 :     rot drop
546 :     then ;
547 :    
548 : jwilke 1.34 \ ticks in interpreter
549 : pazsan 1.1
550 :     : (') ( "name" -- nt ) \ gforth
551 : anton 1.32 name name-too-short?
552 : anton 1.28 find-name dup 0=
553 : pazsan 1.1 IF
554 : anton 1.42 drop -&13 throw
555 : pazsan 1.1 THEN ;
556 :    
557 :     : ' ( "name" -- xt ) \ core tick
558 : crook 1.31 \g @i{xt} represents @i{name}'s interpretation
559 :     \g semantics. Perform @code{-14 throw} if the word has no
560 : pazsan 1.1 \g interpretation semantics.
561 :     (') name?int ;
562 : jwilke 1.34
563 :     has? compiler 0= [IF] \ interpreter only version of IS and TO
564 :    
565 :     : IS ' >body ! ;
566 :     ' IS Alias TO
567 :    
568 :     [THEN]
569 : pazsan 1.1
570 :     \ \ the interpreter loop mar92py
571 :    
572 :     \ interpret 10mar92py
573 :    
574 : anton 1.37 Defer parser ( c-addr u -- )
575 : anton 1.100 Defer parse-word ( "name" -- c-addr u ) \ gforth
576 : anton 1.55 \G Get the next word from the input buffer
577 : anton 1.77 ' (name) IS parse-word
578 :    
579 :     ' parse-word alias name ( -- c-addr u ) \ gforth-obsolete
580 :     \G old name for @code{parse-word}
581 :    
582 : pazsan 1.1 Defer compiler-notfound ( c-addr count -- )
583 :     Defer interpreter-notfound ( c-addr count -- )
584 :    
585 :     : no.extensions ( addr u -- )
586 : anton 1.42 2drop -&13 throw ;
587 : pazsan 1.1 ' no.extensions IS compiler-notfound
588 :     ' no.extensions IS interpreter-notfound
589 :    
590 : anton 1.66 : interpret1 ( ... -- ... )
591 : jwilke 1.33 [ has? backtrace [IF] ]
592 : anton 1.24 rp@ backtrace-rp0 !
593 : jwilke 1.33 [ [THEN] ]
594 : pazsan 1.1 BEGIN
595 :     ?stack name dup
596 :     WHILE
597 :     parser
598 :     REPEAT
599 : anton 1.66 2drop ;
600 :    
601 :     : interpret ( ?? -- ?? ) \ gforth
602 :     \ interpret/compile the (rest of the) input buffer
603 :     [ has? backtrace [IF] ]
604 :     backtrace-rp0 @ >r
605 :     [ [THEN] ]
606 :     ['] interpret1 catch
607 : anton 1.65 [ has? backtrace [IF] ]
608 :     r> backtrace-rp0 !
609 : anton 1.66 [ [THEN] ]
610 :     throw ;
611 : pazsan 1.1
612 :     \ interpreter 30apr92py
613 :    
614 :     \ not the most efficient implementations of interpreter and compiler
615 : jwilke 1.33 : interpreter ( c-addr u -- )
616 : pazsan 1.1 2dup find-name dup
617 :     if
618 :     nip nip name>int execute
619 :     else
620 :     drop
621 :     2dup 2>r snumber?
622 :     IF
623 :     2rdrop
624 :     ELSE
625 :     2r> interpreter-notfound
626 :     THEN
627 :     then ;
628 :    
629 :     ' interpreter IS parser
630 :    
631 :     \ \ Query Evaluate 07apr93py
632 :    
633 :     has? file 0= [IF]
634 : pazsan 1.12 : sourceline# ( -- n ) 1 ;
635 : pazsan 1.61 [ELSE]
636 : pazsan 1.64 has? new-input 0= [IF]
637 : pazsan 1.58 Variable #fill-bytes
638 :     \G number of bytes read via (read-line) by the last refill
639 : pazsan 1.61 [THEN]
640 : pazsan 1.64 [THEN]
641 : pazsan 1.58
642 : pazsan 1.64 has? new-input 0= [IF]
643 : pazsan 1.1 : refill ( -- flag ) \ core-ext,block-ext,file-ext
644 : crook 1.29 \G Attempt to fill the input buffer from the input source. When
645 :     \G the input source is the user input device, attempt to receive
646 :     \G input into the terminal input device. If successful, make the
647 :     \G result the input buffer, set @code{>IN} to 0 and return true;
648 :     \G otherwise return false. When the input source is a block, add 1
649 :     \G to the value of @code{BLK} to make the next block the input
650 :     \G source and current input buffer, and set @code{>IN} to 0;
651 :     \G return true if the new value of @code{BLK} is a valid block
652 :     \G number, false otherwise. When the input source is a text file,
653 :     \G attempt to read the next line from the file. If successful,
654 :     \G make the result the current input buffer, set @code{>IN} to 0
655 :     \G and return true; otherwise, return false. A successful result
656 :     \G includes receipt of a line containing 0 characters.
657 : pazsan 1.12 [ has? file [IF] ]
658 :     blk @ IF 1 blk +! true 0 >in ! EXIT THEN
659 :     [ [THEN] ]
660 :     tib /line
661 :     [ has? file [IF] ]
662 :     loadfile @ ?dup
663 : pazsan 1.59 IF (read-line) throw #fill-bytes !
664 : pazsan 1.12 ELSE
665 :     [ [THEN] ]
666 :     sourceline# 0< IF 2drop false EXIT THEN
667 :     accept true
668 :     [ has? file [IF] ]
669 :     THEN
670 :     1 loadline +!
671 :     [ [THEN] ]
672 :     swap #tib ! 0 >in ! ;
673 : pazsan 1.1
674 :     : query ( -- ) \ core-ext
675 : crook 1.29 \G Make the user input device the input source. Receive input into
676 :     \G the Terminal Input Buffer. Set @code{>IN} to zero. OBSOLESCENT:
677 :     \G superceeded by @code{accept}.
678 : pazsan 1.12 [ has? file [IF] ]
679 :     blk off loadfile off
680 :     [ [THEN] ]
681 : pazsan 1.64 refill drop ;
682 :     [THEN]
683 : pazsan 1.1
684 :     \ save-mem extend-mem
685 :    
686 :     has? os [IF]
687 :     : save-mem ( addr1 u -- addr2 u ) \ gforth
688 :     \g copy a memory block into a newly allocated region in the heap
689 :     swap >r
690 :     dup allocate throw
691 :     swap 2dup r> -rot move ;
692 :    
693 : anton 1.68 : free-mem-var ( addr -- )
694 :     \ addr is the address of a 2variable containing address and size
695 :     \ of a memory range; frees memory and clears the 2variable.
696 :     dup 2@ drop dup
697 :     if ( addr mem-start )
698 :     free throw
699 :     0 0 rot 2!
700 :     else
701 :     2drop
702 :     then ;
703 :    
704 : pazsan 1.1 : extend-mem ( addr1 u1 u -- addr addr2 u2 )
705 :     \ extend memory block allocated from the heap by u aus
706 :     \ the (possibly reallocated piece is addr2 u2, the extension is at addr
707 :     over >r + dup >r resize throw
708 :     r> over r> + -rot ;
709 :     [THEN]
710 :    
711 :     \ EVALUATE 17may93jaw
712 :    
713 : pazsan 1.64 has? file 0= has? new-input 0= and [IF]
714 : pazsan 1.1 : push-file ( -- ) r>
715 : pazsan 1.12 tibstack @ >r >tib @ >r #tib @ >r
716 : pazsan 1.1 >tib @ tibstack @ = IF r@ tibstack +! THEN
717 :     tibstack @ >tib ! >in @ >r >r ;
718 :    
719 :     : pop-file ( throw-code -- throw-code )
720 :     r>
721 : pazsan 1.12 r> >in ! r> #tib ! r> >tib ! r> tibstack ! >r ;
722 : pazsan 1.1 [THEN]
723 :    
724 : pazsan 1.64 has? new-input 0= [IF]
725 : crook 1.29 : evaluate ( c-addr u -- ) \ core,block
726 : crook 1.40 \G Save the current input source specification. Store @code{-1} in
727 :     \G @code{source-id} and @code{0} in @code{blk}. Set @code{>IN} to
728 :     \G @code{0} and make the string @i{c-addr u} the input source
729 :     \G and input buffer. Interpret. When the parse area is empty,
730 :     \G restore the input source specification.
731 : pazsan 1.64 [ has? file [IF] ]
732 : anton 1.92 s" *evaluated string*" loadfilename>r
733 : pazsan 1.64 [ [THEN] ]
734 : crook 1.40 push-file #tib ! >tib !
735 : crook 1.29 >in off
736 :     [ has? file [IF] ]
737 :     blk off loadfile off -1 loadline !
738 :     [ [THEN] ]
739 :     ['] interpret catch
740 : anton 1.56 pop-file
741 : pazsan 1.64 [ has? file [IF] ]
742 : anton 1.92 r>loadfilename
743 : pazsan 1.64 [ [THEN] ]
744 : anton 1.56 throw ;
745 : pazsan 1.64 [THEN]
746 : pazsan 1.1
747 :     \ \ Quit 13feb93py
748 :    
749 :     Defer 'quit
750 :    
751 :     Defer .status
752 :    
753 :     : prompt state @ IF ." compiled" EXIT THEN ." ok" ;
754 :    
755 : anton 1.39 : (quit) ( -- )
756 :     \ exits only through THROW etc.
757 : anton 1.42 \ sp0 @ cell - handler @ &12 + ! \ !! kludge: fix the stack pointer
758 : anton 1.39 \ stored in the system's CATCH frame, so the stack depth will be 0
759 :     \ after the next THROW it catches (it may be off due to BOUNCEs or
760 :     \ because process-args left something on the stack)
761 :     BEGIN
762 : anton 1.98 .status
763 :     ['] cr catch if
764 : anton 1.99 >stderr cr ." Can't print to stdout, leaving" cr
765 : anton 1.98 \ if stderr does not work either, already DoError causes a hang
766 :     2 (bye)
767 :     endif
768 :     query interpret prompt
769 : anton 1.39 AGAIN ;
770 : pazsan 1.1
771 :     ' (quit) IS 'quit
772 :    
773 :     \ \ DOERROR (DOERROR) 13jun93jaw
774 :    
775 :     8 Constant max-errors
776 :     Variable error-stack 0 error-stack !
777 : pazsan 1.64 max-errors has? file [IF] 6 [ELSE] 4 [THEN] * cells allot
778 : pazsan 1.1 \ format of one cell:
779 :     \ source ( addr u )
780 :     \ >in
781 :     \ line-number
782 :     \ Loadfilename ( addr u )
783 :    
784 : pazsan 1.64 : error> ( -- addr u >in line# [addr u] )
785 :     -1 error-stack +!
786 :     error-stack dup @
787 :     [ has? file [IF] 6 [ELSE] 4 [THEN] ] Literal * cells + cell+
788 :     [ has? file [IF] 6 [ELSE] 4 [THEN] ] Literal cells bounds DO
789 :     I @
790 :     cell +LOOP ;
791 :     : >error ( addr u >in line# [addr u] -- )
792 :     error-stack dup @ dup 1+
793 :     max-errors 1- min error-stack !
794 :     [ has? file [IF] 6 [ELSE] 4 [THEN] ] Literal * cells + cell+
795 :     [ has? file [IF] 6 [ELSE] 4 [THEN] 1- ] Literal cells bounds swap DO
796 :     I !
797 :     -1 cells +LOOP ;
798 :    
799 : pazsan 1.1 : dec. ( n -- ) \ gforth
800 : crook 1.40 \G Display @i{n} as a signed decimal number, followed by a space.
801 :     \ !! not used...
802 : pazsan 1.1 base @ decimal swap . base ! ;
803 :    
804 : jwilke 1.23 : dec.r ( u -- ) \ gforth
805 : crook 1.40 \G Display @i{u} as a unsigned decimal number
806 : jwilke 1.23 base @ decimal swap 0 .r base ! ;
807 :    
808 : pazsan 1.1 : hex. ( u -- ) \ gforth
809 : crook 1.40 \G Display @i{u} as an unsigned hex number, prefixed with a "$" and
810 : crook 1.17 \G followed by a space.
811 : crook 1.40 \ !! not used...
812 : jwilke 1.33 [char] $ emit base @ swap hex u. base ! ;
813 : pazsan 1.1
814 : anton 1.95 : typewhite ( addr n -- ) \ gforth
815 :     \G Like type, but white space is printed instead of the characters.
816 :     \ bounds u+do
817 :     0 max bounds ?do
818 : pazsan 1.1 i c@ #tab = if \ check for tab
819 :     #tab
820 :     else
821 :     bl
822 :     then
823 :     emit
824 :     loop ;
825 :    
826 : anton 1.94 : -trailing ( c_addr u1 -- c_addr u2 ) \ string dash-trailing
827 :     \G Adjust the string specified by @i{c-addr, u1} to remove all
828 :     \G trailing spaces. @i{u2} is the length of the modified string.
829 :     BEGIN
830 : pazsan 1.102 dup
831 : anton 1.94 WHILE
832 : pazsan 1.102 1- 2dup + c@ bl <>
833 :     UNTIL 1+ THEN ;
834 : anton 1.94
835 : pazsan 1.1 DEFER DOERROR
836 : jwilke 1.33
837 :     has? backtrace [IF]
838 : anton 1.15 Defer dobacktrace ( -- )
839 :     ' noop IS dobacktrace
840 : jwilke 1.33 [THEN]
841 : pazsan 1.1
842 : jwilke 1.23 : .error-string ( throw-code -- )
843 :     dup -2 =
844 :     IF "error @ ?dup IF count type THEN drop
845 :     ELSE .error
846 :     THEN ;
847 :    
848 : pazsan 1.64 : .error-frame ( throwcode addr1 u1 n1 n2 [addr2 u2] -- throwcode )
849 :     \ addr2 u2: filename of included file - optional
850 : jwilke 1.23 \ n2: line number
851 :     \ n1: error position in input line
852 :     \ addr1 u1: input line
853 : pazsan 1.1 cr error-stack @
854 :     IF
855 : pazsan 1.64 [ has? file [IF] ]
856 :     ." in file included from "
857 :     type ." :"
858 :     [ [THEN] ]
859 :     dec.r drop 2drop
860 : pazsan 1.1 ELSE
861 : pazsan 1.64 [ has? file [IF] ]
862 :     type ." :"
863 :     [ [THEN] ]
864 :     dup >r dec.r ." : " 3 pick .error-string
865 : anton 1.57 r> IF \ if line# non-zero, there is a line
866 :     cr dup 2over type cr drop
867 :     nip -trailing 1- ( line-start index2 )
868 :     0 >r BEGIN
869 :     2dup + c@ bl > WHILE
870 :     r> 1+ >r 1- dup 0< UNTIL THEN 1+
871 :     ( line-start index1 )
872 :     typewhite
873 :     r> 1 max 0 ?do \ we want at least one "^", even if the length is 0
874 :     [char] ^ emit
875 :     loop
876 :     ELSE
877 :     2drop drop
878 :     THEN
879 : jwilke 1.23 THEN ;
880 : pazsan 1.1
881 :     : (DoError) ( throw-code -- )
882 :     [ has? os [IF] ]
883 : pazsan 1.8 >stderr
884 : pazsan 1.1 [ [THEN] ]
885 : pazsan 1.64 source >in @ sourceline# [ has? file [IF] ]
886 :     sourcefilename
887 :     [ [THEN] ] .error-frame
888 : pazsan 1.1 error-stack @ 0 ?DO
889 : pazsan 1.64 error>
890 : pazsan 1.1 .error-frame
891 :     LOOP
892 : jwilke 1.33 drop
893 :     [ has? backtrace [IF] ]
894 :     dobacktrace
895 :     [ [THEN] ]
896 : pazsan 1.8 normal-dp dpp ! ;
897 : pazsan 1.1
898 :     ' (DoError) IS DoError
899 :    
900 :     : quit ( ?? -- ?? ) \ core
901 : crook 1.27 \G Empty the return stack, make the user input device
902 :     \G the input source, enter interpret state and start
903 :     \G the text interpreter.
904 : pazsan 1.64 rp0 @ rp! handler off clear-tibstack
905 :     [ has? new-input 0= [IF] ] >tib @ >r [ [THEN] ]
906 : pazsan 1.1 BEGIN
907 :     [ has? compiler [IF] ]
908 : jwilke 1.76 [compile] [
909 : pazsan 1.1 [ [THEN] ]
910 :     ['] 'quit CATCH dup
911 :     WHILE
912 : anton 1.22 <# \ reset hold area, or we may get another error
913 : pazsan 1.64 DoError
914 :     [ has? new-input [IF] ] clear-tibstack
915 :     [ [ELSE] ] r@ >tib ! r@ tibstack !
916 :     [ [THEN] ]
917 : pazsan 1.1 REPEAT
918 : pazsan 1.64 drop [ has? new-input [IF] ] clear-tibstack
919 :     [ [ELSE] ] r> >tib !
920 :     [ [THEN] ] ;
921 : pazsan 1.1
922 :     \ \ Cold Boot 13feb93py
923 :    
924 :     : (bootmessage)
925 : anton 1.101 ." Gforth " version-string type
926 : pazsan 1.88 ." , Copyright (C) 1995-2003 Free Software Foundation, Inc." cr
927 : anton 1.101 ." Gforth comes with ABSOLUTELY NO WARRANTY; for details type `license'"
928 : pazsan 1.1 [ has? os [IF] ]
929 :     cr ." Type `bye' to exit"
930 :     [ [THEN] ] ;
931 :    
932 :     defer bootmessage
933 :     defer process-args
934 :    
935 :     ' (bootmessage) IS bootmessage
936 :    
937 : anton 1.10 Defer 'cold ( -- ) \ gforth tick-cold
938 : pazsan 1.1 \ hook (deferred word) for things to do right before interpreting the
939 :     \ command-line arguments
940 :     ' noop IS 'cold
941 :    
942 :    
943 : jwilke 1.76 AVariable init8 NIL init8 !
944 : pazsan 1.1
945 :     : cold ( -- ) \ gforth
946 : anton 1.44 [ has? backtrace [IF] ]
947 :     rp@ backtrace-rp0 !
948 :     [ [THEN] ]
949 : pazsan 1.1 [ has? file [IF] ]
950 : pazsan 1.78 os-cold
951 : pazsan 1.1 [ [THEN] ]
952 :     'cold
953 :     init8 chainperform
954 :     [ has? file [IF] ]
955 : anton 1.91 s" *the terminal*" loadfilename 2!
956 : pazsan 1.8 process-args
957 : pazsan 1.12 loadline off
958 : pazsan 1.1 [ [THEN] ]
959 :     bootmessage
960 : pazsan 1.12 quit ;
961 : pazsan 1.1
962 : pazsan 1.64 has? new-input 0= [IF]
963 : anton 1.5 : clear-tibstack ( -- )
964 :     [ has? glocals [IF] ]
965 :     lp@ forthstart 7 cells + @ -
966 :     [ [ELSE] ]
967 :     [ has? os [IF] ]
968 : pazsan 1.8 r0 @ forthstart 6 cells + @ -
969 : anton 1.5 [ [ELSE] ]
970 : pazsan 1.16 sp@ $10 cells +
971 : anton 1.5 [ [THEN] ]
972 :     [ [THEN] ]
973 :     dup >tib ! tibstack ! #tib off >in off ;
974 : pazsan 1.64 [THEN]
975 : anton 1.5
976 : pazsan 1.64 : boot ( path n **argv argc -- )
977 : pazsan 1.1 main-task up!
978 :     [ has? os [IF] ]
979 : pazsan 1.78 os-boot
980 : pazsan 1.1 [ [THEN] ]
981 :     sp@ sp0 !
982 : pazsan 1.74 [ has? peephole [IF] ]
983 : anton 1.87 \ only needed for greedy static superinstruction selection
984 :     \ primtable prepare-peephole-table TO peeptable
985 : pazsan 1.74 [ [THEN] ]
986 : pazsan 1.64 [ has? new-input [IF] ]
987 :     current-input off
988 :     [ [THEN] ]
989 : anton 1.5 clear-tibstack
990 : pazsan 1.1 rp@ rp0 !
991 :     [ has? floating [IF] ]
992 :     fp@ fp0 !
993 :     [ [THEN] ]
994 : anton 1.46 handler off
995 : anton 1.98 ['] cold catch dup -&2049 <> if \ broken pipe?
996 :     DoError cr
997 :     endif
998 : pazsan 1.1 [ has? os [IF] ]
999 : anton 1.35 1 (bye) \ !! determin exit code from throw code?
1000 : pazsan 1.1 [ [THEN] ]
1001 :     ;
1002 :    
1003 :     has? os [IF]
1004 :     : bye ( -- ) \ tools-ext
1005 :     [ has? file [IF] ]
1006 :     script? 0= IF cr THEN
1007 :     [ [ELSE] ]
1008 :     cr
1009 :     [ [THEN] ]
1010 :     0 (bye) ;
1011 :     [THEN]
1012 :    
1013 :     \ **argv may be scanned by the C starter to get some important
1014 :     \ information, as -display and -geometry for an X client FORTH
1015 :     \ or space and stackspace overrides
1016 :    
1017 :     \ 0 arg contains, however, the name of the program.
1018 :    

CVS Admin

Powered by ViewCVS 1.0-dev
(Powered by ViewCVS)

ViewCVS and CVS Help