programming tools for Windows applications development
  Home  |   SwiftForth Archive  |   SwiftX Archive  |

Re: - OOF pre-final

From: Charles Esson <charlese_at_cvs.com.au>
Date: Tue, 02 Feb 1999 14:57:21 +1100

I need to ask some questions.

1) In the word list at the end of your post it says you create methods with : .

I have assumed that they are created with VIRTUAL:

2) If I create a object with NEW, how do I execute an method within that object.

If anton's code this would be:

: fred
        class_name new \ obj<--
        DUP method
        destroy \ <--
;

Regards

Charles Esson

talk_at_forth.com wrote:

> Original sender: ForthCAD <mail_at_forthcad.com>
> This is my pre-final OOF system. The final version will be send in +- 3 =
> months because I think its now time to use it in reals applications to =
> validate some (theorical) choises. Also I must now terminates other =
> works...
>
> The system use normals Forth definitions without any preambule nor =
> postambule. So there is NO overhead on methods.=20
>
> The overhead on data will be minimized: its just a offset calculation =
> always necessary when seeking data in a buffer. (The same in any STRUCT =
> systems)
>
> Encapsulation is done by using unnnamed normal Forth wordlist.
>
> Thanks to Will Baden: I think his proposal is very good: its a minimum =
> that enable multiple models, with a very clear syntax. ( sometime I =
> regret the BUILD word existence, but... )
>
> So I hope this minimum will become near a ANSI standard extension.
>
> Already some extra on the Yerk version are:=20
>
> - easy to write: no multiple SELF, (ouf!)
> - easy to read: same syntax as normal Forth, natural word sequence
> - fastest: no pre/postambule on methods inside a class
> - array of class: (I think Yerk only use "indexed objects" )
> - virtual functions with constant small overhead
> - true encapsulation: Yerk place all methods in the same vocabulary
>
> (Source from here, wordset description at the bottom)
> \ =
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> \ ANSI-CLASS minimum system
> \ Version 0.9 - 31/01/1999
> \ Author: Charles Melice
> \ MAIL: mail_at_forthcad.com
> \ WEB: www.forthcad.com
> \ =
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
>
> ONLY FORTH ALSO DEFINITIONS
>
> \ EMPTY
>
> \ ------------------------------------------------
> \ TO DEFINE IF MISSING
> \ ------------------------------------------------
>
> \ : @REL POSTPONE @ ; IMMEDIATE
> \ : !REL POSTPONE ! ; IMMEDIATE
> \ : ,REL POSTPONE , ; IMMEDIATE
> \ +TO to replace by equivalence
>
> \ ------------------------------------------------
> \ WORDLISTS ENCAPSULATION
> \ ------------------------------------------------
>
> WORDLIST CONSTANT CLASS-WORDLIST
>
> CLASS-WORDLIST SET-CURRENT
>
> WORDLIST DUP CONSTANT PRIVATE-WORDLIST
>
> FORTH-WORDLIST SWAP CLASS-WORDLIST 3 SET-ORDER
>
> \ ------------------------------------------------
> \ IMPORTANT VALUES
> \ ------------------------------------------------
>
> FORTH-WORDLIST SET-CURRENT
>
> 0 VALUE THIS \ seek the object-data base
> 0 VALUE ^CLASS \ seek the in-context class
>
> \ ------------------------------------------------
> \ SOME IMPLEMENTATION WORDS
> \ ------------------------------------------------
>
> PRIVATE-WORDLIST SET-CURRENT
>
> CREATE ^PREV-ORDER 33 CELLS ALLOT
> 0 VALUE PREV-CURRENT
>
> \ used later to define VIRTUAL:=20
> DEFER attach-class-vtable
> DEFER inherit-to-vtemp
>
> : WID> ( class -- addr ) ; IMMEDIATE
> : PARENT> ( class -- addr ) CELL+ ;
> : SIZE> ( class -- addr ) CELL+ CELL+ ;
> : VTABLE> ( class -- addr ) [ 3 CELLS ] LITERAL + ;
>
> : ^SIZE ( -- addr ) ^CLASS SIZE> ;
> : ^VTABLE ( -- addr ) ^CLASS VTABLE> ;
> : ^PARENT ( -- addr ) ^CLASS CELL+ ;
>
> : SaveSearchOrder ( -- )
> get-order dup \ s: widn .. wid1 n n
> ^prev-order ! \ s: widn .. wid1 n
> ^prev-order over cells + \ s: widn .. wid1 n addrmax
> swap 0 \ s: widn .. wid1 addrmax n 0
> ?DO dup >r ! r> cell- LOOP
> drop ;
>
> : RestoreSearchOrder ( -- )
> only
> ^prev-order @ 1+ 1 \ s: n 0
> ?DO \ s: -
> i cells ^prev-order +
> @ context ! also
> LOOP
> previous ;
>
> : AlsoClassSearchOrder ( ^class -- )
> dup parent> @rel ?dup \ have a parent ?
> IF RECURSE THEN \ yes -> SetParentClassSearchOrder
> also @ context ! ;
>
> : SetClassSearchOrder ( -- )
> only forth
> also class-wordlist context !
> ^class AlsoClassSearchOrder ;
>
> : ResetClassSearchOrder ( -- )
> ^class
> BEGIN \ s: -
> previous
> PARENT> @REL
> ?dup 0=3D
> UNTIL ;
>
> : ClassView ( ^CLASS -- )
> to ^class SetClassSearchOrder ;
>
> \ ------------------------------------------------
> \ CLASS DEFINITION
> \ ------------------------------------------------
>
> FORTH-WORDLIST SET-CURRENT
>
> : SUBCLASS ( <<name>> ^parent -- ) \ replace VOCABULARY
> wordlist=20
> create here to ^class \ S: ^parent ^wid
> , \ S: ^parent
> dup ,rel \ S: ^parent
> dup IF size> @ THEN , \ S: - PFA: <wid><parent><size>
> 0 ,REL \ vtable^
> SaveSearchOrder
> get-current to prev-current
> SetClassSearchOrder
> ^class wid> @ set-current \ definitions
> inherit-to-vtemp
> DOES> ; ( -- ^CLASS )
>
> : CLASS ( <<name>> -- )
> 0 SUBCLASS ;
>
> CLASS-WORDLIST SET-CURRENT
>
> : END ( -- )
> attach-class-vtable
> RestoreSearchOrder
> prev-current set-current ;
>
> \ ------------------------------------------------
> \ DATA DEFINITION
> \ ------------------------------------------------
>
> CLASS-WORDLIST SET-CURRENT
>
> : BUFFER: ( <<name>> size -- )
> create
> ^size @ ,
> ^size +!
> DOES> ( body -- offset+THIS )
> @ this + ;
>
> : VARIABLE ( <<name>> -- ) cell BUFFER: ;
>
> \ ------------------------------------------------
> \ SPECIAL WORDLIST LOOKUP
> \ ------------------------------------------------
>
> CLASS-WORDLIST SET-CURRENT
>
> : SUPER ( <<name>> -- )
> ^class cell+ @rel
> dup 0=3D abort" class have no parent"
> ^class >r to ^class
> previous
> '
> state @
> IF compile, ELSE execute THEN
> r> to ^class
> also ^class wid> @ context ! ;
> IMMEDIATE
>
> : COMMON ( <<name>> -- )
> RestoreSearchOrder
> '
> state @
> IF compile, ELSE execute THEN
> SetClassSearchOrder ;
> IMMEDIATE
>
> \ ------------------------------------------------
> \ CLASS-OBJECTS INSTANCE
> \ ------------------------------------------------
>
> PRIVATE-WORDLIST SET-CURRENT
>
> \ TODO: Possibles optimisations:
> \ case...
> \ A - data exist - size > 0
> \ B - data exist with offset
> \ C - virtual method exist vtable <> 0
> \
> \ A B C TODO:
> \ -- -- -- ---------------
> \ 0 0 0 compile,
> \ 0 0 1 save-class compile, restore
> \ 0 1 0 -
> \ 0 1 1 -
> \ 1 0 0 compile,
> \ 1 0 1 save-class compile, restore
> \ 1 1 0 save-this +to compile, restore
> \ 1 1 1 save-class-this compile, restore
> \
>
> : execute-ivar ( ^obj xt -- ) \ not optimal
> ^class this 2>R
> swap
> dup @REL to ^class \ must because virtuals
> cell+ @ +to this
> execute
> 2R> to this to ^class ;
>
> : execute-ivar[] ( index ^obj xt -- ) \ not optimal
> ^class this 2>R
> swap
> dup @REL to ^class \ must because virtuals
> cell+ @ \ S: index xt offset
> rot ^size @ * + \ S: xt offset+index*size
> +to this
> execute
> 2R> to this to ^class ;
>
> : execute-iobj ( ^obj xt -- ) \ not optimal
> ^class this 2>R
> swap
> dup @REL to ^class \ must because virtuals
> cell+ to this
> execute
> 2R> to this to ^class ;
>
> : execute-iobj[] ( index ^obj xt -- )
> ^class this 2>R
> swap
> dup @REL to ^class \ must because virtuals
> cell+ rot \ S: xt ^base index=20
> ^size @ * + \ S: xt offset
> to this
> execute
> 2R> to this to ^class ;
>
> CLASS-WORDLIST SET-CURRENT
>
> : BUILD ( <<objname>> ^CLASS -- )
> ^class >R ClassView \ set new class context
> ^size @ ^CLASS \ S: SIZE CLASS
> R> ClassView \ set original class context
> create
> ,REL ^size @ , \ PFA: <OBJCLASS><OFFSET>
> ^size +! \ S: -
> IMMEDIATE
> DOES>
> ^class >r \ save prev context
> dup @REL \ S: ^obj CLASS
> ClassView \ S: ^obj
> ' \ S: ^obj xt=20
> STATE @
> IF
> postpone 2literal
> postpone execute-ivar
> ELSE
> execute-ivar
> THEN
> r> dup to ^class
> ClassView ;
>
> : BUILD[] ( <<objname>> count ^class -- )
> create
> dup ,REL ^size @ , \ PFA: <OBJCLASS><OFFSET>
> size> @ * ^size +! \ S: -
> IMMEDIATE
> DOES> ( index ^obj -- )
> ^class >r \ save prev context
> dup @REL \ S: index ^obj CLASS
> ClassView \ S: index ^obj
> ' \ S: index ^obj xt
> STATE @
> IF
> postpone 2literal
> postpone execute-ivar[]
> ELSE
> execute-ivar[]
> THEN
> r> dup to ^class
> ClassView ;
>
> FORTH-WORDLIST SET-CURRENT
>
> : BUILD ( <<objname>> ^class -- )
> create
> dup ,rel
> here swap \ S: here ^class
> size> @ dup allot \ PFA: <CLASS><..DATA..>
> 0 fill \ proposal is to initialize
> IMMEDIATE
> DOES>
> SaveSearchOrder
> dup @REL \ S: ^obj CLASS
> ClassView \ S: ^obj
> ' \ S: ^obj xt
> STATE @
> IF
> postpone 2literal
> postpone execute-iobj
> ELSE
> execute-iobj
> THEN
> RestoreSearchOrder ;
>
> : BUILD[] ( <<objname>> count ^class -- )
> create
> dup ,rel \ S: count ^class
> size> @ * \ S: count*size
> here swap \ S: here count*size
> dup allot \ PFA: <CLASS><..DATA..>
> 0 fill \ proposal is to initialize
> IMMEDIATE
> DOES> ( index ^obj -- )
> SaveSearchOrder
> dup @REL \ S: index ^obj CLASS
> ClassView \ S: index ^obj
> ' \ S: index ^obj xt
> STATE @
> IF
> postpone 2literal
> postpone execute-iobj[]
> ELSE
> execute-iobj[]
> THEN
> RestoreSearchOrder ;
>
> =20
>
> \ ------------------------------------------------
> \ (optional) VIRTUAL: ( <<name>> -- )
> \ define a virtual method
> \ ------------------------------------------------
>
> PRIVATE-WORDLIST SET-CURRENT
>
> 100 constant MAX-VIRTUAL
>
> create vTblTemp 0 , MAX-VIRTUAL 2* cells allot
>
> : virt-count ( -- addr )
> ^VTABLE @REL ;
>
> : vtable[] ( n -- addr )
> 2* 1+ cells virt-count + ;
>
> :noname [ IS inherit-to-vtemp ] ( -- )
> 0 vTblTemp !
> ^parent @REL
> IF
> ^class >r
> ^parent @REL to ^class
> ^vtable @REL
> IF
> virt-count @ vTblTemp !
> vTblTemp cell+
> virt-count @ 0
> ?DO
> i vtable[] @REL over !REL
> cell+
> i vtable[] cell+ @REL over !REL
> cell+
> LOOP
> drop
> THEN
> r> to ^class
> THEN
> vTblTemp ^vtable !REL ;
>
> :noname [ IS attach-class-vtable ] ( -- )
> virt-count @
> IF
> here
> virt-count dup @ \ S: body addr count
> dup , 0 \ S: body addr count 0
> ?DO \ S: body addr
> cell+ dup @REL ,REL
> cell+ dup @REL ,REL
> LOOP
> drop
> ^vtable !REL
> ELSE
> 0 ^vtable !REL
> THEN ;
> =20
>
> : in-vtable ( body^ -- pos true | false )
> virt-count @ 0
> ?DO
> i vtable[] cell+ @REL over =3D
> IF drop i TRUE unloop EXIT THEN
> LOOP
> drop FALSE ;
>
> : append-to-vtable ( body^ -- n )
> \ later, we should use allocate/resize
> virt-count @
> dup MAX-VIRTUAL >=3D abort" virtual table overflow - see =
> MAX-VIRTUAL"
>
> vtable[] cell+ !REL
> virt-count @
> dup 1+ virt-count ! ;
>
> : CreateVirtual: ( <<method>> -- vn )
> Create here \ S: bod
> append-to-vtable \ S: vn
> dup 2* 1+ cells , \ S: byte-offset
> \ offset in bytes to speed-up
> DOES> \ TODO: better optimisation
> @ ^vtable @REL + \ this is the virtual overhead
> @REL execute ;=20
>
> \ ------------------------------------------------
> \ Extra words - not defined in ANSI proposal
> \ ------------------------------------------------
>
> CLASS-WORDLIST SET-CURRENT
>
> : VIRTUAL: ( <<name>> -- )
> >IN @
> bl word find
> IF \ S: in^ xt
> >body in-vtable
> IF
> nip \ S: vn
> ELSE
> >IN !
> CreateVirtual: \ S: vn
> THEN
> ELSE \ S: in^ cstr
> drop >IN ! \ S: -
> CreateVirtual: \ S: vn
> THEN
> :noname swap \ S: xt vn
> vtable[] !REL ;
> =20
>
> FORTH-WORDLIST SET-CURRENT
>
> : >THIS ( ^object -- ^membase ) \ usage ' obj >this
> >body cell+ ;
>
> : >CLASS ( ^object -- ^class ) \ usage ' obj >class
> >body @REL ;
>
> : USER> ( ^class -- addr ) \ ' obj >class user> @
> [ 4 CELLS ] LITERAL + ;
>
> : NEW ( ^class -- ^obj )
> dup SIZE> @ cell+
> allocate abort" memory allocation error"
> swap over !REL ;
>
> : NEW[] ( count ^class -- ^obj )
> dup SIZE> @ rot * cell+
> allocate abort" memory allocation error"
> swap over !REL ;
>
> \ FREE DROP can be used - so no collision with RELEASE
>
> : ->" ( <<obj]>> <<method>> -- )
> [char] " word count evaluate
> ^class >R
> dup @REL to ^class \ S: ^obj
> ^class AlsoClassSearchOrder
> ' \ S: ^obj xt
> state @
> IF
> postpone 2literal
> postpone execute-iobj
> ELSE
> execute-iobj
> THEN
> ResetClassSearchOrder
> R> to ^class ;
> IMMEDIATE
>
> : []->" ( index <<obj]>> <<method>> -- )
> [char] " word count evaluate
> ^class >R
> dup @REL to ^class \ S: index ^obj
> ^class AlsoClassSearchOrder
> ' \ S: index ^obj xt
> state @
> IF
> postpone literal
> postpone execute-iobj[]
> ELSE
> execute-iobj[]
> THEN
> ResetClassSearchOrder
> R> to ^class ;
> IMMEDIATE
>
> : .CLASSINFO ( ^class -- )
> SaveSearchOrder
> cr 0 >r
> BEGIN
> dup body> >name count
> swap over cr r@ spaces type cr
> r@ spaces 0 ?DO [char] - emit LOOP
> dup wid> @ context !
> cr r@ spaces words cr
> parent> @rel ?dup 0=3D
> r> 3 + >r=20
> UNTIL
> r> drop
> RestoreSearchOrder ;
>
> : SIZEOF ( ^class -- size )
> size> @ ;
>
> ONLY FORTH ALSO DEFINITIONS
>
> \ ------------------------------------------------
> \ SOURCE END
> \ ------------------------------------------------
>
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3DWil Baden ANSI Class wordset =
> proposal=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
>
> CLASS
> CLASS class
> Construct a class.
> A class is a defining word for a collection of future definitions.
>
> SUBCLASS
> class SUBCLASS classname
> Construct an extension or specialization of a class.
>
> VARIABLE WITHIN A CLASS
> VARIABLE membername
> Define a variable member of a class.
>
> BUFFER: WITHIN A CLASS
> n CHARS BUFFER: membername
> n CELLS BUFFER: membername
> Define a data area member of a class.
>
> CONSTANT WITHIN A CLASS
> n CONSTANT membername
> Define a constant member of a class.
>
> : WITHIN A CLASS
> : membername ... ;
> Define a function member of a class.
>
> ; WITHIN A CLASS
> : membername ... ;
> Terminate the definition of a function member of a class.
>
> END WITHIN A CLASS
> END
> Terminate the construction of a class.
>
> BUILD
> class BUILD objectname
> Build object objectname as an instance of class .
> Objects are used object member .
>
> COMMON WITHIN A CLASS
> COMMON forthword
> Compile forthword from standard dictionary.
>
> SUPER WITHIN A CLASS
> SUPER member
> Compile a member, beginning lookup for it in the superclass.
> This disambiguates members with the same name.
>
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3DMy extension in the above =
> object base memory adress.
>
> ^CLASS
> This value return the context class body adress.
>
>

