V22 introduces the full macro expansion engine. Macros are expanded before the lexer runs, so they can generate any PB code including declarations, statements, and expressions.
#DEFINE name valueSimple text-replacement macros. Every occurrence of name in subsequent source is replaced with value.
#DEFINE MAX_COUNT 100
#DEFINE APP_NAME "MyApp"
LOCAL i AS LONG
FOR i = 1 TO MAX_COUNT
PRINT APP_NAME
NEXT i
#DEFINE symbol produces a diagnostic error.MACRO name(args) = expressionExpression macros that expand inline with argument substitution.
MACRO Add1(x) = (x + 1) MACRO Square(n) = (n * n) MACRO Max(a, b) = IIF((a) > (b), (a), (b)) LOCAL v AS LONG v = Add1(10) ' Expands to: v = (10 + 1) v = Square(v) ' Expands to: v = (v * v)
MACRO name(args) ... END MACROBlock macros that expand to multiple statements. Arguments are substituted by name.
MACRO SAY(text)
PRINT text
END MACRO
MACRO SwapVars(a, b)
LOCAL t AS LONG
t = a
a = b
b = t
END MACRO
FUNCTION PBMAIN() AS LONG
LOCAL x, y AS LONG
x = 10 : y = 20
SwapVars(x, y)
SAY("Hello from macro!")
END FUNCTION
MACROFUNCTION name(args) ... END MACRO = exprFunction-like macros that can declare temporary variables with MACROTEMP. MACROTEMP generates a unique name for each expansion, preventing collisions.
MACROFUNCTION Twice(x)
MACROTEMP t
LOCAL t AS LONG
t = x * 2
END MACRO = t
FUNCTION PBMAIN() AS LONG
LOCAL a, b AS LONG
a = Twice(5) ' a = 10, uses unique temporary
b = Twice(a) ' b = 20, uses different unique temporary
END FUNCTION
MACROFUNCTION does not yet implement every PowerBASIC macro edge case. Basic expression macros with MACROTEMP work well for common patterns.The preprocessor detects and rejects recursive macro invocations and excessive expansion depth (default limit: 256 levels).
' This produces a diagnostic error, not infinite expansion ' #DEFINE X Y ' #DEFINE Y X ' PRINT X ' Error: recursive macro expansion
#INCLUDE ONCE "file.inc" or #INCLUDEONCE "file.inc"Prevents duplicate inclusion of the same file. Useful for header files included from multiple locations. Missing-file diagnostics are emitted when the included file cannot be found.
#INCLUDE ONCE "win32api.inc" #INCLUDEONCE "mytypes.pbi"
V22 explicitly rejects unsupported compile modes with a clear diagnostic instead of silently producing a wrong EXE type:
' #COMPILE DLL "mylib.dll" ' Error: DLL output not yet implemented ' #COMPILE EXE "app.exe" GUI ' Error: GUI subsystem not yet implemented
V22 defines PBXA64_V22 as a conditional symbol, allowing version-gated code:
#IF %DEF(PBXA64_V22)
PRINT "Running under PBXA64 V22 or later"
' Use V22 macro features
#ELSE
PRINT "Older version - macros not available"
#ENDIF
#UNDEF nameRemoves a previously defined conditional symbol or #DEFINE macro.
#DEFINE DEBUG 1 ' ... debug code here ... #UNDEF DEBUG ' Debug code no longer active
| Error | Cause |
|---|---|
| Duplicate #DEFINE | Symbol already defined with a value |
| Recursive macro expansion | Macro expansion led to itself |
| Expansion depth exceeded | Too many nested macro invocations |
| Missing END MACRO | MACRO block not closed |
| MACROFUNCTION arity mismatch | Wrong number of arguments provided |
| #INCLUDE ONCE file not found | Included file does not exist |
| DLL/GUI mode not supported | #COMPILE target not yet implemented |