Using LabelDef in scala macros (2.10)

I am experimenting with scala 2.10 macros. However, in some cases, the problem with LabelDef does not work. To some extent, I looked into the compiler code, read excerpts from the documents of Miguel Garcia , but I was still stuck.

If my understanding is correct, the pseudo-definition will be:
LabelDef(labelName, listOfParameters, stmsAndApply) , where 3 arguments are trees and:
- labelName is the identifier of the LL defined label
- listOfParameters correspond to the arguments passed when applying label-apply, as in $ L (a1, ..., an), and may be empty
- stmsAndApply matches the statement block (maybe not) and the final apply-expression
label-apply means more or less goto for the label

For example, in the case of a simple loop, LabelDef might eventually apply:
LabelDef($L, (), {...; $L()})

Now, if I want to define 2 LabelDef that jump on each other:

 ... LabelDef($L1, (), $L2()) ... LabelDef($L2, (), $L1()) ... 

The 2nd LabelDef is fine, but the compiler throws an error on the 1st, "not found: value $ L2". I assume this is because $ L2 is not yet defined, although there is an attempt to apply it. This tree, built in such a way that would make sense to me. Do I still understand? Because if an error is not expected, this means that my implementation of macros is probably buggy.

In any case, I believe that there should be a way to apply $ L2 (i.e., jump to $ L2) from $ L1, anyway, but I just don’t know how to do it. Does anyone have an example of this or any pointer?


Other obscure points (but currently less worried) about using LabelDef in macros:
- What is the second argument, specifically, how is it used when it is not empty? In other words, what label mechanisms are applied with parameters?
- Is it really to put in the third argument the final expression is something other than a label? (not that I can't try, but the macros are still experimental)
- is it possible to execute the forwarding shortcut - apply to LabelDef? (maybe this is another question)

Any example of macro implementation in the answer is, of course, very welcome!
Cheers

+5
macros scala scala-macros
source share
1 answer

Because if an error is not expected, this means that my implementation of macros is probably buggy.
Yes, it seems like it was a mistake (^^; Although I'm not sure if there is a limitation with a combination of Block / LabelDef with goals.

 def EVIL_LABELS_MACRO = macro EVIL_LABELS_MACRO_impl def EVIL_LABELS_MACRO_impl(c:Context):c.Expr[Unit] = { // fails to expand import c.universe._ val lt1 = newTermName("$L1"); val lt2 = newTermName("$L2") val ld1 = LabelDef(lt1, Nil, Block(c.reify{println("$L1")}.tree, Apply(Ident(lt2), Nil))) val ld2 = LabelDef(lt2, Nil, Block(c.reify{println("$L2")}.tree, Apply(Ident(lt1), Nil))) c.Expr( Block(ld1, c.reify{println("ignored")}.tree, ld2) ) } def FINE_LABELS_MACRO = macro FINE_LABELS_MACRO_impl def FINE_LABELS_MACRO_impl(c:Context):c.Expr[Unit] = { // The End isn't near import c.universe._ val lt1 = newTermName("$L1"); val lt2 = newTermName("$L2") val ld1 = LabelDef(lt1, Nil, Block(c.reify{println("$L1")}.tree, Apply(Ident(lt2), Nil))) val ld2 = LabelDef(lt2, Nil, Block(c.reify{println("$L2")}.tree, Apply(Ident(lt1), Nil))) c.Expr( Block(ld1, c.reify{println("ignored")}.tree, ld2, c.reify{println("The End")}.tree) ) } 

I think the block is parsed on {statements; expression} so the last argument is expression. If the expression LabelDef "falls", for example. EVIL_LABELS_MACRO template, its extension will not be visible in operators; therefore, the error "not found: value $ L2".

So it’s best to make sure that all LabelDef statements are β€œfalling”. FINE_LABELS_MACRO does this and expands to:

 { $L1(){ scala.this.Predef.println("$L1"); $L2() }; scala.this.Predef.println("ignored"); $L2(){ scala.this.Predef.println("$L2"); $L1() }; scala.this.Predef.println("The End") } 
+1
source share

All Articles