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.
The english grammar is freeware, you can use it freely - But it's not Open Source, i.e. you can not change it or publish it in altered way.