It is currently Tue Jul 14, 2020 9:23 pm

All times are UTC + 1 hour




Post new topic Reply to topic  [ 7 posts ] 
Author Message
 Post subject: MacroBuilder module
PostPosted: Sun Sep 08, 2013 4:24 pm 
Offline
Addict
Addict
User avatar

Joined: Mon May 26, 2003 3:07 pm
Posts: 1477
Location: Nantes
  • Define Macro
  • Override method name

original tip from cxAlex : viewtopic.php?f=3&t=53826

Code:
;:=============================================================================
;:- MacroBuilder.pbi
;:- Author          : Eddy
;:- Date            : September 8, 2013
;:- Compiler        : PureBasic 5.20 beta 16 LTS
;:- Target OS       : Mac, Linux, Windows
;:- Source --------------------------------------------------------------------
;:- http://www.purebasic.fr/english/viewtopic.php?f=40&t=56522
;:=============================================================================
CompilerIf Not Defined(MacroBuilder, #PB_Module)
   DeclareModule MacroBuilder
      EnableExplicit
     
      Macro _DoubleQuote
         "
      EndMacro
     
      Macro _Colon
         :
      EndMacro
     
      Macro ConcatMacro(a, b)
         a#b
      EndMacro
     
      Macro DefineMacro(_MacroHead, _MacroBody)
         _Colon#Macro _MacroHead#_Colon#_MacroBody#_Colon#EndMacro
      EndMacro
     
      Macro Override(_Name, _Prefix=_)
         DefineMacro(_Name, ConcatMacro(_Prefix, _Name))
      EndMacro
   EndDeclareModule
   
   Module MacroBuilder
   EndModule
CompilerEndIf


CompilerIf #PB_Compiler_IsMainFile
   ; ********************
   ; EXAMPLE
   ; ********************
   
   UseModule MacroBuilder
   
   DefineMacro(Add(x, y), (x + y))
   DefineMacro(Sub(x, y), (x-y))
   DefineMacro(Mul(x, y), (x*y))
   DefineMacro(Div(x, y), (x / y))
   
   Debug Add(2, 3)
   Debug Sub(2, 3)
   Debug Mul(2, 3)
   Debug Div(2, 3)
   
   Override(OpenConsole)
   
   Procedure OpenConsole(Title$)
      MessageRequester(Title$, "Console is open... or not :)")
   EndProcedure
   
   OpenConsole("OpenConsole")
CompilerEndIf

_________________
Imagewin8.1 x64 5.31 | IDE | PB plugin | Tools | Sprite | JSON | visual tool


Last edited by eddy on Sun Jun 14, 2015 5:14 pm, edited 2 times in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: MacroBuilder module
PostPosted: Sun Sep 08, 2013 4:49 pm 
Offline
Addict
Addict
User avatar

Joined: Wed Aug 31, 2005 11:09 pm
Posts: 3698
Location: Italy
The result of the macro Override being a macro outputting the original identifier preceded by "_" and so seamlessly replacing all the "OpenConsole" in the code with a hidden "_Openconsole" is a pretty clever idea, looks almost native :)

_________________
[ My little PureBasic review ]


Top
 Profile  
Reply with quote  
 Post subject: Re: MacroBuilder module
PostPosted: Sun Sep 08, 2013 10:26 pm 
Offline
Addict
Addict
User avatar

Joined: Mon May 26, 2003 3:07 pm
Posts: 1477
Location: Nantes
- just a minor optimization (extra parameters removed) :wink:
Code:
Macro DefineMacro(_MacroHead, _MacroBody, _Start=, _End=End)
Code:
Macro DefineMacro(_MacroHead, _MacroBody)

_________________
Imagewin8.1 x64 5.31 | IDE | PB plugin | Tools | Sprite | JSON | visual tool


Last edited by eddy on Mon Sep 09, 2013 12:22 am, edited 2 times in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: MacroBuilder module
PostPosted: Sun Sep 08, 2013 11:59 pm 
Offline
Enthusiast
Enthusiast

