The MASM Forum Archive 2004 to 2012

Project Support Forums => HLA Forum => Topic started by: DarkWolf on April 12, 2007, 12:41:48 AM

Title: Object Oriented Code Attempt
Post by: DarkWolf on April 12, 2007, 12:41:48 AM
I started out with the code from the redblack tree example in HIDE.
I was getting lost with the AoA tree edition, it seems a little out of order to me.
I am only getting errors it seems with the name foo for the VMT and procedure.
Is it really that simple ?  :-P

Code is compiled on Linux with v1.89



program ObjCode;



#includeonce ("stdlib.hhf")



type

textclass : class

var

s : string;



procedure create; returns( "esi" );

procedure destroy;

method input( s:string );

method print( s:string );



endclass;



var

foo : textclass;



readonly

VMT( foo );

endreadonly



begin ObjCode;



procedure foo.create; @nodisplay;

begin create;

if( esi = NULL ) then

push( eax );

mem.alloc( @size( foo ));

mov( eax, esi );

pop( eax );

endif;

mov( &foo._VMT_, this._pVMT_ );

end create;



procedure foo.destroy; @nodisplay;

begin destroy;

push( eax );

free( s );

if( isInHeap( esi )) then

free( esi );

endif;

pop( eax );

end destroy;



method foo.input( s ); nodisplay;

begin input

stdin.gets( s );

end input



method foo.print( s ); nodisplay;

begin print

stdout.put( "You entered : ", s );

end print



foo.input;

foo.print;

foo.destroy;



end ObjCode;



Error in file "ObjCode.hla" at line 21 [errid:107447/hlaparse.c]:
syntax error, unexpected LocalVarID.
Near: << ) >>

Error in file "ObjCode.hla" at line 26 [errid:107447/hlaparse.c]:
syntax error, unexpected procedureTkn.
Near: << procedure >>
Title: Re: Object Oriented Code Attempt
Post by: Sevag.K on April 12, 2007, 01:10:38 AM

var

foo : textclass;



readonly

VMT( foo );

endreadonly



VMT has to be a class identifier.  Try:

VMT (textclass);
Title: Re: Object Oriented Code Attempt
Post by: DarkWolf on April 14, 2007, 12:18:16 AM
I see that I didn't use the classname in the VMT . My labels seem all wrong, it reports errors with ObjCode as the program identifier and if I use either foo or textclass in the procedures and methods. With what I set up what would be the correct identifiers ?
Title: Re: Object Oriented Code Attempt
Post by: Sevag.K on April 14, 2007, 02:07:25 AM
OK.  I pumped your code into HIDE and found loads of errors :)

First one we already covered


readonly

VMT( foo );

endreadonly


should be VMT (textclass);

Right under that you have: 

"begin ObjCode;"

Which belongs down below all the class methods/procedures.



procedure foo.create; @nodisplay;


all your procedures use "foo" as a namespace which should be the class name itself "textclass"



method foo.input( s ); nodisplay;

begin input

stdin.gets( s );

end input



method foo.print( s ); nodisplay;

begin print

stdout.put( "You entered : ", s );

end print


-nodisplay should be @nodisplay;
-missing semicolons.
-you have to declare a type for 's' in the method parameters list as in "s:string"




foo.input;

foo.print;

foo.destroy;


The "begin objCode;" should go above these statements.
-foo.input and foo.print expect a string parameter
-foo.destroy needs an empty parameter: "foo.destroy();"

Thats about all the errors HLA reported.

Title: Re: Object Oriented Code Attempt
Post by: DarkWolf on April 14, 2007, 08:09:11 PM

program ObjCode;



#includeonce ("stdlib.hhf")



type

textclass: class

var

s: string;



procedure create; returns( "esi" );

procedure destroy;

method input( s:string );

method print( s:string );



endclass;



var

foo: textclass;



readonly

VMT( textclass );

endreadonly



procedure textclass.create; @nodisplay;

begin create;

if( esi = NULL ) then

push( eax );

mem.alloc( @size( textclass ));

mov( eax, esi );

pop( eax );

endif;

mov( &textclass._VMT_, this._pVMT_ );

end create;



procedure textclass.destroy; @nodisplay;

begin destroy;

push( eax );

free( s );

if( isInHeap( esi )) then

free( esi );

endif;

pop( eax );

end destroy;



method textclass.input( s:string ); @nodisplay;

begin input;

stdin.gets( s );

end input;



method textclass.print( s:string ); @nodisplay;

begin print;

stdout.put( "You entered : ", s );

end print;


begin ObjCode;


foo.input( s );

foo.print( s );

foo.destroy();



end ObjCode;


