Open DavidDudson opened 6 years ago
How about
def extend(c: Defn.Class, ctx: Context): List[Stat] = {
ctx.prefix/enclosingClass/parameters/semanticdb
}
This is probably the easiest option with regards to classloading and is also quite similar to scala-reflect macros. I never like this
in scalameta/paradise and in scalacenter/macros I've moved closer to a scala-reflect compatible interface.
@olafurpg For "Universe" like behaviour I agree that we should use context. perhaps even make it implicit.
For parameters specifically, they are named, and on the class that is the generator.
It seems odd for an author to have to write ctx.parameters.get("foo") or similar in order to access a field that is sitting right in the constructor of the class.
For example...
case class Bar(foo: String) {
def extend(c: Defn.Class, ctx: Context): List[Stat] = {
ctx.parameters.get("foo")
}
}
The above seems really peculiar, not to mention that we would have to use HLists or similar for the args in order to get the right types. I think code generation has value here. (Even if it is slightly more magic).
The arguments to the annotation are not necessarily literals, they can be any syntax. The way I would do it is to separate the annotation from the expansion method
class Foo(arg: String) extends StaticAnnotation
object Foo extends Generator {
def extend(defn: Defn.Class, c: Context): List[Stat] = {
val Lit.String(arg) = c.prefix
...
}
}
I think code generation has value here. (Even if it is slightly more magic).
I would personally start with something more boilerplatey to begin with, and then once the common pattern emerges we can discuss how to improve it. scalagen may be one solution, but shapeless or a custom def macro might also work fine.
Thats fair. Although I think we will want to provide helper methods that provide clearer error messages rather then just a match error. It's a common enough pattern. I see literals used more then any other parameters.
provide helper methods that provide clearer error messages rather then just a match error
Absolutely! I never liked the val Lit.String(x) = ...
pattern
Take for example the following...
What the author wants to write is:
That way, the user writing code which uses the generator, writes valid code as far as the IDE is concerned.
We need a way of injecting
foo
into the class. We also want to create an instance of this thing, that does not have the parameters supplied.What we will end up needing (with semantics) is the following
This is not the only information we need to inject either. Things like a semantic database, will be required in the future.
Theres a few of ways we could do this....
Effectively the same as 1. Except without an annotation.
Before executing the generator code, we pass over a generator to transform the class into something more usable from the generators perspective.
So scalagen actually transforms generator sources, and actual sources.
I prefer 3. So that's what I'm going to explore, any objections should be discussed here.