.

>From talk_at_forth.com Tue Feb 2 11:51:47 1999
To: sftalk_at_forth.com
Message-Id: <m0000131_at_gerd.forthinc.com>
Subject: - oof NEW NEW[] -> []->
From: ForthCAD <mail_at_forthcad.com>
Date: Tue, 2 Feb 1999 11:51:47 -0000

Charles,

There is a bug, but is it Swift or me ?

This test sequence don't work in SwiftForth:

: eval" [char] " parse evaluate ; immediate
: TEST eval" 9 . 8 . " ; \ don't display 9 8 - BUG ?

A solution is to modify the ->" and []->" definition as this:

\ -------------------------------------------------
\ the following to replace ->"
\ -------------------------------------------------
: -> ( <<method>> -- ) ( S: ^obj -- )
    ^class >R
    dup @REL to ^class \ S: ^obj
    ^class AlsoClassSearchOrder
    ' \ S: ^obj xt
    state @
    IF
        postpone 2literal
        postpone execute-iobj
    ELSE
        execute-iobj
    THEN
    ResetClassSearchOrder
    R> to ^class ;
                    IMMEDIATE

\ -------------------------------------------------
\ the following to replace []->"
\ -------------------------------------------------
: ->[] ( index <<method>> -- ) ( S: ^obj -- )
    ^class >R
    dup @REL to ^class \ S: index ^obj
    ^class AlsoClassSearchOrder
    ' \ S: index ^obj xt
    state @
    IF
        postpone literal
        postpone execute-iobj[]
    ELSE
        execute-iobj[]
    THEN
    ResetClassSearchOrder
    R> to ^class ;
                    IMMEDIATE

