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

CVS Admin

Powered by ViewCVS 1.0-dev
(Powered by ViewCVS)

ViewCVS and CVS Help