Although we cannot declare modules within modules, we CAN define variables inside of them with an interface. This was an experiment to see how useful this would be with shapes.
Summary of findings:
- Due to this problem, I couldn't find a way to use a macro to define Shape2i as SHAPE to hide its type.
- This method makes UseModule unappealing as it ends up polluting the local namespace with variable names of the generic interface variables. For example, "UseModule Shape2i" means that I can't make a variable named "triangle".
- Because interfaces cannot declare other interfaces as return types, this usefulness is rather limited.
- This provides a workaround for only one additional depth. This is still useful if modules are designed with this in mind but duplicates a lot of code.
- PureBasic's lack of support for arrays outside of structures is annoying and adds unnecessary verbosity
For example, this:
Code: Select all
Interface IClass
fromXY(_IN x1.Type::INT_32,
_IN y1.Type::INT_32,
_IN x2.Type::INT_32,
_IN y2.Type::INT_32,
_IN x3.Type::INT_32,
_IN y3.Type::INT_32)
EndInterface
Code: Select all
Interface IClass
Declare.IObject
fromXY(
_IN x1.Type::INT_32,
_IN y1.Type::INT_32,
_IN x2.Type::INT_32,
_IN y2.Type::INT_32,
_IN x3.Type::INT_32,
_IN y3.Type::INT_32
)
EndInterface
Some people elsewhere on the forum have expressed confusion over some of my reports and feature requests. I really enjoy programming in PureBasic but I find that I have a habit of it to the limit and frustrating myself in the process; that's why I disappear from time to time.
Anyways, here is the result of the experiment. Note that this is just a sample and some of the modules are only portioned such as SAL and Type.
Enjoy!
Modules:
Code: Select all
;-- SAL
DeclareModule SAL
Macro _IN
EndMacro
Macro _IN_OPT
EndMacro
EndDeclareModule
Module SAL
EndModule
;-- Type
DeclareModule Type
Macro VOID
i
EndMacro
Macro POINTER
i
EndMacro
Macro INT_32
l
EndMacro
Macro INT_32_64
i
EndMacro
Structure POINTER_TYPE
EndStructure
EndDeclareModule
Module Type
EndModule
;-- Geometry
DeclareModule Geometry
Structure Point2i
x.Type::INT_32
y.Type::INT_32
EndStructure
Structure Line2i
x1.Type::INT_32
y1.Type::INT_32
x2.Type::INT_32
y2.Type::INT_32
EndStructure
Structure Point2iArray
point.Point2i[0]
EndStructure
Structure Point2iArray3
point.Point2i[3]
EndStructure
Structure Point2iSizeArray
size.Type::INT_32_64
point.Point2i[0]
EndStructure
Structure Point2iSizeArray3
size.Type::INT_32_64
point.Point2i[3]
EndStructure
EndDeclareModule
Module Geometry
EndModule
;-- Polygon2i
DeclareModule Polygon2i
Structure PointArray Extends Geometry::Point2iArray
EndStructure
Structure PointSizeArray Extends Geometry::Point2iSizeArray
EndStructure
EndDeclareModule
Module Polygon2i
EndModule
;-- Triangle2i
DeclareModule Triangle2i
UseModule SAL
#SIZE=3
Macro OBJECT_POINTER
Type::POINTER
EndMacro
Macro BYTE_ARRAY
Type::POINTER_TYPE
EndMacro
Macro POINT_ARRAY
Type::POINTER_TYPE
EndMacro
Structure PointArray
point.Geometry::Point2i[3]
EndStructure
Structure PointSizeArray Extends Geometry::Point2iSizeArray3
EndStructure
Structure IClassVTable
*new
*fromPoints
*fromXY
EndStructure
Structure IObjectVTable
*copy
*delete
*size
*toByteArray
*toPointArray
*toPointSizeArray
EndStructure
Structure Class
*vTable.IClassVTable
EndStructure
Structure Object
*vTable.IObjectVTable
*class.IClass
size.Type::INT_32_64
shape.PointArray
EndStructure
Interface IClass
new(_IN_OPT *other.Object=0)
fromPoints(_IN *point1.Geometry::Point2i,
_IN *point2.Geometry::Point2i,
_IN *point3.Geometry::Point2i)
fromXY(_IN x1.Type::INT_32,
_IN y1.Type::INT_32,
_IN x2.Type::INT_32,
_IN y2.Type::INT_32,
_IN x3.Type::INT_32,
_IN y3.Type::INT_32)
EndInterface
Interface IObject
copy()
delete()
size()
toByteArray()
toPointArray()
toPointSizeArray()
EndInterface
Declare.OBJECT_POINTER new(_IN_OPT *other.Object=0)
Global class.IClass
EndDeclareModule
Module Triangle2i
UseModule Type
Macro BYTE_ARRAY_POINTER
POINTER
EndMacro
Macro POINT_ARRAY_POINTER
POINTER
EndMacro
Macro POINT_SIZE_ARRAY_POINTER
POINTER
EndMacro
Macro CLASS_POINTER
POINTER
EndMacro
Macro VTABLE_POINTER
POINTER
EndMacro
Declare.VOID setIClassVTable(_IN_OPT *vTable.IClassVTable=0)
Declare.VOID setIObjectVTable(_IN_OPT *vTable.IObjectVTable=0)
;/ Static
Global classVTable.IClassVTable
setIClassVTable(@classVTable)
*instance.Class
*instance=AllocateStructure(Class)
*instance\vTable=@classVTable
class=*instance
;/ STATIC
Procedure.OBJECT_POINTER new(_IN_OPT *other.Object=0)
ProcedureReturn class\new()
EndProcedure
;/ STATIC
Procedure.OBJECT_POINTER newInstance(_IN *this.Class,
_IN_OPT *other.Object=0)
Protected *instance.Object
*instance=AllocateStructure(Object)
*instance\vTable=setIObjectVTable()
*instance\class=class
*instance\size=#Size
If *other
CompilerIf #PB_Compiler_Debugger
If Not *other\size=#Size
DebuggerError("Other object is not the right size")
EndIf
CompilerEndIf
CopyMemory(@*other\shape,@*instance\shape,SizeOf(PointArray))
EndIf
ProcedureReturn *instance
EndProcedure
;/ STATIC
Procedure.OBJECT_POINTER fromPoints(_IN *this.Class,
_IN *point1.Geometry::Point2i,
_IN *point2.Geometry::Point2i,
_IN *point3.Geometry::Point2i)
Protected *shape.Object=class\new()
*shape\shape\point[0]\x=*point1\x
*shape\shape\point[0]\y=*point1\y
*shape\shape\point[1]\x=*point2\x
*shape\shape\point[1]\y=*point2\y
*shape\shape\point[2]\x=*point3\x
*shape\shape\point[2]\y=*point3\y
ProcedureReturn *shape
EndProcedure
;/ STATIC
Procedure.OBJECT_POINTER fromXY(_IN *this.Class,
_IN x1.INT_32,
_IN y1.INT_32,
_IN x2.INT_32,
_IN y2.INT_32,
_IN x3.INT_32,
_IN y3.INT_32)
Protected *shape.Object=class\new()
*shape\shape\point[0]\x=x1
*shape\shape\point[0]\y=y1
*shape\shape\point[1]\x=x2
*shape\shape\point[1]\y=y2
*shape\shape\point[2]\x=x3
*shape\shape\point[2]\y=y3
ProcedureReturn *shape
EndProcedure
Procedure.OBJECT_POINTER copy(_IN *this.Object,
_IN *other.Object)
ProcedureReturn new(*other)
EndProcedure
Procedure.INT_32_64 size(_IN *this.Object)
ProcedureReturn *this\size
EndProcedure
Procedure.VOID delete(_IN *this.Object)
FreeStructure(*this)
EndProcedure
Procedure.BYTE_ARRAY_POINTER toByteArray(_IN *this.Object)
ProcedureReturn @*this\shape
EndProcedure
Procedure.POINT_ARRAY_POINTER toPointArray(_IN *this.Object)
ProcedureReturn @*this\shape
EndProcedure
Procedure.POINT_SIZE_ARRAY_POINTER toPointSizeArray(_IN *this.Object)
ProcedureReturn @*this\size
EndProcedure
;/ Private
Procedure.VTABLE_POINTER setIClassVTable(_IN_OPT *vTable.IClassVTable=0)
If *vTable=0
*vTable=AllocateStructure(IClassVTable)
EndIf
*vTable\new=@newInstance()
*vTable\fromPoints=@fromPoints()
*vTable\fromXY=@fromXY()
ProcedureReturn *vTable
EndProcedure
Procedure.VTABLE_POINTER setIObjectVTable(_IN_OPT *vTable.IObjectVTable=0)
If *vTable=0
*vTable=AllocateStructure(IObjectVTable)
EndIf
*vTable\copy=@copy()
*vTable\size=@size()
*vTable\delete=@delete()
*vTable\toByteArray=@toByteArray()
*vTable\toPointArray=@toPointArray()
*vTable\toPointSizeArray=@toPointSizeArray()
ProcedureReturn *vTable
EndProcedure
EndModule
;-- Shape2i
DeclareModule Shape2i
Macro BYTE_ARRAY
Type::POINTER_TYPE
EndMacro
Structure PointArray Extends Geometry::Point2iArray
EndStructure
Structure PointSizeArray Extends Polygon2i::PointSizeArray
EndStructure
Interface ITriangle Extends Triangle2i::IObject
EndInterface
Global Triangle.Triangle2i::IClass=Triangle2i::class
EndDeclareModule
Module Shape2i
EndModule
Code: Select all
UseModule Type
Define triangle.Shape2i::ITriangle
Define i.INT_32_64
;/ Testing new()
triangle=Shape2i::Triangle\new()
Define *pointArray.Shape2i::PointArray
;/ Testing toPointArray()
*pointArray=triangle\toPointArray()
;/ Testing size()
For i=0 To triangle\size()-1
*pointArray\point[i]\x=i
*pointArray\point[i]\y=i
Next i
;/ Testing assignment()
For i=0 To triangle\size()-1
Debug "*pointArray\point["+Str(i)+"]\x "+Str(*pointArray\point[i]\x)
Debug "*pointArray\point["+Str(i)+"]\y "+Str(*pointArray\point[i]\y)
Next i
Debug ""
Define temp.Shape2i::ITriangle
;/ Testing copy()
temp=triangle\copy()
;/ Testing delete()
triangle\delete()
triangle=temp
;/ Testing copy assignment()
For i=0 To triangle\size()-1
Debug "*pointArray\point["+Str(i)+"]\x "+Str(*pointArray\point[i]\x)
Debug "*pointArray\point["+Str(i)+"]\y "+Str(*pointArray\point[i]\y)
Next i
Debug ""
triangle\delete()
;/ Testing fromXY()
triangle=Shape2i::Triangle\fromXY(65,7, 113,91, 17,91)
;/ Testing toPointSizeArray()
Define *pointSizeArray.Shape2i::PointSizeArray
*pointSizeArray=triangle\toPointSizeArray()
For i=0 To *pointSizeArray\size-1
Debug "*pointSizeArray\point["+Str(i)+"]\x "+Str(*pointSizeArray\point[i]\x)
Debug "*pointSizeArray\point["+Str(i)+"]\y "+Str(*pointSizeArray\point[i]\y)
Next i