\ =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
\ BASIC-CLASSES.F
\ =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

empty
REQUIRES CLASS09

\ =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
\ BASIC CLASSES
\ =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

Class cVar

    variable addr

    : @ ( -- val ) addr @ ;
    : ! ( val -- ) addr ! ;
    : ? ( -- ) addr ? ;
    : +! ( val -- ) addr +! ;
    : 0! ( -- ) 0 addr COMMON ! ;
    : inc ( -- ) 1 +! ;
    : dec ( -- ) -1 +! ;
    : neg ( -- ) @ negate ! ;
End

cVar SubClass cPtr

    cVar build Size

    : _?err ( -- ) abort" memory allocation error" ;

    : allocate ( size -- ) dup Size ! allocate _?err ! ;
    : resize ( size -- ) dup Size ! @ swap resize _?err ! ;
    : free ( -- ) Size 0! @ ?dup IF free _?err 0! THEN ;
End

cPtr SubClass cString

    cVar build _Len

    : _dozstr ( -- ) 0 @ _Len @ chars + C! ;

    : zComputeLen ( zstr -- len )
        0 swap
        BEGIN dup c@ WHILE
            char+
            swap 1+ swap
        REPEAT
        drop ;

    : GetLen ( -- len ) _Len @ ;
    : Type ( -- ) @ _Len @ Type ;
    : ? ( -- ) Type ;

    : Put ( addr len -- )
        _Len ! \ S: addr
        GetLen Size @ >=3D \ S: addr flag
        IF free GetLen 1+ allocate THEN
        @ GetLen move
        _dozstr ;

    : zPut ( zaddr -- ) dup zComputeLen Put ;

    : Concat ( addr len -- )
        dup GetLen + dup Size @ >=3D \ S: addr len size flag
        IF dup 1+ resize THEN \ S: addr len size
        dup _Len !
        over - @ + \ S: addr len ptr+
        swap move
        _dozstr ;

    : zConcat ( zaddr -- ) dup zComputeLen Concat ;

    : SetEmpty ( -- ) _Len 0! _dozstr ;

    : Get ( -- addr count ) @ _Len @ ;

    : [] ( index -- addr ) chars @ + ;

    : FindCharPos ( ch -- index true | false )
>R @ _Len @ 0
        ?DO
            i [] c@ r@ =3D
            IF
                r> drop i TRUE
                UNLOOP EXIT
            THEN
        LOOP
        r> drop FALSE ;

    : free ( -- ) SUPER free _Len 0! ;
End

Class cPoint

    Variable x
    Variable y

    VIRTUAL: NameOf c" cPoint" ;
    : .Name NameOf count type ;

    : @ ( -- x y ) x @ y @ ;
    : ! ( x y -- ) y ! x ! ;
    : ? ( -- ) x ? y ? ;
End

Class cRect

    cPoint build lt \ left-top
    cPoint build rb \ right-bottom

    : @ ( -- left top right bottom ) lt @ rb @ ;
    : ! ( left top right bottom -- ) rb ! lt ! ;
    : ? ( -- ) lt ? [CHAR] - emit 1 spaces =
rb ? ;
End

\ =3D=3D=3D=3D=3D=3D examples =3D=3D=3D=3D=3D=3D

cr
..( NEW immediate mode usage ) cr

cPoint NEW value pPt

1 2 pPt -> !
pPt -> ? cr
pPt -> .Name
cr

..( NEW in a definition ) cr

: m1 [ pPt dup ] -> .Name 1 spaces -> ? ;

m1 cr
8 9 pPt -> !
m1 cr

cr
pPt free drop

( NB:
  Using another pointer type -a cRect where there was a cPoint- is
  an error.

Best regards
Charles Melice )

----------
From: talk_at_forth.com
Sent: mardi 2 f=E9vrier 1999 4:34
To: Members of SF Talk
Subject: re: - OOF pre-final

Original sender: Charles Esson <charlese_at_cvs.com.au>
I need to ask some questions.

1) In the word list at the end of your post it says you create methods =
with : .

I have assumed that they are created with VIRTUAL:

2) If I create a object with NEW, how do I execute an method within that =
object.

If anton's code this would be:

: fred
        class_name new \ obj<--
        DUP method
        destroy \ <--
;

Regards

Charles Esson

.

>From rvn_at_forth.com Tue Feb 2 06:20:57 1999
To: sftalk_at_forth.com
Message-Id: <m0000132_at_gerd.forthinc.com>
Subject: Re: [sftalk] - oof NEW NEW[] -> []->
From: "Rick VanNorman" <rvn_at_forth.com>
Date: Tue, 2 Feb 1999 06:20:57 -0800

>Original sender: ForthCAD <mail_at_forthcad.com>
>Charles,
>
>There is a bug, but is it Swift or me ?
>
>This test sequence don't work in SwiftForth:
>
>: eval" [char] " parse evaluate ; immediate
>: TEST eval" 9 . 8 . " ; \ don't display 9 8 - BUG ?

This is proper behavior of EVALUATE. Notice that the word TEST
is executable, and prints 9 and 8 when run. Evaluate acts on
the string given it in the current system context, either
compilation or interpretation. Here it was compiling, and
so EVALUATE _compiled_ "9 . 8 ." into the word TEST.

