Annotation of gforth/kernel/int.fs, revision 1.3

1.1       pazsan      1: \ definitions needed for interpreter only
                      2: 
                      3: \ \ Revision-Log
                      4: 
                      5: \       put in seperate file                           14sep97jaw 
                      6: 
                      7: \ \ input stream primitives                            23feb93py
                      8: 
                      9: : tib ( -- c-addr ) \ core-ext
                     10:     \ obsolescent
                     11:     >tib @ ;
                     12: 
                     13: Defer source ( -- addr count ) \ core
                     14: \ used by dodefer:, must be defer
                     15: 
                     16: : (source) ( -- addr count )
                     17:     tib #tib @ ;
                     18: ' (source) IS source
                     19: 
                     20: : (word) ( addr1 n1 char -- addr2 n2 )
                     21:   dup >r skip 2dup r> scan  nip - ;
                     22: 
                     23: \ (word) should fold white spaces
                     24: \ this is what (parse-white) does
                     25: 
                     26: \ word parse                                           23feb93py
                     27: 
1.3     ! anton      28: : sword  ( char -- addr len ) \ gforth
        !            29:   \G parses like @code{word}, but the output is like @code{parse} output
        !            30:   \ this word was called PARSE-WORD until 0.3.0, but Open Firmware and
        !            31:   \ dpANS6 A.6.2.2008 have a word with that name that behaves
        !            32:   \ differently (like NAME).
1.1       pazsan     33:   source 2dup >r >r >in @ over min /string
                     34:   rot dup bl = IF  drop (parse-white)  ELSE  (word)  THEN
                     35:   2dup + r> - 1+ r> min >in ! ;
                     36: 
                     37: : word   ( char -- addr ) \ core
