With nested macros you are able to do overloading of procedures.
The following code works and overloads four Procedures to multiply, add, subtract and divide 3D-vectors with 3D-vectors, 3D-vectors with skalars or skalars with 3D-vectors.
Code: Select all
EnableExplicit
Structure Vector
x.f
y.f
z.f
EndStructure
Macro MacroRo
ro
EndMacro
Macro VectorOp(op, opName)
Procedure Vector#opName#Vector(*a.Vector, *b.Vector)
*a\x op *b\x
*a\y op *b\y
*a\z op *b\z
EndProcedure
Procedure Vector#opName#Skalar(*a.Vector, b.f)
*a\x op b
*a\y op b
*a\z op b
EndProcedure
Mac#MacroRo Vector#opName(a, b)
CompilerIf Defined(a, #PB_Variable) ;a is a variable?
CompilerIf Defined(b, #PB_Variable) ;b is a variable?
CompilerIf TypeOf(b) = #PB_Structure ;b has a structure (unfortunality we can not check if the structure is really Vector)
CompilerIf TypeOf(a) = #PB_Structure ;a has a structure
Vector#opName#Vector(a, b) ;a and b have a structur
CompilerElse
Vector#opName#Skalar(b, a) ;b has a structure and a is a normal variable, maybe float or integer
CompilerEndIf
CompilerElse
CompilerIf TypeOf(a) = #PB_Structure
Vector#opName#Skalar(a, b) ;a has a structure and b is a normal variable, maybe float or integer
CompilerElse
CompilerError "VectorMul(Float, Float): At least on parameter has to be of type Vector."
CompilerEndIf
CompilerEndIf
CompilerElse
CompilerIf TypeOf(a) = #PB_Structure
Vector#opName#Skalar(a, b) ;a has a structure und b is a constant value (until now only integers are possible)
CompilerElse
CompilerError "VectorMul(Float, Constant): At least on parameter has to be of type Vector."
CompilerEndIf
CompilerEndIf
CompilerElse
CompilerIf Defined(b, #PB_Variable)
CompilerIf TypeOf(b) = #PB_Structure
Vector#opName#Skalar(b, a) ;b has a structure und a is a constant value
CompilerElse
CompilerError "VectorMul(Constant, Float): At least on parameter has to be of type Vector."
CompilerEndIf
CompilerElse ;a und b sind keine Variablen -> Fehler
CompilerError "VectorMul(Constant, Constant): At least on parameter has to be of type Vector."
CompilerEndIf
CompilerEndIf
; EndMac#MacroRo
EndMacro
;For some reason I had to put the EndMacro after VectorOp instead of uncomment it three lines above
VectorOp(*, Mul)
EndMacro
VectorOp(+, Add)
EndMacro
VectorOp(/, Div)
EndMacro
VectorOp(-, Sub)
EndMacro
; After these macro executions the following procedures exist
; - VectorMulVector(*a.Vector, *b.Vector)
; - VectorMulSkalar(*a.Vector, b.f)
; - VectorAddVector(*a.Vector, *b.Vector)
; - VectorAddSkalar(*a.Vector, b.f)
; - VectorDivVector(*a.Vector, *b.Vector)
; - VectorDivSkalar(*a.Vector, b.f)
; - VectorSubVector(*a.Vector, *b.Vector)
; - VectorSubSkalar(*a.Vector, b.f)
;
; The following four macros help you ignoring the type and order of the parameters (overloading)
; - VectorMul(a, b)
; - VectorAdd(a, b)
; - VectorDiv(a, b)
; - VectorSub(a, b)
Define a.Vector, b.Vector, c.f
a\x = 1 : a\y = 2 : a\z = 3
b\x = 1 : b\y = 2 : b\z = 3
c = 4
Debug "a = (" + a\x + ", " + a\y + ", " + a\z + ")"
Debug "b = (" + b\x + ", " + b\y + ", " + b\z + ")"
Debug "c = " + c
VectorAdd(a, b) ;Vector + Vector
Debug "a + b"
Debug "a = (" + a\x + ", " + a\y + ", " + a\z + ")"
VectorMul(c, a) ;Skalar * Vector
Debug "c * a"
Debug "a = (" + a\x + ", " + a\y + ", " + a\z + ")"
VectorDiv(a, c) ;Vector / Skalar
Debug "a / c"
Debug "a = (" + a\x + ", " + a\y + ", " + a\z + ")"
VectorSub(a, b) ;Vector - Vector
Debug "a - b"
Debug "a = (" + a\x + ", " + a\y + ", " + a\z + ")"
VectorMul(a, 4) ;Vector * 4 ;Until now, it is not possible to using floating point numbers, but integers work as expected
Debug "a * 4"
Debug "a = (" + a\x + ", " + a\y + ", " + a\z + ")"
;To test the error checking uncomment one or more of these lines
;VectorAdd(3, 4)
;VectorAdd(c, c)
;VectorAdd(c, 2)
With native support for nested macros and a better TypeOf() command which also can distinguish between different structures, "constant strings" and constant floating point numbers (123.456), this example could be only the beginning of more advanced macroing.