Alpha version of macros

354 views
Skip to first unread message

Eugene Burmako

unread,
Jan 22, 2012, 6:32:09 PM1/22/12
to scala-internals
Hey! A few days ago, on this Friday, we've merged a pull request to
scala/scala that represents significant progress with macros.

I'd love you to explore our current take on macros and, possibly, get
assistance from a walkthrough from my recent talk in Kyiv (http://
scalamacros.org/talks/2012-01-14-EnAlphaKepler.pdf). Your feedback is
very welcome - if something doesn't work out with your macro test-
drive, let me know, and I'll try to fix the troubles.

In the meanwhile, we'll be polishing the implementation and preparing
a beta version that will be accompanied by a SIP. See you soon!

Simon Ochsenreither

unread,
Jan 22, 2012, 10:18:42 PM1/22/12
to scala-i...@googlegroups.com
Hi Eugene,

thanks for your work!

One question: Earlier documents mentioned a hypothetical SIP-15 "Quasiquotations".
With the introduction of the "enhanced" string interpolation (SIP 11), SIP-15 isn't necessary anymore, right?

Bye,

Simon

Eugene Burmako

unread,
Jan 23, 2012, 4:04:56 AM1/23/12
to scala-internals
This is true to some extent.

Indeed, string interpolation proposal provides an infrastructure to
build quasiquotes upon.

However, there are still some open questions worth specifying (in a
separate proposal or together with macros - not sure which will be
right). First of all, what should a quasiquoter do: just parse the
source string (i.e. emit parser trees) or go for typed trees (i.e.
infer types, resolve implicits and likes)? Also, should it be
implemented as a macro or as a normal function? Moreover, there are
some design decisions to make that regard typechecking of the splices.

On Jan 23, 4:18 am, Simon Ochsenreither

Daniel Sobral

unread,
Jan 23, 2012, 9:22:24 AM1/23/12
to scala-i...@googlegroups.com

Is separate compilation something we can expect to be present when
2.10.0 comes out, or do you plan to "fix" it so macros can be compiled
together with code that uses before that?

--
Daniel C. Sobral

I travel to the future all the time.

Eugene Burmako

unread,
Jan 23, 2012, 9:29:28 AM1/23/12
to scala-internals
I wouldn't count on that - current behaviour is more or less
satisfactory (and conventional, e.g. Nemerle macro system also has
this peculiarity), while we have several high-priority features to
implement before the release. Does separate compilation present a
significant inconvenience in your scenarios?

On Jan 23, 3:22 pm, Daniel Sobral <dcsob...@gmail.com> wrote:

Daniel Sobral

unread,
Jan 23, 2012, 9:43:16 AM1/23/12
to scala-i...@googlegroups.com
On Mon, Jan 23, 2012 at 12:29, Eugene Burmako <eugene....@epfl.ch> wrote:
> I wouldn't count on that - current behaviour is more or less
> satisfactory (and conventional, e.g. Nemerle macro system also has
> this peculiarity), while we have several high-priority features to
> implement before the release. Does separate compilation present a
> significant inconvenience in your scenarios?

It means two things:

1. Files defining macros cannot use them.
2. Software that uses self-defined macros need to be built with two
compilation steps.

The easiest way I can think to achieve this is to segregate all macros
into "macro" packages, and introduce two-step-compilation in SBT where
source from directories named "macro" are compiled in the first step,
and then the second step puts the target directory from the first in
the classpath (not default, iirc) and compiles everything except stuff
inside directories named "macro". The package segregation can be
avoided if you ignore Java convention.

This is not trivial, or, at least, I don't see a trivial way of doing
it. Consider how you'll go about changing Scala's build so that it can
use its own macros, for instance.

Now, macros are not a must-have feature for every piece of software --
Scala has lived without them for a long time, after all. Having
libraries that define useful macros will be useful all on its own, and
having the possibility of using macros, even if makes builds more
complex, will be a big plus. So I'm tagging this as an inconvenient
requirement that can be handled latter, or not at all, if the tooling
makes it mostly painless. I could put all macros on a subproject, for
instance, and have the rest of the code depend on it.

This discussion brought another question to my mind, however: will I
be able to define a macro and then use it in a single REPL session, or
will I have to compile all my macros beforehand?

Eugene Burmako

unread,
Jan 23, 2012, 9:59:19 AM1/23/12
to scala-internals, Paul Phillips
Yeah, this is very valid and awaits a principled solution. With Scala
we have a luxury of multi-stage build already integrated into our
workflow, so we're more or less fine. But, of course, this doesn't
diminish the problem.

Speaking of REPL, I have a feeling that everything will be okay, since
my impression is that REPL compiles every line in a separate
compilation run. Anyways, I'm going to summon Paul (cc'd) to clarify
this situation.

On Jan 23, 3:43 pm, Daniel Sobral <dcsob...@gmail.com> wrote:

Kevin Wright

unread,
Jan 23, 2012, 10:27:21 AM1/23/12
to scala-i...@googlegroups.com, Paul Phillips
If I remember my AD&D correctly, then there's really only one kind of entity that gets summoned...

I've heard people say before that Paul codes like a daemon; but had no idea that it was meant so literally!

Miles Sabin

unread,
Jan 23, 2012, 10:34:53 AM1/23/12
to scala-i...@googlegroups.com, Paul Phillips
On Mon, Jan 23, 2012 at 2:59 PM, Eugene Burmako <eugene....@epfl.ch> wrote:
> Yeah, this is very valid and awaits a principled solution. With Scala
> we have a luxury of multi-stage build already integrated into our
> workflow, so we're more or less fine. But, of course, this doesn't
> diminish the problem.

What's the story for Eclipse? Ie. the presentation and build compilers?

Cheers,


Miles

--
Miles Sabin
tel: +44 7813 944 528
gtalk: mi...@milessabin.com
skype: milessabin
g+: http://www.milessabin.com
http://twitter.com/milessabin
http://www.chuusai.com/

Eugene Burmako

unread,
Jan 23, 2012, 12:37:07 PM1/23/12
to <scala-internals@googlegroups.com>
Haven't looked into IDE support yet. However, this (along with
debugging) is what we will definitely address before the release.

Paul Phillips

unread,
Jan 23, 2012, 12:58:43 PM1/23/12
to scala-i...@googlegroups.com


On Mon, Jan 23, 2012 at 6:59 AM, Eugene Burmako <eugene....@epfl.ch> wrote:
Speaking of REPL, I have a feeling that everything will be okay, since
my impression is that REPL compiles every line in a separate
compilation run. Anyways, I'm going to summon Paul (cc'd) to clarify
this situation.

Correct, the repl will have the easiest time of anything dealing with any staged compilation requirement, since it does so anyway.

Daniel Sobral

unread,
Jan 23, 2012, 1:39:10 PM1/23/12
to scala-i...@googlegroups.com

I was trying to use the alphakeplerdemo, but I'm getting this error:

