PDA

View Full Version : Further Developments in Asmosphere III



Charles Pegge
27-08-2008, 12:08
Built in Object Oriented Programming Model

Unlike previous models this does not rely on user defined macros. It uses virtual tables and pointers in a similar manner to COM. OOP is built into the Asmosphere preprocessor, taking care of all the tricky bits.

This model also supports multiple inheritance - ie a class can have several ancestors.

The extra notation required is minimal. In fact the words class and object are not used at all. The system is an extension of type.

To declare a class, the type statement is divided into 2 parts: The first part contains methods, inherited structures and class static members. The second part contains the set of properties assigned to each object, (inherited properties are automatically appended)

This is a class defined in a single line: ! denotes a method. / divides the two parts of the class, and inherited types must be followed by a comma as usual.

type classAB classA, classB, 4 methodA! 4 methodB! 4 MethodC! membA / 4 vft 4 va 4 vb 4 vc

this is immediately followed by a scoped class builder and a set of methods

(
build classAB
exit
var ClassAB this

methodA:
...
ret 4

methodB:
...
ret 4

...

)


to create an object:

var ClassAB myObject
myObject.vft=&ClassAB_table


which gives us an empty object except for its virtual table pointer, which allows the object to call any of its methods, (including inherited methods)


edx=myObject.methodA ...

Because all the methods are defined inside the brackets, they are not visible to the rest of the program.

Below is a simple piece used to test the basic functionality of the model. To use it you will need the new Oxygen:

http://community.thinbasic.com/index.php?topic=1845.0




' OOP with virtual tables


uses "OXYGEN"
uses "FILE"

dim vv as long
dim src as string

src="
indexers `esi` offset 0 ascending
esi=dataspace 0x100
type ClassA 4 a1! 4 a2! 4 fstatic / 4 pvft 4 pep 4 pip
(
build ClassA
exit
var classA this
a1:
this=&ClassA_Table
ret 4
a2:
this=&ClassA_Table
inc this.pip
ret 4
)
type ClassB 4 b1! 4 b2! / 4 pvft 4 pep 4 pip
(
build ClassB
exit
var classB this
b1:
this=&ClassB_Table
mov eax,66
ret 4
b2:
this=&ClassB_Table
inc this.pip
ret 4
)
type classAA classA, 4 fna! 4 fnb! 4 fnc! 4 fstatic classB, / 4 pvft 4 aa 4 bb
(
build classAA
exit
var ClassAA this
o2 /+4
fna:
this=&ClassAA_Table
inc this.aa
[#vv]=sizeof ClassAA
ret 4
fnb:
this=&ClassAA_Table
ret 4
fnc:
this=&ClassAA_Table
ret 4
)
var classAA myobject
myobject=&ClassAA_table


ecx=myobject.fna ; test method fna
ecx=myobject.fnb ; test method fnb
[#vv]=myobject.b1 ; test inherited method
ret

"
'msgbox 0,o2_view (src)
o2_asmo src
if len(o2_error) then
msgbox 0,"OOP1: "+o2_error()+o2_view (src)
stop
end if
o2_exec
msgbox 0,"0x"+hex$(vv)

Petr Schreiber
27-08-2008, 13:12
I knew you are working on something.
Looks cool, it will take me some time to understand it fully though :)


Thanks,
Petr

Charles Pegge
27-08-2008, 18:36
Well it certainly kept me very quiet for a few days and I can't say it was easy but I think its the only way to really understand this genre of programming. I have not looked at COM for some time now - but it should be possible to create COM objects cleanly as well as implementing more generalised OOP, since similar structures are used in C++.

The invisible work done by the system takes care of constructing tables of function pointers (virtual functions) and organising the elements of inherited structures in general. This was really too complicated to handle in macros so it made sense to internalise it.

kryton9
28-08-2008, 05:37
Charles thanks you always seems to shock in a positive way!

I don't understand how this works:

type classAA classA, 4 fna! 4 fnb! 4 fnc! 4 fstatic classB, / 4 pvft 4 aa 4 bb

In your first post, this I could sort of follow as to what is what:

type classAB classA, classB, 4 methodA! 4 methodB! 4 MethodC! membA / 4 vft 4 va 4 vb 4 vc

So could the code in the script be written as:
type classAA classA, classB, 4 fna! 4 fnb! 4 fnc! 4 fstatic / 4 pvft 4 aa 4 bb

Charles Pegge
28-08-2008, 11:18
Yes Kent, I should clarify that following type the first name is the class you are creating and anything after that is an element or inherited type. It may help if i write it in block form:

type ClassAA
(
classA, ; inherited class
classB, ; inherited class

4 methodA! ; method pointer added for this class (note the ! suffix)
4 methodB! ; another

4 fstatic ; a static class member ( no ! suffix)
; this becomes accessible as 'ClassAA_table.fstatic'

/ ; object members:

4 pvft ; pointer to the virtual function table (always present)
4 va ; a property
4 vb ; another property
4 vc ; ...

)

Charles Pegge
28-08-2008, 14:11
Unions:


type tvec 4 x 4 y 4 z 4 w = 4 red 4 green 4 blue 4 alpha

any number of unions are possible in a type statement. Here is another in block form

type tvec4
(
4 x 4 y 4 z 4 w
=
4 red 4 green 4 blue 4 alpha
=
4 cyan 4 magenta 4 yellow 4 alpha
=
16 v
)




Assignments

Most programming involves moving values from one variable to another - so building the assignment operator in the Assembler can greatly decrease the line count. Though the '=' sign still has a restricted meaning, its functionality has been extended to include most 32 bit assignments via the eax register.

a=b

is translated as:

mov eax,b
mov a,eax


String literals are represented by their starting address, so it is possible to say

var 4 a
a=`hello world`

a can then be used directly many sdk calls which take a string pointer.)
(string literals are always terminated with 2 nulls.

Addresses


c=&d

this is the equivalent of c=varptr(d)


Indirection

**a=*b

the PB equivalent of this is @@a=@b





Once again a new version:
_________________________________________________
http://community.thinbasic.com/index.php?topic=1845.0

Petr Schreiber
28-08-2008, 15:47
Thanks a lot Charles,

this kind of simplifications make asm much more attractive.
Freedom of choice whether to stay cool and write raw assembly or just make life less complicated and use simplified syntax is why I like Oxygen module a lot :)


