How to Debug Macro at Compile Time in FB

Forum for discussion about the documentation project.
Post Reply
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

How to Debug Macro at Compile Time in FB

Post by fxm »

Macros offer a powerful way to extend the language and create reusable code. One reason macros are used is performance.
They are a way of eliminating procedure call overhead because they are always expanded in-line. There is no alternative for this in FreeBASIC because it does not support inline procedures.

Using macros can be extremely unsafe and they hide a lot of pitfalls which are very hard to find.
Procedures give type checking and scoping, but macros just substitute the passed argument.
Another disadvantage of the macro is the size of the program. The reason is, the pre-processor will replace all the macros in the program by its real definition prior to the compilation process of the program.

Looking only at the source code file, the only way to find out what the problem is to look at the definition of the macro and try to understand what happened.
The most common error when using macros is the unbalanced open parentheses (inducing error at compile-time).
Another is to forget putting parentheses around arguments in macro definitions. That can cause some pretty nasty side effects because of operator precedence (inducing error at compile-time or bug at run-time).


When the compiler detects an error inside a macro (after expanding), it provides a rustic error message containing only:
  • the line number where is the call of the macro,
  • the error type,
  • the text of the call (of the macro).
When the error is not obvious (type of error reported blurred), the only solution (with only the call line number) is presently to iteratively execute the following 5 steps until correction successful:
  • Do
    1. call fbc on the source file, but with the '-pp' compile option (fbc command emitting only the pre-processed input file, without compiling),
    2. recover the pre-processed file,
    3. edit and compile directly from this pre-processed file,
    4. analyze the error, understand it, correct it, and compile again the pre-processed file thus modified,
    5. postpone the equivalent correction in the concerned macro body of the original source file.
  • Loop
Example of error on a short code (from @codeFoil):

- Source file (*.bas):

Code: Select all

#Macro FIRST(_x_,_op_)
  For index as Integer = LBound(_x_) to UBound(_x_) - 1
    Print _x_(index) _op_ ", ";
  Next index
  Print _x_(Ubound(_x_))
#EndMacro

#Macro SECOND(_x_)
  Print "Dump: " & #_x_
  FIRST(_x_, +)
#EndMacro

Dim as String test1(0 to ... ) => {"First", "Second", "Third" }
Dim as Integer test2(0 to ...) => { 1, 2 ,3 }

SECOND(test1)
SECOND(test2)

Sleep
  • Compiler output:
    .....\FBIde0.4.6r4_fbc1.06.0\FBIDETEMP.bas(17) error 20: Type mismatch, found ';' in 'SECOND(test2)'
- Pre-processed file (*.pp.bas):

Code: Select all



Dim as String test1(0 to ... ) => {"First", "Second", "Third" }
Dim as Integer test2(0 to ...) => { 1, 2 ,3 }

 Print "Dump: " & $"test1"
 For index as Integer =LBound(test1) to UBound(test1) -1
 Print test1(index) + ", ";
 Next index
 Print test1(Ubound(test1))
 Print "Dump: " & $"test2"
 For index as Integer =LBound(test2) to UBound(test2) -1
 Print test2(index) + ", ";
 Next index
 Print test2(Ubound(test2))

Sleep
  • Compiler output:
    .....\FBIde0.4.6r4_fbc1.06.0\FBIDETEMP.bas(13) error 20: Type mismatch, found ';' in 'Print test2(index) + ", ";'
- Example macro correction in source code (*.bas):

Code: Select all

#Macro FIRST(_x_,_op_)
  For index as Integer = LBound(_x_) to UBound(_x_) - 1
    Print _x_(index) _op_ ", ";
  Next index
  Print _x_(Ubound(_x_))
#EndMacro

#Macro SECOND(_x_)
  Print "Dump: " & #_x_
  FIRST(_x_, &)  ''FIRST(_x_, +)  ''corrected line
#EndMacro

Dim as String test1(0 to ... ) => {"First", "Second", "Third" }
Dim as Integer test2(0 to ...) => { 1, 2 ,3 }

SECOND(test1)
SECOND(test2)

Sleep
  • Output:

    Code: Select all

    Dump: test1
    First, Second, Third
    Dump: test2
    1, 2,  3
Note:
Another solution could be a more detailed error message from compiler, relating to the call of the macro:
  • For example it could be added, at the end of the error message relating to the line of macro call, the exact line number of error inside the macro definition body.
  • In case of nested macros, adding successively the error line number for each macro definition body.
  • Proposal of improved error message for the above example of erroneous code:
    • Compiler output:
      .....\FBIde0.4.6r4_fbc1.06.0\FBIDETEMP.bas(17) error 20: Type mismatch, found ';' in 'SECOND(test2)': from macro line 10, 3
In order to improve the macro debugging, a feature request is already filled in:
#247 Compiler error message concerning #macro could be detailed
Post Reply