--- gforth/prims2x.fs 1994/07/21 10:52:49 1.5 +++ gforth/prims2x.fs 1999/05/10 12:50:49 1.42 @@ -1,3 +1,24 @@ +\ converts primitives to, e.g., C code + +\ Copyright (C) 1995,1996,1997,1998 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: @@ -21,37 +42,64 @@ warnings off -[IFUNDEF] vocabulary include search-order.fs [THEN] -include gray.fs +[IFUNDEF] vocabulary \ we are executed just with kernel image + \ load the rest that is needed + \ (require fails because this file is needed from a + \ different directory with the wordlibraries) +include ./search.fs +include ./extend.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 ; - -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 + 2dup s" -" compare 0= + IF + flush-comment @ 1 = + IF ." #else" + ELSE ." [ELSE]" THEN + ELSE + flush-comment @ 1 = + IF ." #ifdef HAS_" bounds ?DO I c@ toupper emit LOOP + ELSE ." has? " type ." [IF]" THEN + 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 @@ -88,8 +136,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 -8 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 @@ -109,12 +163,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 -- ) @@ -129,16 +182,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 ; @@ -152,7 +231,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 @@ -172,7 +251,21 @@ eof-char singleton charclass eof nowhite ++ <- name ( -- ) -(( ` \ nonl ** nl +Variable forth-flag +Variable c-flag + +(( (( ` f || ` F )) {{ start }} nonl ** + {{ end forth-flag @ IF type cr ELSE 2drop THEN }} +)) <- forth-comment ( -- ) + +(( (( ` c || ` C )) {{ start }} nonl ** + {{ end c-flag @ IF type cr ELSE 2drop THEN }} +)) <- c-comment ( -- ) + +(( (( forth-comment || c-comment )) ?? nonl ** )) <- comment-body + +(( {{ ?flush-comment start }} ` \ comment-body 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 ! }} @@ -182,20 +275,21 @@ 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! }} )) ?? (( nl || eof )) )) <- primitive ( -- ) -(( (( primitive {{ printprim }} )) ** eof )) +(( (( primitive {{ printprim }} )) ** eof )) parser primitives2something warnings @ [IF] .( parser generated ok ) cr @@ -204,11 +298,15 @@ warnings @ [IF] : primfilter ( file-id xt -- ) \ fileid is for the input file, xt ( -- ) is for the output word output ! - here input ! - here swap read-whole-file - dup endinput ! - here - allot + here dup rawinput ! cookedinput ! + here unused rot read-file throw + dup here + endrawinput ! + allot align + checksyncline +\ begin +\ getinput dup eof-char = ?EXIT emit true ?nextchar +\ again ; primitives2something ; \ types @@ -241,22 +339,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 ; @@ -265,9 +366,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 @@ -281,6 +380,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)" @@ -291,7 +394,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 @@ -303,19 +406,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 @@ -348,13 +449,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 -- ) @@ -392,7 +493,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 @@ -407,7 +508,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 @@ -429,6 +530,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 @@ -480,16 +584,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 ) @@ -507,41 +608,131 @@ 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 stores fill-tos - ." NEXT1_P2;" cr + ." NEXT_P2;" cr ." }" cr 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 + ." (Label)&&I_" c-name 2@ type ." ," cr + -1 primitive-number +! ; + +: output-alias ( -- ) flush-comment on + ?flush-comment + ( primitive-number @ . ." alias " ) ." Primitive " 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 ;