home *** CD-ROM | disk | FTP | other *** search
Null Bytes Alternating | 1995-05-19 | 27.6 KB | 411 lines |
- \ multioop.utf ...
- \ a multiple-inheritance object-oriented extension to ANS-Forth
- \ ANS Forth compliant source code is Copyright (c)1992-1994 by
- \ Jack J. Woehr, P.O. Box 51, Golden, Colorado 80402-0051
- \ jax@well.sf.ca.us 72203.1320@compuserve.com
- \ SYSOP RCFB (303) 278-0364 2400/9600/14400
- \ All Rights Reserved
- \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- \ This is free software and can be modified and redistributed under
- \ certain conditions described in the file COPYING.TXT. The
- \ Disclaimer of Warranty and License for this free software are also
- \ contained in the file COPYING.TXT.
- \ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- \ $Revision: 1.1 $
- \
- \ Dependencies: NIP TUCK U.R TRUE FALSE from Core Extensions.
- \ D= from Double.
- \ DEFER from DEFER.UTF
- \ A Standard System still exists after this code is loaded.
-
- : PROVIDES ( c-addr u "ccc< >" --)
- BL WORD FIND NIP 0=
- IF INCLUDED ELSE 2DROP THEN ;
-
- S" UTILS\UTILS.UTF" PROVIDES .(
- S" UTILS\DEFER.UTF" PROVIDES DEFER
-
- MARKER multioop.utf
-
- .( Loading Multioop multiple-inheritance object extensions.) CR
-
- \ A Standard System still exists after this code is loaded.
-
- BASE @ HEX
-
- \ ** Some Utility Words
- : OFF ( a-addr --) 0 SWAP ! ;
- : PERFORM ( a-addr --) @ EXECUTE ;
- : ?ENOUGH ( n --) DEPTH 1- > ABORT" Not enough arguments." ;
- : CELL ( -- n) 1 CELLS ;
- : CELL- ( n1 -- n2) CELL - ;
- : U/ ( u1 u2 -- u3) SWAP S>D ROT UM/MOD NIP ;
- : >= ( n1 n2 -- flag) 1- > ;
-
-
- \ ** The Method Stack .. nested method search and retrieval.
- \ Method stack will grow UPWARDS in memory. May make it easier
- \ to examine and comprehend DUMPs of method stack memory.
-
- 40 CELLS CONSTANT #MSTACK-SIZE \ methodstack size
-
- \ MODE? RAM ( MODE? returns RAM or ROM compilation mode)
- \ ( Use for embedded systems)
- CREATE MSTACK #MSTACK-SIZE ALLOT \ method stack
- \ ?MODE ( Restores the RAM or ROM mode)
-
- MSTACK #MSTACK-SIZE CELLS +
- CONSTANT MSTACK-TOP \ top of methodstack
-
- VARIABLE *MSTACK \ method stack pointer
-
- \ Initialize method stack pointer to one entry before base of
- \ preincrementing MSTACK.
- : MSTACK.INIT ( --)
- MSTACK CELL- *MSTACK !
- ; MSTACK.INIT
-
- \ Test for incipient method stack overflow
- \ (i.e., address about to be preincremented too high in mem).
- : MSTACK-OVER? ( @mstack-ptr -- flag)
- MSTACK-TOP >=
- ;
-
- \ Test for incipient method stack underflow
- \ (i.e., address about to be postdecremented too low in memory).
- : MSTACK-UNDER? ( @mstack-ptr -- flag)
- MSTACK <
- ;
-
- \ Preincrement method stack pointer by size of one entry and push x.
- \ Exercise method stack security.
- : ++MSTACK! ( x --)
- *MSTACK @ DUP
- MSTACK-OVER? ABORT" Method stack overflow."
- CELL+ TUCK ! *MSTACK !
- ;
-
- \ Fetch x and postdecrement method stack pointer by size of one entry.
- \ Exercise method stack security.
- : @MSTACK-- ( -- x)
- *MSTACK @ DUP
- MSTACK-UNDER? ABORT" Method stack underflow."
- DUP CELL- *MSTACK !
- @
- ;
-
- \ Operators analogous to Forth stack operators, some not needed.
-
- \ : MSTACK-DUP ( --)
- \ *MSTACK @ @ ++MSTACK!
- \ ;
-
- : MSTACK-DROP ( --)
- @MSTACK-- DROP
- ;
-
- \ : MSTACK-SWAP ( --)
- \ @MSTACK-- @MSTACK--
- \ SWAP
- \ ++MSTACK! ++MSTACK!
- \ ;
-
- \ : MSTACK-OVER ( --)
- \ *MSTACK @ CELL- @ ++MSTACK!
- \ ;
-
- : MSTACK-DEPTH ( -- n)
- *MSTACK @ MSTACK CELL- - CELL U/
- ;
-
- \ Print out the MSTACK like .S in Forth
- : .MSTACK ( --)
- MSTACK-DEPTH 0=
- IF
- ." Method stack empty. "
- EXIT
- THEN
- MSTACK MSTACK-DEPTH #MSTACK-SIZE MIN 0
- ?DO
- DUP I CELLS + @ 0A U.R
- LOOP
- DROP
- ;
-
-
- \ ** Methods
-
- \ A method record is stored in the method list as two cells:
- \ /SELECTOR/VECTOR/
- 2 CELLS CONSTANT #CELLS/SELECT
- CELL DUP CONSTANT /VECTOR
- CONSTANT /INHERITANCE
-
- \ Having located address of method , discard selector,
- \ execute method. Methods expect base object address of object
- \ to be present on data stack.
- : EXE-METHOD ( obj-addr selector selector-addr --)
- NIP /VECTOR + PERFORM
- ;
-
-
- \ When a method is sought in a class method list, if SELECTOR
- \ is null, VECTOR should point to continuation elsewhere of method
- \ list, or to that of next inheritance class.
- \ If VECTOR null, end of list has been reached and method not found.
-
- \ NEXT-CLASS is passed address of null SELECTOR which is found
- \ associated with a non-null VECTOR, so pushes next cell address
- \ past the location of that VECTOR as the next place to look in
- \ current class in case nesting into inheritance doesn't find a
- \ match. In such case, search will continue after popping method
- \ stack.
- : NEXT-CLASS ( sel-addr1 -- sel-addr2) ( M: -- sel-addr1+cells)
- DUP
- #CELLS/SELECT + ++MSTACK!
- /INHERITANCE + @
- ;
-
- \ If anything left on method stack, return to previous class
- : PREV-CLASS ( -- sel-addr2 | ABORT)
- MSTACK-DEPTH 1 <
- ABORT" Method not found."
- @MSTACK--
- ;
-
- \ Does selector on stack match embedded selector?
- : MATCH-METHOD? ( sel addr -- sel addr flag)
- 2DUP @ =
- ;
-
- \ At end of this portion of a class's own method list, decide if
- \ there are more lists or inheritances.
- : END-OF-CLASS ( sel-addr -- sel-addr | ABORT)
- DUP /INHERITANCE + @ 0=
- IF
- DROP PREV-CLASS
- ELSE
- NEXT-CLASS
- THEN
- ;
-
- \ Given the data address of an object, the selector sought and
- \ the address of the head of a class method list, begin
- \ dereferencing its list of methods and inheritance until a method
- \ is found failure causes ABORT.
- : FIND-METHOD ( obj-addr selector method-list-addr -- method-xt | ABORT)
- MSTACK.INIT \ Clear the deck!
- BEGIN
- MATCH-METHOD? 0=
- WHILE
- DUP @ 0=
- IF
- END-OF-CLASS
- ELSE
- #CELLS/SELECT +
- THEN
-
- REPEAT
- ;
-
-
- \ ** Objects & Classes
-
- \ Object structure is in cell order:
- \ /TYPE/SIZE/PTR-TO-CLASS/PTR-TO-DATA
-
- 0 CELLS CONSTANT /TYPE
- 1 CELLS CONSTANT /SIZE
- 2 CELLS CONSTANT /DATA
- 3 CELLS CONSTANT /CLASS
-
- \ Class structure is in cell order:
- \ /TYPE/METHOD-LIST ..
- 1 CELLS CONSTANT /METHOD-LIST
-
- \ The DOES> code for an object
- : DO-OBJ ( i*x selector obj-addr -- j*x)
- TUCK
- /CLASS + @ /METHOD-LIST +
- FIND-METHOD
- EXE-METHOD
- ;
-
- \ Creating objects
- \ CLASSY if non-zero is the address of last selector/vector pair
- \ in the object under construction.
- VARIABLE CLASSY
-
- \ End a class definition by resetting CLASSY.
- : ;CLASS ( ADDR --)
- CLASSY OFF
- ; ;CLASS \ init for compile time use
-
- \ What a CLASS does: create an object pointing back to its
- \ class which pushes its own address onto Forth data stack.
- \ Objects also contain records of "size" (#entries) and of
- \ "type" (size of one entry). This is the ROM version for
- \ VFSE-332.
- : CREATE-ROM-OBJ ( #entries class-addr "name" --)
- 2 ?ENOUGH \ check stack depth
- \ MODE? >R \ save address space
- ( ROM) \ objects are ROMmable
- CREATE \ create named object
- DUP /TYPE + @ \ get size of one entry from class
- , \ store entry data type
- OVER , \ next is "size" (#entries)
- SWAP OVER \ -- class-addr #entries class-addr R: -- mode
- /TYPE + @ \ get size of one entry from class
- * \ times #entries is data space needed
- ( RAM) HERE >R \ save address to compile into object
- ALLOT \ allot correct num addr units in RAM
- R> ( ROM) , \ compile data space
- , \ then pointer to class
- \ R> ?MODE \ set back to RAM or ROM or whatever
- DOES> ( i*x selector [self] -- j*x)
- DO-OBJ
- ;
-
- \ Here is a RAM version for Jax4th and ZEN.
- : CREATE-RAM-OBJ ( #entries class-addr "name" --)
- 2 ?ENOUGH \ check stack depth
- CREATE \ create named object
- DUP /TYPE + @ \ get size of one entry from class
- , \ store entry data type
- OVER , \ next is "size" (#entries)
- SWAP OVER \ -- class-addr #entries class-addr R: -- mode
- /TYPE + @ \ get size of one entry from class
- * \ times #entries is data space needed
- HERE 2 CELLS + , \ save address to compile into object
- SWAP , \ then pointer to class
- ALLOT \ allot correct num addr units in RAM
- DOES> ( i*x selector [self] -- j*x)
- DO-OBJ
- ;
-
- \ Decide how to vector this in INIT-OOPS later in file.
- DEFER CREATE-OBJ
-
- \ Start a class definition. create a class with no methods.
- \ The class will, at runtime, create objects pointing to itself
- \ of an address unit size per individual entry corresponding
- \ to the assigned value at class-creation time. This will
- \ work for RAM and RAM/ROM systems as long as MODEPRLD.F is
- \ loaded first.
- : CLASS: ( individual-entry-size "name" -- addr)
- 1 ?ENOUGH \ "type" provided?
- \ MODE? >R \ save address space selector
- ( ROM) CREATE \ create CLASS in ROM
- , \ save "type"
- HERE CLASSY ! \ current end of method list
- 0 , 0 , \ /0/0 terminator
- 0 , 0 , \ extra one for after previous gets patched
- \ R> ?MODE \ restore address space selector
- DOES> ( size "name" --) \ runtime action
- CREATE-OBJ \ creates objects
- ;
-
- \ METHODIST non-zero contains method number under definition
- VARIABLE METHODIST
- METHODIST OFF \ init for compile time use
-
- \ Postincrementing count of defined methods.
- \ Methods are numbered 1 - 2^cell-bitsize.
- VARIABLE METHOD-POINTER
- : METHOD-POINTER.INIT ( n --)
- METHOD-POINTER !
- ; 1 METHOD-POINTER.INIT
-
- \ The current value of METHOD-POINTER has to be saved by
- \ the application somewhere in ROM and restored at powerup
- \ if compilation is to continue after an incremental
- \ ROMming of the system. INIT-OOPS takes this number as argument.
-
- \ Patch class method list in order to continue it.
- : PATCH-CLASS ( vector selector --)
- \ MODE? >R ROM \ we're comma-ing into ROM
- HERE \ HERE is where /selector/vector goes
- CLASSY @ \ get where we left off /0/0 in a CLASS
- /VECTOR + ! \ store HERE to its vector
- , , \ store /selector/vector for new method
- HERE CLASSY ! \ update pointer to current end of methods
- 0 , 0 , \ store new /0/0 method list terminator
- 0 , 0 , \ extra one for after previous gets patched
- \ R> ?MODE \ restore address space selector
- ;
-
- \ Terminate a method definition
- : ;M ( --) ( R: sys --)
- METHODIST @ 0= ABORT" No method currently being defined."
- POSTPONE ; \ finish :NONAME definition
- METHODIST @ \ get this method's selector
- PATCH-CLASS \ consume selector and :NONAME xt
- METHODIST OFF \ indicate no method being compiled
- ; IMMEDIATE
-
- \ Create a new method which contains an embedded selector.
- \ The embedded selector is made a Forth CONSTANT if not
- \ yet defined. Don't create the CONSTANT if it's already defined.
- \ Careful about names passed to M: ... they had better either
- \ be undefined or a CONSTANT since M: executes them if found!
-
- : M: ( "name" -- ) ( R: -- sys)
- CLASSY @ 0= ABORT" No CLASS under construction."
- >IN @ \ save input pointer
- BL WORD FIND 0= \ 0 means didn't find
- IF \ if didn't find ..
- DROP >IN ! \ restore input pointer
- METHOD-POINTER @ \ allocate a new method
- DUP CONSTANT \ save number, create name
- 1 METHOD-POINTER +! \ increment method number
- ELSE \ name was found
- NIP \ drop >IN
- EXECUTE \ get extant selector's CONSTANT value
- THEN
- METHODIST ! \ store current methodnum
- :NONAME \ start headerless definition
- ;
-
- \ INHERITS adds a CLASS inheritance to current position in
- \ method list of class under definition. INHERITS doesn't
- \ check to make sure that "name" is a CLASS so be careful!
- \ This could be fixed by keeping a linked list of CLASSes
- \ and searching it in INHERITS.
- \ You can use INHERITS anywhere in a class definition, any
- \ number of times.
- : INHERITS ( "name" --)
- CLASSY @ 0= ABORT" No CLASS under construction."
- ' >BODY /METHOD-LIST + 0 PATCH-CLASS
- ;
-
- \ Get size of an object in number of entries.
- : SIZEOF ( object -- #entries)
- /SIZE + @
- ;
-
- \ Get "type" of each entry in object, i.e., size in address units.
- : TYPEOF ( object -- entry-size)
- /TYPE + @
- ;
-
- : DATAOF ( object -- data-address)
- /DATA + @
- ;
-
- : INIT-OOPS ( first method# --)
- METHOD-POINTER.INIT
- ;CLASS
- METHODIST OFF
- MSTACK.INIT
- ['] CREATE-RAM-OBJ IS CREATE-OBJ \ <- Change for VFSE-332!
- ;
-
- 1 INIT-OOPS
-
- BASE !
-
- \ ~~~~~~~~~~~~~~~~~~~
- \ End of MULTIOOP.UTF
- \ ~~~~~~~~~~~~~~~~~~~
-
-