1.3     ! anton      38:   sword here place  bl here count + c!  here ;
1.1       pazsan     39: 
                     40: : parse    ( char -- addr len ) \ core-ext
                     41:   >r  source  >in @ over min /string  over  swap r>  scan >r
                     42:   over - dup r> IF 1+ THEN  >in +! ;
                     43: 
                     44: \ name                                                 13feb93py
                     45: 
                     46: : capitalize ( addr len -- addr len ) \ gforth
                     47:   2dup chars chars bounds
                     48:   ?DO  I c@ toupper I c! 1 chars +LOOP ;
                     49: 
                     50: [IFUNDEF] (name) \ name might be a primitive
                     51: 
                     52: : (name) ( -- c-addr count )
                     53:     source 2dup >r >r >in @ /string (parse-white)
                     54:     2dup + r> - 1+ r> min >in ! ;
                     55: \    name count ;
                     56: [THEN]
                     57: 
                     58: : name-too-short? ( c-addr u -- c-addr u )
                     59:     dup 0= -&16 and throw ;
                     60: 
                     61: : name-too-long? ( c-addr u -- c-addr u )
                     62:     dup $1F u> -&19 and throw ;
                     63: 
                     64: \ \ Number parsing                                     23feb93py
                     65: 
                     66: \ number? number                                       23feb93py
                     67: 
                     68: hex
                     69: const Create bases   10 ,   2 ,   A , 100 ,
                     70: \                     16     2    10   character
                     71: \ !! this saving and restoring base is an abomination! - anton
                     72: 
                     73: : getbase ( addr u -- addr' u' )
                     74:     over c@ [char] $ - dup 4 u<
                     75:     IF
                     76:        cells bases + @ base ! 1 /string
                     77:     ELSE
                     78:        drop
                     79:     THEN ;
                     80: 
                     81: : s>number ( addr len -- d )
                     82:     base @ >r  dpl on
                     83:     over c@ '- =  dup >r
                     84:     IF
                     85:        1 /string
                     86:     THEN
                     87:     getbase  dpl on  0 0 2swap
                     88:     BEGIN
                     89:        dup >r >number dup
                     90:     WHILE
                     91:        dup r> -
                     92:     WHILE
                     93:        dup dpl ! over c@ [char] . =
                     94:     WHILE
                     95:        1 /string
                     96:     REPEAT  THEN
                     97:         2drop rdrop dpl off
                     98:     ELSE
                     99:        2drop rdrop r>
                    100:        IF
                    101:            dnegate
                    102:        THEN
                    103:     THEN
                    104:     r> base ! ;
                    105: 
                    106: : snumber? ( c-addr u -- 0 / n -1 / d 0> )
                    107:     s>number dpl @ 0=
                    108:     IF
                    109:        2drop false  EXIT
                    110:     THEN
                    111:     dpl @ dup 0> 0= IF
                    112:        nip
                    113:     THEN ;
                    114: 
                    115: : number? ( string -- string 0 / n -1 / d 0> )
                    116:     dup >r count snumber? dup if
                    117:        rdrop
                    118:     else
                    119:        r> swap
                    120:     then ;
                    121: 
                    122: : number ( string -- d )
                    123:     number? ?dup 0= abort" ?"  0<
                    124:     IF
                    125:        s>d
                    126:     THEN ;
                    127: 
                    128: \ \ Comments ( \ \G
                    129: 
                    130: : ( ( compilation 'ccc<close-paren>' -- ; run-time -- ) \ core,file    paren
                    131:     [char] ) parse 2drop ; immediate
                    132: 
                    133: : \ ( -- ) \ core-ext backslash
                    134:     blk @
                    135:     IF
                    136:        >in @ c/l / 1+ c/l * >in !
                    137:        EXIT
                    138:     THEN
                    139:     source >in ! drop ; immediate
                    140: 
                    141: : \G ( -- ) \ gforth backslash
                    142:     POSTPONE \ ; immediate
                    143: 
                    144: \ \ object oriented search list                         17mar93py
                    145: 
                    146: \ word list structure:
                    147: 
                    148: struct
                    149:   cell% field find-method   \ xt: ( c_addr u wid -- nt )
                    150:   cell% field reveal-method \ xt: ( nt wid -- ) \ used by dofield:, must be field
                    151:   cell% field rehash-method \ xt: ( wid -- )      \ re-initializes a "search-data" (hashtables)
                    152:   cell% field hash-method   \ xt: ( wid -- )    \ initializes ""
                    153: \   \ !! what else
                    154: end-struct wordlist-map-struct
                    155: 
                    156: struct
                    157:   cell% field wordlist-id \ not the same as wid; representation depends on implementation
                    158:   cell% field wordlist-map \ pointer to a wordlist-map-struct
                    159:   cell% field wordlist-link \ link field to other wordlists
                    160:   cell% field wordlist-extend \ points to wordlist extensions (eg hashtables)
                    161: end-struct wordlist-struct
                    162: 
                    163: : f83find      ( addr len wordlist -- nt / false )
                    164:     ( wid>wordlist-id ) @ (f83find) ;
                    165: 
                    166: : initvoc              ( wid -- )
                    167:   dup wordlist-map @ hash-method perform ;
                    168: 
                    169: \ Search list table: find reveal
                    170: Create f83search ( -- wordlist-map )
                    171:     ' f83find A,  ' drop A,  ' drop A, ' drop A,
                    172: 
                    173: here NIL A, G f83search T A, NIL A, NIL A,
                    174: AValue forth-wordlist \ variable, will be redefined by search.fs
                    175: 
                    176: AVariable lookup               forth-wordlist lookup !
                    177: \ !! last is user and lookup?! jaw
                    178: AVariable current ( -- addr ) \ gforth
                    179: AVariable voclink      forth-wordlist wordlist-link voclink !
                    180: lookup AValue context
                    181: 
                    182: forth-wordlist current !
                    183: 
                    184: \ \ header, finding, ticks                              17dec92py
                    185: 
                    186: $80 constant alias-mask \ set when the word is not an alias!
                    187: $40 constant immediate-mask
                    188: $20 constant restrict-mask
                    189: 
                    190: \ higher level parts of find
                    191: 
                    192: : flag-sign ( f -- 1|-1 )
                    193:     \ true becomes 1, false -1
                    194:     0= 2* 1+ ;
                    195: 
                    196: : compile-only-error ( ... -- )
                    197:     -&14 throw ;
                    198: 
                    199: : (cfa>int) ( cfa -- xt )
                    200: [ has? compiler [IF] ]
                    201:     dup interpret/compile?
                    202:     if
                    203:        interpret/compile-int @
                    204:     then 
                    205: [ [THEN] ] ;
                    206: 
                    207: : (x>int) ( cfa b -- xt )
                    208:     \ get interpretation semantics of name
                    209:     restrict-mask and
                    210:     if
                    211:        drop ['] compile-only-error
                    212:     else
                    213:        (cfa>int)
                    214:     then ;
                    215: 
                    216: : name>string ( nt -- addr count ) \ gforth     head-to-string
                    217:     \g @var{addr count} is the name of the word represented by @var{nt}.
                    218:     cell+ count $1F and ;
                    219: 
                    220: : ((name>))  ( nfa -- cfa )
                    221:     name>string + cfaligned ;
                    222: 
                    223: : (name>x) ( nfa -- cfa b )
                    224:     \ cfa is an intermediate cfa and b is the flags byte of nfa
                    225:     dup ((name>))
                    226:     swap cell+ c@ dup alias-mask and 0=
                    227:     IF
                    228:         swap @ swap
                    229:     THEN ;
                    230: 
                    231: : name>int ( nt -- xt ) \ gforth
                    232:     \G @var{xt} represents the interpretation semantics of the word
                    233:     \G @var{nt}. Produces @code{' compile-only-error} if
                    234:     \G @var{nt} is compile-only.
                    235:     (name>x) (x>int) ;
                    236: 
                    237: : name?int ( nt -- xt ) \ gforth
                    238:     \G Like name>int, but throws an error if compile-only.
                    239:     (name>x) restrict-mask and
                    240:     if
                    241:        compile-only-error \ does not return
                    242:     then
                    243:     (cfa>int) ;
                    244: 
                    245: : (name>comp) ( nt -- w +-1 ) \ gforth
                    246:     \G @var{w xt} is the compilation token for the word @var{nt}.
                    247:     (name>x) >r 
                    248: [ has? compiler [IF] ]
                    249:     dup interpret/compile?
                    250:     if
                    251:         interpret/compile-comp @
                    252:     then 
                    253: [ [THEN] ]
                    254:     r> immediate-mask and flag-sign
                    255:     ;
                    256: 
                    257: : (name>intn) ( nfa -- xt +-1 )
                    258:     (name>x) tuck (x>int) ( b xt )
                    259:     swap immediate-mask and flag-sign ;
                    260: 
                    261: const Create ???  0 , 3 c, char ? c, char ? c, char ? c,
                    262: \ ??? is used by dovar:, must be created/:dovar
                    263: 
                    264: : >head ( cfa -- nt ) \ gforth  to-name
                    265:  $21 cell do
                    266:    dup i - count $9F and + cfaligned over alias-mask + = if
                    267:      i - cell - unloop exit
                    268:    then
                    269:  cell +loop
                    270:  drop ??? ( wouldn't 0 be better? ) ;
                    271: 
                    272: ' >head ALIAS >name
                    273: 
                    274: : body> 0 >body - ;
                    275: 
                    276: : (search-wordlist)  ( addr count wid -- nt / false )
                    277:     dup wordlist-map @ find-method perform ;
                    278: 
                    279: : search-wordlist ( addr count wid -- 0 / xt +-1 ) \ search
                    280:     \ xt is the interpretation semantics
                    281:     (search-wordlist) dup if
                    282:        (name>intn)
                    283:     then ;
                    284: 
                    285: : find-name ( c-addr u -- nt/0 ) \ gforth
                    286:     \g Find the name @var{c-addr u} in the current search
                    287:     \g order. Return its nt, if found, otherwise 0.
                    288:     lookup @ (search-wordlist) ;
                    289: 
                    290: : sfind ( c-addr u -- 0 / xt +-1  ) \ gforth-obsolete
                    291:     find-name dup
                    292:     if ( nt )
                    293:        state @
                    294:        if
                    295:            (name>comp)
                    296:        else
                    297:            (name>intn)
                    298:        then
                    299:    then ;
                    300: 
                    301: : find ( c-addr -- xt +-1 / c-addr 0 ) \ core,search
                    302:     dup count sfind dup
                    303:     if
                    304:        rot drop
                    305:     then ;
                    306: 
                    307: \ ticks
                    308: 
                    309: : (') ( "name" -- nt ) \ gforth
                    310:     name find-name dup 0=
                    311:     IF
                    312:        drop -&13 bounce
                    313:     THEN  ;
                    314: 
                    315: : '    ( "name" -- xt ) \ core tick
                    316:     \g @var{xt} represents @var{name}'s interpretation
                    317:     \g semantics. Performs @code{-14 throw} if the word has no
                    318:     \g interpretation semantics.
                    319:     (') name?int ;
                    320: 
                    321: \ \ the interpreter loop                                 mar92py
                    322: 
                    323: \ interpret                                            10mar92py
                    324: 
                    325: Defer parser
                    326: Defer name ( -- c-addr count ) \ gforth
                    327: \ get the next word from the input buffer
                    328: ' (name) IS name
                    329: Defer compiler-notfound ( c-addr count -- )
                    330: Defer interpreter-notfound ( c-addr count -- )
                    331: 
                    332: : no.extensions  ( addr u -- )
                    333:     2drop -&13 bounce ;
                    334: ' no.extensions IS compiler-notfound
                    335: ' no.extensions IS interpreter-notfound
                    336: 
                    337: : interpret ( ?? -- ?? ) \ gforth
                    338:     \ interpret/compile the (rest of the) input buffer
                    339:     BEGIN
                    340:        ?stack name dup
                    341:     WHILE
                    342:        parser
                    343:     REPEAT
                    344:     2drop ;
                    345: 
                    346: \ interpreter                                  30apr92py
                    347: 
                    348: \ not the most efficient implementations of interpreter and compiler
                    349: : interpreter ( c-addr u -- ) 
                    350:     2dup find-name dup
                    351:     if
                    352:        nip nip name>int execute
                    353:     else
                    354:        drop
                    355:        2dup 2>r snumber?
                    356:        IF
                    357:            2rdrop
                    358:        ELSE
                    359:            2r> interpreter-notfound
                    360:        THEN
                    361:     then ;
                    362: 
                    363: ' interpreter  IS  parser
                    364: 
                    365: \ \ Query Evaluate                                     07apr93py
                    366: 
                    367: has? file 0= [IF]
                    368: : sourceline# ( -- n )  loadline @ ;
                    369: [THEN]
                    370: 
                    371: : refill ( -- flag ) \ core-ext,block-ext,file-ext
                    372:   blk @  IF  1 blk +!  true  0 >in !  EXIT  THEN
                    373:   tib /line
                    374: [ has? file [IF] ]
                    375:   loadfile @ ?dup
                    376:   IF    read-line throw
                    377:   ELSE
                    378: [ [THEN] ]
                    379:       sourceline# 0< IF 2drop false EXIT THEN
                    380:       accept true
                    381: [ has? file [IF] ]
                    382:   THEN
                    383: [ [THEN] ]
                    384:   1 loadline +!
                    385:   swap #tib ! 0 >in ! ;
                    386: 
                    387: : query   ( -- ) \ core-ext
                    388:     \G obsolescent
                    389:     blk off loadfile off
                    390:     tib /line accept #tib ! 0 >in ! ;
                    391: 
                    392: \ save-mem extend-mem
                    393: 
                    394: has? os [IF]
                    395: : save-mem     ( addr1 u -- addr2 u ) \ gforth
                    396:     \g copy a memory block into a newly allocated region in the heap
                    397:     swap >r
                    398:     dup allocate throw
                    399:     swap 2dup r> -rot move ;
                    400: 
                    401: : extend-mem   ( addr1 u1 u -- addr addr2 u2 )
                    402:     \ extend memory block allocated from the heap by u aus
                    403:     \ the (possibly reallocated piece is addr2 u2, the extension is at addr
                    404:     over >r + dup >r resize throw
                    405:     r> over r> + -rot ;
                    406: [THEN]
                    407: 
                    408: \ EVALUATE                                              17may93jaw
                    409: 
                    410: has? file 0= [IF]
                    411: : push-file  ( -- )  r>
                    412:   sourceline# >r  tibstack @ >r  >tib @ >r  #tib @ >r
                    413:   >tib @ tibstack @ = IF  r@ tibstack +!  THEN
                    414:   tibstack @ >tib ! >in @ >r  >r ;
                    415: 
                    416: : pop-file   ( throw-code -- throw-code )
                    417:   r>
                    418:   r> >in !  r> #tib !  r> >tib !  r> tibstack !  r> loadline !  >r ;
                    419: [THEN]
                    420: 
                    421: : evaluate ( c-addr len -- ) \ core,block
                    422:   push-file  #tib ! >tib !
                    423:   >in off blk off loadfile off -1 loadline !
                    424:   ['] interpret catch
                    425:   pop-file throw ;
                    426: 
                    427: \ \ Quit                                               13feb93py
                    428: 
                    429: Defer 'quit
                    430: 
                    431: Defer .status
                    432: 
                    433: : prompt        state @ IF ."  compiled" EXIT THEN ."  ok" ;
                    434: 
                    435: : (Query)  ( -- )
                    436:     loadfile off  blk off  refill drop ;
                    437: 
                    438: : (quit)  BEGIN  .status cr (query) interpret prompt  AGAIN ;
                    439: 
                    440: ' (quit) IS 'quit
                    441: 
                    442: \ \ DOERROR (DOERROR)                                  13jun93jaw
                    443: 
                    444: 8 Constant max-errors
                    445: Variable error-stack  0 error-stack !
                    446: max-errors 6 * cells allot
                    447: \ format of one cell:
                    448: \ source ( addr u )
                    449: \ >in
                    450: \ line-number
                    451: \ Loadfilename ( addr u )
                    452: 
                    453: : dec. ( n -- ) \ gforth
                    454:     \ print value in decimal representation
                    455:     base @ decimal swap . base ! ;
                    456: 
                    457: : hex. ( u -- ) \ gforth
                    458:     \ print value as unsigned hex number
                    459:     '$ emit base @ swap hex u. base ! ;
                    460: 
                    461: : typewhite ( addr u -- ) \ gforth
                    462:     \ like type, but white space is printed instead of the characters
                    463:     bounds ?do
                    464:        i c@ #tab = if \ check for tab
                    465:            #tab
                    466:        else
                    467:            bl
                    468:        then
                    469:        emit
                    470:     loop ;
                    471: 
                    472: DEFER DOERROR
                    473: 
                    474: : .error-frame ( addr1 u1 n1 n2 addr2 u2 -- )
                    475:   cr error-stack @
                    476:   IF
                    477:      ." in file included from "
                    478:      type ." :" dec.  drop 2drop
                    479:   ELSE
                    480:      type ." :" dec.
                    481:      cr dup 2over type cr drop
                    482:      nip -trailing 1- ( line-start index2 )
                    483:      0 >r  BEGIN
                    484:                   2dup + c@ bl >  WHILE
                    485:                  r> 1+ >r  1- dup 0<  UNTIL  THEN  1+
                    486:      ( line-start index1 )
                    487:      typewhite
                    488:      r> 1 max 0 ?do \ we want at least one "^", even if the length is 0
                    489:                   [char] ^ emit
                    490:      loop
                    491:   THEN
                    492: ;
                    493: 
                    494: : (DoError) ( throw-code -- )
                    495:   [ has? os [IF] ]
                    496:       outfile-id dup flush-file drop >r
                    497:       stderr to outfile-id
                    498:   [ [THEN] ] 
                    499:   sourceline# IF
                    500:                source >in @ sourceline# 0 0 .error-frame
                    501:   THEN
                    502:   error-stack @ 0 ?DO
                    503:     -1 error-stack +!
                    504:     error-stack dup @ 6 * cells + cell+
                    505:     6 cells bounds DO
                    506:       I @
                    507:     cell +LOOP
                    508:     .error-frame
                    509:   LOOP
                    510:   dup -2 =
                    511:   IF 
                    512:      "error @ ?dup
                    513:      IF
                    514:         cr count type 
                    515:      THEN
                    516:      drop
                    517:   ELSE
                    518:      .error
                    519:   THEN
                    520:   normal-dp dpp ! 
                    521:   [ has? os [IF] ] r> to outfile-id [ [THEN] ]
                    522:   ;
                    523: 
                    524: ' (DoError) IS DoError
                    525: 
                    526: : quit ( ?? -- ?? ) \ core
                    527:     rp0 @ rp! handler off >tib @ >r
                    528:     BEGIN
                    529:        [ has? compiler [IF] ]
                    530:        postpone [
                    531:        [ [THEN] ]
                    532:        ['] 'quit CATCH dup
                    533:     WHILE
                    534:        DoError r@ >tib ! r@ tibstack !
                    535:     REPEAT
                    536:     drop r> >tib ! ;
                    537: 
                    538: \ \ Cold Boot                                          13feb93py
                    539: 
                    540: : (bootmessage)
                    541:     ." GForth " version-string type 
                    542:     ." , Copyright (C) 1994-1998 Free Software Foundation, Inc." cr
                    543:     ." GForth comes with ABSOLUTELY NO WARRANTY; for details type `license'"
                    544: [ has? os [IF] ]
                    545:      cr ." Type `bye' to exit"
                    546: [ [THEN] ] ;
                    547: 
                    548: defer bootmessage
                    549: defer process-args
                    550: 
                    551: ' (bootmessage) IS bootmessage
                    552: 
                    553: Defer 'cold 
                    554: \ hook (deferred word) for things to do right before interpreting the
                    555: \ command-line arguments
                    556: ' noop IS 'cold
                    557: 
1.2       anton     558: include ../chains.fs
1.1       pazsan    559: 
                    560: Variable init8
                    561: 
                    562: : cold ( -- ) \ gforth
                    563: [ has? file [IF] ]
                    564:     pathstring 2@ fpath only-path 
                    565:     init-included-files
                    566: [ [THEN] ]
                    567:     'cold
                    568:     init8 chainperform
                    569: [ has? file [IF] ]
                    570:     ['] process-args catch ?dup
                    571:     IF
                    572:       dup >r DoError cr r> negate (bye)
                    573:     THEN
                    574:     argc @ 1 >
                    575:     IF \ there may be some unfinished line, so let's finish it
                    576:        cr
                    577:     THEN
                    578: [ [THEN] ]
                    579:     bootmessage
                    580:     loadline off quit ;
                    581: 
                    582: : boot ( path **argv argc -- )
                    583:     main-task up!
                    584: [ has? os [IF] ]
                    585:     stdout TO outfile-id
                    586: \ !! [ [THEN] ]
                    587: \ !! [ has? file [IF] ]
                    588:     argc ! argv ! pathstring 2!
                    589: [ [THEN] ]
                    590:     sp@ sp0 !
                    591: [ has? glocals [IF] ]
                    592:     lp@ forthstart 7 cells + @ - 
                    593: [ [ELSE] ]
                    594:     [ has? os [IF] ]
                    595:     sp@ $1040 +
                    596:     [ [ELSE] ]
                    597:     sp@ $40 +
                    598:     [ [THEN] ]
                    599: [ [THEN] ]
                    600:     dup >tib ! tibstack ! #tib off >in off
                    601:     rp@ rp0 !
                    602: [ has? floating [IF] ]
                    603:     fp@ fp0 !
                    604: [ [THEN] ]
                    605:     ['] cold catch DoError
                    606: [ has? os [IF] ]
                    607:     bye
                    608: [ [THEN] ]
                    609: ;
                    610: 
                    611: has? os [IF]
                    612: : bye ( -- ) \ tools-ext
                    613: [ has? file [IF] ]
                    614:     script? 0= IF  cr  THEN
                    615: [ [ELSE] ]
                    616:     cr
                    617: [ [THEN] ]
                    618:     0 (bye) ;
                    619: [THEN]
                    620: 
                    621: \ **argv may be scanned by the C starter to get some important
                    622: \ information, as -display and -geometry for an X client FORTH
                    623: \ or space and stackspace overrides
                    624: 
                    625: \ 0 arg contains, however, the name of the program.
                    626: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>