[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 : anton 1.36 require ~+/kernel/version.fs \ version-string
32 : jwilke 1.33 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 : anton 1.38 \ lookup AValue context ( -- addr ) \ gforth
248 :     Defer context ( -- addr ) \ gforth
249 :     \G @code{context} @code{@@} is the wid of the word list at the
250 : crook 1.17 \G top of the search order stack.
251 : pazsan 1.1
252 : anton 1.38 ' lookup is context
253 : pazsan 1.1 forth-wordlist current !
254 :    
255 :     \ \ header, finding, ticks 17dec92py
256 :    
257 : jwilke 1.33 hex
258 :     80 constant alias-mask \ set when the word is not an alias!
259 :     40 constant immediate-mask
260 :     20 constant restrict-mask
261 : pazsan 1.1
262 :     \ higher level parts of find
263 :    
264 :     : flag-sign ( f -- 1|-1 )
265 :     \ true becomes 1, false -1
266 :     0= 2* 1+ ;
267 :    
268 :     : compile-only-error ( ... -- )
269 :     -&14 throw ;
270 :    
271 :     : (cfa>int) ( cfa -- xt )
272 :     [ has? compiler [IF] ]
273 :     dup interpret/compile?
274 :     if
275 :     interpret/compile-int @
276 :     then
277 :     [ [THEN] ] ;
278 :    
279 :     : (x>int) ( cfa b -- xt )
280 :     \ get interpretation semantics of name
281 :     restrict-mask and
282 :     if
283 :     drop ['] compile-only-error
284 :     else
285 :     (cfa>int)
286 :     then ;
287 :    
288 :     : name>string ( nt -- addr count ) \ gforth head-to-string
289 :     \g @var{addr count} is the name of the word represented by @var{nt}.
290 :     cell+ count $1F and ;
291 :    
292 :     : ((name>)) ( nfa -- cfa )
293 :     name>string + cfaligned ;
294 :    
295 :     : (name>x) ( nfa -- cfa b )
296 :     \ cfa is an intermediate cfa and b is the flags byte of nfa
297 :     dup ((name>))
298 :     swap cell+ c@ dup alias-mask and 0=
299 :     IF
300 :     swap @ swap
301 :     THEN ;
302 :    
303 :     : name>int ( nt -- xt ) \ gforth
304 : crook 1.31 \G @i{xt} represents the interpretation semantics of the word
305 :     \G @i{nt}. If @i{nt} has no interpretation semantics (i.e. is
306 :     \G @code{compile-only}), @i{xt} is the execution token for
307 :     \G @code{compile-only-error}, which performs @code{-14 throw}.
308 : pazsan 1.1 (name>x) (x>int) ;
309 :    
310 :     : name?int ( nt -- xt ) \ gforth
311 : crook 1.31 \G Like @code{name>int}, but perform @code{-14 throw} if @i{nt}
312 :     \G has no interpretation semantics.
313 : pazsan 1.1 (name>x) restrict-mask and
314 :     if
315 :     compile-only-error \ does not return
316 :     then
317 :     (cfa>int) ;
318 :    
319 :     : (name>comp) ( nt -- w +-1 ) \ gforth
320 : crook 1.31 \G @i{w xt} is the compilation token for the word @i{nt}.
321 : pazsan 1.1 (name>x) >r
322 :     [ has? compiler [IF] ]
323 :     dup interpret/compile?
324 :     if
325 :     interpret/compile-comp @
326 :     then
327 :     [ [THEN] ]
328 :     r> immediate-mask and flag-sign
329 :     ;
330 :    
331 :     : (name>intn) ( nfa -- xt +-1 )
332 :     (name>x) tuck (x>int) ( b xt )
333 :     swap immediate-mask and flag-sign ;
334 :    
335 : jwilke 1.30 const Create ??? 0 , 3 c, char ? c, char ? c, char ? c,
336 :     \ ??? is used by dovar:, must be created/:dovar
337 :    
338 :     [IFDEF] forthstart
339 :     \ if we have a forthstart we can define head? with it
340 :     \ otherwise leave out the head? check
341 :    
342 : anton 1.14 : head? ( addr -- f )
343 :     \G heuristic check whether addr is a name token; may deliver false
344 :     \G positives; addr must be a valid address
345 :     \ we follow the link fields and check for plausibility; two
346 :     \ iterations should catch most false addresses: on the first
347 :     \ iteration, we may get an xt, on the second a code address (or
348 :     \ some code), which is typically not in the dictionary.
349 :     2 0 do
350 :     dup @ dup
351 :     if ( addr addr1 )
352 :     dup rot forthstart within
353 :     if \ addr1 is outside forthstart..addr, not a head
354 :     drop false unloop exit
355 :     then ( addr1 )
356 :     else \ 0 in the link field, no further checks
357 :     2drop true unloop exit
358 :     then
359 :     loop
360 :     \ in dubio pro:
361 :     drop true ;
362 :    
363 :     : >head ( cfa -- nt ) \ gforth to-head
364 :     $21 cell do ( cfa )
365 :     dup i - count $9F and + cfaligned over alias-mask + =
366 :     if ( cfa )
367 :     dup i - cell - dup head?
368 :     if
369 :     nip unloop exit
370 :     then
371 :     drop
372 :     then
373 :     cell +loop
374 :     drop ??? ( wouldn't 0 be better? ) ;
375 : pazsan 1.1
376 : jwilke 1.30 [ELSE]
377 :    
378 :     : >head ( cfa -- nt ) \ gforth to-head
379 :     $21 cell do ( cfa )
380 :     dup i - count $9F and + cfaligned over alias-mask + =
381 :     if ( cfa ) i - cell - unloop exit
382 :     then
383 :     cell +loop
384 :     drop ??? ( wouldn't 0 be better? ) ;
385 :    
386 :     [THEN]
387 :    
388 : pazsan 1.1 ' >head ALIAS >name
389 :    
390 :     : body> 0 >body - ;
391 :    
392 : crook 1.31 : (search-wordlist) ( addr count wid -- nt | false )
393 : pazsan 1.1 dup wordlist-map @ find-method perform ;
394 :    
395 : crook 1.31 : search-wordlist ( c-addr count wid -- 0 | xt +-1 ) \ search
396 :     \G Search the word list identified by @i{wid}
397 :     \G for the definition named by the string at @i{c-addr count}.
398 : crook 1.17 \G If the definition is not found, return 0. If the definition
399 :     \G is found return 1 (if the definition is immediate) or -1
400 : crook 1.31 \G (if the definition is not immediate) together with the @i{xt}.
401 :     \G The @i{xt} returned represents the interpretation semantics.
402 : pazsan 1.1 (search-wordlist) dup if
403 :     (name>intn)
404 :     then ;
405 :    
406 : crook 1.31 : find-name ( c-addr u -- nt | 0 ) \ gforth
407 :     \g Find the name @i{c-addr u} in the current search
408 :     \g order. Return its @i{nt}, if found, otherwise 0.
409 : pazsan 1.1 lookup @ (search-wordlist) ;
410 :    
411 :     : sfind ( c-addr u -- 0 / xt +-1 ) \ gforth-obsolete
412 :     find-name dup
413 :     if ( nt )
414 :     state @
415 :     if
416 :     (name>comp)
417 :     else
418 :     (name>intn)
419 :     then
420 :     then ;
421 :    
422 : crook 1.31 : find ( c-addr -- xt +-1 | c-addr 0 ) \ core,search
423 : crook 1.17 \G Search all word lists in the current search order
424 : crook 1.31 \G for the definition named by the counted string at @i{c-addr}.
425 : crook 1.17 \G If the definition is not found, return 0. If the definition
426 :     \G is found return 1 (if the definition is immediate) or -1
427 : crook 1.31 \G (if the definition is not immediate) together with the @i{xt}.
428 : pazsan 1.1 dup count sfind dup
429 :     if
430 :     rot drop
431 :     then ;
432 :    
433 : jwilke 1.34 \ ticks in interpreter
434 : pazsan 1.1
435 :     : (') ( "name" -- nt ) \ gforth
436 : anton 1.32 name name-too-short?
437 : anton 1.28 find-name dup 0=
438 : pazsan 1.1 IF
439 :     drop -&13 bounce
440 :     THEN ;
441 :    
442 :     : ' ( "name" -- xt ) \ core tick
443 : crook 1.31 \g @i{xt} represents @i{name}'s interpretation
444 :     \g semantics. Perform @code{-14 throw} if the word has no
445 : pazsan 1.1 \g interpretation semantics.
446 :     (') name?int ;
447 : jwilke 1.34
448 :     has? compiler 0= [IF] \ interpreter only version of IS and TO
449 :    
450 :     : IS ' >body ! ;
451 :     ' IS Alias TO
452 :    
453 :     [THEN]
454 : pazsan 1.1
455 :     \ \ the interpreter loop mar92py
456 :    
457 :     \ interpret 10mar92py
458 :    
459 : anton 1.37 Defer parser ( c-addr u -- )
460 : pazsan 1.1 Defer name ( -- c-addr count ) \ gforth
461 :     \ get the next word from the input buffer
462 :     ' (name) IS name
463 :     Defer compiler-notfound ( c-addr count -- )
464 :     Defer interpreter-notfound ( c-addr count -- )
465 :    
466 :     : no.extensions ( addr u -- )
467 :     2drop -&13 bounce ;
468 :     ' no.extensions IS compiler-notfound
469 :     ' no.extensions IS interpreter-notfound
470 :    
471 :     : interpret ( ?? -- ?? ) \ gforth
472 :     \ interpret/compile the (rest of the) input buffer
473 : jwilke 1.33 [ has? backtrace [IF] ]
474 : anton 1.24 rp@ backtrace-rp0 !
475 : jwilke 1.33 [ [THEN] ]
476 : pazsan 1.1 BEGIN
477 :     ?stack name dup
478 :     WHILE
479 :     parser
480 :     REPEAT
481 :     2drop ;
482 :    
483 :     \ interpreter 30apr92py
484 :    
485 :     \ not the most efficient implementations of interpreter and compiler
486 : jwilke 1.33 : interpreter ( c-addr u -- )
487 : pazsan 1.1 2dup find-name dup
488 :     if
489 :     nip nip name>int execute
490 :     else
491 :     drop
492 :     2dup 2>r snumber?
493 :     IF
494 :     2rdrop
495 :     ELSE
496 :     2r> interpreter-notfound
497 :     THEN
498 :     then ;
499 :    
500 :     ' interpreter IS parser
501 :    
502 :     \ \ Query Evaluate 07apr93py
503 :    
504 :     has? file 0= [IF]
505 : pazsan 1.12 : sourceline# ( -- n ) 1 ;
506 : pazsan 1.1 [THEN]
507 :    
508 :     : refill ( -- flag ) \ core-ext,block-ext,file-ext
509 : crook 1.29 \G Attempt to fill the input buffer from the input source. When
510 :     \G the input source is the user input device, attempt to receive
511 :     \G input into the terminal input device. If successful, make the
512 :     \G result the input buffer, set @code{>IN} to 0 and return true;
513 :     \G otherwise return false. When the input source is a block, add 1
514 :     \G to the value of @code{BLK} to make the next block the input
515 :     \G source and current input buffer, and set @code{>IN} to 0;
516 :     \G return true if the new value of @code{BLK} is a valid block
517 :     \G number, false otherwise. When the input source is a text file,
518 :     \G attempt to read the next line from the file. If successful,
519 :     \G make the result the current input buffer, set @code{>IN} to 0
520 :     \G and return true; otherwise, return false. A successful result
521 :     \G includes receipt of a line containing 0 characters.
522 : pazsan 1.12 [ has? file [IF] ]
523 :     blk @ IF 1 blk +! true 0 >in ! EXIT THEN
524 :     [ [THEN] ]
525 :     tib /line
526 :     [ has? file [IF] ]
527 :     loadfile @ ?dup
528 :     IF read-line throw
529 :     ELSE
530 :     [ [THEN] ]
531 :     sourceline# 0< IF 2drop false EXIT THEN
532 :     accept true
533 :     [ has? file [IF] ]
534 :     THEN
535 :     1 loadline +!
536 :     [ [THEN] ]
537 :     swap #tib ! 0 >in ! ;
538 : pazsan 1.1
539 :     : query ( -- ) \ core-ext
540 : crook 1.29 \G Make the user input device the input source. Receive input into
541 :     \G the Terminal Input Buffer. Set @code{>IN} to zero. OBSOLESCENT:
542 :     \G superceeded by @code{accept}.
543 : pazsan 1.12 [ has? file [IF] ]
544 :     blk off loadfile off
545 :     [ [THEN] ]
546 : pazsan 1.1 tib /line accept #tib ! 0 >in ! ;
547 :    
548 :     \ save-mem extend-mem
549 :    
550 :     has? os [IF]
551 :     : save-mem ( addr1 u -- addr2 u ) \ gforth
552 :     \g copy a memory block into a newly allocated region in the heap
553 :     swap >r
554 :     dup allocate throw
555 :     swap 2dup r> -rot move ;
556 :    
557 :     : extend-mem ( addr1 u1 u -- addr addr2 u2 )
558 :     \ extend memory block allocated from the heap by u aus
559 :     \ the (possibly reallocated piece is addr2 u2, the extension is at addr
560 :     over >r + dup >r resize throw
561 :     r> over r> + -rot ;
562 :     [THEN]
563 :    
564 :     \ EVALUATE 17may93jaw
565 :    
566 :     has? file 0= [IF]
567 :     : push-file ( -- ) r>
568 : pazsan 1.12 tibstack @ >r >tib @ >r #tib @ >r
569 : pazsan 1.1 >tib @ tibstack @ = IF r@ tibstack +! THEN
570 :     tibstack @ >tib ! >in @ >r >r ;
571 :    
572 :     : pop-file ( throw-code -- throw-code )
573 :     r>
574 : pazsan 1.12 r> >in ! r> #tib ! r> >tib ! r> tibstack ! >r ;
575 : pazsan 1.1 [THEN]
576 :    
577 : crook 1.29 : evaluate ( c-addr u -- ) \ core,block
578 :     \G Save the current input source specification. Store -1 in
579 :     \G @code{source-id} and 0 in @code{blk}. Set @code{>IN} to 0 and
580 :     \G make the string @var{c-addr u} the input source and input
581 :     \G buffer. Interpret. When the parse area is empty, restore the
582 :     \G input source specification.
583 :     push-file #tib ! >tib !
584 :     >in off
585 :     [ has? file [IF] ]
586 :     blk off loadfile off -1 loadline !
587 :     [ [THEN] ]
588 :     ['] interpret catch
589 :     pop-file throw ;
590 : pazsan 1.1
591 :     \ \ Quit 13feb93py
592 :    
593 :     Defer 'quit
594 :    
595 :     Defer .status
596 :    
597 :     : prompt state @ IF ." compiled" EXIT THEN ." ok" ;
598 :    
599 :     : (Query) ( -- )
600 : pazsan 1.12 [ has? file [IF] ]
601 :     loadfile off blk off loadline off
602 :     [ [THEN] ]
603 :     refill drop ;
604 : pazsan 1.1
605 : anton 1.39 : (quit) ( -- )
606 :     \ exits only through THROW etc.
607 :     sp0 @ cell - handler @ &12 + ! \ !! kludge: fix the stack pointer
608 :     \ stored in the system's CATCH frame, so the stack depth will be 0
609 :     \ after the next THROW it catches (it may be off due to BOUNCEs or
610 :     \ because process-args left something on the stack)
611 :     BEGIN
612 :     .status cr (query) interpret prompt
613 :     AGAIN ;
614 : pazsan 1.1
615 :     ' (quit) IS 'quit
616 :    
617 :     \ \ DOERROR (DOERROR) 13jun93jaw
618 :    
619 :     8 Constant max-errors
620 :     Variable error-stack 0 error-stack !
621 :     max-errors 6 * cells allot
622 :     \ format of one cell:
623 :     \ source ( addr u )
624 :     \ >in
625 :     \ line-number
626 :     \ Loadfilename ( addr u )
627 :    
628 :     : dec. ( n -- ) \ gforth
629 : crook 1.27 \G Display @var{n} as a signed decimal number, followed by a space.
630 : jwilke 1.23 \G !! not used...
631 : pazsan 1.1 base @ decimal swap . base ! ;
632 :    
633 : jwilke 1.23 : dec.r ( u -- ) \ gforth
634 : crook 1.27 \G Display @var{u} as a unsigned decimal number
635 : jwilke 1.23 base @ decimal swap 0 .r base ! ;
636 :    
637 : pazsan 1.1 : hex. ( u -- ) \ gforth
638 : crook 1.27 \G Display @var{u} as an unsigned hex number, prefixed with a "$" and
639 : crook 1.17 \G followed by a space.
640 : jwilke 1.23 \G !! not used...
641 : jwilke 1.33 [char] $ emit base @ swap hex u. base ! ;
642 : pazsan 1.1
643 :     : typewhite ( addr u -- ) \ gforth
644 :     \ like type, but white space is printed instead of the characters
645 :     bounds ?do
646 :     i c@ #tab = if \ check for tab
647 :     #tab
648 :     else
649 :     bl
650 :     then
651 :     emit
652 :     loop ;
653 :    
654 :     DEFER DOERROR
655 : jwilke 1.33
656 :     has? backtrace [IF]
657 : anton 1.15 Defer dobacktrace ( -- )
658 :     ' noop IS dobacktrace
659 : jwilke 1.33 [THEN]
660 : pazsan 1.1
661 : jwilke 1.23 : .error-string ( throw-code -- )
662 :     dup -2 =
663 :     IF "error @ ?dup IF count type THEN drop
664 :     ELSE .error
665 :     THEN ;
666 :    
667 :     : .error-frame ( throwcode addr1 u1 n1 n2 addr2 u2 -- throwcode )
668 :     \ addr2 u2: filename of included file
669 :     \ n2: line number
670 :     \ n1: error position in input line
671 :     \ addr1 u1: input line
672 :    
673 : pazsan 1.1 cr error-stack @
674 :     IF
675 :     ." in file included from "
676 : jwilke 1.23 type ." :" dec.r drop 2drop
677 : pazsan 1.1 ELSE
678 : jwilke 1.23 type ." :" dec.r ." : " 3 pick .error-string cr
679 :     dup 2over type cr drop
680 : pazsan 1.1 nip -trailing 1- ( line-start index2 )
681 :     0 >r BEGIN
682 :     2dup + c@ bl > WHILE
683 :     r> 1+ >r 1- dup 0< UNTIL THEN 1+
684 :     ( line-start index1 )
685 :     typewhite
686 :     r> 1 max 0 ?do \ we want at least one "^", even if the length is 0
687 :     [char] ^ emit
688 :     loop
689 : jwilke 1.23 THEN ;
690 : pazsan 1.1
691 :     : (DoError) ( throw-code -- )
692 :     [ has? os [IF] ]
693 : pazsan 1.8 >stderr
694 : pazsan 1.1 [ [THEN] ]
695 :     sourceline# IF
696 : pazsan 1.8 source >in @ sourceline# 0 0 .error-frame
697 : pazsan 1.1 THEN
698 :     error-stack @ 0 ?DO
699 :     -1 error-stack +!
700 :     error-stack dup @ 6 * cells + cell+
701 :     6 cells bounds DO
702 :     I @
703 :     cell +LOOP
704 :     .error-frame
705 :     LOOP
706 : jwilke 1.33 drop
707 :     [ has? backtrace [IF] ]
708 :     dobacktrace
709 :     [ [THEN] ]
710 : pazsan 1.8 normal-dp dpp ! ;
711 : pazsan 1.1
712 :     ' (DoError) IS DoError
713 :    
714 :     : quit ( ?? -- ?? ) \ core
715 : crook 1.27 \G Empty the return stack, make the user input device
716 :     \G the input source, enter interpret state and start
717 :     \G the text interpreter.
718 : anton 1.5 rp0 @ rp! handler off clear-tibstack >tib @ >r
719 : pazsan 1.1 BEGIN
720 :     [ has? compiler [IF] ]
721 :     postpone [
722 :     [ [THEN] ]
723 :     ['] 'quit CATCH dup
724 :     WHILE
725 : anton 1.22 <# \ reset hold area, or we may get another error
726 : pazsan 1.1 DoError r@ >tib ! r@ tibstack !
727 :     REPEAT
728 :     drop r> >tib ! ;
729 :    
730 :     \ \ Cold Boot 13feb93py
731 :    
732 :     : (bootmessage)
733 :     ." GForth " version-string type
734 : anton 1.11 ." , Copyright (C) 1998 Free Software Foundation, Inc." cr
735 : pazsan 1.1 ." GForth comes with ABSOLUTELY NO WARRANTY; for details type `license'"
736 :     [ has? os [IF] ]
737 :     cr ." Type `bye' to exit"
738 :     [ [THEN] ] ;
739 :    
740 :     defer bootmessage
741 :     defer process-args
742 :    
743 :     ' (bootmessage) IS bootmessage
744 :    
745 : anton 1.10 Defer 'cold ( -- ) \ gforth tick-cold
746 : pazsan 1.1 \ hook (deferred word) for things to do right before interpreting the
747 :     \ command-line arguments
748 :     ' noop IS 'cold
749 :    
750 :    
751 :     Variable init8
752 :    
753 :     : cold ( -- ) \ gforth
754 :     [ has? file [IF] ]
755 :     pathstring 2@ fpath only-path
756 :     init-included-files
757 :     [ [THEN] ]
758 :     'cold
759 :     init8 chainperform
760 :     [ has? file [IF] ]
761 : pazsan 1.8 process-args
762 : pazsan 1.12 loadline off
763 : pazsan 1.1 [ [THEN] ]
764 :     bootmessage
765 : pazsan 1.12 quit ;
766 : pazsan 1.1
767 : anton 1.5 : clear-tibstack ( -- )
768 :     [ has? glocals [IF] ]
769 :     lp@ forthstart 7 cells + @ -
770 :     [ [ELSE] ]
771 :     [ has? os [IF] ]
772 : pazsan 1.8 r0 @ forthstart 6 cells + @ -
773 : anton 1.5 [ [ELSE] ]
774 : pazsan 1.16 sp@ $10 cells +
775 : anton 1.5 [ [THEN] ]
776 :     [ [THEN] ]
777 :     dup >tib ! tibstack ! #tib off >in off ;
778 :    
779 : pazsan 1.1 : boot ( path **argv argc -- )
780 :     main-task up!
781 :     [ has? os [IF] ]
782 :     stdout TO outfile-id
783 : pazsan 1.7 stdin TO infile-id
784 : pazsan 1.1 \ !! [ [THEN] ]
785 :     \ !! [ has? file [IF] ]
786 :     argc ! argv ! pathstring 2!
787 :     [ [THEN] ]
788 :     sp@ sp0 !
789 : anton 1.5 clear-tibstack
790 : pazsan 1.1 rp@ rp0 !
791 :     [ has? floating [IF] ]
792 :     fp@ fp0 !
793 :     [ [THEN] ]
794 : pazsan 1.8 ['] cold catch DoError cr
795 : pazsan 1.1 [ has? os [IF] ]
796 : anton 1.35 1 (bye) \ !! determin exit code from throw code?
797 : pazsan 1.1 [ [THEN] ]
798 :     ;
799 :    
800 :     has? os [IF]
801 :     : bye ( -- ) \ tools-ext
802 :     [ has? file [IF] ]
803 :     script? 0= IF cr THEN
804 :     [ [ELSE] ]
805 :     cr
806 :     [ [THEN] ]
807 :     0 (bye) ;
808 :     [THEN]
809 :    
810 :     \ **argv may be scanned by the C starter to get some important
811 :     \ information, as -display and -geometry for an X client FORTH
812 :     \ or space and stackspace overrides
813 :    
814 :     \ 0 arg contains, however, the name of the program.
815 :    

CVS Admin

Powered by ViewCVS 1.0-dev
(Powered by ViewCVS)

ViewCVS and CVS Help