Macro paradise

1,265 views
Skip to first unread message

Eugene Burmako

unread,
Dec 18, 2012, 5:38:39 PM12/18/12
to scala-language
Simultaneously with the release of Scala 2.10.0-final, tentatively
scheduled for 26 December 2012, we're going to announce the
availability of paradise/macros, a dedicated branch in our official
Scala repository which will host the latest macro developments.

When things like macro types, macro annotations or type inference-
friendly macros - you name it - get ripe for beta testing, they are
going to end up in paradise/macros. Much like the vanilla Scala, macro
paradise is going to be built nightly and have its own Maven artifact,
so it'll be very easy to use it in your projects.

In this talk I present a couple of new features that will be released
into paradise this Christmas, along with a glimpse of the things to
come. I also discuss the roadmap of macro development for the near
future, so if you want to have something in Scala macros, be sure to
take a look and speak up.

Screencast: http://vimeo.com/user8565009/macro-paradise-talk
Slides: http://scalamacros.org/talks/2012-12-18-MacroParadise.pdf

Pascal Voitot Dev

unread,
Dec 18, 2012, 5:47:11 PM12/18/12
to scala-language
great :D
I spent some time developing JSON macro for Play2.1 and I must say a few helpers would have been welcome :D

Anyway Thanks for great work...

Best Regards
Pascal

On Tue, Dec 18, 2012 at 11:38 PM, Eugene Burmako <xen...@gmail.com> wrote:
nightly

Josh Suereth

unread,
Dec 18, 2012, 5:48:09 PM12/18/12
to scala-l...@googlegroups.com

"Releasing features into paradise" sounds pretty humane.  What aren't you telling us, Eugene?

Erik Osheim

unread,
Dec 18, 2012, 5:49:08 PM12/18/12
to scala-l...@googlegroups.com
On Tue, Dec 18, 2012 at 02:38:39PM -0800, Eugene Burmako wrote:
> When things like macro types, macro annotations or type inference-
> friendly macros - you name it - get ripe for beta testing, they are
> going to end up in paradise/macros. Much like the vanilla Scala, macro
> paradise is going to be built nightly and have its own Maven artifact,
> so it'll be very easy to use it in your projects.

This is great news, especially the maven artifacts. This means I can
create a macros-paradise branch and just keep in sync with your work to
test it and see how it goes. Are you planning on using milestones, or
git revisions, or a separate versioning system?

This is like an early Christmas gift: thanks!

-- Erik

Josh Suereth

unread,
Dec 18, 2012, 5:50:29 PM12/18/12
to scala-l...@googlegroups.com

But where do the features go!

Agreed.  Great work Eugene!

I hope in the future we can mimic this process for SIP work before it hits master.

Eugene Burmako

unread,
Dec 18, 2012, 5:57:54 PM12/18/12
to scala-l...@googlegroups.com
So far the details of versioning are a bit vague. The initial idea was to only provide SNAPSHOT versions, just like vanilla Scala does, but under a different maven groupId. Milestones would be great, but I'm not sure, since they are going to entail corresponding milestone builds of IDE and whatnot. More details will come later this week, once I get to the actual infrastructure setup.

Eugene Burmako

unread,
Dec 18, 2012, 5:58:17 PM12/18/12
to scala-l...@googlegroups.com
Helpers are a sure thing. Please let me know how I can help you with macros or reflection.

Erik Osheim

unread,
Dec 18, 2012, 6:03:00 PM12/18/12
to scala-l...@googlegroups.com
On Tue, Dec 18, 2012 at 11:57:54PM +0100, Eugene Burmako wrote:
> So far the details of versioning are a bit vague. The initial idea was to
> only provide SNAPSHOT versions, just like vanilla Scala does, but under a
> different maven groupId. Milestones would be great, but I'm not sure, since
> they are going to entail corresponding milestone builds of IDE and whatnot.
> More details will come later this week, once I get to the actual
> infrastructure setup.

I see. I guess I'd strongly encourage the use of (even occasional)
milesstones if possible. This way, if someone is using one and
something stops working on an update (in snapshot or a new milestone)
it becomes a lot easier to figure out what has changed. If a library
author only has SNAPSHOT then they're essentially at the mercy of
chance and fate... and you. :)

I don't see why builds of the IDE against SNAPSHOT are any easier than
against milestones, but of course I only have a small piece of the
picture in my head.

Thanks!

-- Erik

Eugene Burmako

unread,
Dec 18, 2012, 6:10:25 PM12/18/12
to scala-l...@googlegroups.com, Josh Suereth, Grzegorz Kossakowski, Adriaan Moors
I rather meant that not a lot of people would expect ecosystem to be rebuilt for every nightly. On the other hand, milestones encourage bigger expectations => more testing and more hassle.

Though I agree that we need to bring method to the madness. Josh, Greg, Adriaan, what would you advise?

Pascal Voitot Dev

unread,
Dec 18, 2012, 6:11:52 PM12/18/12
to scala-language
I'll remember when I have questions ;)
We could implement quite impressive features with macro such as resolving implicits while generating tree.
You can have an insight of those JSON macro in this article I've written a few weeks ago
http://mandubian.com/2012/11/11/JSON-inception/

I currently work on other interesting macro usecases. I'll tell you when there are ready.

Pascal

Grzegorz Kossakowski

unread,
Dec 18, 2012, 6:45:18 PM12/18/12
to Eugene Burmako, scala-l...@googlegroups.com, Josh Suereth, Adriaan Moors
On 18 December 2012 15:10, Eugene Burmako <eugene....@epfl.ch> wrote:
I rather meant that not a lot of people would expect ecosystem to be rebuilt for every nightly. On the other hand, milestones encourage bigger expectations => more testing and more hassle.

Though I agree that we need to bring method to the madness. Josh, Greg, Adriaan, what would you advise?

I think we should start with SNAPSHOTs only (and probably deployed to special repo you need to opt-in) as it's a lot easier to support.

I agree with Eugene that once you start doing milestones people have higher expectations so they'll start asking for IDE support and other libraries being released. Then you have to decide where you want to put those artifacts and how long do you want to keep them. Also, if you get milestones you probably want to have special category of tickets in the issue tracker. You can see it would mean you almost fork entire Scala ecosystem which macro paradise branch is not meant to be doing.

Nightly builds deployed to snapshot repository (which is transient by design) should set the expectations right. It's meant for people play around with latest ideas in macro world but it's not meant to provide stable development environment. If macro-related feature gets fleshed out it should get cleaned up and merged back to master so it becomes part of the next milestone release of the 2.11 cycle. We plan to release milestones every 2 months initially.

--
Grzegorz Kossakowski

Eugene Burmako

unread,
Dec 18, 2012, 7:15:19 PM12/18/12
to scala-language
I forgot to mention that we already have a Scala version named "macro-
paradise" in JIRA, so it's possible to report bugs against macro
paradise using the standard workflow. I've submitted some known issues
using this convention: https://issues.scala-lang.org/secure/IssueNavigator.jspa?mode=hide&requestId=11912.

On Dec 19, 12:45 am, Grzegorz Kossakowski
<grzegorz.kossakow...@gmail.com> wrote:

Paul Butcher

unread,
Dec 19, 2012, 10:02:24 AM12/19/12
to scala-l...@googlegroups.com, Eugene Burmako, Josh Suereth, Adriaan Moors
This is great news - many thanks Eugene.

Regarding SNAPSHOT versions, is there any update on how SBT treats SNAPSHOT compiler versions? I got myself tied in all sorts of knots with it a while ago:


I'd really like to avoid this kind of unpleasantness if possible.

--
paul.butcher->msgCount++

Snetterton, Castle Combe, Cadwell Park...
Who says I have a one track mind?

http://www.paulbutcher.com/
LinkedIn: http://www.linkedin.com/in/paulbutcher
MSN: pa...@paulbutcher.com
AIM: paulrabutcher
Skype: paulrabutcher

Paul Phillips

unread,
Dec 19, 2012, 10:14:01 AM12/19/12
to scala-l...@googlegroups.com, Eugene Burmako, Josh Suereth, Adriaan Moors


On Wed, Dec 19, 2012 at 7:02 AM, Paul Butcher <pa...@paulbutcher.com> wrote:
Regarding SNAPSHOT versions, is there any update on how SBT treats SNAPSHOT compiler versions?

If you run "sbt update" explicitly now, it will update your snapshots. I haven't had a problem with this part in a while. My problem with using a non-standard compiler shifted to this one: https://github.com/harrah/xsbt/issues/626

