[gforth] / gforth / kernel / int.fs  

gforth: gforth/kernel/int.fs


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

CVS Admin

Powered by ViewCVS 1.0-dev
(Powered by ViewCVS)

ViewCVS and CVS Help