Rick

.

>From talk_at_forth.com Tue Feb 2 15:54:09 1999
To: sftalk_at_forth.com
Message-Id: <m0000133_at_gerd.forthinc.com>
Subject: Re: [sftalk] - oof NEW NEW[] -> []->
From: ForthCAD <mail_at_forthcad.com>
Date: Tue, 2 Feb 1999 15:54:09 -0000

Charles Esson, Rick,=20

Thanks for the information on "evaluate".

My last invoice have a big error: I compile a ALLOCATE result as a =
literal.
Its strange because there is no vodka here...

I send now a solution for -> and ->[] with runtime binding. Its slow.

Later I send a solution to make static binding with object adress. (easy =
and
optimal)

Next: CLASS.F BASIC-CLASSES.F WORDSET.TXT

\ =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
\ CLASS.F
\ Version 0.92 - 02/02/1999
\ =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

ONLY FORTH ALSO DEFINITIONS

\ EMPTY

\ ------------------------------------------------
\ TO DEFINE IF MISSING
\ ------------------------------------------------

\ : @REL POSTPONE @ ; IMMEDIATE
\ : !REL POSTPONE ! ; IMMEDIATE
\ : ,REL POSTPONE , ; IMMEDIATE
\ +TO to replace by equivalence

\ ------------------------------------------------
\ WORDLISTS ENCAPSULATION
\ ------------------------------------------------

WORDLIST CONSTANT CLASS-WORDLIST

CLASS-WORDLIST SET-CURRENT

WORDLIST DUP CONSTANT PRIVATE-WORDLIST

FORTH-WORDLIST SWAP CLASS-WORDLIST 3 SET-ORDER

\ ------------------------------------------------
\ IMPORTANT VALUES
\ ------------------------------------------------

FORTH-WORDLIST SET-CURRENT

0 VALUE THIS \ seek the object-data base
0 VALUE ^CLASS \ seek the in-context class

\ ------------------------------------------------
\ SOME IMPLEMENTATION WORDS
\ ------------------------------------------------

PRIVATE-WORDLIST SET-CURRENT

CREATE ^PREV-ORDER 33 CELLS ALLOT
0 VALUE PREV-CURRENT

\ used later to define VIRTUAL:=20
DEFER attach-class-vtable
DEFER inherit-to-vtemp

: WID> ( class -- addr ) ; IMMEDIATE
: PARENT> ( class -- addr ) CELL+ ;
: SIZE> ( class -- addr ) CELL+ CELL+ ;
: VTABLE> ( class -- addr ) [ 3 CELLS ] LITERAL + ;

: ^SIZE ( -- addr ) ^CLASS SIZE> ;
: ^VTABLE ( -- addr ) ^CLASS VTABLE> ;
: ^PARENT ( -- addr ) ^CLASS CELL+ ;

: SaveSearchOrder ( -- )
    get-order dup \ s: widn .. wid1 n n
    ^prev-order ! \ s: widn .. wid1 n
    ^prev-order over cells + \ s: widn .. wid1 n addrmax
    swap 0 \ s: widn .. wid1 addrmax n 0
    ?DO dup >r ! r> cell- LOOP
    drop ;

: RestoreSearchOrder ( -- )
    only
    ^prev-order @ 1+ 1 \ s: n 0
    ?DO \ s: -
        i cells ^prev-order +
        @ context ! also
    LOOP
    previous ;

: AlsoClassSearchOrder ( ^class -- )
    dup parent> @rel ?dup \ have a parent ?
    IF RECURSE THEN \ yes -> SetParentClassSearchOrder
    also @ context ! ;

: SetClassSearchOrder ( -- )
    only forth
    also class-wordlist context !
    ^class AlsoClassSearchOrder ;

: ResetClassSearchOrder ( -- )
    ^class
    BEGIN \ s: -
        previous
        PARENT> @REL
        ?dup 0=3D
    UNTIL ;

: ClassView ( ^CLASS -- )
    to ^class SetClassSearchOrder ;

\ ------------------------------------------------
\ CLASS DEFINITION
\ ------------------------------------------------

FORTH-WORDLIST SET-CURRENT

: SUBCLASS ( <<name>> ^parent -- ) \ replace VOCABULARY
    wordlist=20
    create here to ^class \ S: ^parent ^wid
    , \ S: ^parent
    dup ,rel \ S: ^parent
    dup IF size> @ THEN , \ S: - PFA: <wid><parent><size>
    0 ,REL \ vtable^
    SaveSearchOrder
    get-current to prev-current
    SetClassSearchOrder
    ^class wid> @ set-current \ definitions
    inherit-to-vtemp
    DOES> ; ( -- ^CLASS )

: CLASS ( <<name>> -- )
    0 SUBCLASS ;

CLASS-WORDLIST SET-CURRENT

: END ( -- )
    attach-class-vtable
    RestoreSearchOrder
    prev-current set-current ;

\ ------------------------------------------------
\ DATA DEFINITION
\ ------------------------------------------------

CLASS-WORDLIST SET-CURRENT

: BUFFER: ( <<name>> size -- )
    create
    ^size @ ,
    ^size +!
    DOES> ( body -- offset+THIS )
        @ this + ;

: VARIABLE ( <<name>> -- ) cell BUFFER: ;

\ ------------------------------------------------
\ SPECIAL WORDLIST LOOKUP
\ ------------------------------------------------

CLASS-WORDLIST SET-CURRENT

: SUPER ( <<name>> -- )
    ^class cell+ @rel
    dup 0=3D abort" class have no parent"
    ^class >r to ^class
    previous
    '
    state @
    IF compile, ELSE execute THEN
    r> to ^class
    also ^class wid> @ context ! ;
                                IMMEDIATE

: COMMON ( <<name>> -- )
    RestoreSearchOrder
    '
    state @
    IF compile, ELSE execute THEN
    SetClassSearchOrder ;
                         IMMEDIATE

\ ------------------------------------------------
\ CLASS-OBJECTS INSTANCE
\ ------------------------------------------------

PRIVATE-WORDLIST SET-CURRENT

\ TODO: Possibles optimisations:
\ case...
\ A - data exist - size > 0
\ B - data exist with offset
\ C - virtual method exist vtable <> 0
\
\ A B C TODO:
\ -- -- -- ---------------
\ 0 0 0 compile,
\ 0 0 1 save-class compile, restore
\ 0 1 0 -
\ 0 1 1 -
\ 1 0 0 compile,
\ 1 0 1 save-class compile, restore
\ 1 1 0 save-this +to compile, restore
\ 1 1 1 save-class-this compile, restore
\

: execute-ivar ( ^obj xt -- ) \ not optimal
    ^class this 2>R
    swap
    dup @REL to ^class \ must because virtuals
    cell+ @ +to this
    execute
    2R> to this to ^class ;

: execute-ivar[] ( index ^obj xt -- ) \ not optimal
    ^class this 2>R
    swap
    dup @REL to ^class \ must because virtuals
    cell+ @ \ S: index xt offset
    rot ^size @ * + \ S: xt offset+index*size
    +to this
    execute
    2R> to this to ^class ;

: execute-iobj ( ^obj xt -- ) \ not optimal
    ^class this 2>R
    swap
    dup @REL to ^class \ must because virtuals
    cell+ to this
    execute
    2R> to this to ^class ;

: execute-iobj[] ( index ^obj xt -- )
    ^class this 2>R
    swap
    dup @REL to ^class \ must because virtuals
    cell+ rot \ S: xt ^base index=20
    ^size @ * + \ S: xt offset
    to this
    execute
    2R> to this to ^class ;

CLASS-WORDLIST SET-CURRENT

: BUILD ( <<objname>> ^CLASS -- )
    ^class >R ClassView \ set new class context
    ^size @ ^CLASS \ S: SIZE CLASS
    R> ClassView \ set original class context
    create
    ,REL ^size @ , \ PFA: <OBJCLASS><OFFSET>
    ^size +! \ S: -
    IMMEDIATE
    DOES> ( ^obj -- )
        ^class >r \ save prev context
        dup @REL \ S: ^obj CLASS
        ClassView \ S: ^obj
        ' \ S: ^obj xt=20
        STATE @
        IF
            postpone 2literal
            postpone execute-ivar
        ELSE
            execute-ivar
        THEN
        r> dup to ^class
        ClassView ;