Paul Butcher

unread,
Dec 19, 2012, 10:28:28 AM12/19/12
to scala-l...@googlegroups.com, Eugene Burmako, Josh Suereth, Adriaan Moors
On 19 Dec 2012, at 15:14, Paul Phillips <pa...@improving.org> wrote:
My problem with using a non-standard compiler shifted to this one: https://github.com/harrah/xsbt/issues/626

Hmm - given that that ticket is closed, is the implication that this is fixed with SBT 0.13? It wasn't quite clear to me from the comments in the ticket...

Paul Phillips

unread,
Dec 19, 2012, 1:00:23 PM12/19/12
to scala-l...@googlegroups.com, Eugene Burmako, Josh Suereth, Adriaan Moors


On Wed, Dec 19, 2012 at 7:28 AM, Paul Butcher <pa...@paulbutcher.com> wrote:
Hmm - given that that ticket is closed, is the implication that this is fixed with SBT 0.13? It wasn't quite clear to me from the comments in the ticket...

I'm not real sure either, but my impression is that it won't be "fixed" at all, but that things will work the way I want in 0.13 if I define my build differently.

Simon Ochsenreither

unread,
Dec 19, 2012, 6:23:01 PM12/19/12
to scala-l...@googlegroups.com
Great presentation!

The type macros look pretty impressive even at this stage already. Would they enable us to finally implement a working, JVM compatible Enum class?

Eugene Burmako

unread,
Dec 20, 2012, 3:03:54 AM12/20/12
to scala-l...@googlegroups.com
With the new APi you can emit top-level classes and objects, but if you need inner ones (e.g. to close over something in lexical scope), then the answer is probably no.

Eugene Burmako

unread,
Dec 20, 2012, 3:16:43 AM12/20/12
to scala-language
According to Adriaan's announcement, 2.10.0-final will be released
during the first week of January 2013 [1]. Therefore the release of
paradise/macros will also happen in January.

[1] http://groups.google.com/group/scala-internals/browse_thread/thread/dd1ef14c985c3742

Dave

unread,
Dec 20, 2012, 4:44:38 AM12/20/12
to scala-l...@googlegroups.com
Hi Eugene,
Looks great.
The Lifter example and the db persistence example of type macros are very clear and readible.

Do you also have a thought about compiler plugin macros i.e. application-wide macros and how they are booted (with -Xplugin now only supports the old way compiler plugin interface) and scan all source files in the application and create some stub files or create directly the class files from Asts. And is there something available in a macro equivalent to javax.annotation.processing.RoundEnvironment?
Or should I use the plugin templates (and use classes from import scala.tools.nsc)?

Would be nice if there were some example of a compiler-plugin macro.



Op donderdag 20 december 2012 09:16:43 UTC+1 schreef Eugene Burmako het volgende:

Simon Ochsenreither

unread,
Dec 20, 2012, 9:26:07 AM12/20/12
to scala-l...@googlegroups.com
Hi Eugene,

With the new API you can emit top-level classes and objects, but if you need inner ones (e.g. to close over something in lexical scope), then the answer is probably no.

So a transformation from

object Direction extends scala.Enum {
  object North
  object East
  object South
  object West
}


to

final class Direction private(val name: String, ordinal: Int) extends java.lang.Enum[Direction](name, ordinal)
object Direction {
  val North = new Direction("North", 0)
  val East  = new Direction("East", 0)
  val South = new Direction("South", 0)
  val West  = new Direction("West", 0)

  private val $VALUES = Array(North, East, South, West)
  def values = $VALUES.clone
  def valueOf(name: String) = java.lang.Enum.valueOf(classOf[Stuff], name)
}



should probably work?

Thanks,

Simon

Eugene Burmako

unread,
Dec 20, 2012, 9:37:34 AM12/20/12
to scala-l...@googlegroups.com
Yeah it should, except that you'll need to rename the underlying class. Synthetic classes are put into virtual source files, therefore you'll get an error that companions class Direction and object Direction are defined in different files. However if you name the class as for example Direction$Enum, everything will be fine.

Klaus Havelund

unread,
Dec 20, 2012, 9:39:20 AM12/20/12
to scala-l...@googlegroups.com

This is (approximately) how one should write an enumerated type:

  enum Direction {North,East,South,West}

Anything longer than that is a challenge to keep working. In this one:

object Direction extends scala.Enum {
  object North
  object East
  object South
  object West
}


The following text is surplus: 

object extends scala . object object object object 

Klaus

Simon Ochsenreither

unread,
Dec 20, 2012, 9:54:07 AM12/20/12
to scala-l...@googlegroups.com

This is (approximately) how one should write an enumerated type:

  enum Direction {North,East,South,West}

Anything longer than that is a challenge to keep working.

I agree with that, but considering that Martin ruled out any language change for enums, we have to live with the syntactical options we already have.
Of course it is painful to shoe-horn the java-enum syntax into something which Scala natively understands. But compared to past tries like scala.Enumeration, macros enable us to
  • “interpret” the code in pretty much any way we want, so the notation and the semantics can be a lot less pianful
  • check for common usage errors and report them at compile-time

Eugene Burmako

unread,
Dec 21, 2012, 12:11:58 PM12/21/12
to scala-l...@googlegroups.com
Using c.enclosingRun.units you can gain access to all files being currently compiled. I guess that's what you're looking for when you mean RoundEnvironment?

Speaking of plugin macros, I haven't thought about them much. Currently you need an explicit trigger to activate a macro, be it a call to a def macro or a usage of a type macro.

Dave

unread,
Dec 21, 2012, 2:40:55 PM12/21/12
to scala-l...@googlegroups.com
Maybe it is. Thanks, I shall look at it.

Op vrijdag 21 december 2012 18:11:58 UTC+1 schreef Eugene Burmako het volgende:

Klaus Havelund

unread,
Dec 22, 2012, 1:12:44 PM12/22/12
to scala-l...@googlegroups.com

Let me reconsider what I wrote a few days ago wrt. enumerated types.

I wrote this:

>> This is (approximately) how one should write an enumerated type:
>>
>>   enum Direction {North,East,South,West}
>>
>> Anything longer than that is a challenge to keep working.

as a response to the following way of writing "the same" enumerated type:


  object Direction extends scala.Enum {
    object North
    object East
    object South
    object West
  }

After re-consideration, perhaps this is ok. The reason I say this is that one probably should see enumerated
types a special case of algebraic datatypes:

  http://en.wikipedia.org/wiki/Algebraic_data_type

For example, in Haskell we would write a tree as follows:

  data Tree = Empty
          | Leaf Int
          | Node Tree Tree

In Scala we currently could write this as:

  trait Tree
  case object Empty extends Tree
  case class Leaf(x:Int) extends Tree
  case class Node(left: Tree, right: Tree) extends Tree

If we count letters, Haskell uses 35 non-blank characters, while Scala uses 112, more than 3 times
as many characters. Granted, once you start typing, a few characters more do not really do much harm.
It is not a big deal, but still.

I think I understand why it cannot be as succinct as in Haskell: because Scala is charged with
the additional demanding task of merging functional and object oriented programming, and we might 
want for example to add methods to the alternatives, as in:

  trait Tree

  case object Empty extends Tree {
    override def toString = "*"
  }

  case class Leaf(x:Int) extends Tree {
    override def toString = x.toString
  }

  case class Node(left: Tree, right: Tree) extends Tree {
    override def toString = "<" + left + "," + right + ">"
  }

Hence, the syntax should support adding methods to the alternatives. So one can probably not get
away writing it the Haskel way. Instead, what might be desirable (ignoring the added methods) is something like this:

  datatype Tree {
    object Empty
    class Leaf(x:Int)
    class Node(left: Tree, right: Tree)
  }

(with the slight annoyance that one has to choose between 'object' and 'class') and this does not seem to 
be so far away from:

  object Direction extends Enum {

    object North
    object East
    object South
    object West
  }

Klaus

John Nilsson

unread,
Dec 22, 2012, 2:40:21 PM12/22/12
to scala-l...@googlegroups.com

Object and class can be inferred from the presence of arguments.
Maybe a syntax like
case class Direction match {
North
East
South
West
}
BR
John

Andrés Testi

unread,
Dec 22, 2012, 3:00:15 PM12/22/12
to scala-l...@googlegroups.com
why not object Direction extends scala.Enum('North, 'East, 'South, 'West) ?

Dave

