#macro Elipsis and #if not working together

General FreeBASIC programming questions.
Post Reply
wallyg
Posts: 270
Joined: May 08, 2009 7:08
Location: Tucson Arizona

#macro Elipsis and #if not working together

Post by wallyg »

Or I have a total misunderstanding of this

using C:\FB\WinFBE_Suite\FreeBASIC-1.06.0\fbc -g -s gui -mt "fbSIR.bas"

I have a macro

Code: Select all

#Macro   Signal(Name,Detail,RetValue,Arguments...)
	.
	.
	.
    SignalArgument(Arguments)
    propNofSignals += 1
#EndMacro
#Macro   SignalArgument(TofArg,NofArg,IsPointer,Arguments...)
	.
	.
	.
#Print /#arguments/
#If (Len(#Arguments) > 0)
    SignalArgument(Arguments)
#EndIf 
#EndMacro
This seems to work stripping off the first 3 arguments and recursively processing the remaining arguments

However when it finally gets to the point that the argument Arguments is empty, Signal(Arguments) is still called and causes an error due to invalid arguments being passed (of course, Arguments is the empty string)

During the recursive calls the #print /#Arguments/ statement prints shorter and shorter lists of arguments, and then eventually it prints /""/ which should stop calling SignalArgument. But it does not.

I also tried

Code: Select all

#if (#Arguments <> "")
And that also causes SignalArgument to be called 1 time to many.

This seemed pretty straight forward when I read it in the documentation. What have I misunderstood?
Tourist Trap
Posts: 2958
Joined: Jun 02, 2015 16:24

Re: #macro Elipsis and #if not working together

Post by Tourist Trap »

Hello,

sorry , even if I've done macros with ellipsis in the past, like here:
viewtopic.php?f=7&t=25149&p=225712#p225712

I still can't help you because you don't show an example (or I dont see it...) of usage of your macro. What is the syntax of the call, what objects do you pass, what do you want as result??

Anyway, at first sight I would say that you should not try to test dynamic content with #IF. Use a normal IF instead with variables created in your macro, in a scope block for instance. I say that with not 100% of certainty. Look at my example rather. You probably will find how to adapt it to your issue. Otherwise post a more complete question :)
coderJeff
Site Admin
Posts: 4326
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: #macro Elipsis and #if not working together

Post by coderJeff »

Good find, wallyg. This is part feature request & part bug.

fbc does not support recursive #macro or #define, but also doesn't error in non-trivial cases either.

Example #1, simulates what we are trying to do:

Code: Select all

#macro MX( X, args... )
	#print "   MX()"
	#print "      X    = " #X
	#print "      args = " #args
	#if len( #args ) > 0
		#print "      len(" #args) > 0"
	#else
		#print "      len(" #args) = 0"
	#endif
#endmacro

#macro M( X, args... )
	#print "M()"
	#print "   X    = " #X
	#print "   args = " #args
	MX(X, args )
#endmacro

M(A,B,C)
M(A,B)
M(A)
Output:

Code: Select all

M()
   X    =  $"A"
   args =  $"B,C"
   MX()
      X    =  $"A"
      args =  $"B,C"
      len( $"B,C") >0"
M()
   X    =  $"A"
   args =  $"B"
   MX()
      X    =  $"A"
      args =  $"B"
      len( $"B") >0"
M()
   X    =  $"A"
   args =  ""
   MX()
      X    =  $"A"
      args =  ""
      len( "") =0"
Example #2, directly add recursion. fbc can detect this trivial form of #macro recursion and generates an error:

Code: Select all

#macro MX( X, args... )
	#print "   MX()"
	#print "      X    = " #X
	#print "      args = " #args
	#if len( #args ) > 0
		#print "      len(" #args) > 0"
		MX(args)
	#else
		#print "      len(" #args) = 0"
	#endif
#endmacro

#macro M( X, args... )
	#print "M()"
	#print "   X    = " #X
	#print "   args = " #args
	MX(X, args )
#endmacro

M(A,B,C)
Output:

Code: Select all

M()
   X    =  $"A"
   args =  $"B,C"
   MX()
      X    =  $"A"
      args =  $"B,C"
      len( $"B,C") >0"
macro.bas(20) error 89: Recursive DEFINE not allowed, found 'MX' in 'M(A,B,C)'
macro.bas(20) error 3: Expected End-of-Line, found '#' in 'M(A,B,C)'
      len( $"B,C") =0"
Example #3, adding the #if tricks fbc (it doesn't detect the recursion), and actually causes fbc to hang, never ending it's own internal recursive expansion of MX() -- BUG

Code: Select all

#macro MX( X, args... )
	#print "   MX()"
	#print "      X    = " #X
	#print "      args = " #args
	#if len( #args ) > 0
		#print "      len(" #args ) > 0
		MX(args)
	#else
		#print "      len(" #args ) = 0
	#endif
#endmacro

#macro M( X, args... )
	#print "M()"
	#print "   X    = " #X
	#print "   args = " #args
	#if len( #args ) > 0
		#print "   len(" #args ) > 0
		MX(X, args )
	#endif
#endmacro

M(A,B,C)
Output:

Code: Select all

M()
   X    =  $"A"
   args =  $"B,C"
   len( $"B,C" ) >0
   MX()
      X    =  $"A"
      args =  $"B,C"
      len( $"B,C" ) >0
   MX()
      X    =  $"B"
      args =  $"C"
      len( $"C" ) >0
   MX()
      X    =  $"C"
      args =  ""
... hang forever ....
I couldn't come up with a work-around. Either fbc should track the macro expansions and error (bug), or allow recursion (feature). Though if macro recursion were allowed, it should eventually error on some maximum depth, otherwise, it would just crash the compiler.
Post Reply