Contributed by Chris Rathman
type Shape:class
var x:int32;
var y:int32;
procedure create; @returns("esi"); @external;
procedure getX; @returns("eax"); @external;
procedure getY; @returns("eax"); @external;
method setX(newx:int32); @external;
method setY(newy:int32); @external;
method moveTo(newx:int32; newy:int32); @external;
method rMoveTo(deltax:int32; deltay:int32); @external;
method draw; @abstract;
endclass;
|
unit Shapes;
#include("stdlib.hhf");
#includeonce("Shape.hhf");
static vmt(Shape);
// constructor
procedure Shape.create;
begin create;
if (esi = 0) then
mov(malloc(@size(Shape)), esi);
endif;
mov(&Shape._VMT_, this._pVMT_);
this.setX(0);
this.setY(0);
push(esi);
end create;
// accessors for x & y
procedure Shape.getX;
begin getX;
mov(this.x, eax);
push(eax);
end getX;
procedure Shape.getY;
begin getY;
mov(this.y, eax);
push(eax);
end getY;
method Shape.setX(newx:int32);
begin setX;
mov(newx, this.x);
end setX;
method Shape.setY(newy:int32);
begin setY;
mov(newy, this.y);
end setY;
// move the shape position
method Shape.moveTo(newx:int32; newy:int32);
begin moveTo;
this.setX(newx);
this.setY(newy);
end moveTo;
method Shape.rMoveTo(deltax:int32; deltay:int32);
begin rMoveTo;
push(eax);
push(ebx);
mov(this.x, eax);
add(deltax, eax);
mov(this.y, ebx);
add(deltay, ebx);
this.moveTo(eax, ebx);
pop(ebx);
pop(eax);
end rMoveTo;
end Shapes;
|
type Rectangle:class inherits(Shape)
var width:int32;
var height:int32;
override procedure create; @external;
procedure getWidth; @returns("eax"); @external;
procedure getHeight; @returns("eax"); @external;
method setWidth(newwidth:int32); @external;
method setHeight(newheight:int32); @external;
override method draw; @external;
endclass;
procedure makeRectangle(newx:int32; newy:int32; newwidth:int32; newheight:int32); @returns("esi"); @external;
|
unit Rectangles;
#include("stdlib.hhf");
#includeonce("Shape.hhf");
#includeonce("Rectangle.hhf");
static vmt(Rectangle);
// constructor
procedure Rectangle.create;
begin create;
if (esi = 0) then
mov(malloc(@size(Rectangle)), esi);
endif;
call Shape.create;
mov(&Rectangle._VMT_, this._pVMT_);
this.setWidth(0);
this.setHeight(0);
push(esi);
end create;
// accessors for width & height
procedure Rectangle.getWidth;
begin getWidth;
mov(this.width, eax);
push(eax);
end getWidth;
procedure Rectangle.getHeight;
begin getHeight;
mov(this.height, eax);
push(eax);
end getHeight;
method Rectangle.setWidth(newwidth:int32);
begin setWidth;
mov(newwidth, this.width);
end setWidth;
method Rectangle.setHeight(newheight:int32);
begin setHeight;
mov(newheight, this.height);
end setHeight;
// draw the rectangle
method Rectangle.draw;
begin draw;
push(eax);
mov(this.getX(), eax);
stdout.put("Drawing a Rectangle at:(", (type int32 eax), ",");
mov(this.getY(), eax);
stdout.put((type int32 eax), ") ");
mov(this.getWidth(), eax);
stdout.put("width ", (type int32 eax), ", ");
mov(this.getHeight(), eax);
stdout.put("height ", (type int32 eax), nl);
pop(eax);
end draw;
// make a Rectangle object
procedure makeRectangle(newx:int32; newy:int32; newwidth:int32; newheight:int32);
begin makeRectangle;
Rectangle.create();
(type Rectangle [esi]).moveTo(newx, newy);
(type Rectangle [esi]).setWidth(newwidth);
(type Rectangle [esi]).setHeight(newheight);
push(esi);
end makeRectangle;
end Rectangles;
|
type Circle:class inherits(Shape)
var radius:int32;
override procedure create; @external;
procedure getRadius; @returns("eax"); @external;
method setRadius(newradius:int32); @external;
override method draw; @external;
endclass;
procedure makeCircle(newx:int32; newy:int32; newradius:int32); @returns("esi"); @external;
|
unit Circles;
#include("stdlib.hhf");
#includeonce("Shape.hhf");
#includeonce("Circle.hhf");
static vmt(Circle);
// constructor
procedure Circle.create;
begin create;
if (esi = 0) then
mov(malloc(@size(Circle)), esi);
endif;
call Shape.create;
mov(&Circle._VMT_, this._pVMT_);
this.setRadius(0);
push(esi);
end create;
// accessors for radius
procedure Circle.getRadius;
begin getRadius;
mov(this.radius, eax);
push(eax);
end getRadius;
method Circle.setRadius(newradius:int32);
begin setRadius;
mov(newradius, this.radius);
end setRadius;
// draw the circle
method Circle.draw;
begin draw;
push(eax);
mov(this.getX(), eax);
stdout.put("Drawing a Circle at:(", (type int32 eax), ",");
mov(this.getY(), eax);
stdout.put((type int32 eax), ") ");
mov(this.getRadius(), eax);
stdout.put("radius ", (type int32 eax), nl);
pop(eax);
end draw;
// make a circle object
procedure makeCircle(newx:int32; newy:int32; newradius:int32);
begin makeCircle;
Circle.create();
(type Circle [esi]).moveTo(newx, newy);
(type Circle [esi]).setRadius(newradius);
push(esi);
end makeCircle;
end Circles;
|
program Polymorph;
#includeonce("stdlib.hhf");
#includeonce("Shape.hhf");
#includeonce("Circle.hhf");
#includeonce("Rectangle.hhf");
type pShape: pointer to Shape;
static scribble: pShape[2];
static rect: pointer to Rectangle;
begin Polymorph;
// set up some shape instances
mov(makeRectangle(10, 20, 5, 6), scribble[0*4]);
mov(makeCircle(15, 25, 8), scribble[1*4]);
// iterate through some shapes and handle polymorphically
for (mov(0, ebx); ebx < 2; inc(ebx)) do
scribble.draw[ebx*4]();
scribble.rMoveTo[ebx*4](100, 100);
scribble.draw[ebx*4]();
endfor;
// access a rectangle specific function
mov(makeRectangle(0, 0, 15, 15), rect);
rect.setWidth(30);
rect.draw();
end Polymorph;
|
Drawing a Rectangle at:(10,20) width 5, height 6 Drawing a Rectangle at:(110,120) width 5, height 6 Drawing a Circle at:(15,25) radius 8 Drawing a Circle at:(115,125) radius 8 Drawing a Rectangle at:(0,0) width 30, height 15 |