unread,
Dec 22, 2012, 3:02:13 PM12/22/12
to scala-l...@googlegroups.com
Unfortunately c.enclosingRun.units consists only of 1 file and that is the file which has the usesite (the current unit) and

c.compilerSettings only consists of explicit compiler settings, nothing about the managed and unmanaged sourcefiles etc. and other default settings of the compiler is using to compile. The reading nevertheless works, but I like to query more info about what the compiler is doing. I there also something more elegant for the dummy return type, because I don't have to return anything, but the macro wants something like c.Expr[_] .A Unit would be fine.

 

  def checkSourcesAndCompilerSettingsInCompiletime() = macro checkSourcesAndCompilerSettingsInCompiletimeImpl
  def checkSourcesAndCompilerSettingsInCompiletimeImpl(c: Context)(): c.Expr[Unit] = {
    import c.universe._
    println("Compiler plugin ready")
    println("Compiler has found " + c.enclosingRun.units.size + " source file(s):")
    c.enclosingRun.units.foreach(cu => {
      val fn = cu.source.file.canonicalPath
      var contents = new StringBuffer
      io.Source.fromFile(new File(fn)).getLines.
        foreach(
          contents.append(_).append("\n")
        )
      println(fn)
      println("With content:")
      println(contents.toString)
    })
    println("Compiler has found these setting(s):")
    c.compilerSettings.foreach(println(_))
    reify(()) // dummy return type
  }
}
 

Op vrijdag 21 december 2012 20:40:55 UTC+1 schreef Dave het volgende:

Eugene Burmako

unread,
Dec 22, 2012, 3:14:06 PM12/22/12
to scala-l...@googlegroups.com
1) I just checked c.enclosingRun.units and it works:
21:11 ~/Projects/Kepler_macrosnippet06/sandbox (topic/macrosnippet06)$ scalac Macros.scala
21:11 ~/Projects/Kepler_macrosnippet06/sandbox (topic/macrosnippet06)$ scalac Qwe.scala Test.scala
List(Qwe.scala, Test.scala)

2) Speaking of c.compilerSettings, what kind of information would you like to query?

3) Could you please submit the Unit idea as an enhancement request?

Dave

unread,
Dec 22, 2012, 3:41:26 PM12/22/12
to scala-l...@googlegroups.com


Op zaterdag 22 december 2012 21:14:06 UTC+1 schreef Eugene Burmako het volgende:
1) I just checked c.enclosingRun.units and it works:
21:11 ~/Projects/Kepler_macrosnippet06/sandbox (topic/macrosnippet06)$ scalac Macros.scala
21:11 ~/Projects/Kepler_macrosnippet06/sandbox (topic/macrosnippet06)$ scalac Qwe.scala Test.scala
List(Qwe.scala, Test.scala)

So the files have to be explicit on the command line? But what if it is compiled with sbt? Or with a @myfiles file which can contain sourcefiles and compiler arguments?

2) Speaking of c.compilerSettings, what kind of information would you like to query?

Also the non-explicit compiler settings
 
3) Could you please submit the Unit idea as an enhancement request?

Okay

Dave

unread,
Dec 22, 2012, 5:12:17 PM12/22/12
to scala-l...@googlegroups.com
It seems indeed that the files and compiler options must be on the command line
The @myfiles is supported, but in eclipse and sbt it is not working

C:\scala-2.10.0-RC2\myexamples\volatile>scalac @sources_list.txt
Compiler plugin ready
Compiler has found 2 source file(s):
C:\scala-2.10.0-RC2\myexamples\volatile\A.scala
With content:
class A {
  import Macros._

  checkSourcesAndCompilerSettingsInCompiletime()

}

C:\scala-2.10.0-RC2\myexamples\volatile\B.scala
With content:
class B {
/*
extra file
*/

}

Compiler has found these setting(s):
-deprecation

Op zaterdag 22 december 2012 21:41:26 UTC+1 schreef Dave het volgende:

Dave

unread,
Dec 22, 2012, 5:16:46 PM12/22/12
to scala-l...@googlegroups.com
This has to be in front
object Macros {
  import language.experimental.macros
  import reflect.macros.Context
  import java.io.File

Simon Ochsenreither

unread,
Dec 22, 2012, 5:31:38 PM12/22/12
to scala-l...@googlegroups.com
why not object Direction extends scala.Enum('North, 'East, 'South, 'West) ?

How would the syntax look like if you wanted to have method definitions for each enum?

Andrés Testi

unread,
Dec 22, 2012, 8:12:12 PM12/22/12
to scala-l...@googlegroups.com
you're right

Dave

unread,
Dec 22, 2012, 8:18:49 PM12/22/12
to scala-l...@googlegroups.com
Hi Eugene,
I don't know what it is but for sbt the macro finds all 22 source files in my project.

Op zaterdag 22 december 2012 21:14:06 UTC+1 schreef Eugene Burmako het volgende:

Dave

unread,
Dec 22, 2012, 10:07:50 PM12/22/12
to scala-l...@googlegroups.com
For eclipse "build project" it works too.

Op zondag 23 december 2012 02:18:49 UTC+1 schreef Dave het volgende:

Eugene Burmako

unread,
Dec 23, 2012, 5:10:15 AM12/23/12
to scala-l...@googlegroups.com
Hmm, then under what circumstances did c.enclosingRun.units return only 1 file? Maybe when building incrementally?

Dave

unread,
Dec 23, 2012, 6:22:05 AM12/23/12
to scala-l...@googlegroups.com
I guess that it was incremental compiling, because I had also 6 and 0 files. So it was quite arbitrarily. I had of course clean the project first before building to test the number correctly. I hope that it was that. Is it also possible to get c.enclosingRun.units when the project is not cleaned, but with the same content as if it were cleaned?

Op zondag 23 december 2012 11:10:15 UTC+1 schreef Eugene Burmako het volgende:

Eugene Burmako

unread,
Dec 23, 2012, 6:24:24 AM12/23/12
to scala-l...@googlegroups.com
I honestly don't know. Could you please submit a bug with reproduction steps, so that it's available for us as a reference?

Dave

unread,
Dec 23, 2012, 6:33:05 AM12/23/12
to scala-l...@googlegroups.com
I don't find it a bug, because maybe some might want to write a macro using the incremental feature of c.enclosingRun.units but I need them all and I like my macro be more robust against forgetting 'clean project'. Maybe c.enclosingRun.units should have a parameter 'incrementalOnly' or the opposite 'all'.

Op zondag 23 december 2012 12:24:24 UTC+1 schreef Eugene Burmako het volgende:

Dave

unread,
Dec 23, 2012, 12:51:19 PM12/23/12
to scala-l...@googlegroups.com
Today there was no difference between clean project and direct compiling. Both in eclipse and sbt all files that have to found are found.


Op zondag 23 december 2012 12:24:24 UTC+1 schreef Eugene Burmako het volgende:

Dave

unread,
Dec 23, 2012, 2:01:59 PM12/23/12
to scala-l...@googlegroups.com
Another thing I found is that when I have a macro that expects a String argument then it is not possible to pass a string interpolated String or a raw String.Then the macro doesn't work properly.

Op zondag 23 december 2012 12:24:24 UTC+1 schreef Eugene Burmako het volgende:

Eugene Burmako

unread,
Dec 23, 2012, 2:28:18 PM12/23/12
to scala-l...@googlegroups.com
What do you mean doesn't work properly? Could you please elaborate what you expect and what happens instead?

Dave

unread,
Dec 23, 2012, 4:44:47 PM12/23/12
to scala-l...@googlegroups.com
This
checkSourcesAndCompilerSettingsInCompiletimeLog(raw"C:\Users\Dave\workspacedev2.10\output.txt")
and this
val s = "Dave"
checkSourcesAndCompilerSettingsInCompiletimeLog(s"C:\\Users\\$s\\workspacedev2.10\\output.txt")
don't work
while this (a plain String)
checkSourcesAndCompilerSettingsInCompiletimeLog("C:\\Users\\Dave\\workspacedev2.10\\output.txt")
works. The first two are not passed on the same way as the last.

The macro starts like this:

