Practical: Macro Usage
Here are concrete samples for streamlining development using LuneScript's macro features.
Step 1: Debug Print (_DBGP)
A debugging macro that displays a variable's name and its value simultaneously.
macro _DBGP( val: __exp ) {
print( "%s = %s" ( ,,,,val, ,,val ) );
}
let hoge = 100;
_DBGP( hoge ); // Displays hoge = 100
Step 2: Custom Assertion (_Assert)
A macro that displays a message and halts if a condition is not met.
macro _Assert( cond: __exp, msg: str ) {
if not (,,cond) {
print( "Assertion failed: %s" (,,msg) );
// Add logic to interrupt processing as needed
}
}
_Assert( 1 + 1 == 3, "Math is broken" );
Step 3: Measurement of Execution Time (_Measure)
A macro that measures the execution time of a specific code block.
macro _Measure( label: str, block: __block ) {
{
let startTime = os.clock();
,,block
let endTime = os.clock();
print( "%s: %f sec" (,,label, endTime - startTime) );
}
}
_Measure( "Heavy Process", {
let mut sum = 0;
for i = 1, 1000000 {
sum = sum + i;
}
} );
Step 4: Loading External File Content as Constants
An example using macro-statement to read external configuration files at compile time and expand
them as constants within the code.
macro _LoadConfig( path: str ) {
{
let mut list: List<str> = [];
// Open file at compile time
if! let mut file = io.open( path ) {
let mut line = file.read( "*l" );
while line {
// Remove newlines and add to list
list.insert( (unwrap line).gsub( "[\r\n]", "" ) );
line = file.read( "*l" );
}
file.close();
}
}
// Expand as const
pub const CONFIG_ITEMS = ,,list;
}
// Content of config.txt is expanded into CONFIG_ITEMS at compile time
_LoadConfig( "config.txt" );
foreach item in CONFIG_ITEMS {
print( item );
}
By using
io.open within a macro, you can incorporate external resources directly as part of
your program. This is extremely useful for things like data embedding.
Summary
By leveraging LuneScript macros, you can flexibly achieve boilerplate reduction and complex compile-time-only logic.
- Boilerplate reduction: Shortens code that is written repeatedly.
- Automatic information addition: Variable names and expressions themselves can be used as strings.
- Safe abstraction: Features can be added safely by leveraging scopes.
Refer to the Macros Reference for more advanced features.