: BUILD[] ( <<objname>> count ^class -- )
    create
    dup ,REL ^size @ , \ PFA: <OBJCLASS><OFFSET>
    size> @ * ^size +! \ S: -
    IMMEDIATE
    DOES> ( index ^obj -- )
        ^class >r \ save prev context
        dup @REL \ S: index ^obj CLASS
        ClassView \ S: index ^obj
        ' \ S: index ^obj xt
        STATE @
        IF
            postpone 2literal
            postpone execute-ivar[]
        ELSE
            execute-ivar[]
        THEN
        r> dup to ^class
        ClassView ;

FORTH-WORDLIST SET-CURRENT

: BUILD ( <<objname>> ^class -- )
    create
    dup ,rel
    here swap \ S: here ^class
    size> @ dup allot \ PFA: <CLASS><..DATA..>
    0 fill \ proposal is to initialize
    IMMEDIATE
    DOES>
        SaveSearchOrder
        dup @REL \ S: ^obj CLASS
        ClassView \ S: ^obj
        ' \ S: ^obj xt
        STATE @
        IF
            postpone 2literal
            postpone execute-iobj
        ELSE
            execute-iobj
        THEN
        RestoreSearchOrder ;

: BUILD[] ( <<objname>> count ^class -- )
    create
    dup ,rel \ S: count ^class
    size> @ * \ S: count*size
    here swap \ S: here count*size
    dup allot \ PFA: <CLASS><..DATA..>
    0 fill \ proposal is to initialize
    IMMEDIATE
    DOES> ( index ^obj -- )
        SaveSearchOrder
        dup @REL \ S: index ^obj CLASS
        ClassView \ S: index ^obj
        ' \ S: index ^obj xt
        STATE @
        IF
            postpone 2literal
            postpone execute-iobj[]
        ELSE
            execute-iobj[]
        THEN
        RestoreSearchOrder ;

   =20

\ ------------------------------------------------
\ (optional) VIRTUAL: ( <<name>> -- )
\ define a virtual method
\ ------------------------------------------------

PRIVATE-WORDLIST SET-CURRENT

100 constant MAX-VIRTUAL

create vTblTemp 0 , MAX-VIRTUAL 2* cells allot

: virt-count ( -- addr )
    ^VTABLE @REL ;

: vtable[] ( n -- addr )
    2* 1+ cells virt-count + ;

:noname [ IS inherit-to-vtemp ] ( -- )
    0 vTblTemp !
    ^parent @REL
    IF
        ^class >r
        ^parent @REL to ^class
        ^vtable @REL
        IF
            virt-count @ vTblTemp !
            vTblTemp cell+
            virt-count @ 0
            ?DO
                i vtable[] @REL over !REL
                cell+
                i vtable[] cell+ @REL over !REL
                cell+
            LOOP
            drop
         THEN
         r> to ^class
    THEN
    vTblTemp ^vtable !REL ;

:noname [ IS attach-class-vtable ] ( -- )
    virt-count @
    IF
        here
        virt-count dup @ \ S: body addr count
        dup , 0 \ S: body addr count 0
        ?DO \ S: body addr
            cell+ dup @REL ,REL
            cell+ dup @REL ,REL
        LOOP
        drop
        ^vtable !REL
     ELSE
        0 ^vtable !REL
     THEN ;
           =20

: in-vtable ( body^ -- pos true | false )
    virt-count @ 0
    ?DO
        i vtable[] cell+ @REL over =3D
        IF drop i TRUE unloop EXIT THEN
    LOOP
    drop FALSE ;

: append-to-vtable ( body^ -- n )
    \ later, we should use allocate/resize
    virt-count @
    dup MAX-VIRTUAL >=3D abort" virtual table overflow - see =
MAX-VIRTUAL"

    vtable[] cell+ !REL
    virt-count @
    dup 1+ virt-count ! ;

: CreateVirtual: ( <<method>> -- vn )
    Create here \ S: bod
    append-to-vtable \ S: vn
    dup 2* 1+ cells , \ S: byte-offset
                            \ offset in bytes to speed-up
    DOES> \ TODO: better optimisation
        @ ^vtable @REL + \ this is the virtual overhead
        @REL execute ;=20

\ ------------------------------------------------
\ Extra words - not defined in ANSI proposal
\ ------------------------------------------------

CLASS-WORDLIST SET-CURRENT

: VIRTUAL: ( <<name>> -- )
>IN @
    bl word find
    IF \ S: in^ xt
>body in-vtable
        IF
            nip \ S: vn
        ELSE
>IN !
            CreateVirtual: \ S: vn
        THEN
    ELSE \ S: in^ cstr
        drop >IN ! \ S: -
        CreateVirtual: \ S: vn
    THEN
    :noname swap \ S: xt vn
    vtable[] !REL ;
       =20

FORTH-WORDLIST SET-CURRENT

: >THIS ( ^object -- ^membase ) \ usage ' obj >this
>body cell+ ;

: >CLASS ( ^object -- ^class ) \ usage ' obj >class
>body @REL ;

: USER> ( ^class -- addr ) \ ' obj >class user> @
    [ 4 CELLS ] LITERAL + ;

: NEW ( ^class -- ^obj )
    dup SIZE> @ cell+
    allocate abort" memory allocation error"
    swap over !REL ;

: NEW[] ( count ^class -- ^obj )
    dup SIZE> @ rot * cell+
    allocate abort" memory allocation error"
    swap over !REL ;

\ FREE DROP can be used with object^ allocated with NEW

PRIVATE-WORDLIST SET-CURRENT

create methname 81 allot \ assume method-name maxlen =3D 80 chars

: execute-> ( ^obj caddr count -- )
    methname place
    ^class this 2>R
    dup @REL to ^class
    cell+ to this
    ^class AlsoClassSearchOrder
    methname find \ S: ^obj xt
    ResetClassSearchOrder
    0=3D abort" method not found"
    execute=20
    2R> to this to ^class ;

: execute->[] ( index ^obj caddr count -- )
    methname place \ S: index ^obj
    ^class this 2>R
    dup @REL to ^class
    cell+ swap ^size @ * + to this \ S: -
    ^class AlsoClassSearchOrder
    methname find \ S: ^obj xt
    ResetClassSearchOrder
    0=3D abort" method not found"
    execute=20
    2R> to this to ^class ;

FORTH-WORDLIST SET-CURRENT

\ runtime binding - slow

: -> ( <<method>> ^obj -- )
    state @
    IF
        bl parse postpone sliteral
        postpone execute->
    ELSE
        bl parse
        execute->
    THEN ;
        IMMEDIATE

: ->[] ( <<method>> index ^obj -- )
    state @
    IF
        bl parse postpone sliteral
        postpone execute->[]
    ELSE
        bl parse
        execute->[]
    THEN ;
        IMMEDIATE

: .CLASSINFO ( ^class -- )
    SaveSearchOrder
    cr 0 >r
    BEGIN
        dup body> >name count
        swap over cr r@ spaces type cr
        r@ spaces 0 ?DO [char] - emit LOOP
        dup wid> @ context !
        cr r@ spaces words cr
        parent> @rel ?dup 0=3D
        r> 3 + >r=20
    UNTIL
    r> drop
    RestoreSearchOrder ;

: SIZEOF ( ^class -- size )
    size> @ ;

ONLY FORTH ALSO DEFINITIONS

\ ------------------------------------------------
\ THE END
\ ------------------------------------------------

\ =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
\ BASIC CLASSES
\ =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

empty
REQUIRES CLASS09

Class cVar

    variable addr

    : @ ( -- val ) addr @ ;
    : ! ( val -- ) addr ! ;
    : ? ( -- ) addr ? ;
    : +! ( val -- ) addr +! ;
    : 0! ( -- ) 0 addr COMMON ! ;
    : inc ( -- ) 1 +! ;
    : dec ( -- ) -1 +! ;
    : neg ( -- ) @ negate ! ;
End

cVar SubClass cPtr

    cVar build Size

    : _?err ( -- ) abort" memory allocation error" ;

    : allocate ( size -- ) dup Size ! allocate _?err ! ;
    : resize ( size -- ) dup Size ! @ swap resize _?err ! ;
    : free ( -- ) Size 0! @ ?dup IF free _?err 0! THEN ;
End