Joined: Tue Apr 24, 2012 5:08 pm
Posts: 542
Location: Ontario, Canada
@eddy

Here's our version of the above technique. We use it to dynamically create macros that can be used to generate unique procedure and data names in classes and modules. This is just a small sample to show how we create modular code without actually using modules.

We create a standard "_Block_" macro that can be used whenever a unique name needs to be created. The "_Blank_" and "_Colon_" parameters are needed to ensure that PB doesn't misinterpret the macro contents before it's fully generated.

Code:
Macro _Colon_
  :
EndMacro
     
Macro CreateBlockName(_BlockName_, _Blank_=)
  _Blank_#Macro _B#_Blank_#lock_#_Colon_#_BlockName_#_Colon_#EndMacro
EndMacro
     
Macro DestroyBlockName(_Blank_=)
  UndefineMacro _B#_Blank_#lock_
EndMacro

Macro BeginClass (bvsClassName)
  CreateBlockName(bvsClassName) 
EndMacro

Macro EndClass
  DestroyBlockName()
EndMacro

Macro typObject
  I
EndMacro

Macro DeclareExternalFunction (bvsProcName, bvsDataParmType)
  Declare.bvsDataParmType cls#_Block_#_fun#bvsProcName
EndMacro

Macro BeginClassInterface
  DeclareExternalFunction(Create, typObject) ()
  Interface obj#_Block_
EndMacro

Macro EndClassInterface
  EndInterface
EndMacro

BeginClass (ButtonBar)  ;  Macro _Block_:ButtonBar:EndMacro
BeginClassInterface     ;  Declare.I clsButtonBar_funCreate ()
                        ;  Interface objButtonBar   
EndClassInterface       ;  EndInterface
EndClass                ;  UndefineMacro _Block_

BeginClass (Button)     ;  Macro _Block_:Button:EndMacro
BeginClassInterface     ;  Declare.I clsButton_funCreate ()
                        ;  Interface objButton   
EndClassInterface       ;  EndInterface
EndClass                ;  UndefineMacro _Block_


And for those of you who really love to read my code, here are the two procedures referenced above. As you can see, much of the code is identical, even though the procedures are from two different classes. The underlying code uses the "_Block_" macro to create names that are unique to each class, thereby allowing the entire program to be compiled as a single source file.

Code:
ExternalFunction(Create, typObject) ()            ;  Procedure.I clsButtonBar_funCreate ()
;
;  Create  -  create a class instance
;
  Local(Me, strButtonBar)                         ;    Protected *Self.strButtonBar

  Me = AllocateMemory(SizeOf(strButtonBar))       ;    *Self = AllocateMemory(SizeOf(strButtonBar))
  If IsObject(Me)                                 ;    If *Self <> 0
    InitializeStructure(Me, strButtonBar)         ;      InitializeStructure(*Self, strButtonBar)
    Me\prpVirtualTable = LabelPtr(VirtualTable)   ;      *Self\prpVirtualTable = ?clsButtonBar_lblVirtualTable
    ClassCall(Constructor) (Me)                   ;      clsButtonBar_subConstructor (*Self)
  EndIf                                           ;    EndIf
  ProcedureReturn Me                              ;    ProcedureReturn *Self
EndFunction                                       ;  EndProcedure


Code:
ExternalFunction(Create, typObject) ()            ;  Procedure.I clsButton_funCreate ()
;
;  Create  -  create a class instance
;
  Local(Me, strButton)                            ;    Protected *Self.strButton

  Me = AllocateMemory(SizeOf(strButton))          ;    *Self = AllocateMemory(SizeOf(strButton))
  If IsObject(Me)                                 ;    If *Self <> 0
    InitializeStructure(Me, strButton)            ;      InitializeStructure(*Self, strButton)
    Me\prpVirtualTable = LabelPtr(VirtualTable)   ;      *Self\prpVirtualTable = ?clsButton_lblVirtualTable
    ClassCall(Constructor) (Me)                   ;      clsButton_subConstructor (*Self)
  EndIf                                           ;    EndIf
  ProcedureReturn Me                              ;    ProcedureReturn *Self
