Test if macro is used - conditional jump...

Just starting out? Need help? Post your questions and find answers here.
Dudemeister
User
User
Posts: 29
Joined: Sat Oct 26, 2019 6:48 pm

Test if macro is used - conditional jump...

Post by Dudemeister »

I have a question regarding conditional execution (or jump) from one macro to another. I don't know if I use the correct terminology below, so please be patient with me.

Macro One
    !jmp two_label
EndMacro

Macro Two
    If three_label is used in MyProcedure ;pseudo-code to demonstrate what I need...
        !jmp three_label
    Else
        !jmp four_label
    EndIf
EndMacro

Macro Three
    !jmp four_label
EndMacro

Macro Four
    Do something other than jump
EndMacro


Procedure MyProcedure()
    One
        Do something cool here

    Two
        Do something even more cool here

    Four
        Do some clean up here

    ;Note: macro label 'Three' was not used above in this procedure, so execution jumped directly to macro label 'Four'

EndProcedure


Now that I laid out all that above, here is my question:

Does anyone know of a way to test within one macro if a separate macro is being used (or is called) within a procedure.

Ie: When macro 'Two' executes, the flow of execution will "jump" to macro 'Three', but it will do so only if 'Three' is called in that procedure. If macro 'Three' is not called in the procedure, the flow of execution jumps directly to macro 'Four', instead.

What I am testing here is if it is possible to perform conditional jump from one macro to another macro, based on whether the second macro is called in the procedure.
infratec
Always Here
Always Here
Posts: 7575
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Test if macro is used - conditional jump...

Post by infratec »

If you need to jump, you should think about your code. :wink:

Really, I think if you have to use such jumps, your code flow is not like it should be.

And no, there is no way to test if a Macro is in use.
You can only test if a Macro is defined.

Maybe you can create labels and test if the label is defined.
User avatar
Olliv
Enthusiast
Enthusiast
Posts: 542
Joined: Tue Sep 22, 2009 10:41 pm

Re: Test if macro is used - conditional jump...

Post by Olliv »

Houla...

2 remarks...

1) Please use normalized markups

Code: Select all

[code]Debug "code"
[/code]

2) You should use procedures instead of macros... And in your way, you should use selector

Code: Select all

Dim *Address(255) ; address allocating
; ...
Procedure myProcedure() ; a target address
 Debug "kiki"
EndProcedure
; ...
*Address(0) = @myProcedure() ; set the address
; ...
CallFunctionFast(LabelList(LabelIndex) ) ; equ to Jump or Call
Simpler...
BarryG
Addict
Addict
Posts: 4121
Joined: Thu Apr 18, 2019 8:17 am

Re: Test if macro is used - conditional jump...

Post by BarryG »

Macros can't be called; they're just search/replace of your source code at compile time. Not like procedures.

For example, this source code:

Code: Select all

Macro Counter()
  For c=1 To 10
    n+c
  Next
EndMacro

Counter() ; First "call"

Counter() ; Second "call"

Debug n
Just becomes this when compiled/run:

Code: Select all

For c=1 To 10 ; First "call"
  n+c
Next

For c=1 To 10 ; Second "call"
  n+c
Next

Debug n
User avatar
djes
Addict
Addict
Posts: 1806
Joined: Sat Feb 19, 2005 2:46 pm
Location: Pas-de-Calais, France

Re: Test if macro is used - conditional jump...

Post by djes »

No. A macro is not called. Think a macro as a "cut and paste" code before compilation. I think that you'd like something that is usually done in assembly. In assembly, you can even dynamically alter your code, so the 'jump' value could be changed. But these practices tend to disappear, as it has been used in numerous viruses and trojans.
In PB you can mix assembly (for example a dynamic jmp) in normal code, somewhat as olliv does. Also note that a lot a coders will see that as bad code, because it is difficult to maintain and understand. Anyway, for short code speed demonstration or low level it is OK.

Edit> BarryG ;)
BarryG
Addict
Addict
Posts: 4121
Joined: Thu Apr 18, 2019 8:17 am

Re: Test if macro is used - conditional jump...

Post by BarryG »

djes wrote:Edit> BarryG ;)
:lol:
User avatar
mk-soft
Always Here
Always Here
Posts: 6201
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Test if macro is used - conditional jump...

