I am attempting to build a DSL using Scala macros.
Suppose I have two macros
def add(x: Int, y: Int): Unit = macro Macros.mImpl
def builder(body: => Unit): Unit = macro Macros.builderImpl
where Macros
is some object in which the macro behaviour is defined.
The intended use of these macros is to write things such as:
def example: Unit =
builder {
println("Hello, world!")
// Some statements...
add(4, 5)
// Some more statements...
}
The key thing here is that within the DSL, add
should only be only allowed to occur within a builder
block.
For example, the following should not be allowed:
def bad: Unit = add(4, 5)
I would like to find some way of ensuring that such occurrences of add
are forbidden by the compiler.
Any solution will do: either through the type system (but I really don't see how), or through the macro mechanism itself.
Since macros are expanded from the innermost context outwards (that is, bottom up, not top down), I don't see how I can achieve this from within the macro definition of add
.
(Feel free to modify the return types or definition sites of the macros if it helps; they were chosen for the sake of a simple example.)