Using Macro Attachments in Scala 2.10

Update: I suspect that what I want may not be possible, and I wrote a blog post with my reasoning (and some alternatives) here . I would be very happy if they tell me that I'm wrong.


Suppose I want to instantiate an attribute using the factory method with a macro implementation. This method will take as an argument the path to the resource that the macro will read and parse (at compile time) into the map from line to line.

This part is pretty simple. Now suppose I want to associate the resulting map with an instance that I create so that I can use it in subsequent macro calls associated with this instance.

I absolutely do not want the card to be a member of the instance or exist in any form at run time. I also do not want to analyze the same resource more than once. Here is a sketch of the kind of thing I was aiming for:

import scala.language.experimental.macros import scala.reflect.macros.Context trait Foo { def lookup(key: String): String = macro Foo.lookup_impl } object Foo { def parseResource(path: String): Map[String, String] = ??? def apply(path: String): Foo = macro apply_impl def apply_impl(c: Context)(path: c.Expr[String]): c.Expr[Foo] = { import c.universe._ val m = path.tree match { case Literal(Constant(s: String)) => parseResource(s) } val tree = reify(new Foo {}).tree // Somehow associate the map with this tree here. c.Expr(tree) } def lookup_impl(c: Context)(key: c.Expr[String]): c.Expr[String] = /* Somehow read off the map and look up this key. */ ??? } 

It looks like attachments are for help (thanks to Eugene Burmako for a pointer ), and I have an attachment-based implementation that allows me to write the following:

 Foo("whatever.txt").lookup("x") 

Where apply_impl attaches the map to the tree, and lookup_impl reads this attachment from the same tree that it sees as its prefix. Unfortunately, this is more or less useless since it does not work in the case of foo.lookup("x") , where the prefix tree is just a foo variable.

(Note that in my real case of using foo extends Dynamic , and I'm trying to give a macro implementation for selectDynamic instead of lookup , but this should not be appropriate here: m interested in the general case.)

Is there a way I can use attachments to get what I want? Is there any other approach that would be more appropriate?

+6
source share
1 answer

UPDATE I have to read the question again after the reversal ... :( I just reproduced what you have.


You were there, I think. This works for me:

 object Foo { // Attachment.get somehow needs a wrapper class. // Probably because of generics implicit class LookupMap(m: Map[String, String]) { def get(s: String) = m.get(s) } def parseResource(path: String): LookupMap = Map("test" -> "a") def apply_impl(c: Context)(path: c.Expr[String]): c.Expr[Foo] = { import c.universe._ val m = path.tree match { case Literal(Constant(s: String)) => parseResource(s) } val tree = reify(new Foo {}).tree.updateAttachment(m) c.Expr(tree) } def lookup_impl(c: Context { type PrefixType = Foo }) (key: c.Expr[String]): c.Expr[String] = { import c.universe._ val m = c.prefix.tree.attachments.get[LookupMap].get val s = key.tree match { case Literal(Constant(s: String)) => m.get(s).get } c.Expr(Literal(Constant(s))) } } 
0
source

Source: https://habr.com/ru/post/949162/


All Articles