All errors now point out that I don't have s defined and that there is something still wrong with the procedures.
Did I define s correctly or did I put it in the wrong section ?
The AoA text shows that the methods/procedures are declared in the type section and are defined elsewhere before they are implemented later in the code. I am using them at the bottom and declared them in the type section, did I not define them in the right place ?
Title: Re: Object Oriented Code Attempt
Post by: Sevag.K on April 15, 2007, 05:11:23 AM
That's because you don't have 's' defined outside of the class.  If 's' is going to be the one defined in the class, then you need to do some redesigning of the method parameters.

There is also a missing semicolon on endreadonly.  You can just remove this line since it's depricated.
The "free (s);" in the destroy method should be
mem.free (this.s);

But be careful since you don't allocate any actual memory for the string variable in the class!


Title: Re: Object Oriented Code Attempt
Post by: DarkWolf on April 15, 2007, 06:33:20 PM
I thought that variables used by the class would have to be defined there.
Using the 'this' keyword in the procedures/methods has cleared that up but not for the object foo.

This is where I am in muddy waters, I have a class and an object. I want to define the variables in the class and have the object use them, this is how I thought OO code worked. Where is the allocation done for the class-defined variables ? I would allocate the storage in the input method that gets the user input but that's not right is it, each call to textclass.input would allocate memory and I only free it in the destroy procedure ?

This string variable is where I am having the most trouble getting the OO code setup.
Title: Re: Object Oriented Code Attempt
Post by: Sevag.K on April 15, 2007, 08:14:54 PM
Quote from: DarkWolf on April 15, 2007, 06:33:20 PM
I thought that variables used by the class would have to be defined there.

That is correct.  The problem is that you trying to pass a non-declared variable outside of the class to the class.


Quote
Using the 'this' keyword in the procedures/methods has cleared that up but not for the object foo.

This is where I am in muddy waters, I have a class and an object. I want to define the variables in the class and have the object use them, this is how I thought OO code worked. Where is the allocation done for the class-defined variables ? I would allocate the storage in the input method that gets the user input but that's not right is it, each call to textclass.input would allocate memory and I only free it in the destroy procedure ?

This string variable is where I am having the most trouble getting the OO code setup.

The allocation is done in the declared class object (foo in your case).  However, string types are pointers.  You have to allocate the storage for the strings elsewhere using str.alloc (or using a procedure that automatically allocates memory such as stdin.a_gets ).


program ObjCode;

// a corrected and annotated version

#includeonce ("stdlib.hhf")

type

textclass: class

var
s: string;

procedure create; returns( "esi" );
method destroy; // note this is a method
method input; // note, no parameters needed
method print;

endclass;

readonly

VMT( textclass );


var
foo: textclass; // declare memory for a textclass object



procedure textclass.create; @nodisplay;
begin create;
if( esi = NULL ) then
push( eax );
mem.alloc( @size( textclass ));
mov( eax, esi );
pop( eax );
endif;

mov( &textclass._VMT_, this._pVMT_ );
mov( 0, this.s); // make sure this is cleared

end create;


method  textclass.destroy; @nodisplay; // this is a method now
begin destroy;
push( eax );
if (this.s > 0) then
// free only if s is allocated
// note you can also mem.isInHeap (s), but this is faster
// since we can use s=0 to indicate NULL string.
str.free( this.s ); // use str.free here
endif;

if( mem.isInHeap( esi )) then
mem.free( esi );
endif;

pop( eax );
end destroy;


method textclass.input; @nodisplay;
begin input;

if (this.s > 0) then
// something is already declared here, free it
mem.free (this.s);
endif;
stdout.put ("Enter input :"); // friendly
stdin.a_gets(); // allocate new memory on heap
mov (eax, this.s); // store pointer in s

end input;



method textclass.print; @nodisplay;
begin print;

// something to print only if s is not null
if (this.s > 0) then
stdout.put( "You entered : ", this.s, nl );
endif;

end print;


begin ObjCode;

foo.create(); //important!!
foo.input();
foo.print();
foo.destroy();


end ObjCode;




Title: Re: Object Oriented Code Attempt
Post by: Evenbit on April 15, 2007, 09:24:14 PM
Another quick example...

program grid;

#include( "stdlib.hhf" )



type

point:

class

var

x :dword;

y :dword;

lbl :string;

endvar;



procedure create( xcor:dword; ycor:dword ); @returns( "esi" );

method setLabel( title:string );

procedure getLabel; @returns( "eax" );

method changeX( xcor:dword );

method showAll;

method destroy;

endclass;

endtype;



procedure point.create( xcor:dword; ycor:dword ); @nodisplay;

begin create;



    push( eax );

    if ( esi = 0 ) then

        mem.alloc( @size( point ) );

        mov( eax, esi );

    endif;

    mov( &point._VMT_, this._pVMT_ );

mov( xcor, eax );

mov( eax, this.x );

mov( ycor, eax );

mov( eax, this.y );

mov( 0, eax );

mov( eax, this.lbl );

pop( eax );