cPtr SubClass cString

    cVar build _Len

    : _dozstr ( -- ) 0 @ _Len @ chars + C! ;

    : zComputeLen ( zstr -- len )
        0 swap
        BEGIN dup c@ WHILE
            char+
            swap 1+ swap
        REPEAT
        drop ;

    : GetLen ( -- len ) _Len @ ;
    : Type ( -- ) @ _Len @ Type ;
    : ? ( -- ) Type ;

    : Put ( addr len -- )
        _Len ! \ S: addr
        GetLen Size @ >=3D \ S: addr flag
        IF free GetLen 1+ allocate THEN
        @ GetLen move
        _dozstr ;

    : zPut ( zaddr -- ) dup zComputeLen Put ;

    : Concat ( addr len -- )
        dup GetLen + dup Size @ >=3D \ S: addr len size flag
        IF dup 1+ resize THEN \ S: addr len size
        dup _Len !
        over - @ + \ S: addr len ptr+
        swap move
        _dozstr ;

    : zConcat ( zaddr -- ) dup zComputeLen Concat ;

    : SetEmpty ( -- ) _Len 0! _dozstr ;

    : Get ( -- addr count ) @ _Len @ ;

    : [] ( index -- addr ) chars @ + ;

    : FindCharPos ( ch -- index true | false )
>R @ _Len @ 0
        ?DO
            i [] c@ r@ =3D
            IF
                r> drop i TRUE
                UNLOOP EXIT
            THEN
        LOOP
        r> drop FALSE ;

    : free ( -- ) SUPER free _Len 0! ;
End

Class cPoint

    Variable x
    Variable y

    VIRTUAL: NameOf c" cPoint" ;
    : .Name NameOf count type ;

    : @ ( -- x y ) x @ y @ ;
    : ! ( x y -- ) y ! x ! ;
    : ? ( -- ) x ? y ? ;
End

Class cRect

    cPoint build lt \ left-top
    cPoint build rb \ right-bottom

    : @ ( -- left top right bottom ) lt @ rb @ ;
    : ! ( left top right bottom -- ) rb ! lt ! ;
    : ? ( -- ) lt ? [CHAR] - emit 1 spaces =
rb ? ;
End

\ =3D=3D=3D=3D=3D=3D examples =3D=3D=3D=3D=3D=3D

cr
..( NEW immediate mode usage ) cr

cPoint NEW value pPt

1 2 pPt -> !
pPt -> ? cr
pPt -> .Name
cr

..( -> in a definition ) cr

: m1 pPt -> .Name 1 spaces pPt -> ? ;

m1 cr
8 9 pPt -> !
m1 cr
pPt free drop
cr

..( ->[] immediate mode ) cr

10 cPoint NEW[] value pPt

1 2 0 pPt ->[] !
0 pPt ->[] ? cr=20
3 4 1 pPt ->[] !
1 pPt ->[] ? cr
0 pPt ->[] .Name cr
1 pPt ->[] .Name cr
cr

..( ->[] in definition ) cr
: m2
    10 0
    ?DO \ write i i in pPt[i]
        i i i pPt ->[] !
    LOOP
    10 0
    ?DO \ display pPt[i]
        0 pPt ->[] .Name 1 spaces
        i pPt ->[] ?
        3 spaces
    LOOP ;

m2 cr
pPt free drop

\ =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
\ Wil Baden ANSI Class wordset proposal
\ =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

CLASS
    CLASS class
    Construct a class.
    A class is a defining word for a collection of future definitions.

SUBCLASS
    class SUBCLASS classname
    Construct an extension or specialization of a class.

VARIABLE WITHIN A CLASS
    VARIABLE membername
    Define a variable member of a class.

BUFFER: WITHIN A CLASS
    n CHARS BUFFER: membername
    n CELLS BUFFER: membername
    Define a data area member of a class.

CONSTANT WITHIN A CLASS
    n CONSTANT membername
    Define a constant member of a class.

: WITHIN A CLASS
    : membername ... ;
    Define a function member of a class.

; WITHIN A CLASS
    : membername ... ;
    Terminate the definition of a function member of a class.

END WITHIN A CLASS
    END
    Terminate the construction of a class.

BUILD
    class BUILD objectname
    Build object objectname as an instance of class .
    Objects are used object member .

COMMON WITHIN A CLASS
    COMMON forthword
    Compile forthword from standard dictionary.

SUPER WITHIN A CLASS
    SUPER member
    Compile a member, beginning lookup for it in the superclass.
    This disambiguates members with the same name.

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3DMy extension in the above =
wordset=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

VIRTUAL: WITHIN A CLASS
    VIRTUAL: method ... ;
    Define a virtual method. By default, method defined with : are=20
    no virtual. (see examples)

BUILD[]
    COUNT class BUILD[] objectname
    Build object array objectname.
    Objects are used object member.
    Example: 10 VAR BUILD[] var-array
    ------- 44 5 var-array ! ( store 44 in var-array[5] )

NEW
    class NEW
    Allocate object objectname as an instance of class, and return
    an object pointer. Later, FREE can be used to release the allocated
    memory. ( Probably better to garant portability with a RELEASE word =
)
    See ->

NEW[]
    COUNT class NEW[] value ptr
    Allocate object (0 based) array objectname as an instance of class,=20
    and return an object pointer.
    Later, FREE can be used to release the allocated memory.
    Example: variable va
    ------- 10 VAR NEW[] va !
                44 5 []->" va @" ! ( store 44 in va[5] )

    See []->

->
    ^obj -> method
    Used with object pointer allocated with NEW. Runtime binding (slow)
    Compile time: Compile "method" as a string literal.
    Run time: Set the class context to the ^obj-class context
                    Set the THIS context to the ^obj-data base
                    Find-execute "method"
                    Reset class/this context=20
   =20
    Example: VARIABLE v
    ------- Point NEW v !
                : X@ ( -- x ) =20
                    v @ -> GetX ;
    See NEW

->[]
    index ^obj -> method
    Used with object pointer allocated with NEW[]. Runtime binding =
(slow)
    Compile time: Compile "method" as a string literal.
    Run time: Set the class context to the ^obj-class context
                    Set the THIS context to the ^obj-data base +indexed =
offset
                    Find-execute "method"
                    Reset class/this context=20
   =20
    Example: VARIABLE v
    ------- 10 Point NEW[] v !
                : X[]@ ( i -- x[i] ) =20
                    v @ ->[] GetX ;
    See NEW

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3DOther unnececcary ? =
words=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

SIZEOF
    class SIZEOF
    Returns the class data size.

THIS
    THIS ( -- addr )
    PAD TO THIS
    The current object data base address. a VALUE.

>THIS
    ' obj >THIS ( xt -- membase )
    Convert XT object adress to the object base memory adress.

^CLASS
    This value return the context class body adress.

----------
From: talk_at_forth.com
Sent: mardi 2 f=E9vrier 1999 14:22
To: Members of SF Talk
Subject: re: - oof NEW NEW[] -> []->=20

Original sender: "Rick VanNorman" <rvn_at_forth.com>
>Original sender: ForthCAD <mail_at_forthcad.com>
>Charles,
>
>There is a bug, but is it Swift or me ?
>
>This test sequence don't work in SwiftForth:
>
>: eval" [char] " parse evaluate ; immediate
>: TEST eval" 9 . 8 . " ; \ don't display 9 8 - BUG ?

This is proper behavior of EVALUATE. Notice that the word TEST
is executable, and prints 9 and 8 when run. Evaluate acts on
the string given it in the current system context, either
compilation or interpretation. Here it was compiling, and
so EVALUATE _compiled_ "9 . 8 ." into the word TEST.

Rick

=20

.

>From mail_at_forthcad.com Sun Feb 7 10:13:08 1999
To: sftalk_at_forth.com
Message-Id: <m0000134_at_gerd.forthinc.com>
Subject: - oof 0.95 with test suite 1/3
From: ForthCAD <mail_at_forthcad.com>
Date: Sun, 7 Feb 1999 10:13:08 -0800

This message to cut in 2 files:
  - CLASS.F
  - BASIC-CLASSES.F

\ ------------------------------------------------
\ ------------------------------------------------
\ CLASS.F
\ Version 0.95 - 07/02/1999
\ Author: Charles Melice
\ MAIL: mail_at_forthcad.com
\ WEB: www.forthcad.com
\ ------------------------------------------------
\ ------------------------------------------------

ONLY FORTH ALSO DEFINITIONS DECIMAL
\ EMPTY

\ ------------------------------------------------
\ TO DEFINE IF MISSING
\ ------------------------------------------------

