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 >>
var
foo : textclass;
readonly
VMT( foo );
endreadonly
VMT has to be a class identifier. Try:
VMT (textclass);
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 ?
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.
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 ?
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!
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.
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;
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.
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
Don't know, I haven't tested the linux version of HLA in a while.
Think of me as your guinea pig :-P
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]
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.
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
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 :-)
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.
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.
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
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.
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
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]