macro class template
Posted: Mon Dec 07, 2009 1:33 am
Code: Select all
;Macro class template pbi
;
;An easy way to define classes to visually isolate classes from regular code
;==========================================================================================================
; General useage
;==========================================================================================================
; Macro AClassTemplate(n)
;
; ClassStructure(n)
; ;Structures here
; ClassPrototypes(n)
; ;Prototypes of the methods
; ClassMethods(n)
; ;PublicMethod(n,GetY,.f,*null)
; ; PublicReturn (*this\y)
; ;EndMethod()
; PrivateData(n)
; ;Function pointers
; EndClass()
;
; EndMacro
;==========================================================================================================
#PB440 =0
CompilerIf #PB440
Macro e(e=o):EndMacr#e:EndMacro:Macro m():Macro :e()
m()ss(n):Structure n:e():m()es():EndStructure:e():m()param(p):,p:e():m()ClassPointer(n,pointer):pointer.m_#n :e()
m()ClassStructure(Class):ss(m_#class):*vt :e():m()ClassPrototypes(Class):es():Interface Class#_obj:Destroy(*obj):e()
m()ClassMethods(Class):EndInterface:Procedure new_#class(*obj.m_#class):*obj = AllocateMemory(SizeOf(m_#class))
If *obj: *obj\vt=?class#_vt: EndIf :ProcedureReturn *obj : EndProcedure:Procedure Destroy_#class(*obj):If *obj:
ClearStructure(*obj, m_#class): FreeMemory(*obj)
*obj=0:EndIf:EndProcedure:EndMacro:m()AddressTable(Class):DataSection:Class#_vt::Data.i @Destroy_#Class():e()
m()pFunc(Class,function):Data.i @function#_#class#():e():m()EndClass():EndDataSection:e()
m()PublicMethod(Class,name,type,params):Procedure type name#_#class#(*this.m_#class, params):e()
m()EndMethod():EndProcedure:e():m()PublicReturn:ProcedureReturn:e():m()Private:Protected:e()
CompilerElse
Macro e(e=o):EndMacr#e:EndMacro:Macro m():Macro :e()
m()ss(n):Structure n:e():m()es():EndStructure:e():m()param(p):,p:e():m()ClassPointer(n,pointer):pointer.m_#n :e()
m()ClassStructure(Class):ss(m_#class):*vt :e():m()ClassPrototypes(Class):es():Interface Class#_obj:Destroy(*obj):e()
m()ClassMethods(Class):EndInterface:Procedure New_#class(*obj.m_#class):*obj = AllocateMemory(SizeOf(m_#class))
If *obj: *obj\vt=?class#_vt: EndIf :ProcedureReturn *obj : EndProcedure:Procedure Destroy_#class(*obj):If *obj:
FreeMemory(*obj):*obj=0:EndIf:EndProcedure:EndMacro:m()AddressTable(Class):DataSection:Class#_vt::Data.i @Destroy_#Class():e()
m()pFunc(Class,function):Data.i @function#_#class#():e():m()EndClass():EndDataSection:e()
m()PublicMethod(Class,name,type,params):Procedure type name#_#class#(*this.m_#class, params):e()
m()EndMethod():EndProcedure:e():m()PublicReturn:ProcedureReturn:e():m()Private:Protected:e()
CompilerEndIf
;============================================================================================================
;Notes
;============================================================================================================
; When you have to pass more than one param in a PublicMethod use the param() macro
;
; PublicMethod(n,Set,.f,x.f param(y.f) param(z.f))
;
; If you have not params to pass use *null
; PublicMethod(n,GetX,.f,*null)
;
; If you need to Pass a Class references use the ClassPointer(n,*p2) Macro
;
; PublicMethod(n,Dot,.f,ClassPointer(n,*p2))
; or
; PublicMethod(n,Dot,.f,*p2.m_#n) using m_#n
;
;=============================================================================================================
; Example
;=============================================================================================================
Macro Vector3DClass(n)
ClassStructure(n)
;Structure types in here
x.f
y.f
z.f
mag.f
ClassPrototypes(n)
;Prototypes of the methods
Set(x.f,y.f,z.f)
GetX.f()
GetY.f()
GetZ.f()
;references to another class instance use ClassPointer macro ClassPointer(n,*clspointer)
Dot.f(ClassPointer(n,*p2))
Cross.i(ClassPointer(n,*p2))
ClassMethods(n)
;Public methods of the form
;PublicMethod(n,function-name, return-type, parameters)
;When passing more than one parmeter in the function use the Param() macro
PublicMethod(n,Set,.f,x.f Param(y.f) Param(z.f))
*this\mag = Sqr(x*x+y*y+z*z)
*this\x = x / *this\mag
*this\y = y / *this\mag
*this\z = z / *this\mag
EndMethod()
;If there is no parmameter put in *null
PublicMethod(n,getX,.f,*null)
PublicReturn (*this\x)
EndMethod()
PublicMethod(n,GetY,.f,*null)
PublicReturn (*this\y)
EndMethod()
PublicMethod(n,GetZ,.f,*null)
PublicReturn (*this\z)
EndMethod()
;If you need a reference to another class instance in the parmaeters use the ClassPointer(n,param)
PublicMethod(n,Dot,.f,ClassPointer(n,*p2))
PublicReturn (*this\x * *p2\x) + (*this\y * *p2\y) + (*this\z * *p2\z);
EndMethod()
PublicMethod(n,Cross,.i,ClassPointer(n,*p2))
Protected tx.f,ty.f,tz.f
tx = (*this\y * *p2\z) - (*this\z * *p2\y)
ty = (*this\z * *p2\x) - (*this\x * *p2\z)
tz = (*this\x * *p2\y) - (*this\y * *p2\x)
*this\x = tx
*this\y = ty
*this\z = tz
EndMethod()
AddressTable(n)
;Names of the methods specified in the same order as the ClassPrototypes
pfunc(n,Set)
pFunc(n,GetX)
pFunc(n,GetY)
pFunc(n,GetZ)
pFunc(n,Dot)
pFunc(n,Cross)
;To see the code generated by them macro remove the comment
;and right click in the macro error box select all and copy
EndClass();)
EndMacro
;The Macro Outputs==========================================================================================
;
; Structure m_Vector3D
; *vt
; x.f
; y.f
; z.f
; mag.f
; EndStructure
;
; Interface Vector3D_obj
; Destroy(*obj)
; Set(x.f,y.f,z.f)
; GetX.f()
; GetY.f()
; GetZ.f()
; Dot.f(*p2.m_Vector3D )
; Cross.i(*p2.m_Vector3D )
; EndInterface
;
; Procedure New_Vector3D(*obj.m_Vector3D)
; *obj = AllocateMemory(SizeOf(m_Vector3D))
; If *obj
; *obj\vt=?Vector3D_vt
; EndIf
; ProcedureReturn *obj
; EndProcedure
;
; Procedure Destroy_Vector3D(*obj)
; If *obj: FreeMemory(*obj)
; *obj=0
; EndIf
; EndProcedure
;
; Procedure.f Set_Vector3D(*this.m_Vector3D, x.f ,y.f ,z.f)
; *this\mag = Sqr(x*x+y*y+z*z)
; *this\x = x / *this\mag
; *this\y = y / *this\mag
; *this\z = z / *this\mag
; EndProcedure
;
; Procedure.f GetX_Vector3D(*this.m_Vector3D, *null)
; ProcedureReturn (*this\x)
; EndProcedure
;
; Procedure.f GetY_Vector3D(*this.m_Vector3D, *null)
; ProcedureReturn (*this\y)
; EndProcedure
;
; Procedure.f GetZ_Vector3D(*this.m_Vector3D, *null)
; ProcedureReturn (*this\z)
; EndProcedure
;
; Procedure.f Dot_Vector3D(*this.m_Vector3D, *p2.m_Vector3D )
; ProcedureReturn (*this\x * *p2\x) + (*this\y * *p2\y) + (*this\z * *p2\z)
; EndProcedure
;
; Procedure.i Cross_Vector3D(*this.m_Vector3D, *p2.m_Vector3D )
; Protected tx.f,ty.f,tz.f
; tx = (*this\y * *p2\z) - (*this\z * *p2\y)
; ty = (*this\z * *p2\x) - (*this\x * *p2\z)
; tz = (*this\x * *p2\y) - (*this\y * *p2\x)
; *this\x = tx
; *this\y = ty
; *this\z = tz
; EndProcedure
;
; DataSection: Vector3D_vt:
; Data.i @Destroy_Vector3D()
; Data.i @Set_Vector3D()
; Data.i @GetX_Vector3D()
; Data.i @GetY_Vector3D()
; Data.i @GetZ_Vector3D()
; Data.i @Dot_Vector3D()
; Data.i @Cross_Vector3D()
; EndDataSection
;=============================================================================================================
;
;Test the Class
;=============================================================================================================
;Create Class
Vector3DClass(Vector3D)
;Create objects
Global V1.Vector3D_obj = New_Vector3D(@V1)
Global V2.Vector3D_obj = New_Vector3D(@V2)
If V1 = #Null
Debug "V1 couldn't be created"
End
EndIf
V1\set(1.5, 0.2, -1.98)
V2\set(-1.90,-0.2,1.5)
Debug V1\Dot(V2)
Define x.f=((V1\getX() * V2\getX()) + (V1\gety() * V2\gety()) + (V1\getz() * V2\getz()))
Debug x
Debug V1\Cross(V2)
Debug V1\getX()
Debug V1\getY()
Debug V1\getZ()
V1\Destroy(@V1)
V2\Destroy(@V2)
Debug "done"