EndFunction                                       ;  EndProcedure


Here are the macros used in the above methods. In total, we use about 500 macros in generating our code. As you can see, I'm a big fan of long names and Polish notation. :)

Code:
Macro Me
  *Self
EndMacro

Macro ExternalFunction (bvsProcName, bvsDataParmType)
  Procedure.bvsDataParmType cls#_Block_#_fun#bvsProcName
EndMacro

Macro EndFunction
  EndProcedure
EndMacro

Macro ClassCall (bvsProcName)
  cls#_Block_#_sub#bvsProcName
EndMacro

Macro Local (bvsDataParmName, bvsDataParmType)
  Protected bvsDataParmName.bvsDataParmType
EndMacro

Macro IsObject (bvsDataParmName)
  bvsDataParmName <> 0
EndMacro

Macro LabelPtr (bvsDataParmName)
  ?cls#_Block_#_lbl#bvsDataParmName
EndMacro

_________________
For ten years Caesar ruled with an iron hand, then with a wooden foot, and finally with a piece of string.
~ Spike Milligan


Top
 Profile  
Reply with quote  
 Post subject: Re: MacroBuilder module
PostPosted: Sun Jun 14, 2015 5:21 pm 
Offline
Addict
Addict
User avatar

Joined: Mon May 26, 2003 3:07 pm
Posts: 1477
Location: Nantes
Updated
- ConcatMacro
- Multiple method overrding

Code:
   UseModule MacroBuilder

   Override(OpenConsole)   
   Procedure OpenConsole(Text$)
      MessageRequester(Title$, "The console said "+Text$)
   EndProcedure
   OpenConsole("Eddy")

   Override(OpenConsole)   
   Procedure OpenConsole(Text$)
      MessageRequester(Title$, "Hello "+Text$)
   EndProcedure   
   OpenConsole("Eddy")

_________________
Imagewin8.1 x64 5.31 | IDE | PB plugin | Tools | Sprite | JSON | visual tool


Top
 Profile  
Reply with quote  
 Post subject: Re: MacroBuilder module
PostPosted: Sun May 15, 2016 5:06 pm 
Offline
Enthusiast
Enthusiast

Joined: Mon Feb 04, 2013 5:28 pm
Posts: 333
I would have a use for this, but unfortunately if you invoke DefineMacro from another macro the calling macro just terminates prematurely.

Code:

UseModule MacroBuilder

Macro test()
 Debug "hello"
 DefineMacro(Add(x, y), (x + y))
 Debug "world"
EndMacro   
   
test()
   
 


Should print

hello
world

instead prints

hello

I have the need to create a macro from another macro (and that works) but then continue with the rest of the macro body.


Top
 Profile  
Reply with quote  
 Post subject: Re: MacroBuilder module
PostPosted: Sun May 15, 2016 5:10 pm 
Offline
Enthusiast
Enthusiast

Joined: Mon Feb 04, 2013 5:28 pm
Posts: 333
Simplified

Code:
Macro _C_
  :
EndMacro
     
Macro CreateMacro(_MacroHead, _MacroBody_)
 Macro _MacroHead#_C_#_MacroBody_#_C_#EndMacro
EndMacro

Macro MyMacro(p)
 Debug "hello " + p
 CreateMacro(foo(), "working")
 Debug "world " + p
EndMacro


MyMacro("param") ; should print hello param, world param

Debug foo() ; the foo() macro has been defined


output

Code:
hello param
working


Macros do not seem to work reliably unless you stick to trivial usages, these quirks should be fixed.

Unfortunately I'm not optimist judging from other old standing macro issues still unresolved. :cry:


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 7 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 5 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye