home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Millennium Time Capsule
/
AC2000.BIN
/
disks
/
hbasic_1
/
ooplib
/
ooplib.txt
< prev
next >
Wrap
Text File
|
1994-06-12
|
15KB
|
421 lines
OOPLIB v0.01
HiSoft Basic Object Oriented Programming Library
©1994, Data Uncertain Software - the authors of MODLIB.
Written by Craig Graham
Introduction
=============
OOPLIB provides support for dynamic class & object manipulation from HiSoft Basic2.
The facility is very limited at the moment, but will improve rapidly.
OOPLIB runs on any atari machine up to and including the Falcon, and has a very
minimal code overhead (<2Kbytes for the library code).
Currently, the features implemented are:
o Class declaration
- Attributes are specified in the class declaration
- Only long int (32bit) attributes are supported at the moment.
- Any number of attributes for a given class.
o Object instatiation
- Create an object of a class
o Object deletion
- Get rid of an object that you are finished with
o Attribute manipulation
- You can set the values of an object's attributes.
- You can read those values again.
o Services
- These are still under developement, so at the monoment there aren't any,
I have however, included the syntax that I intend to use for them here in
readiness.
If this seems a little limiting, take a look at some of the example code to see
the possible applications of OOPLIB as it stands.
Classes and objects are declared & created at run time, so a class could be
created 'on-the-fly' by an application (eg. a database program could create
a record class with attributes for each record, and the class could be defined
by the user whilst the program is running depending of what file is loaded).
INSTALLING OOPLIB
==================
You need all the library building stuff from the HiSoft Basic distribution
discs, put it all in a directory along with the file oop.bin, then:
buildlib.ttp gemvdi gemaes gemdos xbios bios menu oop
on a command line (I use mupfel from the gemini distribution).
This will create a new HBASIC.LIB file, which you can copy into your HiSoft
WORKING directory.....don't overwrite your original HiSoft disc's - that may be
a bad move :)
USING OOPLIB
==============
OOPLIB is used in the same way as the aes,vdi and xbios libraries, ie. you have
a LIBRARY statement at the start of your program. The name of the library is
OOP:
eg.
LIBRARY "OOP"
You must also include the OOPLIB header file OOPLIB.BH at the start of your
program in order to use services. This can be omitted if you are only using
the data grouping (attributes) and ignoring the service facilities.
CREATING CLASSES
==================
Classes are created using the following syntax:
class "<class name>","<attribute list>", "<service list>"
Where <class name> is a name for the class :)
and <attribute list> is a comma seperated list of attribute names for the class.
eg.
class "person","age,weight,height", ""
would declare a class called person, where each person has attributes age,weight
and height which may have values assigned to them.
CREATING OBJECTS
==================
You create an object (an instance of a class) using the following syntax:
p&=object&("<class name>")
The function object&() returns a pointer to an object of type <class name>.
eg.
craig&=object&("person")
would create an object of type person. The variable craig& would be a pointer to
the object.
DELETING OBJECTS
==================
An object can be disposed of when you don't need it anymore, returning the
storage it was using to the system. The syntax for this is:
delete_object <object>&
where <object>& is a pointer to the object which you want to delete (as returned
by the object&() call).
eg.
craig&=object&("person") 'create an object of class person
delete_object craig& 'get rid of the object again.
SETTING ATTRIBUTES
====================
Once you have created an object, you can set the values of it's attributes using
the following syntax:
o_iset <object>&, "<attribute name>", <value>
Where <object>& is a pointer to an object (as returned by the object&() call).
<attribute name> is the name of an attribute (one of the ones you specified when
you created the class).
<value> is an integer or long_integer value.
eg.
craig&=object&("person")
o_iset craig&,"age", 22
would set the age attribute of the object pointed to by craig& to be 22
READING ATTRIBUTES
====================
The value of an objects attributes may be read using the following syntax:
v=o_iget&(<object>&, "<attribute name>")
Where <object>& is a pointer to an object (as returned by the object&() call,
and previously used in o_iset).
<attribute name> is the name of an attribute (one of the ones you specified when
you created the class).
eg.
craigs_age=o_iget&(craig&,"age")
would read the age attribute of the object pointed to by craig& (following on
from the previous example, this would return the value 22).
ASSIGMENTS
============
It is important to note that the assignment '=' in HBASIC does not have the same
meaning when dealing with objects.
eg.
a$="person"
b$=a$
Both a$ and b$ are strings with the value of "person". Changing one string will
not affect the other at all, as the assignment operation made a copy of the
string. This is not what happens with objects.
a&=object("person")
b&=a&
Now a& and b& both refer to an object of class person, but in this case, they
both refer to the SAME object. So changing a attribute of b& will change the
same attribute of a&. Deleting one of them will dispose of the object, and leave
them both as invalid pointers, so care must be taken when performing this type
of manipulation.
Also, note that
a&=object("person") 'create one object, pointed to by a&
a&=object("person") 'create another object, and use a& to point to
'this one instead.
will create two objects, and the first one will continue to exist, even though
you can no longer access it via a basic variable. This fact is useful for
creating linked lists, where you only need to have a pointer to the start of the
list, and each element has a 'nextitem' attribute which points to the next
element of the list.
Objects with common attributes can be processed by the same routine
eg. two different types of linked list, both of which have a 'nextitem' attribute
which points to the next element in the list. The same routine could be used to
add a new element to the start of the list.
LIBRARY "OOP"
class "list1","value1,age,nextitem" ,""
class "list2","zap,pow,kerblam,nextitem,spam" ,""
list1_start&=object&("list1")
list2_start&=object&("list2")
e1&=object&("list1")
add_element e1&,list1_start&
e2&=object&("list2")
add_element e1&,list2_start& 'notice that the same routine is called to
'add an element to a different class.
END
SUB add_element(element&, list_start&)
o_iset element&, "nextitem", list_start&
list_start&=element&
END SUB
The above example would work for any class which has a nextitem attribute (in
fact you could have mixed class linked lists as well!!!).
SERVICES
==========
1) SPECIFYING SERVICES
-----------------------
Services are operations associated with an object - conceptually a service is
part of an object, and is stored together with it.
Services for a type are specified as follows:
class "<classname>","<attrib list>", "<service list>"
service "<classname>","<service name>", service_address&
Note that a service line is required for each service in a class.
EG.
class "list1","value1,age,nextitem" ,"addnew"
service "add", VARPTRS(add_element)
This example makes adding a new element to the list class from the previous
example, into a service.
2) CALLING SERVICES
--------------------
A service of a specific object is called using the syntax:
use object&, "<service name>"
EG.
a&=object("list1")
use a&,"addnew"
3) WRITING SERVICES
--------------------
Inside a service routine, you have access to one object by default. The name of
this object is this&. this& is an alias for whichever object the service routine
is working for. For example, in the above example, inside the "addnew" service
call, this& would be an alias for a&, and would be of class "list1".
EG.
LIBRARY "OOP" 'use the OOP library
REM $include OOPLIB.BH 'include the OOPLIB services
' header
class "list","value1,age,nextitem" ,"addnew" 'define the list class
service "list","addnew", VARPTRS(add_element) 'specify the service
mylist&=object&("list") 'create a list object
use mylist&,"addnew" 'use the addnew service to
add another element onto the
list
END
SUB add_element 'The addnew service routine.
STATIC n&
n&=object("list") 'create a new list object
o_iset n&,"nextitem",o_iget&(this&,"nextitem") 'tack the old list onto
the new list -notice the
use of this& to
refferance the current
object.
o_iset this&, "nextitem", n& 'stick the new list onto
the head of the old list.
END SUB
A good example of the use of this would be storing vector graphic objects.
You could have services which performed display, rotation, moving, warping, etc.
FUTURES & TECHNICAL
=====================
This section lays out the eventual aims of OOPLIB, and the direction I am
currently going in, and how I get there.
This is the current state of play: (example code coming up)
=============================================================================
DEFINT a-z
LIBRARY "OOP"
declare_objects 100 'initial number of objects, grows dynamicly but
'better to set a bigish number here as each
'dynamic grow (50 objects) eats into the OS pool.
'Define a linked list class (the simplest dynamic structure you can get).
' each object has a number and a pointer to the next element in the list.
class "linked_list", "next, number", ""
a&=object("linked_list") 'instance of the linked list object
o_iset a&,"number",20 'Set the value of an object attribute.
'o_vset = object value set
b&=object("linked_list") 'another instance of a linked list element
o_iset b&,"number",30
o_iset a&,"next",b& 'link object a to object b
value_b=o_iget(o_vget(a&,"next"),"value")
print value_b
===============================================================================
Ok, not a particularly thrilling example, but you get the idea. At the moment
all that I really have is a dynamic implementation of pointers to records (PASCAL) or
pointers to structures (C). This is more reminiscent of the classes in smalltalk
which are dynamic as well.
This does allow a greater degree of expression than HB does normally, but I'd
like to add methods to the objects as well - but haven't got a clue how to call
a HB function from assembly. I could use the syntax:
service "class name", "service name", varptrs(sub name), "parameters list"
but this presents some problems with parameter passing. For the service to
address the object is fairly straight forward (set a global 'this&' with the
current object like in c++), but passing parameters to perform the equivalent of
a c++
object.service(parameter);
is giving me a headache......what do you think ?
INTERNALS
===========
All the OOP library code is in assembler, and doesn't do auto garbage collect to
speed things up. When an object is disposed of (delete_object a&) it leaves a
hole in the object store - a count of store usage & remaining is kept & the
garbage is taken out when storage runs out, or is forced explicitly using
'flush_objects'.
The objects are accessed via an indirection table:
BASIC OBJECT OBJECT
VARIABLE TABLE STORE
+--------+ +----------+ +-------+
| | | | | |
| a& |---->| object1& |->| O1 |
| | +-->| | | |
+--------+ | +----------+ +-------+
| | | | | | |
| b& |-+ | object2& |->| O2 |
| | +->| | | |
+--------+ | +----------+ +-------+
| | | | | | |
| c& |-++ | object3& | | O3 |
| | | | | |
+--------+ +----------+ +-------+ etc
In the example above, a& and b& both reffer to the same object. The indirection
table allows objects to move in memory transparently to the HB program using
them as the OBJECT TABLE will handle all that.
IDEALS
=======
Ideally, the eventual aim would be to provide windows style complex objects as
well by identifying the object type with an application or accessory which can
provide the services for them.
eg. Metafile object display
class "metafile", "x,y,w,h,image", "display"
service "metafile","display:external[kadinsky.app]","x,y,w,h"
would associate the display service for an object class "metafile" with
the program kandinsky.app so if you wanted to display a metafile at a location,
(quick switch to c++ syntax)
// mymeta is a metafile object.
mymeta.display(10,10,200,200);
This would call kandinsky, passing it either the metafile object or a pointer to
it, and requesting that it displayed it at (10,10) with a size of (200,200).
I am about to field a proposal on the NET & the GEM Interface mailing list about
agreeing a standard for this type of request (either derived from gemini av, or
the more advanced Xacc2 standard). Anyway, that's outside of what I originally
began talking about....views on the HB OOP library first, specificly a syntax
for specifying services (of course, a better idea would be for HiSoft to include
composite types, pointers & objects as part of the main HB language).
Regards.
Craig Graham
(still using HB 2.0)
craig.graham@newcastle.ac.uk