File:  [gforth] / gforth / kernel / basics.fs
Revision 1.29: download - view: text, annotated - select for diffs
Sat Sep 23 15:47:09 2000 UTC (23 years, 7 months ago) by anton
Branches: MAIN
CVS tags: v0-5-0, HEAD
changed FSF address in copyright messages

    1: \ kernel.fs    GForth kernel                        17dec92py
    2: 
    3: \ Copyright (C) 1995,1998,2000 Free Software Foundation, Inc.
    4: 
    5: \ This file is part of Gforth.
    6: 
    7: \ Gforth is free software; you can redistribute it and/or
    8: \ modify it under the terms of the GNU General Public License
    9: \ as published by the Free Software Foundation; either version 2
   10: \ of the License, or (at your option) any later version.
   11: 
   12: \ This program is distributed in the hope that it will be useful,
   13: \ but WITHOUT ANY WARRANTY; without even the implied warranty of
   14: \ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   15: \ GNU General Public License for more details.
   16: 
   17: \ You should have received a copy of the GNU General Public License
   18: \ along with this program; if not, write to the Free Software
   19: \ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
   20: 
   21: \ Idea and implementation: Bernd Paysan (py)
   22: 
   23: \ Needs:
   24: 
   25: require ./vars.fs
   26: 
   27: hex
   28: 
   29: \ labels for some code addresses
   30: 
   31: \- NIL NIL AConstant NIL \ gforth
   32: 
   33: \ Aliases
   34: 
   35: [IFUNDEF] r@
   36: ' i Alias r@ ( -- w ; R: w -- w ) \ core r-fetch
   37: [THEN]
   38: 
   39: \ !! this is machine-dependent, but works on all but the strangest machines
   40: 
   41: : maxaligned ( addr1 -- addr2 ) \ gforth
   42:     \G @i{addr2} is the first address after @i{addr1} that satisfies
   43:     \G all alignment restrictions.
   44:     [ /maxalign 1 - ] Literal + [ 0 /maxalign - ] Literal and ;
   45: \ !! machine-dependent and won't work if "0 >body" <> "0 >body
   46:     \G maxaligned"
   47: ' maxaligned Alias cfaligned ( addr1 -- addr2 ) \ gforth
   48: \G @i{addr2} is the first address after @i{addr1} that is aligned for
   49: \G a code field (i.e., such that the corresponding body is maxaligned).
   50: 
   51: : chars ( n1 -- n2 ) \ core
   52: \G @i{n2} is the number of address units of @i{n1} chars.""
   53: ; immediate
   54: 
   55: 
   56: \ : A!    ( addr1 addr2 -- ) \ gforth
   57: \    dup relon ! ;
   58: \ : A,    ( addr -- ) \ gforth
   59: \    here cell allot A! ;
   60: ' ! alias A! ( addr1 addr2 -- ) \ gforth
   61: 
   62: \ UNUSED                                                17may93jaw
   63: 
   64: has? ec 
   65: [IF]
   66: unlock ram-dictionary area nip lock
   67: Constant dictionary-end
   68: [ELSE]
   69: : dictionary-end ( -- addr )
   70:     forthstart [ 3 cells ] Aliteral @ + ;
   71: [THEN]
   72: 
   73: : usable-dictionary-end ( -- addr )
   74:     dictionary-end [ word-pno-size pad-minsize + ] Literal - ;
   75: 
   76: : unused ( -- u ) \ core-ext
   77:     \G Return the amount of free space remaining (in address units) in
   78:     \G the region addressed by @code{here}.
   79:     usable-dictionary-end here - ;
   80: 
   81: \ here is used for pad calculation!
   82: 
   83: : dp    ( -- addr ) \ gforth
   84:     dpp @ ;
   85: : here  ( -- addr ) \ core
   86:     \G Return the address of the next free location in data space.
   87:     dp @ ;
   88: 
   89: \ on off                                               23feb93py
   90: 
   91: \ on is used by docol:
   92: : on  ( a-addr -- ) \ gforth
   93:     \G Set the (value of the) variable  at @i{a-addr} to @code{true}.
   94:     true  swap ! ;
   95: : off ( a-addr -- ) \ gforth
   96:     \G Set the (value of the) variable at @i{a-addr} to @code{false}.
   97:     false swap ! ;
   98: 
   99: \ dabs roll                                           17may93jaw
  100: 
  101: : dabs ( d -- ud ) \ double d-abs
  102:     dup 0< IF dnegate THEN ;
  103: 
  104: : roll  ( x0 x1 .. xn n -- x1 .. xn x0 ) \ core-ext
  105:   dup 1+ pick >r
  106:   cells sp@ cell+ dup cell+ rot move drop r> ;
  107: 
  108: \ place bounds                                         13feb93py
  109: 
  110: : place  ( addr len to -- ) \ gforth
  111:     over >r  rot over 1+  r> move c! ;
  112: : bounds ( addr u -- addr+u addr ) \ gforth
  113:     \G Given a memory block represented by starting address @i{addr}
  114:     \G and length @i{u} in aus, produce the end address @i{addr+u} and
  115:     \G the start address in the right order for @code{u+do} or
  116:     \G @code{?do}.
  117:     over + swap ;
  118: 
  119: \ (word)                                               22feb93py
  120: 
  121: : scan   ( addr1 n1 char -- addr2 n2 ) \ gforth
  122:     \ skip all characters not equal to char
  123:     >r
  124:     BEGIN
  125: 	dup
  126:     WHILE
  127: 	over c@ r@ <>
  128:     WHILE
  129: 	1 /string
  130:     REPEAT  THEN
  131:     rdrop ;
  132: : skip   ( addr1 n1 char -- addr2 n2 ) \ gforth
  133:     \ skip all characters equal to char
  134:     >r
  135:     BEGIN
  136: 	dup
  137:     WHILE
  138: 	over c@ r@  =
  139:     WHILE
  140: 	1 /string
  141:     REPEAT  THEN
  142:     rdrop ;
  143: 
  144: \ digit?                                               17dec92py
  145: 
  146: : digit?   ( char -- digit true/ false ) \ gforth
  147:   base @ $100 =
  148:   IF
  149:     true EXIT
  150:   THEN
  151:   toupper [char] 0 - dup 9 u> IF
  152:     [ char A char 9 1 + -  ] literal -
  153:     dup 9 u<= IF
  154:       drop false EXIT
  155:     THEN
  156:   THEN
  157:   dup base @ u>= IF
  158:     drop false EXIT
  159:   THEN
  160:   true ;
  161: 
  162: : accumulate ( +d0 addr digit - +d1 addr )
  163:   swap >r swap  base @  um* drop rot  base @  um* d+ r> ;
  164: 
  165: : >number ( ud1 c-addr1 u1 -- ud2 c-addr2 u2 ) \ core to-number
  166:     \G Attempt to convert the character string @var{c-addr1 u1} to an
  167:     \G unsigned number in the current number base. The double
  168:     \G @var{ud1} accumulates the result of the conversion to form
  169:     \G @var{ud2}. Conversion continues, left-to-right, until the whole
  170:     \G string is converted or a character that is not convertable in
  171:     \G the current number base is encountered (including + or -). For
  172:     \G each convertable character, @var{ud1} is first multiplied by
  173:     \G the value in @code{BASE} and then incremented by the value
  174:     \G represented by the character. @var{c-addr2} is the location of
  175:     \G the first unconverted character (past the end of the string if
  176:     \G the whole string was converted). @var{u2} is the number of
  177:     \G unconverted characters in the string. Overflow is not detected.
  178:     0
  179:     ?DO
  180: 	count digit?
  181:     WHILE
  182: 	accumulate
  183:     LOOP
  184:         0
  185:     ELSE
  186: 	1- I' I -
  187: 	UNLOOP
  188:     THEN ;
  189: 
  190: \ s>d um/mod						21mar93py
  191: 
  192: : s>d ( n -- d ) \ core		s-to-d
  193:     dup 0< ;
  194: 
  195: : ud/mod ( ud1 u2 -- urem udquot ) \ gforth
  196:     >r 0 r@ um/mod r> swap >r
  197:     um/mod r> ;
  198: 
  199: \ catch throw                                          23feb93py
  200: 
  201: has? glocals [IF]
  202: : lp@ ( -- addr ) \ gforth	lp-fetch
  203:  laddr# [ 0 , ] ;
  204: [THEN]
  205: 
  206: defer catch ( x1 .. xn xt -- y1 .. ym 0 / z1 .. zn error ) \ exception
  207: \G @code{Executes} @i{xt}.  If execution returns normally,
  208: \G @code{catch} pushes 0 on the stack.  If execution returns through
  209: \G @code{throw}, all the stacks are reset to the depth on entry to
  210: \G @code{catch}, and the TOS (the @i{xt} position) is replaced with
  211: \G the throw code.
  212: 
  213: :noname ( ... xt -- ... 0 )
  214:     execute 0 ;
  215: is catch
  216: 
  217: defer throw ( y1 .. ym nerror -- y1 .. ym / z1 .. zn error ) \ exception
  218: \G If @i{nerror} is 0, drop it and continue.  Otherwise, transfer
  219: \G control to the next dynamically enclosing exception handler, reset
  220: \G the stacks accordingly, and push @i{nerror}.
  221: 
  222: :noname ( y1 .. ym error -- y1 .. ym / z1 .. zn error )
  223:     ?dup if
  224: 	[ has? ec 0= [IF] here forthstart 9 cells + ! [THEN] ]
  225: 	cr .error cr
  226: 	[ has? file [IF] ] script? IF  1 (bye)  ELSE  quit  THEN
  227: 	[ [ELSE] ] quit [ [THEN] ]
  228:     then ;
  229: is throw
  230: 
  231: \ (abort")
  232: 
  233: : (abort")
  234:     "lit >r
  235:     IF
  236: 	r> "error ! -2 throw
  237:     THEN
  238:     rdrop ;
  239: 
  240: : abort ( ?? -- ?? ) \ core,exception-ext
  241:     \G @code{-1 throw}.
  242:     -1 throw ;
  243: 
  244: \ ?stack                                               23feb93py
  245: 
  246: : ?stack ( ?? -- ?? ) \ gforth
  247:     sp@ sp0 @ u> IF    -4 throw  THEN
  248: [ has? floating [IF] ]
  249:     fp@ fp0 @ u> IF  -&45 throw  THEN
  250: [ [THEN] ]
  251: ;
  252: \ ?stack should be code -- it touches an empty stack!
  253: 
  254: \ DEPTH                                                 9may93jaw
  255: 
  256: : depth ( -- +n ) \ core depth
  257:     \G @var{+n} is the number of values that were on the data stack before
  258:     \G @var{+n} itself was placed on the stack.
  259:     sp@ sp0 @ swap - cell / ;
  260: 
  261: : clearstack ( ... -- ) \ gforth clear-stack
  262:     \G remove and discard all/any items from the data stack.
  263:     sp0 @ sp! ;
  264: 
  265: \ Strings						 22feb93py
  266: 
  267: : "lit ( -- addr )
  268:   r> r> dup count + aligned >r swap >r ;
  269: 
  270: \ */MOD */                                              17may93jaw
  271: 
  272: \ !! I think */mod should have the same rounding behaviour as / - anton
  273: : */mod ( n1 n2 n3 -- n4 n5 ) \ core	star-slash-mod
  274:     \G n1*n2=n3*n5+n4, with the intermediate result (n1*n2) being double.
  275:     >r m* r> sm/rem ;
  276: 
  277: : */ ( n1 n2 n3 -- n4 ) \ core	star-slash
  278:     \G n4=(n1*n2)/n3, with the intermediate result being double.
  279:     */mod nip ;
  280: 
  281: \ HEX DECIMAL                                           2may93jaw
  282: 
  283: : decimal ( -- ) \ core
  284:     \G Set @code{base} to &10 (decimal).
  285:     a base ! ;
  286: : hex ( -- ) \ core-ext
  287:     \G Set @code{base} to &16 (hexadecimal).
  288:     10 base ! ;
  289: 

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