MACRO, MACROFUNCTION, MACROTEMP, #DEFINE, and conditional compilation.MACRO name(args) ... END MACROStatement macros allow you to define multi-line blocks of code that are expanded inline at the point of invocation. They are evaluated during preprocessing and substituted directly into the source stream before parsing.
MACRO DEBUG_PRINT(msg)
IF %DEF(DEBUG) THEN
PRINT "[DEBUG]: "; msg
END IF
END MACRO
FUNCTION PBMAIN() AS LONG
DEBUG_PRINT "Program started"
FUNCTION = 0
END FUNCTION
The compiler replaces the macro call with the body, substituting arguments:
' Expanded source sent to parser:
IF %DEF(DEBUG) THEN
PRINT "[DEBUG]: "; "Program started"
END IF
MACROFUNCTION name(args) ... END MACRO = exprFunction macros behave like inline functions. They can contain local variable declarations and statements, and must conclude with END MACRO = expression to specify the return value.
MACROFUNCTION CLAMP(val, min, max)
MACROTEMP t
LOCAL t AS LONG
t = val
IF t < min THEN t = min
IF t > max THEN t = max
END MACRO = t
FUNCTION PBMAIN() AS LONG
LOCAL x AS LONG
x = CLAMP(150, 0, 100)
PRINT "Clamped value: "; x ' Outputs: 100
FUNCTION = 0
END FUNCTION
MACROTEMP varnameWhen writing multi-line macros, declaring a variable inside the macro can cause name collisions if the macro is used inside a loop or another macro. MACROTEMP tells the preprocessor to generate a unique, compiler-managed variable name for each expansion, preventing Duplicate declaration errors.
' Source:
MACROFUNCTION Square(x)
MACROTEMP res
LOCAL res AS LONG
res = x * x
END MACRO = res
' Expanded (compiler generates unique names):
' Expansion 1:
LOCAL __pb_mtemp_1_res AS LONG
__pb_mtemp_1_res = 5 * 5
' Expansion 2:
LOCAL __pb_mtemp_2_res AS LONG
__pb_mtemp_2_res = 10 * 10
#DEFINE name value | #UNDEF name#DEFINE creates simple text-replacement macros. If parentheses follow the name immediately, it becomes a function-like macro. #UNDEF removes a symbol from the preprocessor context.
#DEFINE PI 3.14159265358979 #DEFINE AREA(r) (PI * r * r) #DEFINE DEBUG_MODE 1 LOCAL radius AS DOUBLE radius = 5.0 PRINT "Area: "; AREA(radius) #UNDEF DEBUG_MODE ' DEBUG_MODE is no longer defined below
#IF condition ... #ELSEIF ... #ELSE ... #ENDIFConditionally include or exclude code blocks. Conditions support %DEF(name), numeric constants, and logical operators NOT, AND, OR. The dollar-form ($IF, $ENDIF) is also supported.
#IF %DEF(PBXA64) AND %DEF(X64)
PRINT "Running on 64-bit PBXA64"
#ELSEIF %DEF(DEBUG)
PRINT "Debug build active"
#ELSE
PRINT "Standard release build"
#ENDIF
The following symbols are automatically defined by the preprocessor:
| Symbol | Meaning |
|---|---|
PBXA64 | Always defined for PBXA64 builds |
PBXA64_64 | Defined when compiling for x64 |
WIN64 | Defined for Windows 64-bit targets |
X64 | Defined for x86-64 architecture |
macro expansion depth overflow error.MACROFUNCTIONs strictly enforce argument counts. Mismatches produce a diagnostic error."...") to prevent accidental substitution inside string literals.