[gforth] / gforth / kernel / int.fs  

gforth: gforth/kernel/int.fs


1 : pazsan 1.1 \ definitions needed for interpreter only
2 :    
3 : anton 1.11 \ Copyright (C) 1995,1996,1997,1998 Free Software Foundation, Inc.
4 :    
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 :     \ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 :    
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 : pazsan 1.49 require ./version.fs \ version-string
32 : jwilke 1.33 require ./../chains.fs
33 :    
34 : crook 1.43 : tib ( -- c-addr ) \ core-ext t-i-b
35 : crook 1.40 \G @i{c-addr} is the address of the Terminal Input Buffer.
36 : crook 1.29 \G OBSOLESCENT: @code{source} superceeds the function of this word.
37 : pazsan 1.1 >tib @ ;
38 :    
39 : crook 1.29 Defer source ( -- c-addr u ) \ core
40 : pazsan 1.1 \ used by dodefer:, must be defer
41 : crook 1.40 \G @i{c-addr} is the address of the input buffer and @i{u} is the
42 : crook 1.29 \G number of characters in it.
43 : pazsan 1.1
44 : crook 1.29 : (source) ( -- c-addr u )
45 : pazsan 1.1 tib #tib @ ;
46 :     ' (source) IS source
47 :    
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 :     \ word parse 23feb93py
55 :    
56 : crook 1.29 : sword ( char -- addr len ) \ gforth s-word
57 : crook 1.40 \G Parses like @code{word}, but the output is like @code{parse} output.
58 : anton 1.47 \G @xref{core-idef}.
59 : anton 1.3 \ this word was called PARSE-WORD until 0.3.0, but Open Firmware and
60 :     \ dpANS6 A.6.2.2008 have a word with that name that behaves
61 :     \ differently (like NAME).
62 : pazsan 1.1 source 2dup >r >r >in @ over min /string
63 :     rot dup bl = IF drop (parse-white) ELSE (word) THEN
64 :     2dup + r> - 1+ r> min >in ! ;
65 :    
66 : crook 1.29 : word ( char "<chars>ccc<char>-- c-addr ) \ core
67 : crook 1.40 \G Skip leading delimiters. Parse @i{ccc}, delimited by
68 :     \G @i{char}, in the parse area. @i{c-addr} is the address of a
69 : crook 1.29 \G transient region containing the parsed string in
70 : crook 1.40 \G counted-string format. If the parse area was empty or
71 : crook 1.29 \G contained no characters other than delimiters, the resulting
72 :     \G string has zero length. A program may replace characters within
73 :     \G the counted string. OBSOLESCENT: the counted string has a
74 :     \G trailing space that is not included in its length.
75 :     sword here place bl here count + c! here ;
76 :    
77 :     : parse ( char "ccc<char>" -- c-addr u ) \ core-ext
78 : crook 1.40 \G Parse @i{ccc}, delimited by @i{char}, in the parse
79 :     \G area. @i{c-addr u} specifies the parsed string within the
80 :     \G parse area. If the parse area was empty, @i{u} is 0.
81 : crook 1.29 >r source >in @ over min /string over swap r> scan >r
82 : pazsan 1.1 over - dup r> IF 1+ THEN >in +! ;
83 :    
84 :     \ name 13feb93py
85 :    
86 :     [IFUNDEF] (name) \ name might be a primitive
87 :    
88 : crook 1.40 : (name) ( -- c-addr count ) \ gforth
89 : pazsan 1.1 source 2dup >r >r >in @ /string (parse-white)
90 :     2dup + r> - 1+ r> min >in ! ;
91 :     \ name count ;
92 :     [THEN]
93 :    
94 :     : name-too-short? ( c-addr u -- c-addr u )
95 :     dup 0= -&16 and throw ;
96 :    
97 :     : name-too-long? ( c-addr u -- c-addr u )
98 :     dup $1F u> -&19 and throw ;
99 :    
100 :     \ \ Number parsing 23feb93py
101 :    
102 :     \ number? number 23feb93py
103 :    
104 :     hex
105 :     const Create bases 10 , 2 , A , 100 ,
106 :     \ 16 2 10 character
107 :    
108 : anton 1.18 \ !! protect BASE saving wrapper against exceptions
109 : pazsan 1.1 : getbase ( addr u -- addr' u' )
110 :     over c@ [char] $ - dup 4 u<
111 :     IF
112 :     cells bases + @ base ! 1 /string
113 :     ELSE
114 :     drop
115 :     THEN ;
116 :    
117 : pazsan 1.20 : sign? ( addr u -- addr u flag )
118 : jwilke 1.33 over c@ [char] - = dup >r
119 : pazsan 1.1 IF
120 :     1 /string
121 :     THEN
122 : pazsan 1.20 r> ;
123 :    
124 :     : s>unumber? ( addr u -- ud flag )
125 : pazsan 1.21 base @ >r dpl on getbase
126 : pazsan 1.20 0. 2swap
127 : anton 1.18 BEGIN ( d addr len )
128 : pazsan 1.1 dup >r >number dup
129 : anton 1.18 WHILE \ there are characters left
130 : pazsan 1.1 dup r> -
131 : anton 1.18 WHILE \ the last >number parsed something
132 :     dup 1- dpl ! over c@ [char] . =
133 :     WHILE \ the current char is '.'
134 : pazsan 1.1 1 /string
135 : anton 1.18 REPEAT THEN \ there are unparseable characters left
136 : pazsan 1.21 2drop false
137 : pazsan 1.20 ELSE
138 :     rdrop 2drop true
139 : pazsan 1.21 THEN
140 :     r> base ! ;
141 : pazsan 1.20
142 :     \ ouch, this is complicated; there must be a simpler way - anton
143 :     : s>number? ( addr len -- d f )
144 :     \ converts string addr len into d, flag indicates success
145 : pazsan 1.21 sign? >r
146 : pazsan 1.20 s>unumber?
147 :     0= IF
148 : pazsan 1.21 rdrop false
149 : anton 1.18 ELSE \ no characters left, all ok
150 : pazsan 1.20 r>
151 : pazsan 1.1 IF
152 :     dnegate
153 :     THEN
154 : anton 1.18 true
155 : pazsan 1.21 THEN ;
156 : pazsan 1.1
157 : anton 1.18 : s>number ( addr len -- d )
158 :     \ don't use this, there is no way to tell success
159 :     s>number? drop ;
160 :    
161 : pazsan 1.1 : snumber? ( c-addr u -- 0 / n -1 / d 0> )
162 : anton 1.18 s>number? 0=
163 : pazsan 1.1 IF
164 :     2drop false EXIT
165 :     THEN
166 : anton 1.18 dpl @ dup 0< IF
167 : pazsan 1.1 nip
168 : anton 1.18 ELSE
169 :     1+
170 : pazsan 1.1 THEN ;
171 :    
172 :     : number? ( string -- string 0 / n -1 / d 0> )
173 :     dup >r count snumber? dup if
174 :     rdrop
175 :     else
176 :     r> swap
177 :     then ;
178 :    
179 :     : number ( string -- d )
180 :     number? ?dup 0= abort" ?" 0<
181 :     IF
182 :     s>d
183 :     THEN ;
184 :    
185 :     \ \ Comments ( \ \G
186 :    
187 : crook 1.29 : ( ( compilation 'ccc<close-paren>' -- ; run-time -- ) \ thisone- core,file paren
188 : crook 1.17 \G ** this will not get annotated. The alias in glocals.fs will instead **
189 : crook 1.29 \G It does not work to use "wordset-" prefix since this file is glossed
190 :     \G by cross.fs which doesn't have the same functionalty as makedoc.fs
191 : pazsan 1.1 [char] ) parse 2drop ; immediate
192 :    
193 : crook 1.29 : \ ( -- ) \ thisone- core-ext,block-ext backslash
194 :     \G ** this will not get annotated. The alias in glocals.fs will instead **
195 :     \G It does not work to use "wordset-" prefix since this file is glossed
196 :     \G by cross.fs which doesn't have the same functionalty as makedoc.fs
197 : pazsan 1.12 [ has? file [IF] ]
198 : pazsan 1.1 blk @
199 :     IF
200 :     >in @ c/l / 1+ c/l * >in !
201 :     EXIT
202 :     THEN
203 : pazsan 1.12 [ [THEN] ]
204 : pazsan 1.1 source >in ! drop ; immediate
205 :    
206 : crook 1.19 : \G ( -- ) \ gforth backslash-gee
207 :     \G Equivalent to @code{\} but used as a tag to annotate definition
208 :     \G comments into documentation.
209 : pazsan 1.1 POSTPONE \ ; immediate
210 :    
211 :     \ \ object oriented search list 17mar93py
212 :    
213 :     \ word list structure:
214 :    
215 :     struct
216 :     cell% field find-method \ xt: ( c_addr u wid -- nt )
217 :     cell% field reveal-method \ xt: ( nt wid -- ) \ used by dofield:, must be field
218 :     cell% field rehash-method \ xt: ( wid -- ) \ re-initializes a "search-data" (hashtables)
219 :     cell% field hash-method \ xt: ( wid -- ) \ initializes ""
220 :     \ \ !! what else
221 :     end-struct wordlist-map-struct
222 :    
223 :     struct
224 : pazsan 1.6 cell% field wordlist-map \ pointer to a wordlist-map-struct
225 : anton 1.13 cell% field wordlist-id \ linked list of words (for WORDS etc.)
226 : pazsan 1.1 cell% field wordlist-link \ link field to other wordlists
227 : anton 1.13 cell% field wordlist-extend \ wordlist extensions (eg bucket offset)
228 : pazsan 1.1 end-struct wordlist-struct
229 :    
230 :     : f83find ( addr len wordlist -- nt / false )
231 : pazsan 1.6 wordlist-id @ (f83find) ;
232 : pazsan 1.1
233 :     : initvoc ( wid -- )
234 :     dup wordlist-map @ hash-method perform ;
235 :    
236 :     \ Search list table: find reveal
237 :     Create f83search ( -- wordlist-map )
238 :     ' f83find A, ' drop A, ' drop A, ' drop A,
239 :    
240 : pazsan 1.6 here G f83search T A, NIL A, NIL A, NIL A,
241 : pazsan 1.1 AValue forth-wordlist \ variable, will be redefined by search.fs
242 :    
243 :     AVariable lookup forth-wordlist lookup !
244 :     \ !! last is user and lookup?! jaw
245 :     AVariable current ( -- addr ) \ gforth
246 : crook 1.43 \G @code{Variable} -- holds the @i{wid} of the compilation word list.
247 : pazsan 1.1 AVariable voclink forth-wordlist wordlist-link voclink !
248 : anton 1.38 \ lookup AValue context ( -- addr ) \ gforth
249 :     Defer context ( -- addr ) \ gforth
250 : crook 1.43 \G @code{context} @code{@@} is the @i{wid} of the word list at the
251 :     \G top of the search order.
252 : pazsan 1.1
253 : anton 1.38 ' lookup is context
254 : pazsan 1.1 forth-wordlist current !
255 :    
256 :     \ \ header, finding, ticks 17dec92py
257 :    
258 : jwilke 1.33 hex
259 :     80 constant alias-mask \ set when the word is not an alias!
260 :     40 constant immediate-mask
261 :     20 constant restrict-mask
262 : pazsan 1.1
263 :     \ higher level parts of find
264 :    
265 :     : flag-sign ( f -- 1|-1 )
266 :     \ true becomes 1, false -1
267 :     0= 2* 1+ ;
268 :    
269 :     : compile-only-error ( ... -- )
270 :     -&14 throw ;
271 :    
272 :     : (cfa>int) ( cfa -- xt )
273 :     [ has? compiler [IF] ]
274 :     dup interpret/compile?
275 :     if
276 :     interpret/compile-int @
277 :     then
278 :     [ [THEN] ] ;
279 :    
280 :     : (x>int) ( cfa b -- xt )
281 :     \ get interpretation semantics of name
282 :     restrict-mask and
283 :     if
284 :     drop ['] compile-only-error
285 :     else
286 :     (cfa>int)
287 :     then ;
288 :    
289 :     : name>string ( nt -- addr count ) \ gforth head-to-string
290 : crook 1.40 \g @i{addr count} is the name of the word represented by @i{nt}.
291 : pazsan 1.1 cell+ count $1F and ;
292 :    
293 :     : ((name>)) ( nfa -- cfa )
294 :     name>string + cfaligned ;
295 :    
296 :     : (name>x) ( nfa -- cfa b )
297 :     \ cfa is an intermediate cfa and b is the flags byte of nfa
298 :     dup ((name>))
299 :     swap cell+ c@ dup alias-mask and 0=
300 :     IF
301 :     swap @ swap
302 :     THEN ;
303 :    
304 :     : name>int ( nt -- xt ) \ gforth
305 : crook 1.31 \G @i{xt} represents the interpretation semantics of the word
306 :     \G @i{nt}. If @i{nt} has no interpretation semantics (i.e. is
307 :     \G @code{compile-only}), @i{xt} is the execution token for
308 :     \G @code{compile-only-error}, which performs @code{-14 throw}.
309 : pazsan 1.1 (name>x) (x>int) ;
310 :    
311 :     : name?int ( nt -- xt ) \ gforth
312 : crook 1.31 \G Like @code{name>int}, but perform @code{-14 throw} if @i{nt}
313 :     \G has no interpretation semantics.
314 : pazsan 1.1 (name>x) restrict-mask and
315 :     if
316 :     compile-only-error \ does not return
317 :     then
318 :     (cfa>int) ;
319 :    
320 :     : (name>comp) ( nt -- w +-1 ) \ gforth
321 : crook 1.31 \G @i{w xt} is the compilation token for the word @i{nt}.
322 : pazsan 1.1 (name>x) >r
323 :     [ has? compiler [IF] ]
324 :     dup interpret/compile?
325 :     if
326 :     interpret/compile-comp @
327 :     then
328 :     [ [THEN] ]
329 :     r> immediate-mask and flag-sign
330 :     ;
331 :    
332 :     : (name>intn) ( nfa -- xt +-1 )
333 :     (name>x) tuck (x>int) ( b xt )
334 :     swap immediate-mask and flag-sign ;
335 :    
336 : jwilke 1.30 const Create ??? 0 , 3 c, char ? c, char ? c, char ? c,
337 :     \ ??? is used by dovar:, must be created/:dovar
338 :    
339 :     [IFDEF] forthstart
340 :     \ if we have a forthstart we can define head? with it
341 :     \ otherwise leave out the head? check
342 :    
343 : anton 1.14 : head? ( addr -- f )
344 :     \G heuristic check whether addr is a name token; may deliver false
345 :     \G positives; addr must be a valid address
346 :     \ we follow the link fields and check for plausibility; two
347 :     \ iterations should catch most false addresses: on the first
348 :     \ iteration, we may get an xt, on the second a code address (or
349 :     \ some code), which is typically not in the dictionary.
350 :     2 0 do
351 : anton 1.41 dup dup aligned <> if \ protect @ against unaligned accesses
352 :     drop false unloop exit
353 :     then
354 : anton 1.14 dup @ dup
355 :     if ( addr addr1 )
356 :     dup rot forthstart within
357 :     if \ addr1 is outside forthstart..addr, not a head
358 :     drop false unloop exit
359 :     then ( addr1 )
360 :     else \ 0 in the link field, no further checks
361 :     2drop true unloop exit
362 :     then
363 :     loop
364 :     \ in dubio pro:
365 :     drop true ;
366 :    
367 : anton 1.48 : >head-noprim ( cfa -- nt ) \ gforth to-head-noprim
368 : pazsan 1.45 $25 cell do ( cfa )
369 : anton 1.14 dup i - count $9F and + cfaligned over alias-mask + =
370 :     if ( cfa )
371 :     dup i - cell - dup head?
372 :     if
373 :     nip unloop exit
374 :     then
375 :     drop
376 :     then
377 :     cell +loop
378 :     drop ??? ( wouldn't 0 be better? ) ;
379 : pazsan 1.1
380 : jwilke 1.30 [ELSE]
381 :    
382 : anton 1.48 : >head-noprim ( cfa -- nt ) \ gforth to-head-noprim
383 : pazsan 1.45 $25 cell do ( cfa )
384 : jwilke 1.30 dup i - count $9F and + cfaligned over alias-mask + =
385 :     if ( cfa ) i - cell - unloop exit
386 :     then
387 :     cell +loop
388 :     drop ??? ( wouldn't 0 be better? ) ;
389 :    
390 :     [THEN]
391 : pazsan 1.1
392 :     : body> 0 >body - ;
393 :    
394 : crook 1.31 : (search-wordlist) ( addr count wid -- nt | false )
395 : pazsan 1.1 dup wordlist-map @ find-method perform ;
396 :    
397 : crook 1.31 : search-wordlist ( c-addr count wid -- 0 | xt +-1 ) \ search
398 :     \G Search the word list identified by @i{wid}
399 :     \G for the definition named by the string at @i{c-addr count}.
400 : crook 1.17 \G If the definition is not found, return 0. If the definition
401 :     \G is found return 1 (if the definition is immediate) or -1
402 : crook 1.31 \G (if the definition is not immediate) together with the @i{xt}.
403 :     \G The @i{xt} returned represents the interpretation semantics.
404 : pazsan 1.1 (search-wordlist) dup if
405 :     (name>intn)
406 :     then ;
407 :    
408 : crook 1.31 : find-name ( c-addr u -- nt | 0 ) \ gforth
409 :     \g Find the name @i{c-addr u} in the current search
410 :     \g order. Return its @i{nt}, if found, otherwise 0.
411 : pazsan 1.1 lookup @ (search-wordlist) ;
412 :    
413 :     : sfind ( c-addr u -- 0 / xt +-1 ) \ gforth-obsolete
414 :     find-name dup
415 :     if ( nt )
416 :     state @
417 :     if
418 :     (name>comp)
419 :     else
420 :     (name>intn)
421 :     then
422 :     then ;
423 :    
424 : crook 1.31 : find ( c-addr -- xt +-1 | c-addr 0 ) \ core,search
425 : crook 1.17 \G Search all word lists in the current search order
426 : crook 1.31 \G for the definition named by the counted string at @i{c-addr}.
427 : crook 1.17 \G If the definition is not found, return 0. If the definition
428 :     \G is found return 1 (if the definition is immediate) or -1
429 : crook 1.31 \G (if the definition is not immediate) together with the @i{xt}.
430 : pazsan 1.1 dup count sfind dup
431 :     if
432 :     rot drop
433 :     then ;
434 :    
435 : jwilke 1.34 \ ticks in interpreter
436 : pazsan 1.1
437 :     : (') ( "name" -- nt ) \ gforth
438 : anton 1.32 name name-too-short?
439 : anton 1.28 find-name dup 0=
440 : pazsan 1.1 IF
441 : anton 1.42 drop -&13 throw
442 : pazsan 1.1 THEN ;
443 :    
444 :     : ' ( "name" -- xt ) \ core tick
445 : crook 1.31 \g @i{xt} represents @i{name}'s interpretation
446 :     \g semantics. Perform @code{-14 throw} if the word has no
447 : pazsan 1.1 \g interpretation semantics.
448 :     (') name?int ;
449 : jwilke 1.34
450 :     has? compiler 0= [IF] \ interpreter only version of IS and TO
451 :    
452 :     : IS ' >body ! ;
453 :     ' IS Alias TO
454 :    
455 :     [THEN]
456 : pazsan 1.1
457 :     \ \ the interpreter loop mar92py
458 :    
459 :     \ interpret 10mar92py
460 :    
461 : anton 1.37 Defer parser ( c-addr u -- )
462 : pazsan 1.1 Defer name ( -- c-addr count ) \ gforth
463 :     \ get the next word from the input buffer
464 :     ' (name) IS name
465 :     Defer compiler-notfound ( c-addr count -- )
466 :     Defer interpreter-notfound ( c-addr count -- )
467 :    
468 :     : no.extensions ( addr u -- )
469 : anton 1.42 2drop -&13 throw ;
470 : pazsan 1.1 ' no.extensions IS compiler-notfound
471 :     ' no.extensions IS interpreter-notfound
472 :    
473 :     : interpret ( ?? -- ?? ) \ gforth
474 :     \ interpret/compile the (rest of the) input buffer
475 : jwilke 1.33 [ has? backtrace [IF] ]
476 : anton 1.24 rp@ backtrace-rp0 !
477 : jwilke 1.33 [ [THEN] ]
478 : pazsan 1.1 BEGIN
479 :     ?stack name dup
480 :     WHILE
481 :     parser
482 :     REPEAT
483 :     2drop ;
484 :    
485 :     \ interpreter 30apr92py
486 :    
487 :     \ not the most efficient implementations of interpreter and compiler
488 : jwilke 1.33 : interpreter ( c-addr u -- )
489 : pazsan 1.1 2dup find-name dup
490 :     if
491 :     nip nip name>int execute
492 :     else
493 :     drop
494 :     2dup 2>r snumber?
495 :     IF
496 :     2rdrop
497 :     ELSE
498 :     2r> interpreter-notfound
499 :     THEN
500 :     then ;
501 :    
502 :     ' interpreter IS parser
503 :    
504 :     \ \ Query Evaluate 07apr93py
505 :    
506 :     has? file 0= [IF]
507 : pazsan 1.12 : sourceline# ( -- n ) 1 ;
508 : pazsan 1.1 [THEN]
509 :    
510 :     : refill ( -- flag ) \ core-ext,block-ext,file-ext
511 : crook 1.29 \G Attempt to fill the input buffer from the input source. When
512 :     \G the input source is the user input device, attempt to receive
513 :     \G input into the terminal input device. If successful, make the
514 :     \G result the input buffer, set @code{>IN} to 0 and return true;
515 :     \G otherwise return false. When the input source is a block, add 1
516 :     \G to the value of @code{BLK} to make the next block the input
517 :     \G source and current input buffer, and set @code{>IN} to 0;
518 :     \G return true if the new value of @code{BLK} is a valid block
519 :     \G number, false otherwise. When the input source is a text file,
520 :     \G attempt to read the next line from the file. If successful,
521 :     \G make the result the current input buffer, set @code{>IN} to 0
522 :     \G and return true; otherwise, return false. A successful result
523 :     \G includes receipt of a line containing 0 characters.
524 : pazsan 1.12 [ has? file [IF] ]
525 :     blk @ IF 1 blk +! true 0 >in ! EXIT THEN
526 :     [ [THEN] ]
527 :     tib /line
528 :     [ has? file [IF] ]
529 :     loadfile @ ?dup
530 :     IF read-line throw
531 :     ELSE
532 :     [ [THEN] ]
533 :     sourceline# 0< IF 2drop false EXIT THEN
534 :     accept true
535 :     [ has? file [IF] ]
536 :     THEN
537 :     1 loadline +!
538 :     [ [THEN] ]
539 :     swap #tib ! 0 >in ! ;
540 : pazsan 1.1
541 :     : query ( -- ) \ core-ext
542 : crook 1.29 \G Make the user input device the input source. Receive input into
543 :     \G the Terminal Input Buffer. Set @code{>IN} to zero. OBSOLESCENT:
544 :     \G superceeded by @code{accept}.
545 : pazsan 1.12 [ has? file [IF] ]
546 :     blk off loadfile off
547 :     [ [THEN] ]
548 : pazsan 1.1 tib /line accept #tib ! 0 >in ! ;
549 :    
550 :     \ save-mem extend-mem
551 :    
552 :     has? os [IF]
553 :     : save-mem ( addr1 u -- addr2 u ) \ gforth
554 :     \g copy a memory block into a newly allocated region in the heap
555 :     swap >r
556 :     dup allocate throw
557 :     swap 2dup r> -rot move ;
558 :    
559 :     : extend-mem ( addr1 u1 u -- addr addr2 u2 )
560 :     \ extend memory block allocated from the heap by u aus
561 :     \ the (possibly reallocated piece is addr2 u2, the extension is at addr
562 :     over >r + dup >r resize throw
563 :     r> over r> + -rot ;
564 :     [THEN]
565 :    
566 :     \ EVALUATE 17may93jaw
567 :    
568 :     has? file 0= [IF]
569 :     : push-file ( -- ) r>
570 : pazsan 1.12 tibstack @ >r >tib @ >r #tib @ >r
571 : pazsan 1.1 >tib @ tibstack @ = IF r@ tibstack +! THEN
572 :     tibstack @ >tib ! >in @ >r >r ;
573 :    
574 :     : pop-file ( throw-code -- throw-code )
575 :     r>
576 : pazsan 1.12 r> >in ! r> #tib ! r> >tib ! r> tibstack ! >r ;
577 : pazsan 1.1 [THEN]
578 :    
579 : crook 1.29 : evaluate ( c-addr u -- ) \ core,block
580 : crook 1.40 \G Save the current input source specification. Store @code{-1} in
581 :     \G @code{source-id} and @code{0} in @code{blk}. Set @code{>IN} to
582 :     \G @code{0} and make the string @i{c-addr u} the input source
583 :     \G and input buffer. Interpret. When the parse area is empty,
584 :     \G restore the input source specification.
585 :     push-file #tib ! >tib !
586 : crook 1.29 >in off
587 :     [ has? file [IF] ]
588 :     blk off loadfile off -1 loadline !
589 :     [ [THEN] ]
590 :     ['] interpret catch
591 :     pop-file throw ;
592 : pazsan 1.1
593 :     \ \ Quit 13feb93py
594 :    
595 :     Defer 'quit
596 :    
597 :     Defer .status
598 :    
599 :     : prompt state @ IF ." compiled" EXIT THEN ." ok" ;
600 :    
601 :     : (Query) ( -- )
602 : pazsan 1.12 [ has? file [IF] ]
603 :     loadfile off blk off loadline off
604 :     [ [THEN] ]
605 :     refill drop ;
606 : pazsan 1.1
607 : anton 1.39 : (quit) ( -- )
608 :     \ exits only through THROW etc.
609 : anton 1.42 \ sp0 @ cell - handler @ &12 + ! \ !! kludge: fix the stack pointer
610 : anton 1.39 \ stored in the system's CATCH frame, so the stack depth will be 0
611 :     \ after the next THROW it catches (it may be off due to BOUNCEs or
612 :     \ because process-args left something on the stack)
613 :     BEGIN
614 :     .status cr (query) interpret prompt
615 :     AGAIN ;
616 : pazsan 1.1
617 :     ' (quit) IS 'quit
618 :    
619 :     \ \ DOERROR (DOERROR) 13jun93jaw
620 :    
621 :     8 Constant max-errors
622 :     Variable error-stack 0 error-stack !
623 :     max-errors 6 * cells allot
624 :     \ format of one cell:
625 :     \ source ( addr u )
626 :     \ >in
627 :     \ line-number
628 :     \ Loadfilename ( addr u )
629 :    
630 :     : dec. ( n -- ) \ gforth
631 : crook 1.40 \G Display @i{n} as a signed decimal number, followed by a space.
632 :     \ !! not used...
633 : pazsan 1.1 base @ decimal swap . base ! ;
634 :    
635 : jwilke 1.23 : dec.r ( u -- ) \ gforth
636 : crook 1.40 \G Display @i{u} as a unsigned decimal number
637 : jwilke 1.23 base @ decimal swap 0 .r base ! ;
638 :    
639 : pazsan 1.1 : hex. ( u -- ) \ gforth
640 : crook 1.40 \G Display @i{u} as an unsigned hex number, prefixed with a "$" and
641 : crook 1.17 \G followed by a space.
642 : crook 1.40 \ !! not used...
643 : jwilke 1.33 [char] $ emit base @ swap hex u. base ! ;
644 : pazsan 1.1
645 :     : typewhite ( addr u -- ) \ gforth
646 : crook 1.40 \G Like type, but white space is printed instead of the characters.
647 : pazsan 1.1 bounds ?do
648 :     i c@ #tab = if \ check for tab
649 :     #tab
650 :     else
651 :     bl
652 :     then
653 :     emit
654 :     loop ;
655 :    
656 :     DEFER DOERROR
657 : jwilke 1.33
658 :     has? backtrace [IF]
659 : anton 1.15 Defer dobacktrace ( -- )
660 :     ' noop IS dobacktrace
661 : jwilke 1.33 [THEN]
662 : pazsan 1.1
663 : jwilke 1.23 : .error-string ( throw-code -- )
664 :     dup -2 =
665 :     IF "error @ ?dup IF count type THEN drop
666 :     ELSE .error
667 :     THEN ;
668 :    
669 :     : .error-frame ( throwcode addr1 u1 n1 n2 addr2 u2 -- throwcode )
670 :     \ addr2 u2: filename of included file
671 :     \ n2: line number
672 :     \ n1: error position in input line
673 :     \ addr1 u1: input line
674 :    
675 : pazsan 1.1 cr error-stack @
676 :     IF
677 :     ." in file included from "
678 : jwilke 1.23 type ." :" dec.r drop 2drop
679 : pazsan 1.1 ELSE
680 : jwilke 1.23 type ." :" dec.r ." : " 3 pick .error-string cr
681 :     dup 2over type cr drop
682 : pazsan 1.1 nip -trailing 1- ( line-start index2 )
683 :     0 >r BEGIN
684 :     2dup + c@ bl > WHILE
685 :     r> 1+ >r 1- dup 0< UNTIL THEN 1+
686 :     ( line-start index1 )
687 :     typewhite
688 :     r> 1 max 0 ?do \ we want at least one "^", even if the length is 0
689 :     [char] ^ emit
690 :     loop
691 : jwilke 1.23 THEN ;
692 : pazsan 1.1
693 :     : (DoError) ( throw-code -- )
694 :     [ has? os [IF] ]
695 : pazsan 1.8 >stderr
696 : pazsan 1.1 [ [THEN] ]
697 :     sourceline# IF
698 : pazsan 1.8 source >in @ sourceline# 0 0 .error-frame
699 : pazsan 1.1 THEN
700 :     error-stack @ 0 ?DO
701 :     -1 error-stack +!
702 :     error-stack dup @ 6 * cells + cell+
703 :     6 cells bounds DO
704 :     I @
705 :     cell +LOOP
706 :     .error-frame
707 :     LOOP
708 : jwilke 1.33 drop
709 :     [ has? backtrace [IF] ]
710 :     dobacktrace
711 :     [ [THEN] ]
712 : pazsan 1.8 normal-dp dpp ! ;
713 : pazsan 1.1
714 :     ' (DoError) IS DoError
715 :    
716 :     : quit ( ?? -- ?? ) \ core
717 : crook 1.27 \G Empty the return stack, make the user input device
718 :     \G the input source, enter interpret state and start
719 :     \G the text interpreter.
720 : anton 1.5 rp0 @ rp! handler off clear-tibstack >tib @ >r
721 : pazsan 1.1 BEGIN
722 :     [ has? compiler [IF] ]
723 :     postpone [
724 :     [ [THEN] ]
725 :     ['] 'quit CATCH dup
726 :     WHILE
727 : anton 1.22 <# \ reset hold area, or we may get another error
728 : pazsan 1.1 DoError r@ >tib ! r@ tibstack !
729 :     REPEAT
730 :     drop r> >tib ! ;
731 :    
732 :     \ \ Cold Boot 13feb93py
733 :    
734 :     : (bootmessage)
735 :     ." GForth " version-string type
736 : anton 1.11 ." , Copyright (C) 1998 Free Software Foundation, Inc." cr
737 : pazsan 1.1 ." GForth comes with ABSOLUTELY NO WARRANTY; for details type `license'"
738 :     [ has? os [IF] ]
739 :     cr ." Type `bye' to exit"
740 :     [ [THEN] ] ;
741 :    
742 :     defer bootmessage
743 :     defer process-args
744 :    
745 :     ' (bootmessage) IS bootmessage
746 :    
747 : anton 1.10 Defer 'cold ( -- ) \ gforth tick-cold
748 : pazsan 1.1 \ hook (deferred word) for things to do right before interpreting the
749 :     \ command-line arguments
750 :     ' noop IS 'cold
751 :    
752 :    
753 :     Variable init8
754 :    
755 :     : cold ( -- ) \ gforth
756 : anton 1.44 [ has? backtrace [IF] ]
757 :     rp@ backtrace-rp0 !
758 :     [ [THEN] ]
759 : pazsan 1.1 [ has? file [IF] ]
760 :     pathstring 2@ fpath only-path
761 :     init-included-files
762 :     [ [THEN] ]
763 :     'cold
764 :     init8 chainperform
765 :     [ has? file [IF] ]
766 : pazsan 1.8 process-args
767 : pazsan 1.12 loadline off
768 : pazsan 1.1 [ [THEN] ]
769 :     bootmessage
770 : pazsan 1.12 quit ;
771 : pazsan 1.1
772 : anton 1.5 : clear-tibstack ( -- )
773 :     [ has? glocals [IF] ]
774 :     lp@ forthstart 7 cells + @ -
775 :     [ [ELSE] ]
776 :     [ has? os [IF] ]
777 : pazsan 1.8 r0 @ forthstart 6 cells + @ -
778 : anton 1.5 [ [ELSE] ]
779 : pazsan 1.16 sp@ $10 cells +
780 : anton 1.5 [ [THEN] ]
781 :     [ [THEN] ]
782 :     dup >tib ! tibstack ! #tib off >in off ;
783 :    
784 : pazsan 1.1 : boot ( path **argv argc -- )
785 :     main-task up!
786 :     [ has? os [IF] ]
787 :     stdout TO outfile-id
788 : pazsan 1.7 stdin TO infile-id
789 : pazsan 1.1 \ !! [ [THEN] ]
790 :     \ !! [ has? file [IF] ]
791 :     argc ! argv ! pathstring 2!
792 :     [ [THEN] ]
793 :     sp@ sp0 !
794 : anton 1.5 clear-tibstack
795 : pazsan 1.1 rp@ rp0 !
796 :     [ has? floating [IF] ]
797 :     fp@ fp0 !
798 :     [ [THEN] ]
799 : anton 1.46 handler off
800 : pazsan 1.8 ['] cold catch DoError cr
801 : pazsan 1.1 [ has? os [IF] ]
802 : anton 1.35 1 (bye) \ !! determin exit code from throw code?
803 : pazsan 1.1 [ [THEN] ]
804 :     ;
805 :    
806 :     has? os [IF]
807 :     : bye ( -- ) \ tools-ext
808 :     [ has? file [IF] ]
809 :     script? 0= IF cr THEN
810 :     [ [ELSE] ]
811 :     cr
812 :     [ [THEN] ]
813 :     0 (bye) ;
814 :     [THEN]
815 :    
816 :     \ **argv may be scanned by the C starter to get some important
817 :     \ information, as -display and -geometry for an X client FORTH
818 :     \ or space and stackspace overrides
819 :    
820 :     \ 0 arg contains, however, the name of the program.
821 :    

CVS Admin

Powered by ViewCVS 1.0-dev
(Powered by ViewCVS)

ViewCVS and CVS Help