Macro With Context

Macro definition:

// macro_definition.cj
macro package macro_definition

import std.ast.*

public macro Outter(input: Tokens): Tokens {
    return input
}

public macro Inner(input: Tokens): Tokens {
    assertParentContext("Outter")
    return input
}

Macro call:

// macro_call.cj
package macro_calling

import macro_definition.*

main() {
    @Outter var a = 0
    @Inner var b = 0 // error: The macro call 'Inner' should with the surround code contains a call 'Outter'.
}

Compilation commands:

# Compile the macro definition file.
cjc macro_definition.cj --compile-macro

# Compile the file of the macro to be used.
cjc macro_call.cj -o demo

As shown in the preceding code, the Inner macro uses the assertParentContext function to check whether it is within the Outter macro during a call. The macro call code example indicates such a nesting relationship does not exist between the two macros during the call. Therefore, the compiler reports an error.

Macro definition:

// macro_definition.cj
macro package macro_definition

import std.ast.*

public macro Outter(input: Tokens): Tokens {
    let messages = getChildMessages("Inner")
    for (m in messages) {
        let value1 = m.getString("key1") // get value: "value1"
        let value2 = m.getString("key2") // get value: "value2"
        println("value1: ${value1}  value2: ${value2}")
    }
    return input
}

public macro Inner(input: Tokens): Tokens {
    assertParentContext("Outter")
    setItem("key1", "value1")
    setItem("key2", "value2")
    return input
}

Macro call:

// macro_call.cj
import std.ast.*

import macro_definition.*

main() {
    @Outter(
        @Inner var cnt = 0
    )
    println(cnt)
}

Compilation commands:

# Compile the macro definition file.
cjc macro_definition.cj --compile-macro

# Compile the file of the macro to be used.
cjc macro_call.cj -o demo

Compilation output:

value1: value1  value2: value2

In the preceding code, the inner macro Inner sends messages to the outer macro through setItem. The Outter macro receives a group of message objects from Inner through the getChildMessages function (Inner can be called for multiple times in Outter) and obtains the corresponding value of the message objects through the getString function.