There are two sets of documentation for the ClassVFX system. There is a chapter in the main VFX Forth manual, and there is a full PDF manual in the Manual subdirectory of Lib\OOP\ClassVFX\.
The source code is in the directory Lib\OOP\ClassVFX. The file MakeClassVfx.bld is compiled to produce the production version of the code. TestClassVfx.fth contains test code.
ClassVFX was developed over a number of years in collaboration with Construction Computer Software of Cape Town, South Africa. We gratefully acknowledge their collaboration and permission to release it. ClassVFX is heavily used in their construction industry planning software, which is one of the largest Forth applications ever written. Modifications to ClassVFX will only be released after the agreement of CCS.
ClassVFX is a halfway house between a full object oriented system and an intelligent structures system. Types, or classes, can be defined with single inheritance. Method names have to be predefined using
OPERATOR: <method-name>
Field, or data member, names are private, but are accessible using a dot notation. There are no equivalents of SUPER and SELF. There is no late binding.
In this documentation types and classes are synonymous. Objects are instances of a type. Objects have a default action if no method is specified. Usually the default action is to fetch the contents of the object, but in a few cases the default action is to return an address.
Types/Classes can have both class and instance methods. The default method for a type is to create an instance. If a type is used inside a colon definition a local variable version is created and destroyed at run time.
Operators, or methods, must be declared as above before use.
TYPE: definitions may be used in four ways:
Point.x or x
Point: MyPoint
|
At runtime, the method operates on the address of the data. Because of this, a method which requires the address of the instance structure has to be marked by the word STRUCTURE-METHOD which causes the compiler to generate the address of the instance structure, not the type structure.
ClassVFX allows both CLASS and INSTance methods to be defined for a type. INSTance methods, the default, operate on the address of the data item. CLASS methods operate on the address of the type data structure. As described above, STRUCTURE-METHODs operate on the instance data structure.
Single inheritance can be defined using SUPERCLASS <type> or INHERITS <type> before any field or method is defined.
|
At run-time, methods are provided with the address of the required data. CLASS/TYPE methods receive the address of the TYPE/CLASS data structure, INSTance methods receive the address of the data item. INSTance methods that require the address of the instance data structure must be marked by STRUCTURE-METHOD. Methods may be defined as nameless words:
:M <method-name> ... ;M
or as the action of a method:
MRUNS <method-name> <action-name>
The code below is taken from the definition of the default type.
|
To use the nested field system, the Forth system has been modified to accept compound names in which the elements of the structure are separated by the `.' character. This feature is enabled and disabled by the words +STRUCTURES and -STRUCTURES.
|
Note that not all predefined types support all methods.
|
|
TYPE: definitions, fields, objects and so on all use a common data structure that is generated by the defining words.
These structures are associated with a word (the address provider) that can provide the starting address of the structure implementation. By supplying the cfa of NOOP, no address is provided, and so the structure is purely a template. For templates, address provider = 0 or NOOP, an offset may also be defined. NOOP and 0 are the default address provider and offset of templates. )
A similar structure is used for instances of a TYPE:. These are created by the word MAKE-INST.
The following structure is created by TYPE:
|
The following structure is created by MAKE-INST
|
When an instance is defined inside a colon definition, an uninitialised local variable/array is built. Several instances can be built. Normally the size of all local variables is rounded up to a cell boundary by the compiler
: :M \ struct -- struct ; :M <operator> <actions ...> ;M
defines the start of a method. The method/operator name must
follow.
: ;M \ struct -- struct ; SFP012
marks the end of a method definition.
: MRUNS \ struct -- struct ; MRUNS <operator> <actions> ;M
Defines a method which runs a previously defined word.
: CREATE-INST \ "<name>" -- ; -- addr
From VFX Forth v4.4, this is a synonym for CREATE.
When compiling on previous VFX versions instances needed to
be immediate.
: make-inst \ class -- ; i*x -- j*y ; build instance of type
Builds an instance of a TYPE:. This word has serious
carnal knowledge of the internal workings of VFX Forth.
Don't call us for help!
create type-template \ -- addr
The type chain from which others are derived.
CREATE ptr-template \ -- addr
The ptr chain from which others are derived.
: type:-runtime \ type-struct --
The run-time action of children of TYPE:.
: CURR-TYPE-SIZE \ -- u
Use between TYPE: <name> and END-TYPE to return the current
size of the type.
: TypeChildComp, \ xt --
Compile a child of TYPE:.
: type: \ -- struct ; --
Start a new TYPE: definition.
: PTR: \ -- struct ; --
Make a new structure defining word.
: end-type \ struct --
Finish off a TYPE: definition
: EXTEND-TYPE \ "<type>" -- struct ; EXTEND-TYPE <type> ... END-TYPE
Extend the given TYPE: definition.
: SUPERCLASS \ struct "<type>" -- struct
Use this inside a TYPE: definition before defining any
data or methods. The current type will inherit the data and
methods of the superclass.
: INHERITS \ struct "type" -- struct
A synonym for SUPERCLASS.
: provider: \ struct "name" -- struct ; <name> is address provider
Sets a different address provider.
: with: \ -- ; WITH: <some-provider> LINE: <myline>
Used before declaring an instance to override the default address
provider.
: SKIPPED \ struct size -- struct
Increase overall size of struct by size. SKIPPED can
be used to jump over items from a previous instance.
: OFFSET: \ struct offset -- struct
Define the offset of a TYPE: as starting at a value
other than zero. Must be used before any data is defined.
: TypeCast: \ -- ; TYPECAST: <inst> <type>
Forces a previously defined instance to be a pointer to a type/class.
SYNONYM PointsTo: TypeCast: \ -- ; synonym for TYPECAST:
Forces a previously defined instance to be a pointer to a type/class.
: type-self \ -- type
Used in TYPE: <name> ... END-TYPE to refer to the type/class
being defined.
: EXECUTE-MEMBER-METHOD \ struct-inst member-inst methodid ---
Attempt to execute method for inst. Return true if successful.
: EXECUTE-PTR-MEMBER-METHOD \ member-inst methodid ---
Attempt to execute method for inst. Return true if successful.
: EXECUTE-MEMBERS \ inst method --
Apply the given method to all members of the instance of a type/class.
: TWIST-STRUCTURE \ inst --
Twist structure method
: INIT-STRUCTURE \ inst --
Init structure method
In order to deal with structures and fields without having to backtrack the input stream or the execution order, an additional stage is added to the Forth parser to allow phrases of the forms:
inst.field
inst.field.field
type.field
type.field.field
to be parsed, where each item is separated by a dot character. The first item must be an instance of a type or a type. If it is an instance, the address is provided, otherwise the base address is assumed to be on the stack. Any items between the first and last item add their offsets to the address, and the last item performs the usual operation of the field as defined by an operator. For example:
|
We might define a line as joining two points:
|
: +structures runword \ --
Switch on the structure compiler.
: -structures runword \ --
Switch off the structure compiler.