--- gforth/prims2x.fs 1994/09/08 17:20:12 1.7 +++ gforth/prims2x.fs 1998/11/22 23:18:10 1.34 @@ -1,3 +1,24 @@ +\ converts primitives to, e.g., C code + +\ Copyright (C) 1995 Free Software Foundation, Inc. + +\ This file is part of Gforth. + +\ Gforth is free software; you can redistribute it and/or +\ modify it under the terms of the GNU General Public License +\ as published by the Free Software Foundation; either version 2 +\ of the License, or (at your option) any later version. + +\ This program is distributed in the hope that it will be useful, +\ but WITHOUT ANY WARRANTY; without even the implied warranty of +\ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +\ GNU General Public License for more details. + +\ You should have received a copy of the GNU General Public License +\ along with this program; if not, write to the Free Software +\ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + \ This is not very nice (hard limits, no checking, assumes 1 chars = 1) \ Optimizations: @@ -15,42 +36,63 @@ \ 5) Words that call NEXT themselves have to be done very carefully. \ \ To do: +\ add the store optimization for doubles \ regarding problem 1 above: It would be better (for over) to implement \ the alternative warnings off -[IFUNDEF] vocabulary include search-order.fs [THEN] +require search.fs +require extend.fs + +\ require interpretation.fs +\ require debugs.fs +[IFUNDEF] vocabulary include search.fs [THEN] +[IFUNDEF] environment? include environ.fs [THEN] include gray.fs 100 constant max-effect \ number of things on one side of a stack effect -4096 constant batch-size \ no meaning, just make sure it's >0 255 constant maxchar maxchar 1+ constant eof-char -9 constant tab-char -10 constant nl-char +#tab constant tab-char +#lf constant nl-char : read-whole-file ( c-addr1 file-id -- c-addr2 ) \ reads the contents of the file file-id puts it into memory at c-addr1 \ c-addr2 is the first address after the file block - begin ( c-addr file-id ) - 2dup batch-size swap read-file - if - abort" I/O error" - endif - ( c-addr file-id actual-size ) rot over + -rot - batch-size <> - until - drop ; + >r dup $7fffffff r> read-file throw + ; -variable input \ pointer to next character to be parsed -variable endinput \ pointer to the end of the input (the char after the last) +variable rawinput \ pointer to next character to be scanned +variable endrawinput \ pointer to the end of the input (the char after the last) +variable cookedinput \ pointer to the next char to be parsed +variable line \ line number of char pointed to by input +1 line ! +2variable filename \ filename of original input file +0 0 filename 2! +2variable f-comment +0 0 f-comment 2! +variable skipsynclines \ are sync lines ("#line ...") invisible to the parser? +skipsynclines on + +Variable flush-comment flush-comment off + +: ?flush-comment + flush-comment @ 0= ?EXIT + f-comment 2@ nip + IF cr f-comment 2@ 2 /string 1- + dup IF + flush-comment @ 1 = + IF ." #ifdef HAS_" bounds ?DO I c@ toupper emit LOOP + ELSE ." has? " type ." [IF]" THEN cr + ELSE flush-comment @ 1 = IF ." #endif" ELSE ." [THEN]" THEN + cr THEN + 0 0 f-comment 2! THEN ; : start ( -- addr ) - input @ ; + cookedinput @ ; : end ( addr -- addr u ) - input @ over - ; + cookedinput @ over - ; variable output \ xt ( -- ) of output word @@ -87,8 +129,14 @@ variable effect-in-end ( pointer ) variable effect-out-end ( pointer ) 2variable effect-in-size 2variable effect-out-size +variable c-line +2variable c-filename +variable name-line +2variable name-filename +2variable last-name-filename -variable primitive-number -9 primitive-number ! +variable primitive-number -10 primitive-number ! +Variable function-number 0 function-number ! \ for several reasons stack items of a word are stored in a wordlist \ since neither forget nor marker are implemented yet, we make a new @@ -108,12 +156,11 @@ variable items eof-char max-member \ the whole character set + EOF : getinput ( -- n ) - input @ - dup endinput @ = + rawinput @ endrawinput @ = if - drop eof-char + eof-char else - c@ + cookedinput @ c@ endif ; :noname ( n -- ) @@ -128,16 +175,42 @@ print-token ! getinput member? ; ' testchar? test-vector ! +: checksyncline ( -- ) + \ when input points to a newline, check if the next line is a + \ sync line. If it is, perform the appropriate actions. + rawinput @ >r + s" #line " r@ over compare 0<> if + rdrop 1 line +! EXIT + endif + 0. r> 6 chars + 20 >number drop >r drop line ! r> ( c-addr ) + dup c@ bl = if + char+ dup c@ [char] " <> abort" sync line syntax" + char+ dup 100 [char] " scan drop swap 2dup - save-mem filename 2! + char+ + endif + dup c@ nl-char <> abort" sync line syntax" + skipsynclines @ if + dup char+ rawinput ! + rawinput @ c@ cookedinput @ c! + endif + drop ; + : ?nextchar ( f -- ) - ?not? if - ." syntax error" cr - getinput . cr - input @ endinput @ over - 100 min type cr - abort - endif - input @ endinput @ <> if - 1 input +! - endif ; + ?not? if + filename 2@ type ." :" line @ 0 .r ." : syntax error, wrong char:" + getinput . cr + rawinput @ endrawinput @ over - 100 min type cr + abort + endif + rawinput @ endrawinput @ <> if + rawinput @ c@ + 1 chars rawinput +! + 1 chars cookedinput +! + nl-char = if + checksyncline + endif + rawinput @ c@ cookedinput @ c! + endif ; : charclass ( set "name" -- ) ['] ?nextchar terminal ; @@ -151,7 +224,7 @@ print-token ! : ` ( -- terminal ) ( use: ` c ) ( creates anonymous terminal for the character c ) - [compile] ascii singleton ['] ?nextchar make-terminal ; + char singleton ['] ?nextchar make-terminal ; char a char z .. char A char Z .. union char _ singleton union charclass letter char 0 char 9 .. charclass digit @@ -171,7 +244,8 @@ eof-char singleton charclass eof nowhite ++ <- name ( -- ) -(( ` \ nonl ** nl +(( {{ ?flush-comment start }} ` \ nonl ** nl {{ end + 2dup 2 min s" \+" compare 0= IF f-comment 2! ELSE 2drop THEN }} )) <- comment ( -- ) (( {{ effect-in }} (( {{ start }} c-name {{ end 2 pick item-name 2! item-descr + }} blank ** )) ** {{ effect-in-end ! }} @@ -181,13 +255,14 @@ nowhite ++ (( {{ s" " doc 2! s" " forth-code 2! }} (( comment || nl )) ** - (( {{ start }} name {{ end 2dup forth-name 2! c-name 2! }} tab ++ + (( {{ line @ name-line ! filename 2@ name-filename 2! }} + {{ start }} name {{ end 2dup forth-name 2! c-name 2! }} tab ++ {{ start }} stack-effect {{ end stack-string 2! }} tab ++ {{ start }} name {{ end wordset 2! }} tab ** (( {{ start }} c-name {{ end c-name 2! }} )) ?? nl )) (( ` " ` " {{ start }} (( noquote ++ ` " )) ++ {{ end 1- doc 2! }} ` " nl )) ?? - {{ start }} (( nocolonnl nonl ** nl )) ** {{ end c-code 2! }} + {{ skipsynclines off line @ c-line ! filename 2@ c-filename 2! start }} (( nocolonnl nonl ** nl )) ** {{ end c-code 2! skipsynclines on }} (( ` : nl {{ start }} (( nonl ++ nl )) ++ {{ end forth-code 2! }} )) ?? @@ -203,11 +278,15 @@ warnings @ [IF] : primfilter ( file-id xt -- ) \ fileid is for the input file, xt ( -- ) is for the output word output ! - here input ! + here dup rawinput ! cookedinput ! here swap read-whole-file - dup endinput ! + dup endrawinput ! here - allot align + checksyncline +\ begin +\ getinput dup eof-char = ?EXIT emit true ?nextchar +\ again ; primitives2something ; \ types @@ -240,22 +319,25 @@ constant type-description : fetch-single ( item -- ) >r - r@ item-name 2@ type ." = (" + r@ item-name 2@ type + ." = (" r@ item-type @ type-c-name 2@ type ." ) " r@ item-d-offset @ effect-in-size 2@ data-stack-access ." ;" cr rdrop ; : fetch-double ( item -- ) >r - ." {Double_Store _d; _d.cells.low = " + ." FETCH_DCELL(" + r@ item-name 2@ type ." , " r@ item-d-offset @ dup effect-in-size 2@ data-stack-access - ." ; _d.cells.high = " 1+ effect-in-size 2@ data-stack-access ." ; " - r@ item-name 2@ type ." = _d.dcell;}" cr + ." , " 1+ effect-in-size 2@ data-stack-access + ." );" cr rdrop ; : fetch-float ( item -- ) >r - r@ item-name 2@ type ." = " + r@ item-name 2@ type + ." = " \ ." (" r@ item-type @ type-c-name 2@ type ." ) " r@ item-f-offset @ effect-in-size 2@ fp-stack-access ." ;" cr rdrop ; @@ -264,9 +346,7 @@ constant type-description \ f is true iff the offset of item is the same as on input >r r@ item-name 2@ items @ search-wordlist 0= - if - ." bug" cr abort - endif + abort" bug" execute @ dup r@ = if \ item first appeared in output @@ -280,6 +360,10 @@ constant type-description \ true if item has the same offset as the input TOS item-d-offset @ 1+ effect-in-size 2@ drop = ; +: is-out-tos? ( item -- f ) +\ true if item has the same offset as the input TOS + item-d-offset @ 1+ effect-out-size 2@ drop = ; + : really-store-single ( item -- ) >r r@ item-d-offset @ effect-out-size 2@ data-stack-access ." = (Cell)" @@ -290,7 +374,7 @@ constant type-description >r r@ d-same-as-in? if - r@ is-in-tos? + r@ is-in-tos? r@ is-out-tos? xor if ." IF_TOS(" r@ really-store-single ." );" cr endif @@ -302,19 +386,17 @@ constant type-description : store-double ( item -- ) \ !! store optimization is not performed, because it is not yet needed >r - ." {Double_Store _d; _d.dcell = " r@ item-name 2@ type ." ; " - r@ item-d-offset @ dup effect-out-size 2@ data-stack-access - ." = _d.cells.low; " 1+ effect-out-size 2@ data-stack-access - ." = _d.cells.high;}" cr + ." STORE_DCELL(" r@ item-name 2@ type ." , " + r@ item-d-offset @ dup effect-out-size 2@ data-stack-access + ." , " 1+ effect-out-size 2@ data-stack-access + ." );" cr rdrop ; : f-same-as-in? ( item -- f ) \ f is true iff the offset of item is the same as on input >r r@ item-name 2@ items @ search-wordlist 0= - if - ." bug" cr abort - endif + abort" bug" execute @ dup r@ = if \ item first appeared in output @@ -347,13 +429,13 @@ constant type-description endif rdrop ; -: single-type ( -- xt n1 n2 ) +: single-type ( -- xt1 xt2 n1 n2 ) ['] fetch-single ['] store-single 1 0 ; -: double-type ( -- xt n1 n2 ) +: double-type ( -- xt1 xt2 n1 n2 ) ['] fetch-double ['] store-double 2 0 ; -: float-type ( -- xt n1 n2 ) +: float-type ( -- xt1 xt2 n1 n2 ) ['] fetch-float ['] store-float 0 1 ; : s, ( addr u -- ) @@ -391,7 +473,7 @@ s" DFloat *" single-type starts-with df_ s" SFloat *" single-type starts-with sf_ s" Xt" single-type starts-with xt s" WID" single-type starts-with wid -s" F83Name *" single-type starts-with f83name +s" struct F83Name *" single-type starts-with f83name set-current @@ -406,7 +488,7 @@ set-current endif -1 s+loop \ we did not find a type, abort - ." unknown type prefix" cr ABORT ; + true abort" unknown type prefix" ; : declare ( addr "name" -- ) \ remember that there is a stack item at addr called name @@ -428,6 +510,9 @@ set-current i declaration item-descr +loop ; +: fetch ( addr -- ) + dup item-type @ type-fetch-handler execute ; + : declarations ( -- ) wordlist dup items ! set-current effect-in effect-in-end @ declaration-list @@ -479,16 +564,13 @@ set-current ." IF_TOS(TOS = sp[0]);" cr endif ; -: fetch ( addr -- ) - dup item-type @ type-fetch-handler execute ; - : fetches ( -- ) effect-in-end @ effect-in ?do i fetch item-descr +loop ; : stack-pointer-updates ( -- ) -\ we do not check if an update is a noop; gcc does this for us +\ we need not check if an update is a noop; gcc does this for us effect-in-size 2@ effect-out-size 2@ rot swap - ( d-in d-out f-diff ) @@ -506,18 +588,26 @@ set-current i store item-descr +loop ; -: output-c ( -- ) +: .stack-list ( start end -- ) + swap ?do + i item-name 2@ type space + item-descr +loop ; + +: output-c ( -- ) 1 flush-comment ! + ?flush-comment ." I_" c-name 2@ type ." : /* " forth-name 2@ type ." ( " stack-string 2@ type ." ) */" cr ." /* " doc 2@ type ." */" cr + ." NAME(" [char] " emit forth-name 2@ type [char] " emit ." )" cr \ debugging ." {" cr ." DEF_CA" cr declarations compute-offsets \ for everything else + ." NEXT_P0;" cr flush-tos fetches - stack-pointer-updates cr - ." NAME(" [char] " emit forth-name 2@ type [char] " emit ." )" cr \ debugging + stack-pointer-updates ." {" cr + ." #line " c-line @ . [char] " emit c-filename 2@ type [char] " emit cr c-code 2@ type ." }" cr ." NEXT_P1;" cr @@ -528,19 +618,103 @@ set-current cr ; -: output-label ( -- ) - ." &&I_" c-name 2@ type ." ," cr ; - -: output-alias ( -- ) - primitive-number @ . ." alias " forth-name 2@ type cr - -1 primitive-number +! ; +: output-funclabel ( -- ) + 1 function-number +! + ." &I_" c-name 2@ type ." ," cr ; + +: output-forthname ( -- ) + 1 function-number +! + '" emit forth-name 2@ type '" emit ." ," cr ; + +: output-c-func ( -- ) + 1 function-number +! + ." void I_" c-name 2@ type ." () /* " forth-name 2@ type + ." ( " stack-string 2@ type ." ) */" cr + ." /* " doc 2@ type ." */" cr + ." NAME(" [char] " emit forth-name 2@ type [char] " emit ." )" cr + \ debugging + ." {" cr + ." DEF_CA" cr + declarations + compute-offsets \ for everything else + ." NEXT_P0;" cr + flush-tos + fetches + stack-pointer-updates + ." {" cr + ." #line " c-line @ . [char] " emit c-filename 2@ type [char] " emit cr + c-code 2@ type + ." }" cr + ." NEXT_P1;" cr + stores + fill-tos + ." NEXT_P2;" cr + ." }" cr + cr ; + +: output-label ( -- ) 1 flush-comment ! + ?flush-comment + ." [" -2 primitive-number @ - 0 .r ." ] " + ." (Label)&&I_" c-name 2@ type ." ," cr + -1 primitive-number +! ; + +: output-alias ( -- ) flush-comment on + ?flush-comment + primitive-number @ . ." alias " forth-name 2@ type cr + -1 primitive-number +! ; + +: output-forth ( -- ) flush-comment on + ?flush-comment + forth-code @ 0= + IF \ output-alias + \ this is bad for ec: an alias is compiled if tho word does not exist! + \ JAW + ELSE ." : " forth-name 2@ type ." ( " + effect-in effect-in-end @ .stack-list ." -- " + effect-out effect-out-end @ .stack-list ." )" cr + forth-code 2@ type cr + -1 primitive-number +! + THEN ; + +: output-tag-file ( -- ) + name-filename 2@ last-name-filename 2@ compare if + name-filename 2@ last-name-filename 2! + #ff emit cr + name-filename 2@ type + ." ,0" cr + endif ; + +: output-tag ( -- ) + output-tag-file + forth-name 2@ 1+ type + 127 emit + space forth-name 2@ type space + 1 emit + name-line @ 0 .r + ." ,0" cr ; + +[IFDEF] documentation +: register-doc ( -- ) + get-current documentation set-current + forth-name 2@ nextname create + forth-name 2@ 2, + stack-string 2@ condition-stack-effect 2, + wordset 2@ 2, + c-name 2@ condition-pronounciation 2, + doc 2@ 2, + set-current ; +[THEN] : process-file ( addr u xt -- ) - >r r/o open-file - if - ." cannot open file" cr abort - endif - warnings @ if - ." ------------ CUT HERE -------------" cr endif - r> primfilter ; + >r + 2dup filename 2! + 0 function-number ! + r/o open-file abort" cannot open file" + warnings @ if + ." ------------ CUT HERE -------------" cr endif + r> primfilter ; + +: process ( xt -- ) + bl word count rot + process-file ;