Macro With Context

The macro definitions are as follows:

// 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
}

The macro calls are as follows:

// 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'.
}

The compilation commands are as follows:

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

# Compile the file using macros
cjc macro_call.cj -o demo

As shown in the code above, the Inner macro uses the assertParentContext function during definition to check whether it is called within an Outter macro. In the given macro call scenario, since Outter and Inner don't have such a nesting relationship during invocation, the compiler will report an error.

The macro definitions are as follows:

// 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
}

The macro calls are as follows:

// macro_call.cj
import macro_definition.*

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

The compilation commands are as follows:

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

# Compile the file using macros
cjc macro_call.cj -o demo

Compilation phase output:

value1: value1  value2: value2

In the above code, the inner macro Inner sends messages to the outer macro through setItem; the Outter macro receives a set of message objects from Inner via the getChildMessages function (Outter can call Inner multiple times); finally, the corresponding values are retrieved using the message object's getString function.