--- gforth/prim 2002/02/10 14:02:25 1.92 +++ gforth/prim 2002/09/24 16:50:28 1.99 @@ -53,15 +53,18 @@ \ your code does not fall through, the results are not stored into the \ stack. Use different names on both sides of the '--', if you change a \ value (some stores to the stack are optimized away). -\ -\ +\ +\ For superinstructions the syntax is: +\ +\ forth-name [/ c-name] = forth-name forth-name ... +\ \ \ The stack variables have the following types: \ \ name matches type \ f.* Bool \ c.* Char -\ [nw].* Cell +\ [nw].* Cell \ u.* UCell \ d.* DCell \ ud.* UDCell @@ -101,6 +104,7 @@ \E inst-stream stack-prefix # \E \E set-current +\E store-optimization on \ \ @@ -179,7 +183,7 @@ SET_IP((Xt *)(((Cell)(IP-1))+ndisp)); define(condbranch, $1 ( `#'ndisp $2 ) $3 $4 SET_IP((Xt *)(((Cell)(IP-1))+ndisp)); -TAIL; +INST_TAIL; } SUPER_CONTINUE; $5 @@ -189,7 +193,7 @@ $5 $1-lp+!`#' ( `#'ndisp `#'nlocals $2 ) $3_lp_plus_store_number $4 lp += nlocals; SET_IP((Xt *)(((Cell)(IP-2))+ndisp)); -TAIL; +INST_TAIL; } SUPER_CONTINUE; @@ -216,7 +220,7 @@ if (f==0) { sp++; IF_spTOS(spTOS = sp[0]); SET_IP((Xt *)(((Cell)(IP-1))+ndisp)); - TAIL; + INST_TAIL; } SUPER_CONTINUE; @@ -311,7 +315,7 @@ nlimit=0; (?do) ( #ndisp nlimit nstart -- R:nlimit R:nstart ) gforth paren_question_do if (nstart == nlimit) { SET_IP((Xt *)(((Cell)(IP-1))+ndisp)); - TAIL; + INST_TAIL; } SUPER_CONTINUE; : @@ -327,7 +331,7 @@ SUPER_CONTINUE; (+do) ( #ndisp nlimit nstart -- R:nlimit R:nstart ) gforth paren_plus_do if (nstart >= nlimit) { SET_IP((Xt *)(((Cell)(IP-1))+ndisp)); - TAIL; + INST_TAIL; } SUPER_CONTINUE; : @@ -343,7 +347,7 @@ SUPER_CONTINUE; (u+do) ( #ndisp ulimit ustart -- R:ulimit R:ustart ) gforth paren_u_plus_do if (ustart >= ulimit) { SET_IP((Xt *)(((Cell)(IP-1))+ndisp)); - TAIL; + INST_TAIL; } SUPER_CONTINUE; : @@ -359,7 +363,7 @@ SUPER_CONTINUE; (-do) ( #ndisp nlimit nstart -- R:nlimit R:nstart ) gforth paren_minus_do if (nstart <= nlimit) { SET_IP((Xt *)(((Cell)(IP-1))+ndisp)); - TAIL; + INST_TAIL; } SUPER_CONTINUE; : @@ -375,7 +379,7 @@ SUPER_CONTINUE; (u-do) ( #ndisp ulimit ustart -- R:ulimit R:ustart ) gforth paren_u_minus_do if (ustart <= ulimit) { SET_IP((Xt *)(((Cell)(IP-1))+ndisp)); - TAIL; + INST_TAIL; } SUPER_CONTINUE; : @@ -2163,7 +2167,7 @@ Variable UP wcall ( u -- ) gforth IF_fpTOS(fp[0]=fpTOS); FP=fp; -sp=(Cell*)(SYSCALL(Cell(*)(Cell *, void *))u)(sp, &FP); +sp=(Cell*)(SYSCALL(Cell*(*)(Cell *, void *))u)(sp, &FP); fp=FP; IF_spTOS(spTOS=sp[0];) IF_fpTOS(fpTOS=fp[0]); @@ -2171,10 +2175,23 @@ IF_fpTOS(fpTOS=fp[0]); \+file open-dir ( c_addr u -- wdirid wior ) gforth open_dir +""Open the directory specified by @i{c-addr, u} +and return @i{dir-id} for futher access to it."" wdirid = (Cell)opendir(tilde_cstr(c_addr, u, 1)); wior = IOR(wdirid == 0); read-dir ( c_addr u1 wdirid -- u2 flag wior ) gforth read_dir +""Attempt to read the next entry from the directory specified +by @i{dir-id} to the buffer of length @i{u1} at address @i{c-addr}. +If the attempt fails because there is no more entries, +@i{ior}=0, @i{flag}=0, @i{u2}=0, and the buffer is unmodified. +If the attempt to read the next entry fails because of any other reason, +return @i{ior}<>0. +If the attempt succeeds, store file name to the buffer at @i{c-addr} +and return @i{ior}=0, @i{flag}=true and @i{u2} equal to the size of the file name. +If the length of the file name is greater than @i{u1}, +store first @i{u1} characters from file name into the buffer and +indicate "name too long" with @i{ior}, @i{flag}=true, and @i{u2}=@i{u1}."" struct dirent * dent; dent = readdir((DIR *)wdirid); wior = 0; @@ -2192,6 +2209,7 @@ if(dent == NULL) { } close-dir ( wdirid -- wior ) gforth close_dir +""Close the directory specified by @i{dir-id}."" wior = IOR(closedir((DIR *)wdirid)); filename-match ( c_addr1 u1 c_addr2 u2 -- flag ) gforth match_file @@ -2409,14 +2427,20 @@ a_addr = (Cell *)(up+u); compile-prim ( xt1 -- xt2 ) new compile_prim xt2 = (Xt)compile_prim((Label)xt1); -lit@ / lit_fetch = lit @ +\ lit@ / lit_fetch = lit @ + +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+ / lit_plus = lit + +\ lit+ / lit_plus = lit + + +lit+ ( n1 #n2 -- n ) new lit_plus +n=n1+n2; does-exec ( #a_cfa -- R:nest a_pfa ) new does_exec a_pfa = PFA(a_cfa); @@ -2431,6 +2455,217 @@ IF_spTOS(spTOS = sp[0]); #endif SET_IP(DOES_CODE1(a_cfa)); +abranch-lp+!# ( #a_target #nlocals -- ) gforth abranch_lp_plus_store_number +/* this will probably not be used */ +lp += nlocals; +SET_IP((Xt *)a_target); + +\+ + +abranch ( #a_target -- ) gforth +SET_IP((Xt *)a_target); +: + r> @ >r ; + +\ acondbranch(forthname,stackeffect,restline,code,forthcode) +\ this is non-syntactical: code must open a brace that is closed by the macro +define(acondbranch, +$1 ( `#'a_target $2 ) $3 +$4 SET_IP((Xt *)a_target); +INST_TAIL; +} +SUPER_CONTINUE; +$5 + +\+glocals + +$1-lp+!`#' ( `#'a_target `#'nlocals $2 ) $3_lp_plus_store_number +$4 lp += nlocals; +SET_IP((Xt *)a_target); +INST_TAIL; +} +SUPER_CONTINUE; + +\+ +) + +acondbranch(a?branch,f --,f83 aquestion_branch, +if (f==0) { +,: + 0= dup \ !f !f \ !! still uses relative addresses + r> dup @ \ !f !f IP branchoffset + rot and + \ !f IP|IP+branchoffset + swap 0= cell and + \ IP'' + >r ;) + +\ we don't need an lp_plus_store version of the ?dup-stuff, because it +\ is only used in if's (yet) + +\+xconds + +a?dup-?branch ( #a_target f -- f ) new aquestion_dupe_question_branch +""The run-time procedure compiled by @code{?DUP-IF}."" +if (f==0) { + sp++; + IF_spTOS(spTOS = sp[0]); + SET_IP((Xt *)a_target); + INST_TAIL; +} +SUPER_CONTINUE; + +a?dup-0=-?branch ( #a_target f -- ) new aquestion_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 +few cycles in that case, but is easy to convert to a CONDBRANCH +invocation */ +if (f!=0) { + sp--; + SET_IP((Xt *)a_target); + NEXT; +} +SUPER_CONTINUE; + +\+ +\f[THEN] +\fhas? skiploopprims 0= [IF] + +acondbranch(a(next),R:n1 -- R:n2,cmFORTH aparen_next, +n2=n1-1; +if (n1) { +,: + r> r> dup 1- >r + IF @ >r ELSE cell+ >r THEN ;) + +acondbranch(a(loop),R:nlimit R:n1 -- R:nlimit R:n2,gforth aparen_loop, +n2=n1+1; +if (n2 != nlimit) { +,: + r> r> 1+ r> 2dup = + IF >r 1- >r cell+ >r + ELSE >r >r @ >r THEN ;) + +acondbranch(a(+loop),n R:nlimit R:n1 -- R:nlimit R:n2,gforth aparen_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 */ +Cell olddiff = n1-nlimit; +n2=n1+n; +if ((olddiff^(olddiff+n))>=0 /* the limit is not crossed */ + || (olddiff^n)>=0 /* it is a wrap-around effect */) { +,: + r> swap + r> r> 2dup - >r + 2 pick r@ + r@ xor 0< 0= + 3 pick r> xor 0< 0= or + IF >r + >r @ >r + ELSE >r >r drop cell+ >r THEN ;) + +\+xconds + +acondbranch(a(-loop),u R:nlimit R:n1 -- R:nlimit R:n2,gforth aparen_minus_loop, +UCell olddiff = n1-nlimit; +n2=n1-u; +if (olddiff>u) { +,) + +acondbranch(a(s+loop),n R:nlimit R:n1 -- R:nlimit R:n2,gforth aparen_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)."" +/* !! check this thoroughly */ +Cell diff = n1-nlimit; +Cell newdiff = diff+n; +if (n<0) { + diff = -diff; + newdiff = -newdiff; +} +n2=n1+n; +if (diff>=0 || newdiff<0) { +,) + +a(?do) ( #a_target nlimit nstart -- R:nlimit R:nstart ) gforth aparen_question_do +if (nstart == nlimit) { + SET_IP((Xt *)a_target); + INST_TAIL; +} +SUPER_CONTINUE; +: + 2dup = + IF r> swap rot >r >r + @ >r + ELSE r> swap rot >r >r + cell+ >r + THEN ; \ --> CORE-EXT + +\+xconds + +a(+do) ( #a_target nlimit nstart -- R:nlimit R:nstart ) gforth aparen_plus_do +if (nstart >= nlimit) { + SET_IP((Xt *)a_target); + INST_TAIL; +} +SUPER_CONTINUE; +: + swap 2dup + r> swap >r swap >r + >= + IF + @ + ELSE + cell+ + THEN >r ; + +a(u+do) ( #a_target ulimit ustart -- R:ulimit R:ustart ) gforth aparen_u_plus_do +if (ustart >= ulimit) { + SET_IP((Xt *)a_target); + INST_TAIL; +} +SUPER_CONTINUE; +: + swap 2dup + r> swap >r swap >r + u>= + IF + @ + ELSE + cell+ + THEN >r ; + +a(-do) ( #a_target nlimit nstart -- R:nlimit R:nstart ) gforth aparen_minus_do +if (nstart <= nlimit) { + SET_IP((Xt *)a_target); + INST_TAIL; +} +SUPER_CONTINUE; +: + swap 2dup + r> swap >r swap >r + <= + IF + @ + ELSE + cell+ + THEN >r ; + +a(u-do) ( #a_target ulimit ustart -- R:ulimit R:ustart ) gforth aparen_u_minus_do +if (ustart <= ulimit) { + SET_IP((Xt *)a_target); + INST_TAIL; +} +SUPER_CONTINUE; +: + swap 2dup + r> swap >r swap >r + u<= + IF + @ + ELSE + cell+ + THEN >r ; + +\+ + include(peeprules.vmg) \+