\ : @REL POSTPONE @ ; IMMEDIATE
\ : !REL POSTPONE ! ; IMMEDIATE
\ : ,REL POSTPONE , ; IMMEDIATE

\ ------------------------------------------------
\ WORDLISTS ENCAPSULATION
\ ------------------------------------------------

WORDLIST CONSTANT CLASS-WORDLIST

CLASS-WORDLIST SET-CURRENT

WORDLIST DUP CONSTANT PRIVATE-WORDLIST

FORTH-WORDLIST SWAP CLASS-WORDLIST 3 SET-ORDER

\ ------------------------------------------------
\ USER VARS - How to use this !!!!
\ ------------------------------------------------

CLASS-WORDLIST SET-CURRENT
(
#USER
CELL +USER ^THIS \ seek the object-data base
CELL +USER ^CLASS \ seek the in-context class
TO #USER
)
VARIABLE ^THIS
VARIABLE ^CLASS

\ ------------------------------------------------
\ DIVERS
\ ------------------------------------------------

PRIVATE-WORDLIST SET-CURRENT

CREATE ^PREV-ORDER 33 CELLS ALLOT
0 VALUE PREV-CURRENT

\ used later to define VIRTUAL:
DEFER attach-class-vtable
DEFER inherit-to-vtemp

: WID> ( class -- addr ) ; IMMEDIATE
: PARENT> ( class -- addr ) CELL+ ;
: SIZE> ( class -- addr ) CELL+ CELL+ ;
: VTABLE> ( class -- addr ) [ 3 CELLS ] LITERAL + ;

: ^SIZE ( -- addr ) ^CLASS @ SIZE> ;
: ^VTABLE ( -- addr ) ^CLASS @ VTABLE> ;
: ^PARENT ( -- addr ) ^CLASS @ CELL+ ;

: SaveSearchOrder ( -- )
    get-order dup \ s: widn .. wid1 n n
    ^prev-order ! \ s: widn .. wid1 n
    ^prev-order over cells + \ s: widn .. wid1 n addrmax
    swap 0 \ s: widn .. wid1 addrmax n 0
    ?DO dup >R ! R> cell- LOOP
    drop ;

: RestoreSearchOrder ( -- )
    only
    ^prev-order @ 1+ 1 \ s: n 0
    ?DO \ s: -
        i cells ^prev-order +
        @ context ! also
    LOOP
    previous ;

: AlsoClassSearchOrder ( ^class -- )
    dup parent> @rel ?dup \ have a parent ?
    IF RECURSE THEN \ yes -> SetParentClassSearchOrder
    also @ context ! ;

: SetClassSearchOrder ( -- )
    only forth
    also class-wordlist context !
    ^CLASS @ AlsoClassSearchOrder ;

: ResetClassSearchOrder ( -- )
    ^CLASS @
    BEGIN \ s: -
        previous
        PARENT> @REL
        ?dup 0=
    UNTIL ;

: ClassView ( ^CLASS -- )
    ^CLASS ! SetClassSearchOrder ;

\ ------------------------------------------------
\ CLASS DEFINITION
\ ------------------------------------------------

FORTH-WORDLIST SET-CURRENT

: SUBCLASS ( <<name>> ^parent -- ) \ replace VOCABULARY
    wordlist
    create here ^CLASS ! \ S: ^parent ^wid
    , \ S: ^parent
    dup ,rel \ S: ^parent
    dup IF size> @ THEN , \ S: - PFA: <wid><parent><size>
    0 ,REL \ vtable^
    SaveSearchOrder
    get-current to prev-current
    SetClassSearchOrder
    ^CLASS @ wid> @ set-current \ definitions
    inherit-to-vtemp
    DOES> ; ( -- ^CLASS )

: CLASS ( <<name>> -- )
    0 SUBCLASS ;

CLASS-WORDLIST SET-CURRENT

: END ( -- )
    attach-class-vtable
    RestoreSearchOrder
    prev-current set-current ;

\ ------------------------------------------------
\ DATA DEFINITION
\ ------------------------------------------------

CLASS-WORDLIST SET-CURRENT

: BUFFER: ( <<name>> size -- )
    create
    ^size @ ,
    ^size +!
    DOES> ( body -- offset+THIS )
        @ ^THIS @ + ;

: VARIABLE ( <<name>> -- ) cell BUFFER: ;

\ ------------------------------------------------
\ SPECIAL WORDLIST LOOKUP
\ ------------------------------------------------

PRIVATE-WORDLIST SET-CURRENT

: exe-newclass ( xt class -- )
    ^CLASS @ >R ^CLASS !
    execute
    R> ^CLASS ! ;

CLASS-WORDLIST SET-CURRENT

: SUPER ( <<name>> -- )
    ^CLASS @ cell+ @REL
    dup 0= abort" class have no parent"
    previous
    bl word find 0=
    IF
        END
        TRUE abort" method not found"
    THEN \ S: class xt
    also ^CLASS @ wid> @ context !
    swap \ S: xt class
    state @
    IF
        postpone 2literal \ TODO: optimize when no virtual:
        postpone exe-newclass
    ELSE
        exe-newclass
    THEN ;
          IMMEDIATE

: COMMON ( <<name>> -- )
    RestoreSearchOrder
    '
    state @
    IF compile, ELSE execute THEN
    SetClassSearchOrder ;
                         IMMEDIATE

\ ------------------------------------------------
\ CLASS-OBJECTS INSTANCE
\ ------------------------------------------------

PRIVATE-WORDLIST SET-CURRENT

\ TODO: Possibles optimisations:
\ case...
\ A - data exist - size > 0
\ B - data exist with offset
\ C - virtual method exist vtable <> 0
\
\ A B C TODO:
\ -- -- -- ---------------
\ 0 0 0 compile,
\ 0 0 1 save-class compile, restore
\ 0 1 0 -
\ 0 1 1 -
\ 1 0 0 compile,
\ 1 0 1 save-class compile, restore
\ 1 1 0 save-this +to compile, restore
\ 1 1 1 save-class-this compile, restore
\

: execute-ivar ( ^obj xt -- ) \ not optimal
    ^CLASS @ ^THIS @ 2>R
    swap
    dup @REL ^CLASS ! \ must because virtuals
    cell+ @ ^THIS +!
    execute
    2R> ^THIS ! ^CLASS ! ;

: execute-ivar[] ( index ^obj xt -- ) \ not optimal
    ^CLASS @ ^THIS @ 2>R
    swap
    dup @REL ^CLASS ! \ must because virtuals
    cell+ @ \ S: index xt offset
    rot ^size @ * + \ S: xt offset+index*size
    ^THIS +!
    execute
    2R> ^THIS ! ^CLASS ! ;

: execute-iobj ( ^obj xt -- ) \ not optimal
    ^CLASS @ ^THIS @ 2>R
    swap
    dup @REL ^CLASS ! \ must because virtuals
    cell+ ^THIS !
    execute
    2R> ^THIS ! ^CLASS ! ;

: execute-iobj[] ( index ^obj xt -- )
    ^CLASS @ ^THIS @ 2>R
    swap
    dup @REL ^CLASS ! \ must because virtuals
    cell+ rot \ S: xt ^base index
    ^size @ * + \ S: xt offset
    ^THIS !
    execute
    2R> ^THIS ! ^CLASS ! ;

: INTERPRET-OBJECT-METHOD ( ^obj xt-exe-xx <<method>> -- )
>R
    ^CLASS @ >R \ save prev context
    dup @REL \ S: ^obj CLASS
    ClassView \ S: ^obj
    bl word find \ S: ^obj xt
    R> ClassView
    0= abort" method not found"
    STATE @
    IF
        postpone 2literal
        R> compile,
    ELSE
        ResetClassSearchOrder
        R> execute
    THEN ;

CLASS-WORDLIST SET-CURRENT

