Test if macro is used - conditional jump...
-
- User
- Posts: 29
- Joined: Sat Oct 26, 2019 6:48 pm
Test if macro is used - conditional jump...
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.
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.
Re: Test if macro is used - conditional jump...
If you need to jump, you should think about your code.
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.

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.
Re: Test if macro is used - conditional jump...
Houla...
2 remarks...
1) Please use normalized markups[/code]
2) You should use procedures instead of macros... And in your way, you should use selector
Simpler...
2 remarks...
1) Please use normalized markups
Code: Select all
[code]Debug "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
Re: Test if macro is used - conditional jump...
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:
Just becomes this when compiled/run:
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
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
Re: Test if macro is used - conditional jump...
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
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

Re: Test if macro is used - conditional jump...
djes wrote:Edit> BarryG

Re: Test if macro is used - conditional jump...
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'.
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
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Re: Test if macro is used - conditional jump...
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()
-
- User
- Posts: 29
- Joined: Sat Oct 26, 2019 6:48 pm
Re: Test if macro is used - conditional jump...
@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:
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:
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:
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
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
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.
-
- User
- Posts: 29
- Joined: Sat Oct 26, 2019 6:48 pm
Re: Test if macro is used - conditional jump...
@Olliv
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.Olliv wrote:Houla...
2 remarks...
1) Please use normalized markups
Re: Test if macro is used - conditional jump...
The negation operator exists of course in PB (as in all languages): Not (some others languages use '!')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.

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
Code: Select all
If Not OpenFile(...
While Not Eof(...
I do this systematically, so as not to forget to process the possible error before the rest of the code.
-
- User
- Posts: 29
- Joined: Sat Oct 26, 2019 6:48 pm
Re: Test if macro is used - conditional jump...
@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.
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.
Re: Test if macro is used - conditional jump...
I never used something else than the inbuild help
Or ... this forum.

Or ... this forum.

Re: Test if macro is used - conditional jump...
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.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.
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
Re: Test if macro is used - conditional jump...
@Dudemeister
30 years... Welcome. Teston 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.
Be careful to external PDF help file you can find on www. You should check on this forum if it is a right version !
30 years... Welcome. Test
Code: Select all
PBCompiler.EXE PureBasicFile.PB /Commented
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...
Last edited by Olliv on Sun Nov 03, 2019 12:00 pm, edited 1 time in total.