Petr

jcfuller
29-08-2008, 12:02
Charles,
Sorry if this is out of place but can Asmosphere be used by other systems other than ThinBasic?
I've been toying around with tcc and the classes would be fun to use(actually play with).

James

ErosOlmi
29-08-2008, 12:41
James,

inside Oxygen there are FreeBasic sources of thinBasic module. It should not be complex to compile as generic DLL.

In any case have a look at: http://www.jose.it-berater.org/smfforum/index.php?board=154.0

Ciao
Eros

Charles Pegge
29-08-2008, 13:43
Hi James,

I am running behind on the standalone version of Oxygen. thinBasic has the leading edge and is actually a very good environment for developing and testing modular software.

Oxygen.bas (included in the version on the JRS forum) replaces the thinBasic.bas top end for use as a conventional DLL. I compile this in sync with the thinBasic version but my packaging and testing scheme for this needs a little more work.

Charles Pegge
31-08-2008, 12:47
Method Overloading

Extending the OOP facilities, it is now possible to deploy several versions of the same method, each taking different parameters. During assembly, the preprocessor checks the param signature against the function signatures for a match. If no match is found then an error will eventually be flagged by the linker.

This mechanism also ensures that the correct param types are used with all methods, whether there are multiple versions of the mehod or not.

These are examples of method signatures:
(commas are ignored)


myfunc: ( a ) ...
myfunc: ( a,a ) ...
myfunc: ( a, a, a ) ...
myfunc: ( a a a ) ..
myfunc: ( long long ) ..

myfun: ( long double)
...
ret 16


In the body of the type declaration, methods have a pling postfix so the format is:

myfunc! (long long)
myfunc! (long double)


With

The with instruction is used to avoid repeating long names when doing multiple assignments.


with myobject.material.color
.red=.5
.green=.4
.blue=.6
.alpha=.9
with ``


with can optionally use quotes.

This is some basic code for testing these new features and showing how the syntax works:



' OOP with virtual tables


uses "OXYGEN"
uses "FILE"