  def checkSourcesAndCompilerSettingsInCompiletimeLog(filename: String) = macro checkSourcesAndCompilerSettingsInCompiletimeLogImpl
  def checkSourcesAndCompilerSettingsInCompiletimeLogImpl(c: Context)(filename: c.Expr[String]): c.Expr[Unit] = {
    import c.universe._
    val Literal(Constant(s_filename: String)) = filename.tree
    val out = new PrintWriter(new File(s_filename))

Op zondag 23 december 2012 20:28:18 UTC+1 schreef Eugene Burmako het volgende:

Eugene Burmako

unread,
Dec 23, 2012, 4:47:17 PM12/23/12
to scala-l...@googlegroups.com
Yeah, that's because string interpolation is desugared into an expression supposed to evaluate at runtime. As a workaround you can pattern match against that expression and extract its literal parts. Try showRaw to see its structure.

Dave

unread,
Dec 24, 2012, 8:30:06 AM12/24/12
to scala-l...@googlegroups.com
Okay I have a pattern matching, only I get an error for newTermName
method newTermName is not a case class constructor, nor does it have an unapply/unapplySeq method



    val s_filename = filename.tree match { 
      case _@Apply(/* raw string */
               Select(
                 Apply(
                   Select(
                     Select(
                       Ident("scala"), newTermName("StringContext")
                     ),
                     newTermName("apply")
                   ),
                   List(
                     Literal(
                       Constant(fname: String)
                     )
                   )
                 ),
                 newTermName("raw")
               ),
               List()
             ) => fname
      case _@Apply(/* spliced string */
               Select(
                 Apply(
                   Select(
                     Select(
                       Ident("scala"), newTermName("StringContext")
                     ),
                     newTermName("apply")
                   ),
                   List(
                     Literal(
                       Constant(beforesplice: String)
                     ),
                     Literal(
                       Constant(aftersplice: String)
                     )
                   )
                 ),
                 newTermName("s")
               ),
               List(
                 splice@Ident(newTermName("s")
               )
             ) => beforesplice + splice + aftersplice    
      case _@Literal( /* plain string */
              Constant(fname: String)
            ) => fname  
    } 





Op zondag 23 december 2012 22:47:17 UTC+1 schreef Eugene Burmako het volgende:

Eugene Burmako

unread,
Dec 24, 2012, 8:31:22 AM12/24/12
to scala-l...@googlegroups.com
You can't match against newTermName. Either write a guard (2.10.0) or use TermName (macro-paradise).

Dave

unread,
Dec 24, 2012, 8:52:46 AM12/24/12
to scala-l...@googlegroups.com
Do the guards also work in RC5?
I changed it to
case ss if ss == Apply(/* spliced string */

In the spliced string I get

overloaded method value Apply with alternatives: (sym: c.universe.Symbol,args: c.universe.Tree*)c.universe.Tree <and> => c.universe.ApplyExtractor
 cannot be applied to (c.universe.Select, List[String])

The raw string seems to accept it


case rs if rs == Apply(/* raw string */

doesn't raise an error

Op maandag 24 december 2012 14:31:22 UTC+1 schreef Eugene Burmako het volgende:

Eugene Burmako

unread,
Dec 24, 2012, 8:58:47 AM12/24/12
to scala-l...@googlegroups.com
I meant guards for names as in case Ident(name) if name == newTermName(...) =>

Dave

unread,
Dec 24, 2012, 10:24:53 AM12/24/12
to scala-l...@googlegroups.com
The raw string works but for the spliced string I don't know how I get the splice back
splice is a c.universe.Ident but has to be a String

               List(
                 splice@Ident(s2)
               )
             )  if sc == newTermName("StringContext") &&
                  a ==  newTermName("apply") &&
                  s1 == newTermName("s") &&
                  s2 == newTermName("s")

                  => beforesplice + splice + aftersplice    

Op maandag 24 december 2012 14:58:47 UTC+1 schreef Eugene Burmako het volgende:

Eugene Burmako

unread,
Dec 24, 2012, 10:38:00 AM12/24/12
to scala-l...@googlegroups.com
I don't think it's going to be easy to evaluate arbitrary trees. Sure you could traverse the enclosing trees and find that there's a ValDef named s, which has "Dave" as its right-hand side. But in general case this isn't going to work.

Bottom line: it's definitely possible to evaluate trivial interpolations like s"foo", but close to impossible to evaluate interpolations with splices.

Eugene Burmako

unread,
Dec 24, 2012, 6:07:15 PM12/24/12
to scala-language, Paul Butcher
I've just published a build of macro-paradise to Sonatype. No more
dropbox builds, no more compiling my branch from sources. Playing with
type macros is as easy as adding these three lines to your SBT
project: https://github.com/scalamacros/sbt-example-paradise/blob/master/project/Build.scala#L9-11.

On Dec 24, 4:38 pm, Eugene Burmako <eugene.burm...@epfl.ch> wrote:
> I don't think it's going to be easy to evaluate arbitrary trees. Sure you
> could traverse the enclosing trees and find that there's a ValDef named s,
> which has "Dave" as its right-hand side. But in general case this isn't
> going to work.
>
> Bottom line: it's definitely possible to evaluate trivial interpolations
> like s"foo", but close to impossible to evaluate interpolations with
> splices.
>
> On 24 December 2012 16:24, Dave <dave.mahabiers...@hotmail.com> wrote:
>
>
>
>
>
>
>
> > The raw string works but for the spliced string I don't know how I get the
> > splice back
> > splice is a c.universe.Ident but has to be a String
>
> >                List(
> >>                  splice@Ident(s2)
> >>                )
> >>              )  if sc == newTermName("StringContext") &&
> >>                   a ==  newTermName("apply") &&
> >>                   s1 == newTermName("s") &&
> >>                   s2 == newTermName("s")
> >>                   => beforesplice + splice + aftersplice
>
> > Op maandag 24 december 2012 14:58:47 UTC+1 schreef Eugene Burmako het
> > volgende:
>
> >> I meant guards for names as in case Ident(name) if name ==
> >> newTermName(...) =>
>
> >> On 24 December 2012 14:52, Dave <dave.mah...@hotmail.com**> wrote:
>
> >>> Do the guards also work in RC5?
> >>> I changed it to
>
> >>>> case ss if ss == Apply(/* spliced string */
>
> >>> In the spliced string I get
>
> >>> overloaded method value Apply with alternatives: (sym:
> >>>> c.universe.Symbol,args: c.universe.Tree*)c.universe.**Tree <and> =>
> >>>> c.universe.ApplyExtractor
> >>>>  cannot be applied to (c.universe.Select, List[String])
>
> >>> The raw string seems to accept it
>
> >>> case rs if rs == Apply(/* raw string */
>
> >>> doesn't raise an error
>
> >>> Op maandag 24 december 2012 14:31:22 UTC+1 schreef Eugene Burmako het
> >>> volgende:
>
> >>>> You can't match against newTermName. Either write a guard (2.10.0) or
> >>>> use TermName (macro-paradise).
>
> >>>>>> On 23 December 2012 22:44, Dave <dave.mah...@hotmail.com**> wrote:
>
> >>>>>>> This
> >>>>>>>> checkSourcesAndCompilerSetting******sInCompiletimeLog(raw"C:\**
> >>>>>>>> Users****\Dave\workspacedev2.10\**output.****txt")
> >>>>>>>> and this
> >>>>>>>> val s = "Dave"
> >>>>>>>> checkSourcesAndCompilerSetting******sInCompiletimeLog(s"C:\\Users\*
> >>>>>>>> *****\$s\\workspacedev2.10\\output.******txt")
> >>>>>>>> don't work
> >>>>>>>> while this (a plain String)
> >>>>>>>> checkSourcesAndCompilerSetting******sInCompiletimeLog("C:\\Users\\*
> >>>>>>>> *****Dave\\workspacedev2.10\\**output****.txt")
> >>>>>>>> works. The first two are not passed on the same way as the last.
>
> >>>>>>>> The macro starts like this:
>
> >>>>>>>>   def checkSourcesAndCompilerSetting******sInCompiletimeLog(filename:
> >>>>>>>> String) = macro checkSourcesAndCompilerSetting******
> >>>>>>>> sInCompiletimeLogImpl
> >>>>>>>>   def checkSourcesAndCompilerSetting******sInCompiletimeLogImpl(c:

Eugene Burmako

unread,
Dec 25, 2012, 3:02:43 PM12/25/12
to scala-language
As discussed with Adriaan, macro-paradise is now branched off master.
Update your scalaVersion to "2.11.0-SNAPSHOT":
https://github.com/scalamacros/sbt-example-paradise/blob/master/project/Build.scala#L9-11.

On Dec 25, 12:07 am, Eugene Burmako <xeno...@gmail.com> wrote:
> I've just published a build of macro-paradise to Sonatype. No more
> dropbox builds, no more compiling my branch from sources. Playing with
> type macros is as easy as adding these three lines to your SBT
> project:https://github.com/scalamacros/sbt-example-paradise/blob/master/proje....

Paul Butcher

unread,
Dec 29, 2012, 11:22:53 AM12/29/12
to scala-l...@googlegroups.com, Eugene Burmako, Josh Suereth, Adriaan Moors
On 19 Dec 2012, at 15:14, Paul Phillips <pa...@improving.org> wrote:

On Wed, Dec 19, 2012 at 7:02 AM, Paul Butcher <pa...@paulbutcher.com> wrote:
Regarding SNAPSHOT versions, is there any update on how SBT treats SNAPSHOT compiler versions?

If you run "sbt update" explicitly now, it will update your snapshots. I haven't had a problem with this part in a while. My problem with using a non-standard compiler shifted to this one: https://github.com/harrah/xsbt/issues/626

So I've just run an "sbt update" in my project, and the scala-library and scala-reflection libraries have both been updated (to 2.11.0-20121229.042200-5). But the compiler itself has not been - when I go into the REPL, I still get:

Welcome to Scala version 2.11.0-20121225-185448-74d60036f5 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_09).

How do I get sbt to update the scala-compiler as well as the libraries that it uses? I'm using sbt 0.13.0-20121202-052047.

--
paul.butcher->msgCount++

Snetterton, Castle Combe, Cadwell Park...
Who says I have a one track mind?

http://www.paulbutcher.com/
LinkedIn: http://www.linkedin.com/in/paulbutcher
MSN: pa...@paulbutcher.com
AIM: paulrabutcher
Skype: paulrabutcher

Eugene Burmako

unread,
Dec 29, 2012, 11:33:42 AM12/29/12
to scala-l...@googlegroups.com, Josh Suereth, Adriaan Moors
That's strange, because the compiler has successfully been published this night: https://scala-webapps.epfl.ch/jenkins/view/misc/job/macro-paradise-nightly-publish/10/console.

Maybe there's a problem with how SBT creates repls?

Paul Butcher

unread,
Dec 29, 2012, 11:36:01 AM12/29/12
to scala-l...@googlegroups.com, Josh Suereth, Adriaan Moors
Yup - it's not a publishing problem as far as I can see.

I don't think that it's a REPL problem specifically - I could see it downloading scala-library and scala-reflect, but not scala-compiler.

There must be some way to kick sbt into updating the scala-compiler.jar, I just don't know what it is.

--
paul.butcher->msgCount++

Snetterton, Castle Combe, Cadwell Park...
Who says I have a one track mind?

http://www.paulbutcher.com/
LinkedIn: http://www.linkedin.com/in/paulbutcher
MSN: pa...@paulbutcher.com
AIM: paulrabutcher
Skype: paulrabutcher

Eugene Burmako

unread,
Dec 29, 2012, 11:38:27 AM12/29/12
to scala-l...@googlegroups.com, Josh Suereth, Adriaan Moors
I don't know much about sbt, but probably deleting ~/.sbt and ~/.ivy2 could help. I also heard that somewhat similar cases were fixed by `sbt reboot`.

Paul Butcher

unread,
Dec 29, 2012, 11:47:52 AM12/29/12
to scala-l...@googlegroups.com, Josh Suereth, Adriaan Moors
Yeah - I tried an sbt reboot to no effect :-(

I'm certain that deleting ~/.sbt and ~/.ivy2 will "fix" (for a very loose definition of "fix") the problem, but it's going to be a major PITA if I have to do that every time I want to update to a new compiler release. In fact, if that's the "solution" then I'll go back to building the compiler from source as it's much less hassle.

--
paul.butcher->msgCount++

Snetterton, Castle Combe, Cadwell Park...
Who says I have a one track mind?

http://www.paulbutcher.com/
LinkedIn: http://www.linkedin.com/in/paulbutcher
MSN: pa...@paulbutcher.com
AIM: paulrabutcher
Skype: paulrabutcher

Paul Phillips

unread,
Dec 29, 2012, 11:56:29 AM12/29/12
to scala-l...@googlegroups.com, Eugene Burmako, Josh Suereth, Adriaan Moors


On Sat, Dec 29, 2012 at 8:22 AM, Paul Butcher <pa...@paulbutcher.com> wrote:
How do I get sbt to update the scala-compiler as well as the libraries that it uses? I'm using sbt 0.13.0-20121202-052047.

That it would successfully update scala-library and scala-reflect but not scala-compiler is such an unlikely combination (based on how things are broken down by sbt) that I think it most likely you have misread your situation.

Paul Butcher

unread,
Dec 29, 2012, 12:04:05 PM12/29/12
to scala-l...@googlegroups.com, Eugene Burmako, Josh Suereth, Adriaan Moors
Here's the console log:

Last login: Fri Dec 28 23:31:17 on ttys001
pauls-macbook:~ paul$ cd personal/ScalaMock.typemacros/
pauls-macbook:ScalaMock.typemacros paul$ sbt
Detected sbt version 0.13.0-20121202-052047
Starting sbt: invoke with -help for other options
Using /Users/paul/.sbt/0.13.0-20121202-052047 as sbt dir, -sbt-dir to override.
[info] Loading project definition from /Users/paul/personal/ScalaMock.typemacros/project
[info] Set current project to ScalaMock (in build file:/Users/paul/personal/ScalaMock.typemacros/)
[info] Defining */*:log-level
[info] The new value will be used by no settings or tasks.
[info] Reapplying settings...
[info] Set current project to ScalaMock (in build file:/Users/paul/personal/ScalaMock.typemacros/)
[info] Defining */*:console-project::trace-level, */*:console::trace-level and 2 others.
[info] The new values will be used by no settings or tasks.
[info] Run `last` for details.
[info] Reapplying settings...
[info] Set current project to ScalaMock (in build file:/Users/paul/personal/ScalaMock.typemacros/)
ScalaMock:typemacros:3.0> update
[info] Updating {file:/Users/paul/personal/ScalaMock.typemacros/}core...
[info] Updating {file:/Users/paul/personal/ScalaMock.typemacros/}ScalaMock...
[info] Resolving org.scalatest#scalatest_2.10.0;2.0.M5 ...
[info] Done updating.
[info] Resolving org.scala-lang.macro-paradise#scala-library;2.11.0-SNAPSHOT ...
[info] [SUCCESSFUL ] org.scala-lang.macro-paradise#scala-reflect;2.11.0-SNAPSHOT!scala-reflect.jar (11020ms)
[info] [SUCCESSFUL ] org.scala-lang.macro-paradise#scala-library;2.11.0-SNAPSHOT!scala-library.jar (18922ms)
[info] Done updating.
[info] Updating {file:/Users/paul/personal/ScalaMock.typemacros/}scalatest...
[info] Resolving org.scalatest#scalatest_2.10.0;2.0.M5 ...
[info] Done updating.
[info] Updating {file:/Users/paul/personal/ScalaMock.typemacros/}examples...
[info] Updating {file:/Users/paul/personal/ScalaMock.typemacros/}core_tests...
[info] Resolving org.scalatest#scalatest_2.10.0;2.0.M5 ...
[info] Done updating.
[info] Resolving org.scalatest#scalatest_2.10.0;2.0.M5 ...
[info] Done updating.
[success] Total time: 53 s, completed 29-Dec-2012 16:12:11

As you can see there are exactly two occasions where it downloads something - once for scala-library and once for scala-reflect. There's no mention of scala-compiler at all :-(

I don't know how to read this any other way?

Paul Phillips

unread,
Dec 29, 2012, 12:12:18 PM12/29/12
to scala-l...@googlegroups.com, Eugene Burmako, Josh Suereth, Adriaan Moors


On Sat, Dec 29, 2012 at 9:04 AM, Paul Butcher <pa...@paulbutcher.com> wrote:
As you can see there are exactly two occasions where it downloads something - once for scala-library and once for scala-reflect. There's no mention of scala-compiler at all :-(

I trust you have a dependency on scala-compiler? That output is what I'd expect to see if you didn't.

Eugene Burmako

unread,
Dec 29, 2012, 12:14:06 PM12/29/12
to scala-l...@googlegroups.com, Josh Suereth, Adriaan Moors
Do you have to have a dependency on scala-compiler to use repl?

Paul Butcher

unread,
Dec 29, 2012, 12:19:45 PM12/29/12
to scala-l...@googlegroups.com, Josh Suereth, Adriaan Moors
I don't have a dependency on scala-compiler.jar - but I do have:

    scalaVersion := "2.11.0-SNAPSHOT",

Note that I don't want to link against the compiler - I just want sbt to use the most recent snapshot of the compiler when building my code. Is there really no way to achieve this without linking against the compiler?

--
paul.butcher->msgCount++

Snetterton, Castle Combe, Cadwell Park...
Who says I have a one track mind?

http://www.paulbutcher.com/
LinkedIn: http://www.linkedin.com/in/paulbutcher
MSN: pa...@paulbutcher.com
AIM: paulrabutcher
Skype: paulrabutcher

On 29 Dec 2012, at 17:14, Eugene Burmako <eugene....@epfl.ch> wrote:

Paul Phillips

unread,
Dec 29, 2012, 12:22:59 PM12/29/12
to scala-l...@googlegroups.com, Josh Suereth, Adriaan Moors


On Sat, Dec 29, 2012 at 9:14 AM, Eugene Burmako <eugene....@epfl.ch> wrote:
Do you have to have a dependency on scala-compiler to use repl?

Not to use SOME repl, but maybe to use the repl you want.

Paul Phillips

unread,
Dec 29, 2012, 12:27:28 PM12/29/12
to scala-l...@googlegroups.com, Josh Suereth, Adriaan Moors


On Sat, Dec 29, 2012 at 9:19 AM, Paul Butcher <pa...@paulbutcher.com> wrote:
Note that I don't want to link against the compiler - I just want sbt to use the most recent snapshot of the compiler when building my code. Is there really no way to achieve this without linking against the compiler?

This part of your log:
[info] Resolving org.scala-lang.macro-paradise#scala-library;2.11.0-SNAPSHOT ...
[info]  [SUCCESSFUL ] org.scala-lang.macro-paradise#scala-reflect;2.11.0-SNAPSHOT!scala-reflect.jar (11020ms)
[info]  [SUCCESSFUL ] org.scala-lang.macro-paradise#scala-library;2.11.0-SNAPSHOT!scala-library.jar (18922ms)
[info] Done updating.
It is dependency resolution (note "Resolving.") When it is updating the compiler it will use, it looks like this:


Note "Getting".

Paul Butcher

unread,
Dec 29, 2012, 12:30:45 PM12/29/12
to scala-l...@googlegroups.com, Josh Suereth, Adriaan Moors
So how do I force it to do that again?

--
paul.butcher->msgCount++

Snetterton, Castle Combe, Cadwell Park...
Who says I have a one track mind?

http://www.paulbutcher.com/
LinkedIn: http://www.linkedin.com/in/paulbutcher
MSN: pa...@paulbutcher.com
AIM: paulrabutcher
Skype: paulrabutcher

Paul Butcher

unread,
Dec 29, 2012, 12:32:08 PM12/29/12
to scala-l...@googlegroups.com, Josh Suereth, Adriaan Moors
So I just tried adding a dependency on the compiler. This *does* cause the scala-compiler.jar to be downloaded (yay!) but does *not* cause it to be used when compiling or starting the REPL. Here's a log:

pauls-macbook:ScalaMock.typemacros paul$ sbt
Detected sbt version 0.13.0-20121202-052047
Starting sbt: invoke with -help for other options
Using /Users/paul/.sbt/0.13.0-20121202-052047 as sbt dir, -sbt-dir to override.
[info] Loading project definition from /Users/paul/personal/ScalaMock.typemacros/project
[info] Compiling 1 Scala source to /Users/paul/personal/ScalaMock.typemacros/project/target/scala-2.9.2/sbt-0.13/classes...
[info] Set current project to ScalaMock (in build file:/Users/paul/personal/ScalaMock.typemacros/)
[info] Defining */*:log-level
[info] The new value will be used by no settings or tasks.
[info] Reapplying settings...
[info] Set current project to ScalaMock (in build file:/Users/paul/personal/ScalaMock.typemacros/)
[info] Defining */*:console-project::trace-level, */*:console::trace-level and 2 others.
[info] The new values will be used by no settings or tasks.
[info] Run `last` for details.
[info] Reapplying settings...
[info] Set current project to ScalaMock (in build file:/Users/paul/personal/ScalaMock.typemacros/)
ScalaMock:typemacros:3.0> update
[info] Updating {file:/Users/paul/personal/ScalaMock.typemacros/}ScalaMock...
[info] Updating {file:/Users/paul/personal/ScalaMock.typemacros/}core...
[info] Resolving org.scala-lang.macro-paradise#scala-compiler;2.11.0-SNAPSHOT ...
[info] [SUCCESSFUL ] org.scala-lang.macro-paradise#scala-compiler;2.11.0-SNAPSHOT!scala-compiler.jar (34529ms)
[info] Done updating.
[info] Resolving org.scala-lang#scala-library;2.11.0-SNAPSHOT ...
[info] Updating {file:/Users/paul/personal/ScalaMock.typemacros/}scalatest...
[info] Resolving org.scalatest#scalatest_2.10.0;2.0.M5 ...
[info] Done updating.
[info] Resolving org.scalatest#scalatest_2.10.0;2.0.M5 ...
[info] Done updating.
[info] Updating {file:/Users/paul/personal/ScalaMock.typemacros/}examples...
[info] Updating {file:/Users/paul/personal/ScalaMock.typemacros/}core_tests...
[info] Resolving org.scalatest#scalatest_2.10.0;2.0.M5 ...
[info] Done updating.
[info] Resolving org.scalatest#scalatest_2.10.0;2.0.M5 ...
[info] Done updating.
[success] Total time: 57 s, completed 29-Dec-2012 17:29:10
ScalaMock:typemacros:3.0> core/console
[info] Starting scala interpreter...
[info] 
Welcome to Scala version 2.11.0-20121225-185448-74d60036f5 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_09).
Type in expressions to have them evaluated.
Type :help for more information.

scala> 
[success] Total time: 4 s, completed 29-Dec-2012 17:29:31

Note that the REPL is still 2.11.0-20121225-185448-74d60036f5

--
paul.butcher->msgCount++

Snetterton, Castle Combe, Cadwell Park...
Who says I have a one track mind?

http://www.paulbutcher.com/
LinkedIn: http://www.linkedin.com/in/paulbutcher
MSN: pa...@paulbutcher.com
AIM: paulrabutcher
Skype: paulrabutcher

Paul Phillips

unread,
Dec 29, 2012, 12:35:44 PM12/29/12
to scala-l...@googlegroups.com, Josh Suereth, Adriaan Moors


On Sat, Dec 29, 2012 at 9:30 AM, Paul Butcher <pa...@paulbutcher.com> wrote:
So how do I force it to do that again?

In my recent experience, an explicit call to "sbt update" will update snapshots - but it may have been broken for this use as recently as 0.12.1. I forget, so I refer only to 0.12.2-RC1.

Paul Phillips

unread,
Dec 29, 2012, 12:36:24 PM12/29/12
to scala-l...@googlegroups.com, Josh Suereth, Adriaan Moors


On Sat, Dec 29, 2012 at 9:32 AM, Paul Butcher <pa...@paulbutcher.com> wrote:
Note that the REPL is still 2.11.0-20121225-185448-74d60036f5

Now that the jar is actually present, try an sbt "reboot full".

Paul Butcher

unread,
Dec 29, 2012, 12:37:18 PM12/29/12
to scala-l...@googlegroups.com, Josh Suereth, Adriaan Moors
OK  - I guess I should ask this on the sbt mailing list.

--
paul.butcher->msgCount++

Snetterton, Castle Combe, Cadwell Park...
Who says I have a one track mind?

http://www.paulbutcher.com/
LinkedIn: http://www.linkedin.com/in/paulbutcher
MSN: pa...@paulbutcher.com
AIM: paulrabutcher
Skype: paulrabutcher

Paul Butcher

unread,
Dec 29, 2012, 12:40:28 PM12/29/12
to scala-l...@googlegroups.com, Josh Suereth, Adriaan Moors
That doesn't do the trick either I'm afraid :-(

ScalaMock:typemacros:3.0> reboot full
Getting net.java.dev.jna jna 3.2.3 ...
:: retrieving :: org.scala-sbt#boot-jna
confs: [default]
1 artifacts copied, 0 already retrieved (838kB/13ms)
Getting org.scala-sbt sbt 0.13.0-20121202-052047 ...
:: retrieving :: org.scala-sbt#boot-app
confs: [default]
41 artifacts copied, 0 already retrieved (8514kB/121ms)
Getting Scala 2.9.2 (for sbt)...
:: retrieving :: org.scala-sbt#boot-scala
confs: [default]
4 artifacts copied, 0 already retrieved (20090kB/105ms)
[info] Loading project definition from /Users/paul/personal/ScalaMock.typemacros/project
[info] Set current project to ScalaMock (in build file:/Users/paul/personal/ScalaMock.typemacros/)
ScalaMock:typemacros:3.0> console
Getting org.scala-lang.macro-paradise Scala 2.11.0-SNAPSHOT ...
[SUCCESSFUL ] org.scala-lang.macro-paradise#jline;2.11.0-SNAPSHOT!jline.jar (2854ms)
:: retrieving :: org.scala-sbt#boot-scala
confs: [default]
5 artifacts copied, 0 already retrieved (23168kB/32ms)
[info] Starting scala interpreter...
[info] 
Welcome to Scala version 2.11.0-20121225-185448-74d60036f5 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_09).
Type in expressions to have them evaluated.
Type :help for more information.

scala> 

--
paul.butcher->msgCount++

Snetterton, Castle Combe, Cadwell Park...
Who says I have a one track mind?

http://www.paulbutcher.com/
LinkedIn: http://www.linkedin.com/in/paulbutcher
MSN: pa...@paulbutcher.com
AIM: paulrabutcher
Skype: paulrabutcher

Paul Phillips

unread,
Dec 29, 2012, 12:43:07 PM12/29/12
to scala-l...@googlegroups.com, Josh Suereth, Adriaan Moors


On Sat, Dec 29, 2012 at 9:40 AM, Paul Butcher <pa...@paulbutcher.com> wrote:
That doesn't do the trick either I'm afraid :-(

Oh, well I just noticed you're trying to make it use a really non-standard compiler (as in not just a different version, but in a different package.) I know nothing about that and if I had to make it work in sbt I would fully expect to utterly fail. You're already closer than I'd ever expect to get.

Paul Butcher

unread,
Dec 29, 2012, 12:45:37 PM12/29/12
to scala-l...@googlegroups.com, Josh Suereth, Adriaan Moors
I may just give up and go back to building the compiler from source.

Eugene - if this can't be made to work, then I *strongly* suggest that you stop publishing macro-paradise jars. It's just going to lead to heartbreak if people are going to end up with out of date and/or inconsistent builds.

I'll ask the question on the sbt mailing list in case there's any wisdom to be gained there.

--
paul.butcher->msgCount++

Snetterton, Castle Combe, Cadwell Park...
Who says I have a one track mind?

http://www.paulbutcher.com/
LinkedIn: http://www.linkedin.com/in/paulbutcher
MSN: pa...@paulbutcher.com
AIM: paulrabutcher
Skype: paulrabutcher

Eugene Burmako

unread,
Dec 29, 2012, 7:43:51 PM12/29/12
to scala-l...@googlegroups.com, Josh Suereth, Adriaan Moors
If that's any consolation, I reproduced the bug on my laptop. I'll try to patch SBT in the near future.

Johannes Rudolph

unread,
Dec 30, 2012, 4:55:25 AM12/30/12
to scala-l...@googlegroups.com, Eugene Burmako, Josh Suereth, Adriaan Moors
On Sat, Dec 29, 2012 at 6:04 PM, Paul Butcher <pa...@paulbutcher.com> wrote:
>> How do I get sbt to update the scala-compiler as well as the libraries
>> that it uses? I'm using sbt 0.13.0-20121202-052047.

Have you tried a more recent version of sbt 0.13.0-SNAPSHOT? The fix for

https://github.com/harrah/xsbt/issues/626

seemed to have come into sbt only after the version you are using (not
sure how far this issue is really related to your problem).

--
Johannes

-----------------------------------------------
Johannes Rudolph
http://virtual-void.net

Paul Butcher

unread,
Dec 30, 2012, 5:02:28 AM12/30/12
to scala-l...@googlegroups.com, Eugene Burmako, Josh Suereth, Adriaan Moors
On 30 Dec 2012, at 09:55, Johannes Rudolph <johannes...@googlemail.com> wrote:

Have you tried a more recent version of sbt 0.13.0-SNAPSHOT?

There doesn't seem to *be* a more recent snapshot than this. The most recent version of sbt-launch is 0.13.0-20121203-052125:


Although as I pointed out in this earlier message to this group, that doesn't work because there is no matching release of sbt:


So, as far as I can tell, I'm using the most recent working snapshot of 0.13.0. Am I missing something?

Johannes Rudolph

unread,
Dec 30, 2012, 5:24:39 AM12/30/12
to scala-l...@googlegroups.com, Eugene Burmako, Josh Suereth, Adriaan Moors
On Sun, Dec 30, 2012 at 11:02 AM, Paul Butcher <pa...@paulbutcher.com> wrote:
> There doesn't seem to *be* a more recent snapshot than this. The most recent
> version of sbt-launch is 0.13.0-20121203-052125:
>
> http://repo.typesafe.com/typesafe/ivy-snapshots/org.scala-sbt/sbt-launch/


Yes, forget what I was saying. I was accidentally using an old local
build of sbt.

Julian Schrittwieser

unread,
Feb 21, 2013, 6:16:29 AM2/21/13
to scala-l...@googlegroups.com
I'm trying to use macros to introduce new classes. 
It seems c.introduceTopLevel is the correct way to do this: c.introduceTopLevel(packageName, q"class $className")

However, the created class is then only visible in the file where this macro was called, not in any other files from the same package. Is this intended? How can I work around this?

Is it possible to have a macro return a class definition? Like 

createClass("MyClass")

turns into

class MyClass

Otherwise, great work!

On Tuesday, December 18, 2012 11:38:39 PM UTC+1, Eugene Burmako wrote:
Simultaneously with the release of Scala 2.10.0-final, tentatively
scheduled for 26 December 2012, we're going to announce the
availability of paradise/macros, a dedicated branch in our official
Scala repository which will host the latest macro developments.

When things like macro types, macro annotations or type inference-
friendly macros - you name it - get ripe for beta testing, they are
going to end up in paradise/macros. Much like the vanilla Scala, macro
paradise is going to be built nightly and have its own Maven artifact,
so it'll be very easy to use it in your projects.

In this talk I present a couple of new features that will be released
into paradise this Christmas, along with a glimpse of the things to
come. I also discuss the roadmap of macro development for the near
future, so if you want to have something in Scala macros, be sure to
take a look and speak up.

Screencast: http://vimeo.com/user8565009/macro-paradise-talk
Slides: http://scalamacros.org/talks/2012-12-18-MacroParadise.pdf

Eugene Burmako

unread,
Feb 21, 2013, 7:55:32 AM2/21/13
to scala-l...@googlegroups.com
This has to do with the order of compilation. If you write c.introduceTopLevel(package, q"class C") in file Foo.scala and then write "class D extends package.C" in Bar.scala, then "scalac Foo.scala Bar.scala" will work, whereas "scalac Bar.scala Foo.scala" will not.

So far macros cannot expand like you suggested. c.introduceMember described in http://scalamacros.org/news/2013/02/19/macro-annotations-and-call-for-ideas.html might help if you really need that functionality.


--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-languag...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Julian Schrittwieser

unread,
Feb 21, 2013, 7:58:42 AM2/21/13
to scala-l...@googlegroups.com
Well, I'm using sbt to compile, so I'm not sure how to specify the order of the files.

However, if I understand you correctly, I should be able to do 

 c.introduceMember(TargetClass, q"class MyClass")

in A.scala, and 

import TargetClass._

in B.scala. Then, compilation order shouldn't matter, right?

Eugene Burmako

unread,
Feb 21, 2013, 8:03:53 AM2/21/13
to scala-l...@googlegroups.com
Unfortunately, the compilation order would still matter. If you try to refer to something that's been generated by a macro before the macro is run, then it's not going to work. Could you elaborate on your use case?

Julian Schrittwieser

unread,
Feb 21, 2013, 8:07:13 AM2/21/13
to scala-l...@googlegroups.com
I'm writing a Units of Measure system in Scala: https://github.com/Mononofu/Units-of-Measure

Units are represented as Type parameters, eg Measure[SUnit[Meter, Pos1]](10) for "10 m". 

Of course, the user should be able to introduce his own units, so I want to make a macro that creates new top level classes so they can be used as type parameters.

(this macro should also introduce more information besides a simple "class Meter", like information for automatic conversion between units, etc)

Julian Schrittwieser

unread,
Feb 22, 2013, 5:34:53 AM2/22/13
to scala-l...@googlegroups.com
Ok, I now split up compilation into three phases to work around this:
  1. unit macros (package macroimpl)
  2. unit definitions (package units)
  3. code that actually uses the units (package macros)

Now I'm trying to lookup the defined units in my other helper macros. I found "Context.topLevelDef(name: Name)"
If I call this (from a function in macroimpl) as c.topLevelDef(c.universe.newTypeName("units.Meter")), I should get the Tree of the Meter class, shouldn't I?
Meter is defined in the package units. However, I only get "EmptyTree" as a result.

Do you happen to now what I'm doing wrong?

Eugene Burmako

unread,
Feb 22, 2013, 9:00:43 AM2/22/13
to scala-l...@googlegroups.com
topLevelDef only works for the trees being currently compiled. If you're compiling core, then the trees you generated in units are already gone.

By the way, why wouldn't you write type Meter = Unit("m"), where Unit is a type macro? That would free you from a necessity to split the compilation into phases.

Also what's the desired use case of topLevelDef? If you need to get some sort of metadata, why not put it into an annotation and slap it onto the result of Unit("m")?

Julian Schrittwieser

unread,
Feb 22, 2013, 9:09:10 AM2/22/13
to scala-l...@googlegroups.com
That's a great idea, I think I'll do it your way. Should work without a problem, thanks a lot :)

(I thought topLevelDef would give me access to all definitions visible in the scope of the macro application. Is there another function that does that?)

cheers. Julian

Eugene Burmako

unread,
Feb 22, 2013, 9:12:39 AM2/22/13
to scala-l...@googlegroups.com
It's not possible to get a tree of a given definition after it's already been compiled. Well, it is possible, but you'll need to decompile java bytecode to reconstruct those trees.

Julian Schrittwieser

unread,
Feb 22, 2013, 9:21:47 AM2/22/13
to scala-l...@googlegroups.com
I am confused.

Say I have a file a.scala, with a class A. I compile this first.
I also have a file b.scala, which I compile second. In this file, my code would be able to access class A. So why would a macro not be able to? (I understand that it can't get the Tree for class A, but I don't need that - reading the value of some static field would be enough)

Am I making some kind of mental mistake here? Sorry for the trouble.

Eugene Burmako

unread,
Feb 22, 2013, 9:25:05 AM2/22/13
to scala-l...@googlegroups.com
Both normal code and macros will be able to access the symbol of class A (and hence its annotations, which can host arbitrary trees by the way).

Julian Schrittwieser

unread,
Feb 22, 2013, 9:29:04 AM2/22/13
to scala-l...@googlegroups.com

Yes, but how do I do this? I thought topLevelDef would allow me to do this, but it seems it doesn't.

Eugene Burmako

unread,
Feb 22, 2013, 9:33:30 AM2/22/13
to scala-l...@googlegroups.com
c.mirror.staticClass("Blah")

Julian Schrittwieser

unread,
Feb 23, 2013, 5:24:56 PM2/23/13
to scala-l...@googlegroups.com
That doesn't seem to work. If I call c.mirror.staticClass("Meter"), I get an exception during macro expansion:
scala.reflect.internal.MissingRequirementError: class Meter not found.
However, most certainly is visible - if I comment out that line, my macro is able to create and return the following expression without a problem:
  new Measure[Meter](2)
(and the program then compiles and runs successfully)

I also tried to fully qualify the class name, but couldn't get it to work either. (You can see it in context at https://github.com/Mononofu/Units-of-Measure/blob/master/macros/macro_impl.scala#L199)

It seems like I'm still doing something wrong - do you happen to have an idea what it might be?

thanks for all the help so far,
julian

Eugene Burmako

unread,
Feb 24, 2013, 5:05:07 AM2/24/13
to scala-l...@googlegroups.com
Have you tried using the fully qualified name "Units.Meter"?

Julian Schrittwieser

unread,
Feb 24, 2013, 5:09:01 AM2/24/13
to scala-l...@googlegroups.com
Yes, and that fails with "object Units.Meter in compiler mirror not found"
Additionally, in real use, I wouldn't know the fully qualified name, but only the last part ("Meter"), which is imported and visible at the location of the macro usage.

Eugene Burmako

unread,
Feb 24, 2013, 5:14:24 AM2/24/13
to scala-l...@googlegroups.com
Did you use newTermName("Units.Meter") or newTypeName("Units.Meter")?

Could you be more specific about "wouldn't know the fully qualified name"? Could you show an example of the usage you're envisioning?

Julian Schrittwieser

unread,
Feb 24, 2013, 5:18:46 AM2/24/13
to scala-l...@googlegroups.com
well, I decided to define the types as you suggested: 

units/units.scala (all files refer to) https://github.com/Mononofu/Units-of-Measure:

object Units {
  trait Meter extends MyUnit("Meter", "m")
  trait Second extends MyUnit("Second", "s")
}

So I'm not creating that type with a macro, it's normal Scala code. (MyUnit is a macro, but so far it doesn't modify the trait). Meter is perfectly visible from normal code, as you can see eg in core/src/main/scala/macro.scala. It's just that I can't access it from any macros, like the one defined in macros/macro_impl.scala on line 174.

When I said "wouldn't know the fully qualified name" I meant that the user should be able to define units wherever he wants - as long as she then imports them so that they are visible it should work. So I can't assume that they are always going to be at "Units.Meter". (which doesn't work anyway)

Eugene Burmako

unread,
Feb 24, 2013, 5:22:13 AM2/24/13
to scala-l...@googlegroups.com
If you wish, we could have an IM chat right now. Check out http://xeno.by for my gtalk and skype.

Julian Schrittwieser

unread,
Feb 24, 2013, 5:24:56 AM2/24/13
to scala-l...@googlegroups.com
That would be fantastic, yes. I did send you a chat invite for your gmail address. 


You received this message because you are subscribed to a topic in the Google Groups "scala-language" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/scala-language/IcDNzjhxV3E/unsubscribe?hl=en.
To unsubscribe from this group and all its topics, send an email to scala-languag...@googlegroups.com.

marvin.hansen

unread,
Feb 24, 2013, 11:47:59 PM2/24/13
to scala-l...@googlegroups.com
Hi,

I've just started working on a macro that allows compiler checks on
 enables range constrains on numeric data types. The idea is simple:

Let's define

type Day = Int with Range(1, 31)  // suggested syntax, I'm happy for better ideas...

so that

val inValidDay : Day = 42

throws a compile error.

My primary motivation is to simplify the creation of well specified parameters
that are checked at compile time in order to allow much stricter type checking.
In some areas, like medical industry, there are a bunch of well specified and sometimes
even standardized data formats and types available. Expressing and checking them straightforward
in Scala would be really useful.

However, while exploring the idea further, I struggle with querying type information
from the actual context. The current macro code is available at:

https://github.com/marvin-hansen/Scalarius/blob/master/macros/src/main/scala/TestMacro.scala

and a small main class for testing as well:

https://github.com/marvin-hansen/Scalarius/blob/master/core/src/main/scala/main.scala

My questions are:

1) How do I access a typeTag of a parameter given to the macro?
Just to start with the smallest possible case for querying type information.

Using mirrors hasn't really worked for me because I have no explicit
static reference to the class calling the macro i.e.

 c.mirror.staticModule("Location") // Location is not explicit known.

2) Is there some kind of "dynamic" reference, or ideally, a type-tree
that contains all type information for the given context which I can traverse?

A simple

    val tree = c.universe.TypeTree

apparently does not provide me the desired collection of all type information
so is there something else I should know?

3) Considering the intention of range constrains on numeric types,
I'm not exactly sure how exactly to specify a custom type range without interfering
with existing Scala syntax. Following the idea of the Lifter macro[1], is there a way to
mix-in a trait into an existing type to "append" a range definition that my macro can use?

[1]
https://github.com/xeno-by/typemacros-lifter


A related idea:
As macro annotations allow the addition of arbitrary methods to any class, transforming type constrains
into run-time checks and adding a simple check to all affected methods could allow some kind
of "ad-hoc type debugging".
For instance, in some cases, parameters are determined dynamically during run-time,
maybe depending on query results. Instead of printing out the parameter over and over again, 
defining a custom range and just setting a boolean flag for run-time checks actually allows me to verify the
correctness of the parameter range with a minimum amount time and without any fuzz. Not sure how often that's the case for
you, but I've had such a situation a few times with a system that dynamically re-configures itself during run-time.


In any case, I appreciate any help on the type access issue. 

Thank you
Marvin
It is loading more messages.
0 new messages