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