File:  [gforth] / gforth / objects.fs
Revision 1.2: download - view: text, annotated - select for diffs
Tue Mar 11 16:00:40 1997 UTC (27 years, 1 month ago) by anton
Branches: MAIN
CVS tags: v0-3-0, HEAD
added primitive K
the Makefile now works with Digital Unix make
renamed the gforth-makeimage variable GFORTH into GFORTHD
fixed bug in comp-image (can now generate data-relocatable images).
gforth-makeimage uses a new option --no-offset-im to avoid differences
	from the command line
Documentation changes
fixed another bug involving relocatablility of code addresses.
my_alloc now works on machines without MAP_FILE and MAP_PRIVATE

    1: \ yet another Forth objects extension
    2: 
    3: \ written by Anton Ertl 1996
    4: \ public domain
    5: 
    6: \ This (in combination with compat/struct.fs) is in ANS Forth (with an
    7: \ environmental dependence on case insensitivity; convert everything
    8: \ to upper case for state sensitive systems).
    9: 
   10: \ If you don't use Gforth, you have to load compat/struct.fs first.
   11: \ compat/struct.fs and this file together use the following words:
   12: 
   13: \ from CORE :
   14: \ : 1- + swap invert and ; Create >r rot r@ dup , r> DOES> @ chars
   15: \ cells 2* here - allot drop over execute 2dup move 2! 2@ ! ['] >body
   16: \ ' Variable POSTPONE immediate ." . cr Constant +!
   17: \ from CORE-EXT :
   18: \ tuck :noname compile, true 
   19: \ from BLOCK-EXT :
   20: \ \ 
   21: \ from DOUBLE :
   22: \ 2Constant 2VARIABLE 
   23: \ from EXCEPTION :
   24: \ throw catch 
   25: \ from EXCEPTION-EXT :
   26: \ abort" 
   27: \ from FILE :
   28: \ ( 
   29: \ from FLOAT :
   30: \ floats 
   31: \ from FLOAT-EXT :
   32: \ dfloats sfloats 
   33: \ from MEMORY :
   34: \ allocate resize 
   35: \ from TOOLS-EXT :
   36: \ [IF] [THEN]
   37: 
   38: \ ---------------------------------------
   39: \ MANUAL:
   40: 
   41: \ A class is defined like this:
   42: 
   43: \ <parent> class
   44: \   ... field <name>
   45: \   ...
   46: 
   47: \   ... inst-var <name>
   48: \   ...
   49: 
   50: \ selector <name>
   51: 
   52: \ :noname ( ... object -- ... )
   53: \   ... ;
   54: \ method <name> \ new method
   55: \ ...
   56: 
   57: \ :noname ( ... object -- ... )
   58: \   ... ;
   59: \ overrides <name> \ existing method
   60: \ ...
   61: 
   62: \ end-class <name>
   63: 
   64: \ you can write fields, inst-vars, selectors, methods and overrides in
   65: \ any order.
   66: 
   67: \ A call of a method looks like this:
   68: 
   69: \ ... <object> <method>
   70: 
   71: \ (<object> just needs to reside on the stack, there's no need to name it).
   72: 
   73: \ Instead of defining a method with ':noname ... ;', you can define it
   74: \ also with 'm: ... ;m'. The difference is that with ':noname' the
   75: \ "self" object is on the top of stack; with 'm:' you can get it with
   76: \ 'this'. You should use 'this' only in an 'm:' method even though the
   77: \ sample implementation does not enforce this.
   78: 
   79: \ The difference between a field and and inst-var is that the field
   80: \ refers to an object at the top of data stack (i.e. a field has the
   81: \ stack effect (object -- addr), whereas the inst-var refers to this
   82: \ (i.e., it has the stack effect ( -- addr )); obviously, an inst-var
   83: \ can only be used in an 'm:' method.
   84: 
   85: \ 'method' defines a new method selector and binds a method to it.
   86: 
   87: \ 'selector' defines a new method selector without binding a method to
   88: \ it (you can use this to define abstract classes)
   89: 
   90: \ 'overrides' binds a different method (than the parent class) to an
   91: \ existing method selector.
   92: 
   93: \ If you want to perform early binding, you can do it like this:
   94: 
   95: \ ... <object> [bind] <class> <method> \ compilation
   96: \ ... <object> bind  <class> <method> \ interpretation
   97: 
   98: \ You can get at the method from the method selector and the class like
   99: \ this:
  100: 
  101: \ bind' <class> <method>
  102: \ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  103: 
  104: \ needs struct.fs
  105: 
  106: \ helper words
  107: 
  108: : -rot ( a b c -- c a b )
  109:     rot rot ;
  110: 
  111: : perform ( ... addr -- ... )
  112:     @ execute ;
  113: 
  114: : save-mem	( addr1 u -- addr2 u ) \ gforth
  115:     \ copy a memory block into a newly allocated region in the heap
  116:     swap >r
  117:     dup allocate throw
  118:     swap 2dup r> -rot move ;
  119: 
  120: : extend-mem	( addr1 u1 u -- addr addr2 u2 )
  121:     \ extend memory block allocated from the heap by u aus
  122:     \ the (possibly reallocated piece is addr2 u2, the extension is at addr )
  123:     over >r + dup >r resize throw
  124:     r> over r> + -rot ;
  125: 
  126: : 2,	( w1 w2 -- ) \ gforth
  127:     here 2 cells allot 2! ;
  128: 
  129: : const-field ( size1 align1 -- size2 align2 )
  130:     1 cells: field
  131: does> ( addr -- w )
  132:     @ + @ ;
  133: 
  134: struct
  135:     1 cells: field object-map
  136: end-struct object-struct
  137: 
  138: struct
  139:     2 cells: field class-map
  140:     const-field class-instance-size \ aus
  141:     const-field class-instance-align \ aus
  142: end-struct class-struct
  143: 
  144: 2variable current-map \ address and size (in aus) of the current map
  145: 
  146: : class ( class -- size align )
  147:     dup class-map 2@ save-mem current-map 2!
  148:     dup class-instance-size
  149:     swap class-instance-align ;
  150: 
  151: : end-class ( size align "name" -- )
  152:     create
  153:     current-map 2@ 2,
  154:     swap , , ;
  155: 
  156: : no-method ( -- )
  157:     abort" no method defined" ;
  158: 
  159: : method ( xt "name" -- )
  160:     \ define method and selector
  161:     current-map 2@ ( xt map-addr map-size )
  162:     create dup ,
  163:     1 cells extend-mem current-map 2!
  164:     !
  165: does> ( ... object -- ... )
  166:     ( object addr )
  167:     @ over ( object-map ) @ + ( object xtp ) perform ;
  168: 
  169: : selector ( "name" -- )
  170:     \ define a method selector for later overriding in subclasses
  171:     ['] no-method method ;
  172: 
  173: : override! ( xt method-xt -- )
  174:     >body @ current-map 2@ drop + ! ;
  175: 
  176: : overrides ( xt "selector" -- )
  177:     \ replace default method "method" with xt
  178:     ' override! ;
  179: 
  180: : alloc-instance ( class -- object )
  181:     \ make a new, (almost) uninitialized instance of a class
  182:     dup class-instance-size allocate throw
  183:     swap class-map 2@ drop over ( object-map ) ! ;
  184: 
  185: \ this/self, instance variables etc.
  186: 
  187: variable thisp
  188: : this ( -- object )
  189:     \ rename this into self if you are a Smalltalk fiend
  190:     thisp @ ;
  191: 
  192: : m: ( -- xt colon-sys ) ( run-time: object -- )
  193:     :noname 
  194:     POSTPONE this
  195:     POSTPONE >r
  196:     POSTPONE thisp
  197:     POSTPONE ! ;
  198: 
  199: : ;m ( colon-sys -- ) ( run-time: -- )
  200:     POSTPONE r>
  201:     POSTPONE thisp
  202:     POSTPONE !
  203:     POSTPONE ; ; immediate
  204: 
  205: : catch ( ... xt -- ... n )
  206:     \ make it safe to call CATCH within a method.
  207:     \ should also be done with all words containing CATCH.
  208:     this >r catch r> thisp ! ;
  209: 
  210: : inst-var ( size1 align1 size align -- size2 align2 )
  211:     field
  212: does> ( -- addr )
  213:     ( addr1 ) @ this + ;
  214: 
  215: \ early binding stuff
  216: 
  217: \ this is not generally used, only where you want to do something like
  218: \ superclass method invocation (so that you don't have to name your methods)
  219: 
  220: : (bind) ( class method-xt -- xt )
  221:     >body @ swap class-map 2@ drop + @ ;
  222: 
  223: : bind' ( "class" "method" -- xt )
  224:     ' >body ' (bind) ;
  225: 
  226: : bind ( ... object "class" "method" -- ... )
  227:     bind' execute ;
  228: 
  229: : [bind] ( compile-time: "class" "method" -- ; run-time: ... object -- ... )
  230:     bind' compile, ; immediate
  231: 
  232: \ the object class
  233: 
  234: 0 0 save-mem current-map 2!
  235: object-struct \ no class to inherit from, so we have to do this manually
  236: :noname ( object -- )
  237:     ." object:" dup . ." class:" object-map @ . ;
  238: method print
  239: end-class object
  240: 
  241: \ examples
  242: true [if]
  243: cr object alloc-instance print
  244: 
  245: object class
  246: :noname ( object -- )
  247:     drop ." undefined" ;
  248: overrides print
  249: end-class nothing
  250: 
  251: nothing alloc-instance constant undefined
  252: 
  253: cr undefined print
  254: 
  255: \ instance variables and this
  256: object class
  257: 1 cells: inst-var count-n
  258: m: ( object -- )
  259:     count-n @ . ;m
  260: overrides print
  261: m: ( object -- )
  262:    0 count-n ! ;m
  263: method init
  264: m: ( object -- )
  265:     1 count-n +! ;m
  266: method inc
  267: end-class counter
  268: 
  269: counter alloc-instance constant counter1
  270: 
  271: cr
  272: counter1 init
  273: counter1 print
  274: counter1 inc
  275: counter1 print
  276: counter1 inc
  277: counter1 inc
  278: counter1 inc
  279: counter1 print
  280: counter1 print
  281: 
  282: \ examples of static binding
  283: 
  284: cr undefined bind object print
  285: : object-print ( object -- )
  286:     [bind] object print ;
  287: 
  288: cr undefined object-print
  289: [then]

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