\ Optimized Instance Variables
\ These are intended to make it easier to use instance variables.
\ These IVARS will automatically fetch their data.  This can be optimized
\ like crazy.  If you want to store into them, you use IV=> .
\
\ Author: Phil Burk
\ Copyright 1986 Delta Research
\
\ MOD: PLB 5/13/87 Make iv&> immediate, use os+
\ MOD: PLB 9/13/88 Convert to new addressing mode, add IV.BYTES
\      Add signed ivars.

ANEW TASK-OBJ_IVARS

decimal
\ Support for fetching and storing into instance variables .
\ These should not be called directly.

\ Make JFORTH compile @ ! etc. inline for speed.
#host_amiga_jforth .IF
max-inline @ 20 max-inline !
.THEN

false .IF
: IV@  ( offset -- value , fetch from LONG instance variable )
    os+ @
;
: IVW@ ( offset -- value , fetch from SHORT instance variable )
    os+ w@
;
: IVC@ ( offset -- value , fetch from SHORT instance variable )
    os+ c@
;

: IV!  ( value offset -- , store into LONG instance variable )
    os+ !
;
: IVW!  ( value offset -- , store into SHORT instance variable )
    os+ w!
;
: IVC!  ( value offset -- , store into BYTE instance variable )
    os+ c!
;
.THEN

: IV+!  ( value offset -- , store into LONG instance variable )
    os+ +!
;

#host_amiga_jforth .IF
    max-inline !
.THEN

: CREATE.IVAR ( size <name> -- )
    CREATE ob.make.member   immediate
    DOES>  ( -- address-ivar )
        ?comp compile os.copy
        ob.stats compile+@bytes
;

\ These words are for declaring instance variables.
\ Some of this code appears redundant but is needed because they
\ are CREATE-DOES> words.
: IV.LONG  ( <name> --IN-- , declare a cell wide instance variable )
    4 create.ivar
;

: IV.SHORT  ( <name> --IN-- , declare a 16 bit wide instance variable )
    -2 create.ivar
;

: IV.USHORT  ( <name> --IN-- , declare a 16 bit wide instance variable )
    2 create.ivar
;

: IV.BYTE  ( <name> --IN-- , declare a byte wide instance variable )
    -1 create.ivar
;

: IV.UBYTE  ( <name> --IN-- , declare a byte wide instance variable )
    1 create.ivar
;

: IV=>  ( value <ivar> -- , store into ivar )
    ?COMP
    compile os.copy
    ob.stats? compile+!bytes
; immediate

: IV+>  ( value <ivar> -- , add value to ivar )
    ?COMP
    ob.stats? cell = 
    IF [compile] literal compile iv+!
    ELSE " IV+>" " IV+> only works on IV.LONG !"
         er_fatal er.report
    THEN
; immediate

: IV&   ( offset -- address_ivar )
    os+
;

: IV&>  ( <ivar> --IN-- address_ivar , calculate address of ivar )
    ?COMP
    ob.findit ob.offset@ [compile] literal compile os+
; immediate

\ This is for declaring a field of bytes in an object.
: IV.BYTES ( n <name> -- , declare a field of bytes )
    CREATE ob.make.member immediate
    DOES> ?comp @ [compile] literal compile os+
;

\ Test suite.
if-testing @ .IF
METHOD GETNEW:
METHOD GETOLD:
METHOD TESTNEW@:
METHOD TESTOLD@:
METHOD TESTNEW!:
METHOD TESTOLD!:
METHOD GETALL:
METHOD BUMPNEW:
V: #DO

:CLASS  TIV

IV.BYTE MY-IVBYTE
IV.SHORT MY-IVSHORT
IV.LONG MY-IVLONG

LONG   MY-LONG

:M INIT: init: super 
    55    iv=> my-ivbyte
    6666   iv=> my-ivshort
    123456 iv=> my-ivlong
    5678 my-long !
;M

:M GETNEW:   my-ivlong
;M

:M BUMPNEW:  iv+> my-ivlong
;M

:M GETOLD:   my-long @
;M

:M GETALL:   my-ivbyte
    my-ivshort   my-ivlong
;M

:M TESTNEW@: #DO @ 0 DO  MY-IVLONG DROP LOOP
;M
:M TESTOLD@: #DO @ 0 DO  MY-LONG DROP LOOP
;M

:M TESTNEW!: #DO @ 0 DO  1234 iv=> MY-IVLONG LOOP
;M
:M TESTOLD!: #DO @ 0 DO  1234 MY-LONG ! LOOP
;M

;CLASS

\ Benchmark

TIV MYTIV
100000 #do !
: TNEW@ testnew@: mytiv ;
: TOLD@ testold@: mytiv ;

: TNEW! testnew!: mytiv ;
: TOLD! testold!: mytiv ;
.THEN
