Overriding standard library with macros together with modules
Posted: Thu Jul 28, 2022 2:40 pm
You can override a standard library procedure with your own macro and then let the macro call your own custom procedure and from your custom procedure call the real library procedure, like the decorator pattern.
This is however dependent on the order you define your procedure and macro, moving the macro definition before the procedure definition will result in an endless loop, because the decorator will use the macro instead of the standard library procedure.
However when using modules, you can't call your own global procedure from within a module and procedures within modules can't be defined before a macro definition (only procedure declarations are allowed in the module declaration)
Thus the following code will not use the decorator because of global scoping
And the following will result in an endless loop.
If I split the Decorator into two modules, where the decorator procedure is in the first and the macro in the second it does work
This is however really convoluted. Is there any other way?
Reason why I'm asking is that there are some memory leak tracking code posted on this forum that uses this override technique but without modules
https://www.purebasic.fr/english/viewtopic.php?t=39168
Simplified
https://www.purebasic.fr/english/viewtopic.php?t=56737
Modifying this code to using two modules and compiler directives everywhere is quite messy. It is easier to just call the decorator directly, but then your code will be less portable if other projects does not have the same decorator.
Code: Select all
Procedure MessageRequesterDecorator(Title$, Text$ , Flags = #Null)
Debug "Hello from decorator!"
MessageRequester(Title$, Text$, Flags)
EndProcedure
Macro MessageRequester(Title, Text , Flags = #Null)
MessageRequesterDecorator(Title, Text, Flags)
EndMacro
MessageRequester("Info", "Hello, World!")However when using modules, you can't call your own global procedure from within a module and procedures within modules can't be defined before a macro definition (only procedure declarations are allowed in the module declaration)
Thus the following code will not use the decorator because of global scoping
Code: Select all
Procedure MessageRequesterDecorator(Title$, Text$ , Flags = #Null)
Debug "Hello from decorator!"
MessageRequester(Title$, Text$, Flags)
EndProcedure
Macro MessageRequester(Title, Text , Flags = #Null)
MessageRequesterDecorator(Title, Text, Flags)
EndMacro
DeclareModule MyModule
Declare Run()
EndDeclareModule
Module MyModule
Procedure Run()
MessageRequester("Info", "Hello, World!")
EndProcedure
EndModule
MyModule::Run() ; decorator not calledAnd the following will result in an endless loop.
Code: Select all
DeclareModule Decorator
Declare MessageRequesterDecorator(Title$, Text$ , Flags = #Null)
Macro MessageRequester(Title, Text , Flags = #Null)
MessageRequesterDecorator(Title, Text, Flags)
EndMacro
EndDeclareModule
Module Decorator
Procedure MessageRequesterDecorator(Title$, Text$ , Flags = #Null)
Debug "Hello from decorator!"
MessageRequester(Title$, Text$, Flags)
EndProcedure
EndModule
DeclareModule MyModule
Declare Run()
EndDeclareModule
Module MyModule
UseModule Decorator
Procedure Run()
MessageRequester("Info", "Hello, World!")
EndProcedure
EndModule
MyModule::Run() ; endless loopCode: Select all
DeclareModule Decorator
Declare MessageRequesterDecorator(Title$, Text$ , Flags = #Null)
EndDeclareModule
Module Decorator
Procedure MessageRequesterDecorator(Title$, Text$ , Flags = #Null)
Debug "Hello from decorator!"
MessageRequester(Title$, Text$, Flags)
EndProcedure
EndModule
DeclareModule Override
Macro MessageRequester(Title, Text , Flags = #Null)
Decorator::MessageRequesterDecorator(Title, Text, Flags)
EndMacro
EndDeclareModule
Module Override
EndModule
DeclareModule MyModule
Declare Run()
EndDeclareModule
Module MyModule
UseModule Override
Procedure Run()
MessageRequester("Info", "Hello, World!")
EndProcedure
EndModule
MyModule::Run()Reason why I'm asking is that there are some memory leak tracking code posted on this forum that uses this override technique but without modules
https://www.purebasic.fr/english/viewtopic.php?t=39168
Simplified
https://www.purebasic.fr/english/viewtopic.php?t=56737
Modifying this code to using two modules and compiler directives everywhere is quite messy. It is easier to just call the decorator directly, but then your code will be less portable if other projects does not have the same decorator.