日本語

Macros

LuneScript macros are a powerful feature that expands and generates code (AST) at compile time.

Definition

Defined using the macro keyword. By convention, macro names begin with an underscore _.

macro _dprint( exp: __exp ) {
    print( "DEBUG:", ,,exp );
}

Arguments

In addition to regular types, you can specify macro-specific types for macro arguments.

macro _assign( symbol: sym, val: int ) {
    ,,symbol = ,,val;
}
let mut val = 0;
_assign( val, 10 ); // Expanded as val = 10;

Quoting (Expansion Operators)

When using arguments in the macro body (expand-statement), use the following operators to control expansion.

Operator Description
,, Expands the value of the argument directly as code.
,,, Expands the string value of the argument as a symbol name.
,,,, Converts the symbol name of the argument into a string literal and expands it.
pub macro _hello( name: str ) {
    print( "Hello, ", ,,name );
}

Macro Statement

A macro definition consists of a macro-statement (the first {}) for calculations and preparation, and an expand-statement (the latter part) for generating actual code.

Within the macro-statement, standard LuneScript calculation features can be used to determine the content of the expanded code dynamically. Furthermore, by using the `{} operator, fragments of code (of type stat) can be stored into variables and listed.

Example of Dynamic Code Generation

The following example automatically defines a series of variables by the specified count.

macro _GenVars( prefix: str, count: int ) {
    {
        // macro-statement: Create a list of code to expand
        let mut stats: List<stat> = [];
        for i = 1, count {
            let varName = "%s%d" (prefix, i);
            stats.insert( `{
                let ,,,"v_%s"(varName)~~ = ,,i;
            } );
        }
    }
    // expand-statement: Expand the generated list all at once
    ,,stats;
}

_GenVars( "val", 3 );
// Expanded as let v_val1 = 1; let v_val2 = 2; let v_val3 = 3;
print( v_val1, v_val2, v_val3 ); // 1 2 3

Constraints within macro-statement

Caution: Conflict with Lua Reserved Words

If a variable name in the code expanded by a macro conflicts with a Lua reserved word (such as end), an error will occur after transcompilation. Be careful with variable names used inside macros.
Macros are a complex feature, and their overuse can detract from code readability. Please use them appropriately.