end create;



method point.setLabel( title:string ); @nodisplay;

begin setLabel;



push( eax );

mov( title, eax );

mov( eax, this.lbl );

pop( eax );



end setLabel;



procedure point.getLabel; @nodisplay;

begin getLabel;



mov( this.lbl, eax );



end getLabel;



method point.changeX( xcor:dword ); @nodisplay;

begin changeX;



push( eax );

mov( xcor, eax );

mov( eax, this.x );

pop( eax );



end changeX;



method point.showAll; @nodisplay;

begin showAll;



mov( this.lbl, eax );

if ( eax != 0 ) then

stdout.put( this.lbl, "  " );

else

stdout.put( "<void>  " );

endif;

stdout.putu32( this.x );

stdout.puts( " " );

stdout.putu32( this.y );

stdout.newln();

stdout.put( "----", nl );



end showAll;



method point.destroy; @nodisplay;

begin destroy;



push( eax );

mov( this.lbl, eax );

if ( eax != 0 ) then

str.free( eax );

endif;

pop( eax );

if ( isInHeap( esi ) ) then

        mem.free( esi );

    endif;



end destroy;



readonly

VMT( point );



var

dart :point;

temp :pointer to point;



static

s :string;

c :byte[64];

t :string;



begin grid;



str.init( c[0], 64 );

mov( eax, s );

str.cat( "Hello", s );

str.a_cpy( s );

mov( eax, t );



dart.create( 5, 6 );

dart.setLabel( t );

dart.showAll();

dart.changeX( 8 );

dart.showAll();

dart.destroy();



str.cat( " World", s );

str.a_cpy( s );

mov( eax, t );

point.create( 50, 60 );

mov( esi, temp );

(type point [esi]).setLabel( t );



point.create( 2, 2 );

(type point [esi]).showAll();

(type point [esi]).destroy();



temp.showAll();

temp.destroy();



end grid;



Nathan.
Title: Re: Object Oriented Code Attempt
Post by: DarkWolf on April 16, 2007, 11:15:37 PM
Attempting to compile either example gives me this error from the linker.
It apparently only compiles a binary file and not an executable.
Command was 'hla ObjCode.hla'. :

ld: warning: cannot find entry symbol _start; not setting start address

But if I use my makefile it works. Is there a difference between my makefile and hla's default operation ?

Makefile:

project: ObjCode.o
hla -x:ObjCode ObjCode.o

ObjCode.o: ObjCode.hla
hla -c ObjCode.hla

clean:
rm *.o
rm *.asm
rm *.inc

nomore: rm *.*


Nevertheless I have to study and make sure I can get right from now on.  ;-)  :U
Title: Re: Object Oriented Code Attempt
Post by: Sevag.K on April 17, 2007, 12:15:31 AM
Don't know, I haven't tested the linux version of HLA in a while.
Title: Re: Object Oriented Code Attempt
Post by: DarkWolf on April 18, 2007, 11:59:46 PM
Think of me as your guinea pig  :-P
Title: Re: Object Oriented Code Attempt
Post by: DarkWolf on June 23, 2007, 11:34:44 PM
Speaking of testing and guinea pigs.

I split up the file and tried to make a header and unit, to use makefile and maybe expand later.
After fiddling with ar to make the library, my current error is that the textclass isn't defined when compiling the main program.
I can compile the unit and make the .a file (linux version of .lib) but it won't recognize foo as an object of textclass.

I was following the shape example from electronic edition AoA and I don't see a section I may have missed.
The header has the class definition, the unit has the procedure definitions and VMT and the main program has the actual implementation.

( I never had guinea pigs growing up, hamsters and hermit crabs, but not guinea pigs. )



[attachment deleted by admin]
Title: Re: Object Oriented Code Attempt
Post by: Sevag.K on June 24, 2007, 12:37:00 AM
I got ubuntu working so I'm go with linux problems :)

Your biggest problem is that you don't declare your class methods/procedures as external.  You have to do this if you want to work with units!


// 23/06/2007 15:58:07   
// HLA v1.96 Linux

// Sean Shaffer, DarkWolf, KB3IMT

// Experimenting with OO

#if( !@defined( objcode_hhf ))
?objcode_hhf := true;

type
textclass: class
var
s: string;

procedure create; returns( "esi" ); @external;
method destroy; @external; // note this is a method
method input; @external; // note, no parameters needed
method print; @external;

endclass;

#endif;


Also, to get it to compile without complaints, I changed the objcode.hhf include to the current directory;

#includeonce ("objcode.hhf")

And used this makefile


project: objcode.o objcode.a
hla -x:objcode objcode.o objcode.a

objcode.o: objcode.hla
hla -cg objcode.hla

objcode.a: objcode2.o
ar -q objcode.a objcode2.o

objcode2.o: objcode2.hla objcode.hhf
hla -cg objcode2.hla