dcs@ayanami:~/github/alphakeplerdemo (skeleton)$ scalac -Xmacros Rx.scala
Rx.scala:24: error: unbound wildcard type
def macro forAllMatches(pattern: String, f: _): Unit = {
^
one error found


Shouldn't it have worked?

Eugene Burmako

unread,
Jan 23, 2012, 1:43:56 PM1/23/12
to scala-i...@googlegroups.com
It would if you used the compiler from alphakeplerdemo: https://github.com/xeno-by/alphakeplerdemo/tree/skeleton/compiler. The underscore syntax hasn't yet reached the upstream.

Dave

unread,
Jan 30, 2012, 8:09:50 AM1/30/12
to scala-internals
Hi Eugene,

am I missing something?

C:\Users\Dave\alphakeplerdemo>.\compiler\scala.bat -Xquasiquotes
Welcome to Scala version 2.10.0.fatal: No names found, cannot describe
anything.
(Java HotSpot(TM) Client VM, Java 1.6.0_30).
Type in expressions to have them evaluated.
Type :help for more information.

scala> val two = scala"2"
<console>:7: error: value scala is not a member of
scala.reflect.QuasiquoteLiter
al
val two = scala"2"
^

scala> val four = scala"$two + $two"
<console>:7: error: not found: value two
val four = scala"$two + $two"
^





On 23 jan, 19:43, Eugene Burmako <eugene.burm...@epfl.ch> wrote:
> It would if you used the compiler from alphakeplerdemo:https://github.com/xeno-by/alphakeplerdemo/tree/skeleton/compiler. The
> underscore syntax hasn't yet reached the upstream.
>
> On 23 January 2012 19:39, Daniel Sobral <dcsob...@gmail.com> wrote:
>
>
>
> > On Sun, Jan 22, 2012 at 21:32, Eugene Burmako <eugene.burm...@epfl.ch>
> > wrote:
> > > Hey! A few days ago, on this Friday, we've merged a pull request to
> > > scala/scala that represents significant progress with macros.
>
> > > I'd love you to explore our current take on macros and, possibly, get
> > > assistance from a walkthrough from my recent talk in Kyiv (http://
> > > scalamacros.org/talks/2012-01-14-EnAlphaKepler.pdf). Your feedback is
> > > very welcome - if something doesn't work out with your macro test-
> > > drive, let me know, and I'll try to fix the troubles.
>
> > > In the meanwhile, we'll be polishing the implementation and preparing
> > > a beta version that will be accompanied by a SIP. See you soon!
>
> > I was trying to use the alphakeplerdemo, but I'm getting this error:
>
> > dcs@ayanami:~/github/alphakeplerdemo (skeleton)$ scalac -Xmacros Rx.scala
> > Rx.scala:24: error: unbound wildcard type
> >  def macro forAllMatches(pattern: String, f: _): Unit = {
> >                                              ^
> > one error found
>
> > Shouldn't it have worked?
> > --
> > Daniel C. Sobral
>
> > I travel to the future all the time.- Tekst uit oorspronkelijk bericht niet weergeven -
>
> - Tekst uit oorspronkelijk bericht weergeven -

Eugene Burmako

unread,
Jan 30, 2012, 9:12:14 AM1/30/12
to scala-i...@googlegroups.com
Hello! 

Sorry, the slides have the interpolation id wrong. In this demo, you need to write c"..." to get the quasiquote. Thanks for catching this mistake - I've just updated the slides (http://scalamacros.org/talks/2012-01-14-EnAlphaKepler.pdf) to fix it.

Cheers,
Eugene

Dave

unread,
Jan 30, 2012, 10:04:41 AM1/30/12
to scala-internals
Okay, and where comes showRaw from?

scala> four match { case c"2 + $x" => println(showRaw(x)) }
<console>:10: error: not found: value showRaw
four match { case c"2 + $x" => println(showRaw(x)) }
^


On 30 jan, 15:12, Eugene Burmako <eugene.burm...@epfl.ch> wrote:
> Hello!
>
> Sorry, the slides have the interpolation id wrong. In this demo, you need
> to write c"..." to get the quasiquote. Thanks for catching this mistake -
> I've just updated the slides (http://scalamacros.org/talks/2012-01-14-EnAlphaKepler.pdf) to fix it.
>
> Cheers,
> Eugene
>
> > > - Tekst uit oorspronkelijk bericht weergeven -- Tekst uit oorspronkelijk bericht niet weergeven -

Eugene Burmako

unread,
Jan 30, 2012, 10:40:37 AM1/30/12
to scala-i...@googlegroups.com
import scala.reflect.mirror._

Dave

unread,
Jan 30, 2012, 11:25:11 AM1/30/12
to scala-internals
I got this:

scala> four
res5: scala.reflect.Code[Int] = Code(tree = 2.$plus(2), manifest =
Int)

scala> four match { case c"2 + $x" => println(showRaw(x))
| case _ => println("something else")
| }
something else

Extracting quasi-quotations does not seem to work.
Is something changed in the syntax?

I have to add an extra line "case _ => println("something else")"
which is not mentioned in the pdf, because otherwise I get a non-
exhaustive error.



On 30 jan, 16:40, Eugene Burmako <eugene.burm...@epfl.ch> wrote:
> import scala.reflect.mirror._
>

Eugene Burmako

unread,
Jan 30, 2012, 12:04:31 PM1/30/12
to scala-i...@googlegroups.com
All right, my mistake again. You should match code.tree, not code. Guide has been updated again, thanks.

Dave

unread,
Jan 30, 2012, 12:47:13 PM1/30/12
to scala-internals
Yeah!

scala> four.tree match { case c"2 + $x" => println(showRaw(x))
| case _ => println("something else")
| }
Literal(Constant(2))


On Jan 30, 6:04 pm, Eugene Burmako <eugene.burm...@epfl.ch> wrote:
> All right, my mistake again. You should match code.tree, not code. Guide
> has been updated again, thanks.
>
> > > - Tekst uit oorspronkelijk bericht weergeven -- Hide quoted text -
>
> - Show quoted text -

Dave

unread,
Jan 31, 2012, 1:34:08 PM1/31/12
to scala-internals
Is it (already) possible to translate this idiomatic Nemerle code to
Scala?

[MacroUsage(MacroPhase.BeforeTypedMembers, MacroTargets.Class)]
macro Extensible(typeBuilder : TypeBuilder)
{
ExtensibleImpl.DoTransform(Macros.ImplicitCTX(), typeBuilder)
}

module ExtensibleImpl
{
public DoTransform(typer : Typer, typeBuilder : TypeBuilder) :
void
{
Macros.DefineCTX(typer);

//here goes the rest
}
}

And the use site of the macro e.g.:

[Extensible]
public abstract class Node {}

so in other words what is TypeBuilder, Typer and the macro attribute
[Extensible]
in Scala?

And is there an equivalent typeBuilder.Define(ast) in Scala?

e.g. in:

def defineMethod(ast : ClassMember) : void { typeBuilder.Define(ast) }

Dave

unread,
Feb 2, 2012, 5:40:47 AM2/2/12
to scala-internals
Eugene, maybe you are in the best position to answer this question
below.

Eugene Burmako

unread,
Feb 2, 2012, 6:08:00 AM2/2/12
to scala-internals
Speaking of the typeBuilder question, inside a macro you have access
to compiler context via an implicit parameter that's generated into
macro signatures. This context represents a restricted subset of the
compiler API, and this subset currently doesn't include any facilities
to operate on classes/members.

For now making macro defs stable is our top priority. Codegen in the
large (macro types) is a next step, but it's hard to predict when it's
going to happen. Same for macro annotations. We kinds of like them,
but implementing them is not our priority now.

Simon Ochsenreither

unread,
Feb 2, 2012, 6:26:56 AM2/2/12
to scala-i...@googlegroups.com
Hi Eugene,

So what are the plans regarding macros and 2.10? I'm a bit scared of the idea that Scala devs are again pushing out some (cool) feature _without_ any reasonable example/implementation on how to use it. (See scala.Dynamic, scala.DelayedInit, ...)

The 2.10 release seems to be one of the largest feature releases ever, even without macros. I assume Typesafe wants to release it before (or on) ScalaDays, so the time is running out fast for testing.

The meeting notes also stopped being publsihed months ago, so it is really hard to see in which direction Scala is moving. It is not your fault of course but I find the information coming from Typesafe/EPFL to be _very_ lacking.

Thanks!

Simon

Ismael Juma

unread,
Feb 2, 2012, 6:36:04 AM2/2/12
to scala-i...@googlegroups.com
On Thu, Feb 2, 2012 at 11:26 AM, Simon Ochsenreither <simon.och...@googlemail.com> wrote:
The 2.10 release seems to be one of the largest feature releases ever, even without macros. I assume Typesafe wants to release it before (or on) ScalaDays, so the time is running out fast for testing.

Why do you assume that?

Best,
Ismael

Simon Ochsenreither

unread,
Feb 2, 2012, 6:58:24 AM2/2/12
to scala-i...@googlegroups.com
Because they said[1] that Scala 2.10 is released in the beginning of 2012. And April is probably already a stretched term for "beginning".

[1]
http://www.slideshare.net/Odersky
http://it-republik.de/jaxenter/news/Martin-Odersky-gibt-Einblick-in-Scala-2.10-061074.html
http://www.slideshare.net/marakana/martin-odersky-whats-next-for-scala

Eugene Burmako

unread,
Feb 2, 2012, 6:59:30 AM2/2/12
to scala-internals
Hi Simon,

I am currently preparing a SIP and it will depend on how that is
discussed whether and when the idea is accepted.

All the best,
Eugene

On Feb 2, 12:26 pm, Simon Ochsenreither

Ismael Juma

unread,
Feb 2, 2012, 4:23:58 PM2/2/12
to scala-i...@googlegroups.com
On Thu, Feb 2, 2012 at 11:58 AM, Simon Ochsenreither <simon.och...@googlemail.com> wrote:
Because they said[1] that Scala 2.10 is released in the beginning of 2012. And April is probably already a stretched term for "beginning".

Looks difficult to achieve given that we have only had a single milestone, features are still being developed and it's already February.

Best,
Ismael

Adriaan Moors

unread,
Feb 3, 2012, 7:25:30 AM2/3/12
to scala-i...@googlegroups.com
The meeting notes also stopped being publsihed months ago,
that's my fault -- I've been busy with the virtual pattern matcher implementation, scala-virtualized maintenance, a conference and of course the xmas break

I'm going to make a summary of the notes you have missed, but I'm confident that 90% of their contents has been covered by discussion on this very list.

adriaan

Eugene Burmako

unread,
May 2, 2012, 9:52:26 AM5/2/12
to Dave, Eugene Burmako, scala-i...@googlegroups.com
Hi Dave,

A lot of stuff was going on, so we never had time to implement
quasiquotes. As of now, they are in a separate branch, awaiting review
and merging.

Do you have any specific scenario in mind that involves quasiquotes?

Cheers,
Eugene

On 2 May 2012, at 15:21, Dave <dave.mah...@hotmail.com> wrote:

> Hi Eugene,
>
> I re-tried the example with the quasiquotes in 2.10.0-M3, but it's not
> working and -Xquasiquotes doesn't seem available.
> Is there a syntax change?
>
> C:\Users\Dave>scala
> Welcome to Scala version 2.10.0-M3 (Java HotSpot(TM) Client VM, Java
> 1.7.0_04).
> Type in expressions to have them evaluated.
> Type :help for more information.
>
> scala> val two = c"2"
> <console>:7: error: value c is not a member of StringContext
> val two = c"2"
> ^
>
>
>
> On 23 jan, 20:43, Eugene Burmako <eugene.burm...@epfl.ch> wrote:
>> It would if you used the compiler from alphakeplerdemo:https://github.com/xeno-by/alphakeplerdemo/tree/skeleton/compiler. The
>> underscore syntax hasn't yet reached the upstream.
>>
>> On 23 January 2012 19:39, Daniel Sobral <dcsob...@gmail.com> wrote:
>>
>>
>>
>>> On Sun, Jan 22, 2012 at 21:32, Eugene Burmako <eugene.burm...@epfl.ch>
>>> wrote:
>>>> Hey! A few days ago, on this Friday, we've merged a pull request to
>>>> scala/scala that represents significant progress with macros.
>>
>>>> I'd love you to explore our current take on macros and, possibly, get
>>>> assistance from a walkthrough from my recent talk in Kyiv (http://
>>>> scalamacros.org/talks/2012-01-14-EnAlphaKepler.pdf). Your feedback is
>>>> very welcome - if something doesn't work out with your macro test-
>>>> drive, let me know, and I'll try to fix the troubles.
>>
>>>> In the meanwhile, we'll be polishing the implementation and preparing
>>>> a beta version that will be accompanied by a SIP. See you soon!
>>
>>> I was trying to use the alphakeplerdemo, but I'm getting this error:
>>
>>> dcs@ayanami:~/github/alphakeplerdemo (skeleton)$ scalac -Xmacros Rx.scala
>>> Rx.scala:24: error: unbound wildcard type
>>> def macro forAllMatches(pattern: String, f: _): Unit = {
>>> ^
>>> one error found
>>
>>> Shouldn't it have worked?
>>> --
>>> Daniel C. Sobral
>>

Dave

unread,
May 2, 2012, 10:43:03 AM5/2/12
to scala-internals
Hi Eugene,
I was just checking if the quasiquotes were included milestone 3 and
used the example from the slides.

Can the scala macros define methods?
In the alpha version you said they couldn't, but I don't know if that
is changed.

def defineMethod(ast : ClassMember) : void { typeBuilder.Define(ast) }
defineMethod(<[ decl: public abstract $("is" + methodSufix : usesite)($
(paramName : usesite) : $(baseType : typed)) : bool;]>);

and add custom attributes like in Nemerle to make a macro that calls a
macro for certain group of classes

foreach (type in typeBuilder.GetAllSubTypes())
type.Ast.AddCustomAttribute(Util.locate(type.NameLocation,
<[ ExprProblemMacros.ImplementIsAs ]>));
}

Both scenarios (method definition insertion and macro calling macro)
use quasi-quotations.

On 2 mei, 15:52, Eugene Burmako <eugene.burm...@epfl.ch> wrote:
> Hi Dave,
>
> A lot of stuff was going on, so we never had time to implement
> quasiquotes. As of now, they are in a separate branch, awaiting review
> and merging.
>
> Do you have any specific scenario in mind that involves quasiquotes?
>
> Cheers,
> Eugene
>
> >> - Tekst uit oorspronkelijk bericht weergeven -- Tekst uit oorspronkelijk bericht niet weergeven -

Eugene Burmako

unread,
May 2, 2012, 10:55:08 AM5/2/12
to scala-i...@googlegroups.com
In M3 (and, most likely, in 2.10.0 final), macros are unable to alter symbol tables (i.e. they can emit local classes, but they cannot create/modify globally visible classes). 

We surely want to implement this feature, but that won't be easy, so we have to delay it to a future release.

Dave

unread,
May 2, 2012, 9:21:16 AM5/2/12
to Eugene Burmako, scala-i...@googlegroups.com
Hi Eugene,

I re-tried the example with the quasiquotes in 2.10.0-M3, but it's not
working and -Xquasiquotes doesn't seem available.
Is there a syntax change?

C:\Users\Dave>scala
Welcome to Scala version 2.10.0-M3 (Java HotSpot(TM) Client VM, Java
1.7.0_04).
Type in expressions to have them evaluated.
Type :help for more information.

scala> val two = c"2"
<console>:7: error: value c is not a member of StringContext
val two = c"2"
^



On 23 jan, 20:43, Eugene Burmako <eugene.burm...@epfl.ch> wrote:
> It would if you used the compiler from alphakeplerdemo:https://github.com/xeno-by/alphakeplerdemo/tree/skeleton/compiler. The
> underscore syntax hasn't yet reached the upstream.
>
> On 23 January 2012 19:39, Daniel Sobral <dcsob...@gmail.com> wrote:
>
>
>
> > On Sun, Jan 22, 2012 at 21:32, Eugene Burmako <eugene.burm...@epfl.ch>
> > wrote:
> > > Hey! A few days ago, on this Friday, we've merged a pull request to
> > > scala/scala that represents significant progress with macros.
>
> > > I'd love you to explore our current take on macros and, possibly, get
> > > assistance from a walkthrough from my recent talk in Kyiv (http://
> > > scalamacros.org/talks/2012-01-14-EnAlphaKepler.pdf). Your feedback is
> > > very welcome - if something doesn't work out with your macro test-
> > > drive, let me know, and I'll try to fix the troubles.
>
> > > In the meanwhile, we'll be polishing the implementation and preparing
> > > a beta version that will be accompanied by a SIP. See you soon!
>
> > I was trying to use the alphakeplerdemo, but I'm getting this error:
>
> > dcs@ayanami:~/github/alphakeplerdemo (skeleton)$ scalac -Xmacros Rx.scala
> > Rx.scala:24: error: unbound wildcard type
> >  def macro forAllMatches(pattern: String, f: _): Unit = {
> >                                              ^
> > one error found
>
> > Shouldn't it have worked?
> > --
> > Daniel C. Sobral
>

Dave

unread,
May 4, 2012, 6:08:12 PM5/4/12
to scala-internals
Hi Eugene,
Is it possible to convert something like the simplest Nemerle macro to
Scala?

macro m () {
Nemerle.IO.printf ("compile-time\n");
<[ Nemerle.IO.printf ("run-time\n") ]>;
}


On 2 mei, 16:55, Eugene Burmako <eugene.burm...@epfl.ch> wrote:
> In M3 (and, most likely, in 2.10.0 final), macros are unable to alter
> symbol tables (i.e. they can emit local classes, but they cannot
> create/modify globally visible classes).
>
> We surely want to implement this feature, but that won't be easy, so we
> have to delay it to a future release.
>

Eugene Burmako

unread,
May 5, 2012, 2:08:15 AM5/5/12
to scala-i...@googlegroups.com
import scala.reflect.makro.Context

def m(c: Context) = {
  println("compile-time")
  c.reify(println("run-time"))
}

def foo = macro m

Dave

unread,
May 5, 2012, 8:21:29 AM5/5/12
to scala-internals
Thanks, Eugene

>On 5 mei, 08:08, Eugene Burmako <eugene.burm...@epfl.ch> wrote:
> import scala.reflect.makro.Context
>
> def m(c: Context) = {
>   println("compile-time")
>   c.reify(println("run-time"))
>
> }
>
> def foo = macro m
>

Dave

unread,
May 7, 2012, 8:36:01 AM5/7/12
to scala-internals
Hi Eugene,
Is there a way to unquote within reify?

def m(c: Context) = {
val x = 42
c.reify(val y = $x)
}

And is reify intended as the new quasi-quotation syntax like the old
c"val y = 5"?
Or is it something else?


On 5 mei, 08:08, Eugene Burmako <eugene.burm...@epfl.ch> wrote:
> import scala.reflect.makro.Context
>
> def m(c: Context) = {
>   println("compile-time")
>   c.reify(println("run-time"))
>
> }
>
> def foo = macro m
>

Eugene Burmako

unread,
May 7, 2012, 8:43:15 AM5/7/12
to scala-i...@googlegroups.com
Yes, reify is intended to be a quasiquoting facility.

However it's not a drop-in replacement for c"..." quasiquotes, because it only works with well-typed trees (i.e. you cannot assemble trees with statically unknown types using reify). OTOH reify doesn't require adding new concepts to the table, neither it requires implementing and polishing a complex library functionality such as c"..." quasiquotes. So the [usefullness/spent time] ratio was in favor of reify, but not in favor of quasiquotes. We might add quasiquotes later, though.

Unquoting aka splicing in current model is performed with Expr.eval.

Your example would look as follows:

val x = c.Expr(Literal(Constant(42)) // or c.reify(42)
c.reify(val y = x.eval)

Dave

unread,
May 7, 2012, 9:30:06 AM5/7/12
to scala-internals
And is it possible to extract using reify/eval syntax?

scala> import reflect.mirror._
import reflect.mirror._

scala> val two = reify(2)
two: reflect.mirror.Expr[Int(2)] = Expr[Int(2)](2)

scala> val four = reify(two.eval + two.eval)
four: reflect.mirror.Expr[Int(4)] = Expr[Int(4)](4)

scala> four.tree match { case reify(2 + x.eval) =>
println(showRaw(x)) }
<console>:13: error: macro method reify is not a case class
constructor, nor doe
s it have an unapply/unapplySeq method
four.tree match { case reify(2 + x.eval) =>
println(showRaw(x)) }
^
<console>:13: error: not found: value x
four.tree match { case reify(2 + x.eval) =>
println(showRaw(x)) }

^
<console>:13: error: Could not typecheck extractor call: case class
reify with a
rguments List($plus(2, x.eval))
four.tree match { case reify(2 + x.eval) =>
println(showRaw(x)) }
^



On 7 mei, 14:43, Eugene Burmako <eugene.burm...@epfl.ch> wrote:
> Yes, reify is intended to be a quasiquoting facility.
>
> However it's not a drop-in replacement for c"..." quasiquotes, because it
> only works with well-typed trees (i.e. you cannot assemble trees with
> statically unknown types using reify). OTOH reify doesn't require adding
> new concepts to the table, neither it requires implementing and polishing a
> complex library functionality such as c"..." quasiquotes. So the
> [usefullness/spent time] ratio was in favor of reify, but not in favor of
> quasiquotes. We might add quasiquotes later, though.
>
> Unquoting aka splicing in current model is performed with Expr.eval.
>
> Your example would look as follows:
>
> val x = c.Expr(Literal(Constant(42)) // or c.reify(42)
> c.reify(val y = x.eval)
>

Eugene Burmako

unread,
May 7, 2012, 9:41:10 AM5/7/12
to scala-i...@googlegroups.com, Olivier Chafik
No, unfortunately not.

However, take a look at Olivier Chafik's compilets: https://github.com/ochafik/Scalaxy/wiki/Scalaxy-Compilets.

Stefan Zeiger

unread,
May 7, 2012, 9:46:22 AM5/7/12
to scala-i...@googlegroups.com
Hi,

I was trying to do some cross-stage execution in M3 but I can't seem to
get it working. The idea is to take a function and a parameter for it,
and run it at compile time (provided it does not reference any
non-static values). The resulting value is then reified and shipped to
run time.

// Allows reification of a value (as opposed to an expression)
trait Reifyable[T] {
def apply(c: Context, v: T): c.Expr[T]
}

object Reifyable {
// Reify a string value by creating a literal for it
implicit val stringReifyable: Reifyable[String] = new Reifyable[String] {
def apply(c: Context, v: String): c.Expr[String] = {
import c.mirror._
Expr(Literal(Constant(v)))
}
}
}

object CompileTime {
// Run the given function on its input at compile time and insert the
resulting value
def eval[P, R](f: P => R, p: P)(implicit r: Reifyable[R]): R = macro
eval_impl[P, R]

def eval_impl[P, R : c.TypeTag](c: Context)(f: c.Expr[P => R], p:
c.Expr[P])(r: c.Expr[Reifyable[R]]): c.Expr[R] = {
import c.mirror._
val p_ = Expr[P](c.resetAllAttrs(p.tree)).eval
println("p: "+p_)
val f_ = Expr[P => R](c.resetAllAttrs(f.tree)).eval
println("f: "+f_)
val r_ = Expr[Reifyable[R]](c.resetAllAttrs(r.tree)).eval
println("r: "+r_)
val res = f_(p_)
println("res: "+res)
r_.apply(c, res)
}
}

This works for p, but not for f and r in my test case:

class MacrosTest {
@Test def testCompileTime() {
val res: String = CompileTime.eval[Int, String](X.foo _, 42)
}
}

class X {
def bar(i: Int): String = { println("running bar"); "bar:"+i }
}

object X {
def foo(i: Int): String = { println("running foo"); "foo:"+i }
}

Trying to evaluate f gives me:

[error] object foo is not a member of package X
[error] at
scala.tools.nsc.ToolBoxes$ToolBox.runExpr(ToolBoxes.scala:49)
[error] at scala.reflect.api.Exprs$Expr.eval(Exprs.scala:15)
[error] at
com.novocode.macrostuff.CompileTime$.eval_impl(MacroStuff.scala:89)
[error] val res: String = CompileTime.eval[Int, String](X.foo _, 42)
[error] ^

And for r I get:

[error] scala.tools.nsc.ToolBoxes$ToolBox$ToolBoxError: reflective
toolbox has failed: cannot operate on trees that are already typed
[error] at
scala.tools.nsc.ToolBoxes$ToolBox.runExpr(ToolBoxes.scala:49)
[error] at scala.reflect.api.Exprs$Expr.eval(Exprs.scala:15)
[error] at
com.novocode.macrostuff.CompileTime$.eval_impl(MacroStuff.scala:89)
[error] val res: String = CompileTime.eval[Int, String](X.foo _, 42)

Am I doing something wrong here, am I running into bugs, or is it just
not supported at the moment so I should give up?

-sz

Eugene Burmako

unread,
May 7, 2012, 10:07:36 AM5/7/12
to scala-i...@googlegroups.com
The first error happens because you use sbt.

The second error happens because toolboxes reject already typed trees. That's because of non-idempotency of typer. Though, I wonder why it happens - you just did resetAllAttrs.

Stefan Zeiger

unread,
May 7, 2012, 10:29:14 AM5/7/12
to scala-i...@googlegroups.com
On 2012-05-07 16:07, Eugene Burmako wrote:
The first error happens because you use sbt.

Ah, I thought there were only problems at run-time. Is there some work-around for the compilation? Like adding some custom classpath magic to set the macro lookup path in sbt?


The second error happens because toolboxes reject already typed trees. That's because of non-idempotency of typer. Though, I wonder why it happens - you just did resetAllAttrs.

Yes, that's the issue :)

BTW, I first tried the whole Expr(c.resetAllAttrs(x.tree)).eval stuff without a type parameter on Expr and got completely wrong types inferred (they all became Expr[R]).

Another thing: Is there a way to easily check if a tree contains non-static references without actually trying to evaluate it?

-sz

Eugene Burmako

unread,
May 7, 2012, 10:49:30 AM5/7/12
to scala-i...@googlegroups.com
Not sure about classpath magic, because I know virtuall nothing about sbt. The goal you want to achieve is having scala-library.jar and your custom classes on the same classloader.

Mark Harrah

unread,
May 8, 2012, 12:04:24 PM5/8/12
to scala-i...@googlegroups.com
On Mon, 7 May 2012 16:49:30 +0200
Eugene Burmako <eugene....@epfl.ch> wrote:

> Not sure about classpath magic, because I know virtuall nothing about sbt.
> The goal you want to achieve is having scala-library.jar and your custom
> classes on the same classloader.

If we are talking about compile-time (hard to keep track sometimes), this is probably not ever going to happen. sbt loads the Scala compiler and library in a class loader that rarely changes. (It will always load the compiler and library together, which you asked about in an earlier email.) This keeps the classes optimized. Application classes change frequently, so they are loaded in a child class loader where they can be dropped and garbage collected.

-Mark

Dave

unread,
May 26, 2012, 5:01:43 AM5/26/12
to scala-internals


On 7 mei, 14:43, Eugene Burmako <eugene.burm...@epfl.ch> wrote:
> Yes, reify is intended to be a quasiquoting facility.
>


Shouldn't it be called quasiquote then?

scala> val two = quasiquote(2)
two: reflect.mirror.Expr[Int(2)] = Expr[Int(2)](2)

or short

scala> val two = qq(2)

Eugene Burmako

unread,
May 26, 2012, 1:43:28 PM5/26/12
to scala-i...@googlegroups.com

Also, the notion of multi-stage computations is at the root of our macro system, and reify fits this context much better.

Dave

unread,
Jun 13, 2012, 11:56:59 AM6/13/12
to scala-internals
Hi Eugene,
how do I convert this macro to milestone 4? It worked in milestone 3.

compiletime.scala
=================
import language.experimental.macros
import scala.reflect.makro.Context

object MacroSample {
def compiledTime(): String = macro compiledTime_impl

def compiledTime_impl(c: Context)(): c.Expr[String] = {
import c.mirror._
import c.reify
val date = Expr(Literal(Constant(new java.util.Date().toString)))
reify("Compiled Time: " + date.eval)
}
}

Expr, Literal and Constant seem to have been removed.


On 26 mei, 19:43, Eugene Burmako <eugene.burm...@epfl.ch> wrote:
> Quasiquoting is something more general:http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.87.1527&rep=...
> .
>
> Also, the notion of multi-stage computations is at the root of our macro
> system, and reify fits this context much better.
>
> On 26 May 2012 11:01, Dave <dave.mahabiers...@hotmail.com> wrote:
>
>
>
>
>
> > On 7 mei, 14:43, Eugene Burmako <eugene.burm...@epfl.ch> wrote:
> > > Yes, reify is intended to be a quasiquoting facility.
>
> > Shouldn't it be called quasiquote then?
>
> > scala> val two = quasiquote(2)
> > two: reflect.mirror.Expr[Int(2)] = Expr[Int(2)](2)
>
> > or short
>
> > scala> val two = qq(2)
> > two: reflect.mirror.Expr[Int(2)] = Expr[Int(2)](2)- Tekst uit oorspronkelijk bericht niet weergeven -

Eugene Burmako

unread,
Jun 13, 2012, 12:05:56 PM6/13/12
to scala-i...@googlegroups.com
Hi Dave,

Please, use the migration guide from [1]. That post also contains a link to the reflection pre-SIP, which would be a useful read, because reflection API is the backbone of macros.

Your particular compilation errors can be remedied by replacing "c.mirror._" with "c.universe._" and "eval" with "splice".

Should you have any further questions, I'm here to help.


Cheers,
Eugene

Dave

unread,
Jun 13, 2012, 2:13:30 PM6/13/12
to scala-internals
Okay thanks Eugene,

This works:

import language.experimental.macros
import scala.reflect.makro.Context

object MacroSample {
def compiledTime(): String = macro compiledTime_impl

def compiledTime_impl(c: Context)(): c.Expr[String] = {
import c.universe._
import c.reify
val date = c.Expr(Literal(Constant(new
java.util.Date().toString)))
reify("Compiled Time: " + date.splice)
}
}

I will read the reflection pre-SIP.


On 13 jun, 18:05, Eugene Burmako <eugene.burm...@epfl.ch> wrote:
> Hi Dave,
>
> Please, use the migration guide from [1]. That post also contains a link to
> the reflection pre-SIP, which would be a useful read, because reflection
> API is the backbone of macros.
>
> Your particular compilation errors can be remedied by replacing
> "c.mirror._" with "c.universe._" and "eval" with "splice".
>
> Should you have any further questions, I'm here to help.
>
> [1]http://groups.google.com/group/scala-language/browse_thread/thread/bf...
>
> Cheers,
> Eugene
> > > - Tekst uit oorspronkelijk bericht weergeven -- Tekst uit oorspronkelijk bericht niet weergeven -
Reply all
Reply to author
Forward
0 new messages