: BUILD ( <<objname>> ^CLASS -- )
    create
    dup ,REL ^size @ , \ PFA: <OBJCLASS><OFFSET>
    size> @ ^size +! \ S: -
    IMMEDIATE
    DOES> ( ^obj -- )
        ['] execute-ivar
        INTERPRET-OBJECT-METHOD ;

: BUILD[] ( <<objname>> count ^class -- )
    create
    dup ,REL ^size @ , \ PFA: <OBJCLASS><OFFSET>
    size> @ * ^size +! \ S: -
    IMMEDIATE
    DOES> ( index ^obj -- )
        ['] execute-ivar[]
        INTERPRET-OBJECT-METHOD ;

FORTH-WORDLIST SET-CURRENT

: BUILD ( <<objname>> ^class -- )
    create
    dup ,rel
    here swap \ S: here ^class
    size> @ dup allot \ PFA: <CLASS><..DATA..>
    0 fill \ proposal is to initialize
    IMMEDIATE
    DOES>
        SaveSearchOrder
        ['] execute-iobj
        INTERPRET-OBJECT-METHOD
        RestoreSearchOrder ;

: BUILD[] ( <<objname>> count ^class -- )
    create
    dup ,rel \ S: count ^class
    size> @ * \ S: count*size
    here swap \ S: here count*size
    dup allot \ PFA: <CLASS><..DATA..>
    0 fill \ proposal is to initialize
    IMMEDIATE
    DOES> ( index ^obj -- )
        SaveSearchOrder
        ['] execute-iobj[]
        INTERPRET-OBJECT-METHOD
        RestoreSearchOrder ;

\ ------------------------------------------------
\ (optional) VIRTUAL: ( <<name>> -- )
\ define a virtual method
\ ------------------------------------------------

PRIVATE-WORDLIST SET-CURRENT

100 constant MAX-VIRTUAL

create vTblTemp 0 , MAX-VIRTUAL 2* cells allot

: virt-count ( -- addr )
    ^VTABLE @REL ;

: vtable[] ( n -- addr )
    2* 1+ cells virt-count + ;

:noname [ IS inherit-to-vtemp ] ( -- )
    0 vTblTemp !
    ^parent @REL
    IF
        ^CLASS @ >R
        ^parent @REL ^CLASS !
        ^vtable @REL
        IF
            virt-count @ vTblTemp !
            vTblTemp cell+
            virt-count @ 0
            ?DO
                i vtable[] @REL over !REL
                cell+
                i vtable[] cell+ @REL over !REL
                cell+
            LOOP
            drop
         THEN
         R> ^CLASS !
    THEN
    vTblTemp ^vtable !REL ;

:noname [ IS attach-class-vtable ] ( -- )
    virt-count @
    IF
        here
        virt-count dup @ \ S: body addr count
        dup , 0 \ S: body addr count 0
        ?DO \ S: body addr
            cell+ dup @REL ,REL
            cell+ dup @REL ,REL
        LOOP
        drop
        ^vtable !REL
     ELSE
        0 ^vtable !REL
     THEN ;

: in-vtable ( body^ -- pos true | false )
    virt-count @ 0
    ?DO
        i vtable[] cell+ @REL over =
        IF drop i TRUE unloop EXIT THEN
    LOOP
    drop FALSE ;

: append-to-vtable ( body^ -- n )
    \ later, we should use allocate/resize
    virt-count @
    dup MAX-VIRTUAL >= abort" virtual table overflow - see MAX-VIRTUAL"

    vtable[] cell+ !REL
    virt-count @
    dup 1+ virt-count ! ;

: CreateVirtual: ( <<method>> -- vn )
    Create here \ S: bod
    append-to-vtable \ S: vn
    dup 2* 1+ cells , \ S: byte-offset
                            \ offset in bytes to speed-up
    DOES> \ TODO: better optimisation
        @ ^vtable @REL + \ this is the virtual overhead
        @REL execute ;

\ ------------------------------------------------
\ Extra words - not defined in ANSI proposal
\ ------------------------------------------------

CLASS-WORDLIST SET-CURRENT

: VIRTUAL: ( <<name>> -- )
>IN @
    bl word find
    IF \ S: in^ xt
>body in-vtable
        IF
            nip \ S: vn
        ELSE
>IN !
            CreateVirtual: \ S: vn
        THEN
    ELSE \ S: in^ cstr
        drop >IN ! \ S: -
        CreateVirtual: \ S: vn
    THEN
    :noname swap \ S: xt vn
    vtable[] !REL ;

FORTH-WORDLIST SET-CURRENT

: THIS ( -- mem-base ) ^THIS @ ;

: >THIS ( ^object -- ^membase ) \ usage ' obj >this
>body cell+ ;

: >CLASS ( ^object -- class ) \ usage ' obj >class
>body @REL ;

: USER> ( ^class -- addr ) \ ' obj >class user> @
    [ 4 CELLS ] LITERAL + ;

: NEW ( ^class -- ^obj )
    dup SIZE> @ cell+
    allocate abort" memory allocation error"
    swap over !REL ;

: NEW[] ( count ^class -- ^obj )
    dup SIZE> @ rot * cell+
    allocate abort" memory allocation error"
    swap over !REL ;

\ FREE DROP can be used with object^ allocated with NEW

PRIVATE-WORDLIST SET-CURRENT

create methname 81 allot \ assume method-name maxlen = 80 chars

: execute-> ( ^obj caddr count -- )
    methname place
    ^CLASS @ THIS @ 2>R
    dup @REL ^CLASS !
    cell+ THIS !
    ^CLASS @ AlsoClassSearchOrder
    methname find \ S: ^obj xt
    ResetClassSearchOrder
    0= abort" method not found"
    execute
    2R> THIS ! ^CLASS ! ;

: execute->[] ( index ^obj caddr count -- )
    methname place \ S: index ^obj
    ^CLASS @ THIS @ 2>R
    dup @REL ^CLASS !
    cell+ swap ^size @ * + THIS ! \ S: -
    ^CLASS @ AlsoClassSearchOrder
    methname find \ S: ^obj xt
    ResetClassSearchOrder
    0= abort" method not found"
    execute
    2R> THIS ! ^CLASS ! ;

FORTH-WORDLIST SET-CURRENT

\ runtime binding - slow

: LATER ( ^obj <<method>> -- )
    state @
    IF
        bl parse postpone sliteral
        postpone execute->
    ELSE
        bl parse
        execute->
    THEN ;
        IMMEDIATE

: LATER[] ( <<method>> index ^obj -- )
    state @
    IF
        bl parse postpone sliteral
        postpone execute->[]
    ELSE
        bl parse
        execute->[]
    THEN ;
        IMMEDIATE

\ static binding - fast

PRIVATE-WORDLIST SET-CURRENT

: M' ( ^class <<method>> -- xt )
    SaveSearchOrder
    only AlsoClassSearchOrder
    bl word find
    RestoreSearchOrder
    0= abort" method not found" ;

: CM' ( ^class <<method>> -- xt )
    only AlsoClassSearchOrder
    bl word find
    SetClassSearchOrder
    0= abort" method not found" ;

CLASS-WORDLIST SET-CURRENT

\ TODO: test - nothing tested

: -> ( ^class <<method>> -- )
    CM'
    postpone literal
    postpone execute-ivar ;
                            IMMEDIATE

: ->[] ( index ^class <<method>> -- )
    CM'
    postpone literal
    postpone execute-ivar[] ;
                            IMMEDIATE

FORTH-WORDLIST SET-CURRENT

\ TODO: test - a few tested

: -> ( ^class <<method>> -- )
    M'
    postpone literal
    postpone execute-iobj ;
                            IMMEDIATE

: ->[] ( index ^class <<method>> -- )
    M'
    postpone literal
    postpone execute-iobj[] ;
                            IMMEDIATE

: .CLASSINFO ( ^class -- )
    context @ >R
    cr 0 >R
    BEGIN \ S: ^class
        dup body> >name count
        swap over cr r@ spaces type cr
        r@ spaces 0 ?DO [char] - emit LOOP
        dup wid> @ context !
        cr r@ spaces words cr
        parent> @rel ?dup 0=
        R> 3 + >R
    UNTIL
    R> drop
    R> context ! ;

: SIZEOF ( ^class -- size )
    size> @ ;

ONLY FORTH ALSO DEFINITIONS

\ -- The End --

\ ------------------------------------------------
\ ------------------------------------------------
\ BASIC-CLASSES.F
\ Author: Charles Melice
\ MAIL: mail_at_forthcad.com
\ ------------------------------------------------
\ ------------------------------------------------

ONLY FORTH ALSO DEFINITIONS DECIMAL
EMPTY
REQUIRES CLASS

1 IMPORT: MessageBeep ( 0 )

: beep 0 MessageBeep drop ;

Class cVar
    variable addr

    : @ ( -- val ) addr @ ;
    : ! ( val -- ) addr ! ;
    : ? ( -- ) addr ? ;
    : +! ( val -- ) addr +! ;
    : 0! ( -- ) 0 addr COMMON ! ;
    : inc ( -- ) 1 +!