--- gforth/prim 2000/11/14 10:36:02 1.66 +++ gforth/prim 2002/01/20 19:04:10 1.91 @@ -72,8 +72,36 @@ \ df_.* DFloat * \ sf_.* SFloat * \ xt.* XT -\ wid.* WID \ f83name.* F83Name * + +\E stack data-stack sp Cell +\E stack fp-stack fp Float +\E stack return-stack rp Cell +\E +\E get-current prefixes set-current +\E +\E s" Bool" single data-stack type-prefix f +\E s" Char" single data-stack type-prefix c +\E s" Cell" single data-stack type-prefix n +\E s" Cell" single data-stack type-prefix w +\E s" UCell" single data-stack type-prefix u +\E s" DCell" double data-stack type-prefix d +\E s" UDCell" double data-stack type-prefix ud +\E s" Float" single fp-stack type-prefix r +\E s" Cell *" single data-stack type-prefix a_ +\E s" Char *" single data-stack type-prefix c_ +\E s" Float *" single data-stack type-prefix f_ +\E s" DFloat *" single data-stack type-prefix df_ +\E s" SFloat *" single data-stack type-prefix sf_ +\E s" Xt" single data-stack type-prefix xt +\E s" struct F83Name *" single data-stack type-prefix f83name +\E s" struct Longname *" single data-stack type-prefix longname +\E +\E return-stack stack-prefix R: +\E inst-stream stack-prefix # +\E +\E set-current + \ \ \ @@ -102,15 +130,15 @@ \ these m4 macros would collide with identifiers undefine(`index') undefine(`shift') +undefine(`symbols') + +\g control noop ( -- ) gforth -; : ; -lit ( -- w ) gforth -w = (Cell)NEXT_INST; -INC_IP(1); +lit ( #w -- w ) gforth : r> dup @ swap cell+ >r ; @@ -118,6 +146,7 @@ execute ( xt -- ) core ""Perform the semantics represented by the execution token, @i{xt}."" ip=IP; IF_spTOS(spTOS = sp[0]); +SUPER_END; EXEC(xt); perform ( a_addr -- ) gforth @@ -125,6 +154,7 @@ perform ( a_addr -- ) gforth /* and pfe */ ip=IP; IF_spTOS(spTOS = sp[0]); +SUPER_END; EXEC(*(Xt *)a_addr); : @ execute ; @@ -132,44 +162,41 @@ EXEC(*(Xt *)a_addr); \fhas? skipbranchprims 0= [IF] \+glocals -branch-lp+!# ( -- ) gforth branch_lp_plus_store_number +branch-lp+!# ( #ndisp #nlocals -- ) gforth branch_lp_plus_store_number /* this will probably not be used */ -lp += (Cell)(IP[1]); -goto branch; +lp += nlocals; +SET_IP((Xt *)(((Cell)(IP-2))+ndisp)); \+ -branch ( -- ) gforth -branch: -SET_IP((Xt *)(((Cell)IP)+(Cell)NEXT_INST)); +branch ( #ndisp -- ) gforth +SET_IP((Xt *)(((Cell)(IP-1))+ndisp)); : r> dup @ + >r ; -\ condbranch(forthname,restline,code,forthcode) +\ condbranch(forthname,stackeffect,restline,code,forthcode) \ this is non-syntactical: code must open a brace that is closed by the macro define(condbranch, -$1 $2 -$3 SET_IP((Xt *)(((Cell)IP)+(Cell)NEXT_INST)); +$1 ( `#'ndisp $2 ) $3 +$4 SET_IP((Xt *)(((Cell)(IP-1))+ndisp)); TAIL; } -else - INC_IP(1); -$4 +SUPER_CONTINUE; +$5 \+glocals -$1-lp+!# $2_lp_plus_store_number -$3 lp += (Cell)(IP[1]); -SET_IP((Xt *)(((Cell)IP)+(Cell)NEXT_INST)); +$1-lp+!`#' ( `#'ndisp `#'nlocals $2 ) $3_lp_plus_store_number +$4 lp += nlocals; +SET_IP((Xt *)(((Cell)(IP-2))+ndisp)); TAIL; } -else - INC_IP(2); +SUPER_CONTINUE; \+ ) -condbranch(?branch,( f -- ) f83 question_branch, +condbranch(?branch,f --,f83 question_branch, if (f==0) { ,: 0= dup \ !f !f @@ -183,18 +210,17 @@ if (f==0) { \+xconds -?dup-?branch ( f -- f ) new question_dupe_question_branch +?dup-?branch ( #ndisp f -- f ) new question_dupe_question_branch ""The run-time procedure compiled by @code{?DUP-IF}."" if (f==0) { sp++; IF_spTOS(spTOS = sp[0]); - SET_IP((Xt *)(((Cell)IP)+(Cell)NEXT_INST)); - NEXT; + SET_IP((Xt *)(((Cell)(IP-1))+ndisp)); + TAIL; } -else - INC_IP(1); +SUPER_CONTINUE; -?dup-0=-?branch ( f -- ) new question_dupe_zero_equals_question_branch +?dup-0=-?branch ( #ndisp f -- ) new question_dupe_zero_equals_question_branch ""The run-time procedure compiled by @code{?DUP-0=-IF}."" /* the approach taken here of declaring the word as having the stack effect ( f -- ) and correcting for it in the branch-taken case costs a @@ -202,24 +228,23 @@ few cycles in that case, but is easy to invocation */ if (f!=0) { sp--; - SET_IP((Xt *)(((Cell)IP)+(Cell)NEXT_INST)); + SET_IP((Xt *)(((Cell)(IP-1))+ndisp)); NEXT; } -else - INC_IP(1); +SUPER_CONTINUE; \+ \f[THEN] \fhas? skiploopprims 0= [IF] -condbranch((next),( R:n1 -- R:n2 ) cmFORTH paren_next, +condbranch((next),R:n1 -- R:n2,cmFORTH paren_next, n2=n1-1; if (n1) { ,: r> r> dup 1- >r IF dup @ + >r ELSE cell+ >r THEN ;) -condbranch((loop),( R:nlimit R:n1 -- R:nlimit R:n2 ) gforth paren_loop, +condbranch((loop),R:nlimit R:n1 -- R:nlimit R:n2,gforth paren_loop, n2=n1+1; if (n2 != nlimit) { ,: @@ -227,7 +252,7 @@ if (n2 != nlimit) { IF >r 1- >r cell+ >r ELSE >r >r dup @ + >r THEN ;) -condbranch((+loop),( n R:nlimit R:n1 -- R:nlimit R:n2 ) gforth paren_plus_loop, +condbranch((+loop),n R:nlimit R:n1 -- R:nlimit R:n2,gforth paren_plus_loop, /* !! check this thoroughly */ /* sign bit manipulation and test: (x^y)<0 is equivalent to (x<0) != (y<0) */ /* dependent upon two's complement arithmetic */ @@ -245,13 +270,13 @@ if ((olddiff^(olddiff+n))>=0 /* the li \+xconds -condbranch((-loop),( u R:nlimit R:n1 -- R:nlimit R:n2 ) gforth paren_minus_loop, +condbranch((-loop),u R:nlimit R:n1 -- R:nlimit R:n2,gforth paren_minus_loop, UCell olddiff = n1-nlimit; n2=n1-u; if (olddiff>u) { ,) -condbranch((s+loop),( n R:nlimit R:n1 -- R:nlimit R:n2 ) gforth paren_symmetric_plus_loop, +condbranch((s+loop),n R:nlimit R:n1 -- R:nlimit R:n2,gforth paren_symmetric_plus_loop, ""The run-time procedure compiled by S+LOOP. It loops until the index crosses the boundary between limit and limit-sign(n). I.e. a symmetric version of (+LOOP)."" @@ -283,14 +308,12 @@ nlimit=0; : r> swap rot >r >r >r ; -(?do) ( nlimit nstart -- R:nlimit R:nstart ) gforth paren_question_do +(?do) ( #ndisp nlimit nstart -- R:nlimit R:nstart ) gforth paren_question_do if (nstart == nlimit) { - IF_spTOS(spTOS = sp[0]); - goto branch; - } -else { - INC_IP(1); + SET_IP((Xt *)(((Cell)(IP-1))+ndisp)); + TAIL; } +SUPER_CONTINUE; : 2dup = IF r> swap rot >r >r @@ -301,14 +324,12 @@ else { \+xconds -(+do) ( nlimit nstart -- R:nlimit R:nstart ) gforth paren_plus_do +(+do) ( #ndisp nlimit nstart -- R:nlimit R:nstart ) gforth paren_plus_do if (nstart >= nlimit) { - IF_spTOS(spTOS = sp[0]); - goto branch; - } -else { - INC_IP(1); + SET_IP((Xt *)(((Cell)(IP-1))+ndisp)); + TAIL; } +SUPER_CONTINUE; : swap 2dup r> swap >r swap >r @@ -319,14 +340,12 @@ else { cell+ THEN >r ; -(u+do) ( ulimit ustart -- R:ulimit R:ustart ) gforth paren_u_plus_do +(u+do) ( #ndisp ulimit ustart -- R:ulimit R:ustart ) gforth paren_u_plus_do if (ustart >= ulimit) { - IF_spTOS(spTOS = sp[0]); - goto branch; - } -else { - INC_IP(1); + SET_IP((Xt *)(((Cell)(IP-1))+ndisp)); + TAIL; } +SUPER_CONTINUE; : swap 2dup r> swap >r swap >r @@ -337,14 +356,12 @@ else { cell+ THEN >r ; -(-do) ( nlimit nstart -- R:nlimit R:nstart ) gforth paren_minus_do +(-do) ( #ndisp nlimit nstart -- R:nlimit R:nstart ) gforth paren_minus_do if (nstart <= nlimit) { - IF_spTOS(spTOS = sp[0]); - goto branch; - } -else { - INC_IP(1); + SET_IP((Xt *)(((Cell)(IP-1))+ndisp)); + TAIL; } +SUPER_CONTINUE; : swap 2dup r> swap >r swap >r @@ -355,14 +372,12 @@ else { cell+ THEN >r ; -(u-do) ( ulimit ustart -- R:ulimit R:ustart ) gforth paren_u_minus_do +(u-do) ( #ndisp ulimit ustart -- R:ulimit R:ustart ) gforth paren_u_minus_do if (ustart <= ulimit) { - IF_spTOS(spTOS = sp[0]); - goto branch; - } -else { - INC_IP(1); + SET_IP((Xt *)(((Cell)(IP-1))+ndisp)); + TAIL; } +SUPER_CONTINUE; : swap 2dup r> swap >r swap >r @@ -405,6 +420,8 @@ k ( R:n R:d1 R:d2 -- n R:n R:d1 R:d2 ) \ digit is high-level: 0/0% +\g strings + move ( c_from c_to ucount -- ) core ""Copy the contents of @i{ucount} aus at @i{c-from} to @i{c-to}. @code{move} works correctly even if the two areas overlap."" @@ -514,6 +531,8 @@ u2 = u1-n; : tuck - >r + r> dup 0< IF - 0 THEN ; +\g arith + + ( n1 n2 -- n ) core plus n = n1+n2; @@ -911,6 +930,8 @@ f = FLAG(u1-u2 < u3-u2); : over - >r - r> u< ; +\g internal + sp@ ( -- a_addr ) gforth sp_fetch a_addr = sp+1; @@ -938,6 +959,8 @@ fp = f_addr; ""The primitive compiled by @code{EXIT}."" SET_IP((Xt *)w); +\g stack + >r ( w -- R:w ) core to_r : (>r) ; @@ -1188,7 +1211,7 @@ f83name2=f83name1; r> @ REPEAT THEN nip nip ; : (find-samelen) ( u f83name1 -- u f83name2/0 ) - BEGIN 2dup cell+ c@ $1F and <> WHILE @ dup 0= UNTIL THEN ; + BEGIN 2dup cell+ c@ $1F and <> WHILE @ dup 0= UNTIL THEN ; \+hash @@ -1333,7 +1356,6 @@ a_addr = (Cell *)DOES_CODE(xt); code-address! ( c_addr xt -- ) gforth code_address_store ""Create a code field with code address @i{c-addr} at @i{xt}."" MAKE_CF(xt, c_addr); -CACHE_FLUSH(xt,(size_t)PFA(0)); : ! ; @@ -1341,7 +1363,6 @@ does-code! ( a_addr xt -- ) gforth does ""Create a code field at @i{xt} for a child of a @code{DOES>}-word; @i{a-addr} is the start of the Forth code after @code{DOES>}."" MAKE_DOES_CF(xt, a_addr); -CACHE_FLUSH(xt,(size_t)PFA(0)); : dodoes: over ! cell+ ! ; @@ -1349,7 +1370,6 @@ does-handler! ( a_addr -- ) gforth does_ ""Create a @code{DOES>}-handler at address @i{a-addr}. Normally, @i{a-addr} points just behind a @code{DOES>}."" MAKE_DOES_HANDLER(a_addr); -CACHE_FLUSH((caddr_t)a_addr,DOES_HANDLER_SIZE); : drop ; @@ -1377,6 +1397,8 @@ n=1; \f[THEN] +\g hostos + key-file ( wfileid -- n ) gforth paren_key_file #ifdef HAS_FILE fflush(stdout); @@ -1425,6 +1447,7 @@ cache."" FLUSH_ICACHE(c_addr,u); (bye) ( n -- ) gforth paren_bye +SUPER_END; return (Label *)n; (system) ( c_addr u -- wretval wior ) gforth peren_system @@ -1449,7 +1472,7 @@ c_addr2 = getenv(cstr(c_addr1,u1,1)); u2 = (c_addr2 == NULL ? 0 : strlen(c_addr2)); open-pipe ( c_addr u wfam -- wfileid wior ) gforth open_pipe -wfileid=(Cell)popen(cstr(c_addr,u,1),fileattr[wfam]); /* ~ expansion of 1st arg? */ +wfileid=(Cell)popen(cstr(c_addr,u,1),pfileattr[wfam]); /* ~ expansion of 1st arg? */ wior = IOR(wfileid==0); /* !! the man page says that errno is not set reliably */ close-pipe ( wfileid -- wretval wior ) gforth close_pipe @@ -1591,7 +1614,7 @@ if (wior) clearerr((FILE *)wfileid); read-line ( c_addr u1 wfileid -- u2 flag wior ) file read_line -""this is only for backward compatibility"" +/* this may one day be replaced with : read-line (read-line) nip ; */ Cell c; flag=-1; for(u2=0; u2d_name); - if(u2 > u1) + if(u2 > u1) { u2 = u1; + wior = -512-ENAMETOOLONG; + } memmove(c_addr, dent->d_name, u2); } @@ -2181,7 +2204,8 @@ flag = FLAG(!fnmatch(pattern, string, 0) newline ( -- c_addr u ) gforth ""String containing the newline sequence of the host OS"" char newline[] = { -#ifdef unix +#if defined(unix) || defined(__MACH__) +/* Darwin/MacOS X sets __MACH__, but not unix. */ '\n' #else '\r','\n' @@ -2282,3 +2306,133 @@ for(u2=0; u2next)) + if ((UCell)LONGNAME_COUNT(longname1)==u && + memcasecmp(c_addr, longname1->name, u)== 0 /* or inline? */) + break; +longname2=longname1; +: + BEGIN dup WHILE (findl-samelen) dup WHILE + >r 2dup r@ cell+ cell+ capscomp 0= + IF 2drop r> EXIT THEN + r> @ + REPEAT THEN nip nip ; +: (findl-samelen) ( u longname1 -- u longname2/0 ) + BEGIN 2dup cell+ @ lcount-mask and <> WHILE @ dup 0= UNTIL THEN ; + +\+hash + +(hashlfind) ( c_addr u a_addr -- longname2 ) new paren_hashlfind +struct Longname *longname1; +longname2=NULL; +while(a_addr != NULL) +{ + longname1=(struct Longname *)(a_addr[1]); + a_addr=(Cell *)(a_addr[0]); + if ((UCell)LONGNAME_COUNT(longname1)==u && + memcasecmp(c_addr, longname1->name, u)== 0 /* or inline? */) + { + longname2=longname1; + break; + } +} +: + BEGIN dup WHILE + 2@ >r >r dup r@ cell+ @ lcount-mask and = + IF 2dup r@ cell+ cell+ capscomp 0= + IF 2drop r> rdrop EXIT THEN THEN + rdrop r> + REPEAT nip nip ; + +(tablelfind) ( c_addr u a_addr -- longname2 ) new paren_tablelfind +""A case-sensitive variant of @code{(hashfind)}"" +struct Longname *longname1; +longname2=NULL; +while(a_addr != NULL) +{ + longname1=(struct Longname *)(a_addr[1]); + a_addr=(Cell *)(a_addr[0]); + if ((UCell)LONGNAME_COUNT(longname1)==u && + memcmp(c_addr, longname1->name, u)== 0 /* or inline? */) + { + longname2=longname1; + break; + } +} +: + BEGIN dup WHILE + 2@ >r >r dup r@ cell+ @ lcount-mask and = + IF 2dup r@ cell+ cell+ -text 0= + IF 2drop r> rdrop EXIT THEN THEN + rdrop r> + REPEAT nip nip ; + +\+ + +\+peephole + +\g peephole + +primtable ( -- wprimtable ) new +""wprimtable is a table containing the xts of the primitives indexed +by sequence-number in prim (for use in prepare-peephole-table)."" +wprimtable = (Cell)primtable(symbols+DOESJUMP+1,MAX_SYMBOLS-DOESJUMP-1); + +prepare-peephole-table ( wprimtable -- wpeeptable ) new prepare_peephole_opt +""wpeeptable is a data structure used by @code{peephole-opt}; it is +constructed by combining a primitives table with a simple peephole +optimization table."" +wpeeptable = prepare_peephole_table((Xt *)wprimtable); + +peephole-opt ( xt1 xt2 wpeeptable -- xt ) new peephole_opt +""xt is the combination of xt1 and xt2 (according to wpeeptable); if +they cannot be combined, xt is 0."" +xt = peephole_opt(xt1, xt2, wpeeptable); + +call ( #a_callee -- R:a_retaddr ) new +""Call callee (a variant of docol with inline argument)."" +#ifdef DEBUG + { + CFA_TO_NAME((((Cell *)a_callee)-2)); + fprintf(stderr,"%08lx: call %08lx %.*s\n",(Cell)ip,(Cell)a_callee, + len,name); + } +#endif +a_retaddr = (Cell *)IP; +SET_IP((Xt *)a_callee); + +useraddr ( #u -- a_addr ) new +a_addr = (Cell *)(up+u); + +compile-prim ( xt1 -- xt2 ) new compile_prim +xt2 = (Xt)compile_prim((Label)xt1); + +lit@ ( #a_addr -- w ) new lit_fetch +w = *a_addr; + +lit-perform ( #a_addr -- ) new lit_perform +ip=IP; +SUPER_END; +EXEC(*(Xt *)a_addr); + +lit+ ( #n1 n2 -- n3 ) new lit_plus +n3 = n1 + n2; + +does-exec ( #a_cfa -- R:nest a_pfa ) new does_exec +a_pfa = PFA(a_cfa); +nest = (Cell)ip; +IF_spTOS(spTOS = sp[0]); +#ifdef DEBUG + { + CFA_TO_NAME(a_cfa); + fprintf(stderr,"%08lx: does %08lx %.*s\n", + (Cell)ip,(Cell)a_cfa,len,name); + } +#endif +SET_IP(DOES_CODE1(a_cfa)); + +include(peeprules.vmg) + +\+