clean:
rm *.o
rm *.asm
rm *.inc

nomore: rm *.*


You weren't properly linking in objcode.a

If you want to add a lib path on the command line, the proper syntax is:

hla -x:objcode objcode.o objcode.a -lib./

But it's not needed if the library resides in the current directory.
Title: Re: Object Oriented Code Attempt
Post by: DarkWolf on June 24, 2007, 09:03:25 PM
Duh, I can't believe I forgot to mark them @external.

Well all is good now and I also forgot that the lib and header could be in the same directory. For some reason I was thinking I had to put them relative to the set paths.
Yea, time to screw something else up   :wink
Title: Re: Object Oriented Code Attempt
Post by: DarkWolf on July 01, 2007, 01:17:43 AM
Can I set a boolean variable in a header ?

boolean := false;

this returns an error that it expected ; where it found :=
I wanted to use a boolean variable as a flag and clear it by default.

What is the variable for the file.create() method ?
The HLAref says that I can use filevar.create() where filevar is the variable
But if the variable is in a class do I need to use this.filevar in the place of filevar ?

I'm getting there, I'll just be screwing up the little things for awhile :-)
Title: Re: Object Oriented Code Attempt
Post by: Evenbit on July 01, 2007, 01:27:53 AM
Quote from: DarkWolf on July 01, 2007, 01:17:43 AM
Can I set a boolean variable in a header ?

boolean := false;

this returns an error that it expected ; where it found :=
I wanted to use a boolean variable as a flag and clear it by default.

You will want...
flag01    :boolean    :=    false;

Quote
What is the variable for the file.create() method ?
The HLAref says that I can use filevar.create() where filevar is the variable
But if the variable is in a class do I need to use this.filevar in the place of filevar ?

I'm getting there, I'll just be screwing up the little things for awhile :-)

Something like...
MyFile    :file;
or..
MyFile    :pointer to file

Nathan.
Title: Re: Object Oriented Code Attempt
Post by: DarkWolf on July 01, 2007, 05:01:23 PM
Well I use a different name for my flag but that is exactly what I have in the header and it doesn't work.
I don't see what difference there is between :
isUnit: boolean := false;
and
flag01    :boolean    :=    false;
Apart from whitespace, but I never had a problem with that before.

Argh, it was one page above what I was reading. (slaps hand on forehead, I need a SHOF icon :-p )
But now I am thinking (and maybe a little too hard), I will need to use the file.class methods in another class.
TO have my method write to a file I need it to call the methods of the file.class from the standard library.

Am I thinking too hard or is there an issue if I call say MyFile.put("whatever") from inside a method from another class.
Title: Re: Object Oriented Code Attempt
Post by: Randall Hyde on July 02, 2007, 07:11:57 PM
As long as your declaration appears in a CONST, STATIC, or READONLY section, it should be fine.  I.e.,


static
    isUnit :boolean := false;


HOWEVER, keep in mind that if you do this, you will create a *distinct* copy of this variable in every file in which you include that header. And if you also make the symbol @external, you will get a linker error.

I suspect that from the name of the variable you're wanting to create a constant that you can check with conditional assembly, e.g.,


const
   isUnit :boolean := false;


But if you really want to include the variable in multiple files (as part of the header file), then the typical way to do this is


// in your header file:

static // or readonly

  isUnit:boolean; @external;


and then in *only one* of your .hla files (that includes the header files), you'll want the following:


static // or readonly
  isUnit :boolean := false;

hLater,
Randy Hyde


Title: Re: Object Oriented Code Attempt
Post by: DarkWolf on July 04, 2007, 11:13:15 PM
No, I don't intend it to be constant. Only false by default, I'll set it to true if I need to.
But I see that I am using the wrong section.

Conditional compiling was not what I originally intended, at first I wanted to use them to determine the file I was writing.
For instance, if isUnit was true it would write a file without the program ID statement.
Title: Re: Object Oriented Code Attempt
Post by: Randall Hyde on July 05, 2007, 08:50:48 PM
Quote from: DarkWolf on July 04, 2007, 11:13:15 PM
No, I don't intend it to be constant. Only false by default, I'll set it to true if I need to.

In that case, use the @external directive, and in the *one* source file where you actually define the variable (rather than just use it), set it to false (in the STATIC section).
hLater,
Randy Hyde
Title: Re: Object Oriented Code Attempt
Post by: DarkWolf on July 22, 2007, 01:55:35 AM
So far this is what I got and I know it is probably poorly written  :-p

I know that I need to clean it up. I didn't want it to ask for each string variable from the user but I started writing it that way.
And I am not sure about writing the file based on the boolean values.
(Don't bother with the exe in the zip I know it's bad.)

I didn't get to do much with it this week (10 hour shifts at work and Neverwinter Nights :-p )

[attachment deleted by admin]