Post by mk-soft »

When jumping, it is important to note that it can lead to errors in the program if it is not handled correctly. See in the help for 'FakeReturn'

Better to work with break.

You can also create your own keywords with macros and add them in the editor.
For example 'Do, ExitDo, EndDo'.

Code: Select all

;-TOP

EnableExplicit

Macro Do
  Repeat
EndMacro

Macro ExitDo
  Break
EndMacro

Macro EndDo
  Until #True
EndMacro


Define a = 25

Repeat ; Do
  
  If a < 10
    Debug "Is lower 10"
    Break ; ExitDo
  EndIf
  
  a + 10
  If a > 30
    Debug "Is bigger 30"
    Break ; ExitDo
  EndIf
  
  a * 1000
  
Until #True ; EndDo

Debug "a = " + a
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
infratec
Always Here
Always Here
Posts: 7575
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Test if macro is used - conditional jump...

Post by infratec »

As real 'working' code:

Code: Select all

Macro One
  one_label:
  Goto  two_label
EndMacro

Macro Two
  two_label:
  CompilerIf Defined(three_label, #PB_Label)
    Goto three_label
  CompilerElse
    Goto four_label
  CompilerEndIf
EndMacro

Macro Three
  three_label:
  Goto  four_label
EndMacro

Macro Four
  four_label:
  Debug "4"
EndMacro


Procedure MyProcedure()
  One
  Debug "Do something cool here"
  
  Two
  Debug "Do something even more cool here"
  
  Four
  Debug "Do some clean up here"
  
  ;Note: macro label 'Three' was not used above in this procedure, so execution jumped directly to macro label 'Four'
  
EndProcedure

MyProcedure()
Dudemeister
User
User
Posts: 29
Joined: Sat Oct 26, 2019 6:48 pm

Re: Test if macro is used - conditional jump...

Post by Dudemeister »

@infratec

Your genius there is exactly what I was looking for, and it's working great. Now, before I unveil my mad experiment that I am doing with this, I need to know one last thing related to this.

Regarding the compiler directive:

Code: Select all

CompilerIf Defined(three_label, #PB_Label)
    Goto three_label
CompilerElse
    Goto four_label
CompilerEndIf
This structure worked perfectly in the majority of my experimental code, but there is one spot where I need the negation of "CompilerIf Defined()". So, my new question that arises from this is, does PB have a negation keyword similar to Not? I can't find one in the documentation (yet) so I thought I'd ask to be sure.

Example:

Code: Select all

CompilerIf Not Defined(three_label, #PB_Label)
    Goto four_label
CompilerEndIf

Or...

CompilerIf Defined(three_label, #PB_Label) = False
    Goto four_label
CompilerEndIf
Are either of the above examples possible in PB? The reason I ask about this is because in one spot, if "three_label" is defined, I don't want anything to happen. But if "three_label" is not defined, then I want it to goto "four_label", and I don't want to be left to write sloppy code like this:

Code: Select all

CompilerIf Defined(three_label, #PB_Label)
    ;leave blank so that nothing happens
CompilerElse
    Goto four_label
CompilerEndIf
Last edited by Dudemeister on Sat Nov 02, 2019 5:15 pm, edited 1 time in total.
Dudemeister
User
User
Posts: 29
Joined: Sat Oct 26, 2019 6:48 pm

Re: Test if macro is used - conditional jump...

Post by Dudemeister »

@Olliv
Olliv wrote:Houla...

2 remarks...

1) Please use normalized markups
I deeply apologize. Despite having programmed for 30+ years (in other languages), this is my first time ever using an online forum. So, please forgive my slowness at learning the proper protocol for doing things.
Marc56us
Addict
Addict
Posts: 1600
Joined: Sat Feb 08, 2014 3:26 pm

Re: Test if macro is used - conditional jump...

Post by Marc56us »

This structure worked perfectly in the majority of my experimental code, but there is one spot where I need the negation of "CompilerIf Defined()". So, my new question that arises from this is, does PB have a negation keyword similar to Not? I can't find one in the documentation (yet) so I thought I'd ask to be sure.
The negation operator exists of course in PB (as in all languages): Not (some others languages use '!')
:arrow: Variables and Types

And it is easy to test

Code: Select all

#PureConstant = 10

CompilerIf Defined(PureConstant, #PB_Constant) 
    Debug "Constant IS declared"
CompilerEndIf

; Test 'Not'
CompilerIf Not Defined(Constant_not_declared, #PB_Constant) 
    Debug "Constant is NOT declared"
CompilerEndIf

Code: Select all

Constant IS declared
Constant is NOT declared
"Not" is also very convenient to make code easy to maintain.

Code: Select all

If Not OpenFile(...
While Not Eof(...
So it is enough to search all the " Not " to go to all the locations to be processed next as in an error handler.
I do this systematically, so as not to forget to process the possible error before the rest of the code.
Dudemeister
User
User
Posts: 29
Joined: Sat Oct 26, 2019 6:48 pm

Re: Test if macro is used - conditional jump...

Post by Dudemeister »

@Marc56us

Thank you, Sir!

That was very lacking on my part to not think to look in among the operators...

Update: > I just found I can download a PDF version of the PB manual. It's a bit more searchable than the online version.
infratec
Always Here
Always Here
Posts: 7575
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Test if macro is used - conditional jump...

Post by infratec »

I never used something else than the inbuild help :wink:

Or ... this forum. :mrgreen:
#NULL
Addict
Addict
Posts: 1497
Joined: Thu Aug 30, 2007 11:54 pm
Location: right here

Re: Test if macro is used - conditional jump...

Post by #NULL »

infratec wrote:And no, there is no way to test if a Macro is in use.
You can only test if a Macro is defined.
It's actually the other way round. There is no #PB_Macro for Defined() so you can't know if it's defined, even though you can undefine it. But you can define a constant in a macro to indicate that the macro has been used up to the current point in compiletime. Works only with multiline macro bodies.

Code: Select all


Macro foo
  Debug "foo"
  #_foo_used = 1
EndMacro

Debug "macro used : " + Defined(_foo_used, #PB_Constant)  ; 0
foo
Debug "macro used : " + Defined(_foo_used, #PB_Constant)  ; 1
UndefineMacro foo
Debug "macro used : " + Defined(_foo_used, #PB_Constant)  ; 1

User avatar
Olliv
Enthusiast
Enthusiast
Posts: 542
Joined: Tue Sep 22, 2009 10:41 pm

Re: Test if macro is used - conditional jump...

Post by Olliv »

@Dudemeister

30 years... Welcome. Test

Code: Select all

PBCompiler.EXE PureBasicFile.PB /Commented
on command prompt to get Assembly equivalent file (named PureBasic.ASM). You could see CallFunctionFast() is equ to CALL [xxx] in ASM language.

As you maybe know Call and Jmp are different : 'Call' uses the stack (pointed with ESP or RSP CPU register) and restores EIP (or RIP on X64 version, old reg was just 'IP' meaning Instruction Pointor) from the stack when single RET ASM statement is found (equ to basic native RETURN statement).

So, with JuMP, you have to manage the end of routine.
Macro can be used, but two difficulties are there :

1) Recursivity is forbidden and often fatally warned on compiling.
2) Macro syntax is very very hard.

i.e.

Code: Select all

; macro version

Macro ICountMyselfOnCompiling()
Debug MacroExpandedCount

; but I can be concatenated on basis user keywords...
#I# MacroExpandedCount = MacroExpandedCount * MacroExpandedCount ; here mul op is pre-calculated (square result is a meta data)

EndMacro

ICountMyselfOnCompiling()
Debug #I1
ICountMyselfOnCompiling()
Debug #I2


; procedure version (Stack is just used to store origin address value, and, optionally, Y value)
Procedure ICountWithHardStack()
Static X ; (Careful : Stack is not used for X integer)
Define Y = 100 ; (But Y is stored in stack, temporarily)
X + Y ; equ to X = X + Y
Debug X
; But concatenate X or Y directly in value names, is unabled... Just enabled on macros...
EndProcedure

ICountWithHardStack()
ICountWithHardStack()
Debug Y ; 0 because Y is erased : Its name is unknown here, and its value is in an obsolete place in stack now...
Be careful to external PDF help file you can find on www. You should check on this forum if it is a right version !
Last edited by Olliv on Sun Nov 03, 2019 12:00 pm, edited 1 time in total.
Post Reply