dim vv as long
dim src as string

src="
; signatures
; with
;
indexers `esi` offset 0 ascending
esi=dataspace 0x100
var 4 ab
type a 4 v
var a abc

type ClassA 4 a1! 4 a2! 4 fstaticA / 4 pvft 4 pp1 4 pp2
(
build ClassA
exit
var classA this
a1:
this=&ClassA_Table
ret 4
a2:
this=&ClassA_Table
inc this.pp1
ret 4
)
type ClassB 4 b1! (a a) 4 b2! / 4 pvft 4 pp1 4 pp2
(
build ClassB
exit
var classB this
b1: (a a)
this=&ClassB_Table
mov eax,66
ret 12
b2:
this=&ClassB_Table
inc this.pp1
ret 4
)
type classAA
(
classA ova
classB,

4 fna!
4 fnb! ()
4 fnc! ()
4 fnc! ( a )
4 fnc! ( a a )
4 fnc! ( a a a )
4 fstatic

/

4 pvft
4 aa
4 bb
)
(
build classAA
exit

var ClassAA this


fna:
this=&ClassAA_Table
inc this.aa
[#vv]=sizeof ClassAA
ret 4

fnb:()
this=&ClassAA_Table
ret 4

fnc: ()
[#vv]=-5
ret 4

fnc: (a)
[#vv]=10
ret 8

fnc: (a,a)
[#vv]=2
ret 12

fnc: (a,a,a)
this=&ClassAA_Table
[#vv]=42
ret 16
)
var classAA myobject
myobject=&ClassAA_table


edi=myobject.fna ; test method fna
edi=myobject.fnb ; test method fnb
edi=myobject.fnc abc 1 2 ; test method fnc with sig 3
edi=myobject.fnc 1 1 ; test method fnc with sig 2
edi=myobject.fnc abc ; test method fnc with sig 1
edi=myobject.fnc ; test method fnc with sig 0
[#vv]=myobject.b1 1 1 ; test inherited method

classA_table.fstaticA =1 ; class static
classAA_table.fstatic =1 ; class static
classAA_table.ova.fstaticA =1 ; class static inherited

myobject.aa=3 ; own property
myobject.pp1=2 ; inherited property
myobject.ova.pp1=2 ; inherited property with extended name

with myobject.ova ; same as above using WITH prefix
; alternative ..
with `myobject.ova` ; same as above using WITH quoted prefix
.pp1=2 ;
with ; clear WITH
; alternative ..
with `` ; clear WITH by empty quotes

ret

"
'END OF SRC

'msgbox 0,o2_view (src)
'file_save("t.txt",o2_view(src))
o2_asmo src
if len(o2_error) then
msgbox 0,"OOP1: "+o2_error()+o2_view (src)
stop
end if
o2_exec
msgbox 0,"0x"+hex$(vv)





New Version with Signatures and Overloading

http://community.thinbasic.com/index.php?topic=1845.0

Petr Schreiber
01-09-2008, 14:00
Hi Charles,

thanks for new release.
Very nice to see you organized some of the code to subfolders for better clarity.


Petr

Charles Pegge
01-09-2008, 14:47
I am also consolidating multiple test pieces into single files. So they can be run in one go. The aim is to have a fully automated test suite that can be triggered after every compile.

PS Igor Pavlov's 7z is excellent for file compression. I am using the console version with batch files.

jcfuller
01-09-2008, 15:10
I am also consolidating multiple test pieces into single files. So they can be run in one go. The aim is to have a fully automated test suite that can be triggered after every compile.

PS Igor Pavlov's 7z is excellent for file compression. I am using the console version with batch files.


Charles,
I haven't been doing anything with your excellent code and ThinBasic so I might be way off base here but I use aPlib for most of my compression needs especially where extreme fast decompression is needed. I converted the asm decompression code to both Pb and Fb and use the dll for compression. Might be worth a look??
http://www.ibsensoftware.com/products_aPLib.html
James

ErosOlmi
01-09-2008, 15:54
... I haven't been doing anything with your excellent code and ThinBasic so ...


ahi ahi ahi ;D

Charles Pegge
01-09-2008, 16:58
Thank you James, a decompression overhead of 169 bytes is very impressive! I'm only using compression to package my code postings at the moment. But I can see where dynamic decompression might come in very handy for textures with Opengl.

With regard to using Oxygen with other systems, I will include the Oxygen.bas which substitutes thinBasic_Oxygen.bas to make a standard DLL, and a couple of APIs in the source code folder. (It will only add about 4k to the zip file :) )

jcfuller
01-09-2008, 19:07
... I haven't been doing anything with your excellent code and ThinBasic so ...


ahi ahi ahi ;D



Even though I am retired now there never seems to be enough hours in the day to pursue every avenue I am interested. :) My plate has been a bit full of PowerBASIC.

James

Charles Pegge
02-09-2008, 12:14
Using thinBasic (Preview version) 1.7.0.0

With the enhanced thinBasic syntax for declarations, functions written in Oxygen can be seamlessly integrated, and treated like normal subs and functions.

It can be as simple as this:



' Asmosphere
' test Declare .. at

uses "OXYGEN"

dim src as string

src="
xor eax,eax
mov al,[esp+4]
(
cmp al,97
jl exit
cmp al,122
jg exit
sub al,32
)
ret 4
"
'END OF SRC

o2_asmo src

Declare Function upper (ByVal cChar As Byte) As Long at o2_buf 0

msgbox 0,"uppercase of ascii 100 is "+upper 100

ErosOlmi
02-09-2008, 12:40
So,

if I have understood well:

create your Oxygen function code
transform it into machine code and leave the code into the buffer (buffer zero)
Line: "O2_ASMO src"
DECLARE the function using thinBasic generic function declaration and at the same time assign Oxygen code pointer to thinBasic function
Line: "DECLARE FUNCTION ..." in this case "O2_BUF 0" return the code pointer to buffer zero
from now on, you can call Oxygen function from thinBasic script using thinBasic syntax like any other user defined functions


Great.
Eros

PS: from Oxygen help file O2_Buf is supposed to return none while in reality it seems returning the code pointer to a buffernumber.

Petr Schreiber
02-09-2008, 12:43
Charles,

this is very nice - it would not occur to me.
I think worth adding to help file.


Petr

Charles Pegge
02-09-2008, 13:10
Yes the help file needs refreshing. There have not been many additions to the basic instructions but they have acquired various enhancements over the last few months, but I think the o2_buf return was an omission.

The code buffer has 512 places - alternatively the assembled code can be fed into strings eg
dim sfun1 as string=o2_asm src then taking the strptr as the pointer

Here is how to build many functions using the Oxygen buffer system



' Asmosphere
' test Declare .. at

uses "OXYGEN"

dim src as string

src="
xor eax,eax
mov al,[esp+4]
(
cmp al,97
jl exit
cmp al,122
jg exit
sub al,32
)
ret 4
"
o2_buf 1 : o2_asmo src

Declare Function upper (ByVal cChar As Byte) As Long at o2_buf 1
src="
xor eax,eax
mov al,[esp+4]
(
cmp al,65
jl exit
cmp al,90
jg exit
add al,32
)
ret 4
"
o2_buf 2 : o2_asmo src

Declare Function lower (ByVal cChar As Byte) As Long at o2_buf 2


msgbox 0,"uppercase of ascii 100 is "+upper (100) + $crlf + _
"lowercase of ascii 68 is "+lower (68) + $crlf

Charles Pegge
02-09-2008, 16:31
Another example for the manual: :)

Around the first function, I have put a more typical framework, which involves preserving important registers, allocating workspace for local variables and giving parameters proper names to refer to. The EBX register also gets an address to the o2 runtime kernel.

You will find that this is typical of compiled functions in other languages - but with Assembly code, if your function does not alter ebx esi or edi or use local variables then you can dispense with the overhead.



' Asmosphere
' test Declare .. at

uses "OXYGEN"

dim src as string

src="
indexers `ebp` offset 8 ascending ' params
var 4 cchar ' params passed on stack
indexers `ebp` offset 0 descending ' locals
var 4 a b c d ' local stack variables
push ebp '
mov ebp,esp ' set up local ptr
sub esp,100 ' space for locals
push ebx ' save vital registers
push esi '
push edi '
mov ebx,KERNEL ' base address of o2 kernel funs
;------- start here
mov eax,cchar
and eax,0xff
(
cmp al,97
jl exit
cmp al,122
jg exit
sub al,32
)
;------ restore status quo
pop edi
pop esi
pop ebx
mov esp,ebp
pop ebp
ret 4 ' return releasing param bytes from stack (stdcall)
"
o2_buf 1 : o2_asmo src
if len(o2_error) then msgbox 0,o2_view src : stop

Declare Function upper (ByVal cChar As Byte) As Long at o2_buf 1
src="
xor eax,eax
mov al,[esp+4]
(
cmp al,65
jl exit
cmp al,90
jg exit
add al,32
)
ret 4
"
o2_buf 2 : o2_asmo src

Declare Function lower (ByVal cChar As Byte) As Long at o2_buf 2


msgbox 0,"uppercase of ascii 100 is "+upper (100) + $crlf + _
"lowercase of ascii 68 is "+lower (68) + $crlf

Charles Pegge
05-09-2008, 21:20
Adaptations for COM programmming

The quest is to produce tidy COM in Assembler using the Oxygen OOP model. This is really more of a versatility test than a proper implementation of COM at this stage.

One of the little problems that arose when I tried Oxygen's OOP model with COM is that multiple inheritance proved to be a mismatch, so I devised a way of indicating single inheritance using the keyword of.


type IUnknown
(
4 QueryInterface (a p)
4 AddRef ()
4 Release()
4 Counter
/
4 pvft
)

type IKnown
(
of IUnknown,
/
4 test_interface
4 other_interface
)




To help with virtual structures and pointering, a variable can now be associated with a specific register and have a structure associated with it. Example:


var IUnknown this [ecx]
...
mov ecx,[esp+4]
...
this.addref
...

Class virtual table generation has also been internally simplified but apart from that not much has had to be altered. Inevitably reconfiguring the synapses to cope with the very abstract convolutions of COM is the biggest challenge.





Oxygen Update:

http://community.thinbasic.com/index.php?topic=1845.0


The program below does very little other than to test the COM structures and pointering are performing correctly. An interface is switched by calling QueryInterface, with one of the GUIDs. A pointer to the new interface itest is granted. This interface is adopted then released.




' Test COM


uses "OXYGEN"
uses "FILE"

dim vv,ww as long
dim src as string

src="

esi=dataspace 0x1000 ; persistent memory inline
indexers `esi` offset 0 ascending


type IUnknown
(
4 QueryInterface (a p) ; HRESULT QueryInterface( REFIID iid,void ** ppvObject)
4 AddRef () ; ULONG AddRef(void)
4 Release() ; ULONG Release(void)
4 Counter
/
4 pvft
)

type IKnown
(
of IUnknown,
/
4 test_interface
4 other_interface
)


;class tables like IUnknown_table are automatically
;created whenever '/' is present in the type definition

;these interfaces are global ready-made
var Iunknown iUnk
var iKnown itest
var iknown iother

;set pvft for each interface

iunk.pvft =&Iunknown_table
itest.pvft =&iknown_table
iother.pvft =&iknown_table

;initialise properties

with itest
.test_interface=&itest
.other_interface=&iother
with iother
.test_interface=&itest
.other_interface=&iother
with ``


( ; start of methods

build IUnknown
build Iknown

[#vv]=itest.test_interface
'[#ww]=i.counter

; create test and other interfaces

exit

var IKnown this [ecx]

QueryInterface: (a p)
(
(
data hl0 hw0 hw0 00 00 00 00 00 00 00 01
mov edx,[esp+8]
proc matchGuid edx eax
cmp eax,0
jz exit
ecx=&itest
var iknown this [ecx]
mov ecx,this.test_interface
jmp long matched
)
(
data hl2339B54C hw3453 hw11D2 93 B9, 00, 00, 00, 00, 00, 00
mov edx,[esp+8]
proc matchGuid edx eax
cmp eax,0
jz exit
mov ecx,[esp+4] ; self matched
jmp long matched
)
(
data hl3339B54C hw3453 hw11D2 93 B9, 00, 00, 00, 00, 00, 00
mov edx,[esp+8]
proc matchGuid edx eax
cmp eax,0
jz exit
mov ecx,this.other_interface
jmp long matched
)

unmatched: ; fall thru to here
mov eax,[esp+12]
mov [eax],0
mov eax,0x80004002 ; E_NOINTERFACE
ret 12

matched:
'mov ecx,[esp+4]
this.addref
mov eax,[esp+12]
mov [eax],ecx ;
mov eax,0 ; S_OK
ret 12
)

AddRef: ()
(
mov ecx,[esp+4] ; address of this interface
mov eax,this.pvft ; address of interface
var Iknown i [eax]
inc i.counter ; static counter in _table
ret 4
)

Release: ()
(
mov ecx,[esp+4] ; address of this interface
mov edx,this.pvft ; address of interface
var IUnknown i [edx]
(
cmp i.counter,0
jz exit
dec i.counter ; static counter
jnz exit
' counter is zero so release object here ...
)
ret 4
)


; private function
matchGUID: ; (pGUID1 pGUID2) as bool
(
push esi
push edi
mov esi,[esp+12]
mov edi,[esp+16]
mov eax,[esi]
cmp eax,[edi]
jnz nomatch
add esi,4
add edi,4
mov eax,[esi]
cmp eax,[edi]
jnz nomatch
add esi,4
add edi,4
mov eax,[esi]
cmp eax,[edi]
jnz nomatch
add esi,4
add edi,4
mov eax,[esi]
cmp eax,[edi]
jnz nomatch
mov eax,1
jmp xit
nomatch:
mov eax,0
xit:
pop edi
pop esi
ret 8
)

) ; end of methods Iknown



; kickstart
;----------
var iunknown ii
var 4 pi refiid
refiid=data hl0 hw0 hw0 00 00 00 00 00 00 00 01
ii.pvft=&iunknown_table
ii.QueryInterface refiid &pi

cmp eax,0 ; S_OK
(
jnz exit ; no interface available
mov ecx,pi ; adopt the new interface
var Iknown this [ecx]
this.Release()
)
ret

"
'END OF SRC

file_save("t.txt",o2_view(src))
o2_asmo src
if len(o2_error) then
msgbox 0,"COM: "+o2_error()+o2_view (src)
stop
end if
o2_exec
msgbox 0,"0x"+hex$(vv)+$crlf+"0x"+hex$(ww)

Petr Schreiber
05-09-2008, 21:28
:)

very advanced stuff as usual, thanks Charles.

One thing with following fragment:


with itest
.test_interface=&itest
.other_interface=&iother
with iother
.test_interface=&itest
.other_interface=&iother
with ``


Is it legal to end two with statements with single with ``?


Thanks,
Petr

Charles Pegge
05-09-2008, 21:42
Yes Petr, I have not made with a block structure. It simply holds the prefix until a new one is given or until it is nulled. This gives it considerable flexibility. With can take a whole name or part of a name involved in the assignment - anything you wish to avoid repeating. Quotes are optional but allow the possibility of prefixing several words

Petr Schreiber
05-09-2008, 21:57
Thanks for explanation,

so with serves again for kind of "state toggle".
As I know it now, I understand it.
I like state machines as well :)


Petr

Charles Pegge
05-09-2008, 23:18
The whole of Oxygen relies heavily on its global state. It has a very flat structure with lots of gotos :). Breaks all the rules, but the compilation task really demands it. error trapping and reporting is very simple and its easy to climb back on the horse and continue. To get flexibility into the system, the preprocessor generates its own macros and feeds them back into the loop recursively until they resolve into assembly code.

Charles Pegge
09-09-2008, 07:17
A few more features:

Defs

Defs is an efficient way to provide sets of equates. Example:

defs key a 97 b 98 c 99 d 100 ...

these can then be referred to a key.a key.b key.c etc


OOP

Private Members

These are elements which are invisible to derived classes - but still exist in the object. So they are only accesible using methods inherited from the ancestral class.

Any element can be made private by appending a dash (minus sign) after the element definition.


Abstract Members

These are denoted by any element that has a size of zero!

Derived types must provide matching real elements to replace these before they can be used to instantiate objects. They specify the general structure of a type before getting down to specific implementations.

These I hope complete the Oxygen OOP facilities. But there is much to explore - so many different combinations.



Oxygen Update
http://community.thinbasic.com/index.php?topic=1845.0

Charles Pegge
17-09-2008, 13:29
Oxygen seems to be approaching the limit of what can be usefully added to its preprocessor. So this facility is one of the finishing touches - at least for Object Oriented Programming. I hope that after this, very few adjustments will be required to implement the next layer for high level programming, namely H2O

Dynamic Objects

static object:

var myclass myobject

dynamic object:

var &myclass myobject


By adding an extra level of indirection this enables objects to be created and destroyed dynamically during runtime.
Methods can be called using the same syntax as static objects
(currently this simplified syntax only applies to method calls not property setting)

Using macros we can then implement new and delete, very similar to c++.


new myclass myobject
myobject.mymethod
...
delete myobject


Oxygen Update
http://community.thinbasic.com/index.php?topic=1845.0






Uses "Oxygen"
Uses "File"

'------------------------------------------------------

dim vv,ww as long
dim src as string

'------------------------------------------------------

src="
; testing virtual objects
def locals indexers ebp offset 0 descending %l push ebp %l mov ebp,esp %l sub esp,%1
def free_locals mov esp,ebp %l pop ebp
def workspace indexers esi offset 0 ascending %l esi=getmemory %1
def free_workspace freememory esi

locals 1024

type cc 4 fn1! 4 fn2! / 4 pvt
(
static
build cc
exit

var cc this [ecx]

fn1:
[#vv]=0xace1
ret 4

fn2:
[#vv]=0xace2
ret 4

)
def new
(
push edx
var &%1 %2
edx=getmemory sizeof %1
[edx]=&%1_table
mov %2,edx
pop edx
)

def delete
(
freememory %1
mov %1,0
)

new cc vo
vo.fn1
vo.fn2
delete vo
free_locals
ret
"
'file_save("t.txt",o2_view (src))
'msgbox 0,"ZM20: "+o2_error+o2_view (src) : stop
o2_asmo src : if len(o2_error) then msgbox 0,"ZM20: "+o2_error+o2_view (src) : stop
o2_exec : msgbox 0,"0x"+hex$(vv) : stop

Petr Schreiber
17-09-2008, 13:42
Hi Charles,

good update, with new and delete it is very easy to follow the code.


Petr

Charles Pegge
22-09-2008, 22:55
A number of small changes that help to improve the source code structure. In particular multi level exits, fwd jumps and colon-separated statements. I hope to illustrate these over the next few posts. The code below shows how contracts (essentially defining and testing a function's inputs and outputs) can be controlled - activated for testing then omitted when no longer needed in the final code. It also makes use of some of the new features.

Oxygen Update
http://community.thinbasic.com/index.php?topic=1845.0



from test_preproc.tbasic



uses "Oxygen"
uses "File"

dim vv as long
dim src as string

src="
; contract blocks
;
indexers esi offset 0 ascending : esi=dataspace 400 ' static space
def check1 ; skip ' remove the semicolon to skip all blocks headed 'check1'
proc myfunc 1 0 3 4 ' our test function
ret ' end of prog
;
myfunc:
(
push ebp : mov ebp,esp : sub esp,100 ' stack space for locals
indexers ebp offset 8 ascending var 4 a b c d ' parameters
indexers ebp offset 0 descending var 4 i j k m ' locals
check1 ' contract block
(
cmp a, 0 : jz fwd error ' fwd ensures forward jump to the next error label
cmp a, 10 : jg fwd error
cmp a,-10 : jl fwd error
cmp b, 0 : jz fwd error
cmp b, 10 : jg fwd error
cmp b,-10 : jl fwd error
)
;
;... main body of function
;
[#vv]=0 : jmp fwd finish ' no errors detected so go to next finish
;
error: [#vv]=666 ' error const
finish: mov esp,ebp : pop ebp ' release local stack space
ret 16 ' return releasing params from stack
)
"
'file_save("t.txt",o2_view (src))
'msgbox 0,"ZM26: "+o2_error+o2_view (src) : stop
o2_asmo src : if len(o2_error) then msgbox 0,"ZM26: "+o2_error+o2_view (src) : stop
o2_exec : msgbox 0,"0x"+str$(vv) : stop