Skip to content
This repository was archived by the owner on Feb 20, 2019. It is now read-only.

Commit 63d7709

Browse files
committed
Merge pull request #118 from phaller/topic/2.11
Enable cross compilation
2 parents ec048ed + b4bd8ca commit 63d7709

File tree

7 files changed

+100
-62
lines changed

7 files changed

+100
-62
lines changed

core/src/main/scala/pickling/Compat.scala

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ import scala.collection.generic.CanBuildFrom
1313

1414
// this is only necessary because 2.10.x doesn't support macro bundles
1515
object Compat {
16+
// provides a source compatibility stub
17+
implicit class HasPt[A, B](t: (A, B)) {
18+
def pt: A = t._1
19+
}
20+
1621
def PicklerMacros_impl[T: c.WeakTypeTag](c: Context)(format: c.Expr[PickleFormat]): c.Expr[SPickler[T]] = {
1722
val c0: c.type = c
1823
val bundle = new { val c: c0.type = c0 } with PicklerMacros
@@ -91,24 +96,9 @@ object Compat {
9196
c.Expr[FastTypeTag[T]](bundle.impl[T])
9297
}
9398

94-
def FastTypeTagMacros_apply(c: Context)(key: c.Expr[String]): c.Expr[FastTypeTag[_]] = {
99+
def FastTypeTagMacros_apply(c: Context)(key: c.Expr[String]): c.Expr[FastTypeTag[t]] forSome { type t } = {
95100
val c0: c.type = c
96101
val bundle = new { val c: c0.type = c0 } with FastTypeTagMacros
97-
c.Expr[FastTypeTag[_]](bundle.apply(key.tree))
98-
}
99-
}
100-
101-
trait Reflection211Compat { self: Macro =>
102-
val c: Context
103-
import c.universe._
104-
105-
object TermName {
106-
def apply(s: String) = newTermName(s)
107-
def unapply(name: TermName): Option[String] = Some(name.toString)
108-
}
109-
110-
object TypeName {
111-
def apply(s: String) = newTypeName(s)
112-
def unapply(name: TypeName): Option[String] = Some(name.toString)
102+
c.Expr(bundle.apply(key.tree))
113103
}
114104
}

core/src/main/scala/pickling/Macros.scala

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ trait PicklerMacros extends Macro {
3030
)
3131

3232
def getField(fir: FieldIR): Tree =
33-
if (fir.isPublic) q"picklee.${TermName(fir.name)}"
33+
if (fir.isPublic) q"picklee.${newTermName(fir.name)}"
3434
else reflectively("picklee", fir)(fm => q"$fm.get.asInstanceOf[${fir.tpe}]").head //TODO: don't think it's possible for this to return an empty list, so head should be OK
3535

3636
// this exists so as to provide as much information as possible about the size of the object
@@ -103,7 +103,7 @@ trait PicklerMacros extends Macro {
103103
"""
104104
}
105105
}
106-
if (fir.isPublic) List(putField(q"picklee.${TermName(fir.name)}"))
106+
if (fir.isPublic) List(putField(q"picklee.${newTermName(fir.name)}"))
107107
else reflectively("picklee", fir)(fm => putField(q"$fm.get.asInstanceOf[${fir.tpe}]"))
108108
} else {
109109
// NOTE: this means that we've encountered a primary constructor parameter elided in the "constructors" phase
@@ -131,7 +131,7 @@ trait PicklerMacros extends Macro {
131131
"""
132132
}
133133
}
134-
def pickleLogic = tpe match {
134+
def pickleLogic: Tree = tpe match {
135135
case NothingTpe => c.abort(c.enclosingPosition, "cannot pickle Nothing") // TODO: report the serialization path that brought us here
136136
case _ => unifiedPickle
137137
}
@@ -176,13 +176,16 @@ trait PicklerMacros extends Macro {
176176
}
177177
}
178178

179+
import HasCompat._
180+
179181
// purpose of this macro: implementation of genUnpickler[T]. i.e., the macro that is selected via implicit
180182
// search and which initiates the process of generating an unpickler for a given type T.
181183
// NOTE: dispatch is done elsewhere. unpicklers generated by genUnpickler[T] only know how to process T
182184
// but not its subclasses or the types convertible to it!
183185
trait UnpicklerMacros extends Macro {
184186
def impl[T: c.WeakTypeTag](format: c.Tree): c.Tree = preferringAlternativeImplicits {
185187
import c.universe._
188+
import compat._
186189
import definitions._
187190
val tpe = weakTypeOf[T]
188191
val targs = tpe match { case TypeRef(_, _, targs) => targs; case _ => Nil }
@@ -240,11 +243,11 @@ trait UnpicklerMacros extends Macro {
240243
if (sym.isModuleClass || pendingFields.isEmpty) {
241244
instantiationLogic
242245
} else {
243-
val instance = TermName(tpe.typeSymbol.name + "Instance")
246+
val instance = newTermName(tpe.typeSymbol.name + "Instance")
244247

245248
val initPendingFields = pendingFields.flatMap(fir => {
246249
val readFir = readField(fir.name, fir.tpe)
247-
if (fir.isPublic && fir.hasSetter) List(q"$instance.${TermName(fir.name)} = $readFir".asInstanceOf[Tree])
250+
if (fir.isPublic && fir.hasSetter) List(q"$instance.${newTermName(fir.name)} = $readFir".asInstanceOf[Tree])
248251
else if (fir.accessor.isEmpty) List()
249252
else reflectively(instance, fir)(fm => q"$fm.set($readFir)".asInstanceOf[Tree])
250253
})
@@ -352,7 +355,7 @@ trait PickleMacros extends Macro {
352355
def nonFinalDispatch = {
353356
val nullDispatch = CaseDef(Literal(Constant(null)), EmptyTree, createPickler(NullTpe, builder))
354357
val compileTimeDispatch = compileTimeDispatchees(tpe) filter (_ != NullTpe) map (subtpe =>
355-
CaseDef(Bind(TermName("clazz"), Ident(nme.WILDCARD)), q"clazz == classOf[$subtpe]", createPickler(subtpe, builder))
358+
CaseDef(Bind(newTermName("clazz"), Ident(nme.WILDCARD)), q"clazz == classOf[$subtpe]", createPickler(subtpe, builder))
356359
)
357360
//TODO OPTIMIZE: do getClass.getClassLoader only once
358361
val runtimeDispatch = CaseDef(Ident(nme.WILDCARD), EmptyTree, q"SPickler.genPickler(this.getClass.getClassLoader, clazz)")

core/src/main/scala/pickling/Runtime.scala

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@ package scala.pickling
22

33
import scala.pickling.internal._
44

5-
import scala.reflect.runtime.universe._
6-
import definitions._
7-
import scala.reflect.runtime.{universe => ru}
5+
import scala.reflect.runtime.universe.Mirror
86
import ir._
97

108
object Runtime {
@@ -22,7 +20,18 @@ object Runtime {
2220
)
2321
}
2422

23+
// provides a source compatibility stub
24+
// in Scala 2.10.x, it will make `import compat._` compile just fine,
25+
// even though `c.universe` doesn't have `compat`
26+
// in Scala 2.11.0, it will be ignored, becase `import c.universe._`
27+
// brings its own `compat` in scope and that one takes precedence
28+
private object HasCompat { val compat = ??? }; import HasCompat._
29+
2530
abstract class PicklerRuntime(classLoader: ClassLoader, preclazz: Class[_], share: refs.Share) {
31+
import scala.reflect.runtime.universe._
32+
import definitions._
33+
import scala.reflect.runtime.{universe => ru}
34+
import compat._
2635

2736
val clazz = if (preclazz != null) Runtime.toUnboxed.getOrElse(preclazz, preclazz) else null
2837
val mirror = runtimeMirror(classLoader)
@@ -60,6 +69,7 @@ abstract class PicklerRuntime(classLoader: ClassLoader, preclazz: Class[_], shar
6069
}
6170

6271
class InterpretedPicklerRuntime(classLoader: ClassLoader, preclazz: Class[_])(implicit share: refs.Share) extends PicklerRuntime(classLoader, preclazz, share) {
72+
import scala.reflect.runtime.universe._
6373

6474
debug("InterpretedPicklerRuntime: preclazz = " + preclazz)
6575
debug("InterpretedPicklerRuntime: clazz = " + clazz)
@@ -143,6 +153,10 @@ class InterpretedPicklerRuntime(classLoader: ClassLoader, preclazz: Class[_])(im
143153
// TODO: currently this works with an assumption that sharing settings for unpickling are the same as for pickling
144154
// of course this might not be the case, so we should be able to read `share` from the pickle itself
145155
class InterpretedUnpicklerRuntime(mirror: Mirror, tag: FastTypeTag[_])(implicit share: refs.Share) {
156+
import scala.reflect.runtime.universe._
157+
import definitions._
158+
import scala.reflect.runtime.{universe => ru}
159+
146160
val tpe = tag.tpe
147161
val sym = tpe.typeSymbol.asType
148162
debug("UnpicklerRuntime: tpe = " + tpe)

core/src/main/scala/pickling/Tools.scala

Lines changed: 44 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@ import scala.language.existentials
66

77
import scala.reflect.macros.Context
88
import scala.reflect.api.Universe
9-
import scala.reflect.runtime.universe._
10-
import scala.reflect.runtime.{universe => ru}
119

1210
import scala.collection.mutable.{Map => MutableMap, ListBuffer => MutableList, WeakHashMap, Set => MutableSet}
1311
import scala.collection.mutable.{Stack => MutableStack, Queue => MutableQueue}
1412

1513
import java.lang.ref.WeakReference
1614

15+
import HasCompat._
16+
1717
object Tools {
1818
private val subclassCaches = new WeakHashMap[AnyRef, WeakReference[AnyRef]]()
1919

@@ -44,6 +44,7 @@ object Tools {
4444
class Tools[C <: Context](val c: C) {
4545
val u: c.universe.type = c.universe
4646
import u._
47+
import compat._
4748
import definitions._
4849

4950
def blackList(sym: Symbol) = sym == AnyClass || sym == AnyRefClass || sym == AnyValClass || sym == ObjectClass
@@ -238,9 +239,10 @@ abstract class ShareAnalyzer[U <: Universe](val u: U) {
238239
}
239240
}
240241

241-
abstract class Macro extends Reflection211Compat { self =>
242+
abstract class Macro { self =>
242243
val c: Context
243244
import c.universe._
245+
import compat._
244246
import definitions._
245247
val RefTpe = weakTypeOf[refs.Ref]
246248

@@ -258,7 +260,7 @@ abstract class Macro extends Reflection211Compat { self =>
258260
private def innerType(target: Tree, name: String): Type = {
259261
def fail(msg: String) = c.abort(c.enclosingPosition, s"$msg for ${target} of type ${target.tpe}")
260262
// val carrier = c.typeCheck(tq"${target.tpe}#${TypeName(name)}", mode = c.TYPEmode, silent = true)
261-
val carrier = c.typeCheck(q"{ val x: ${target.tpe}#${TypeName(name)} = ??? }", silent = true)
263+
val carrier = c.typeCheck(q"{ val x: ${target.tpe}#${newTypeName(name)} = ??? }", silent = true)
262264
carrier match {
263265
case EmptyTree => fail(s"Couldn't resolve $name")
264266
case Block(ValDef(_, _, tpt, _) :: _, _) => tpt.tpe.normalize match {
@@ -316,10 +318,10 @@ abstract class Macro extends Reflection211Compat { self =>
316318
def syntheticPackageName: String = "scala.pickling.synthetic"
317319
def syntheticBaseName(tpe: Type): TypeName = {
318320
val raw = tpe.key.split('.').map(_.capitalize).mkString("")
319-
val encoded = TypeName(raw).encoded
320-
TypeName(encoded)
321+
val encoded = newTypeName(raw).encoded
322+
newTypeName(encoded)
321323
}
322-
def syntheticBaseQualifiedName(tpe: Type): TypeName = TypeName(syntheticPackageName + "." + syntheticBaseName(tpe).toString)
324+
def syntheticBaseQualifiedName(tpe: Type): TypeName = newTypeName(syntheticPackageName + "." + syntheticBaseName(tpe).toString)
323325

324326
def syntheticPicklerName(tpe: Type): TypeName = syntheticBaseName(tpe) + syntheticPicklerSuffix()
325327
def syntheticPicklerQualifiedName(tpe: Type): TypeName = syntheticBaseQualifiedName(tpe) + syntheticPicklerSuffix()
@@ -334,35 +336,44 @@ abstract class Macro extends Reflection211Compat { self =>
334336
def syntheticPicklerUnpicklerSuffix(): String = "PicklerUnpickler"
335337

336338
def preferringAlternativeImplicits(body: => Tree): Tree = {
339+
import Compat._
340+
341+
val candidates = c.enclosingImplicits
342+
val ourPt = candidates.head.pt
343+
337344
def debug(msg: Any) = {
338-
val padding = " " * (c.enclosingImplicits.length - 1)
345+
val padding = " " * (candidates.length - 1)
339346
// Console.err.println(padding + msg)
340347
}
341-
debug("can we enter " + c.enclosingImplicits.head._1 + "?")
342-
debug(c.enclosingImplicits)
343-
c.enclosingImplicits match {
344-
case (ourPt, _) :: (theirPt, _) :: _ if ourPt =:= theirPt =>
345-
debug(s"no, because: ourPt = $ourPt, theirPt = $theirPt")
346-
// c.diverge()
347-
c.abort(c.enclosingPosition, "stepping aside: repeating itself")
348-
case _ =>
349-
debug(s"not sure, need to explore alternatives")
350-
c.inferImplicitValue(c.enclosingImplicits.head._1, silent = true) match {
351-
case success if success != EmptyTree =>
352-
debug(s"no, because there's $success")
353-
c.abort(c.enclosingPosition, "stepping aside: there are other candidates")
354-
// c.diverge()
355-
case _ =>
356-
debug("yes, there are no obstacles. entering " + c.enclosingImplicits.head._1)
357-
val result = body
358-
debug("result: " + result)
359-
result
360-
}
348+
349+
debug("can we enter " + ourPt + "?")
350+
debug(candidates)
351+
352+
if ((candidates.size >= 2) && {
353+
val theirPt = candidates.tail.head.pt
354+
ourPt =:= theirPt
355+
}) {
356+
debug(s"no, because: ourPt = $ourPt, theirPt = ${candidates.tail.head.pt}")
357+
// c.diverge()
358+
c.abort(c.enclosingPosition, "stepping aside: repeating itself")
359+
} else {
360+
debug(s"not sure, need to explore alternatives")
361+
c.inferImplicitValue(ourPt, silent = true) match {
362+
case success if success != EmptyTree =>
363+
debug(s"no, because there's $success")
364+
c.abort(c.enclosingPosition, "stepping aside: there are other candidates")
365+
// c.diverge()
366+
case _ =>
367+
debug("yes, there are no obstacles. entering " + ourPt)
368+
val result = body
369+
debug("result: " + result)
370+
result
371+
}
361372
}
362373
}
363374

364375
private var reflectivePrologueEmitted = false // TODO: come up with something better
365-
def reflectively(target: String, fir: FieldIR)(body: Tree => Tree): List[Tree] = reflectively(TermName(target), fir)(body)
376+
def reflectively(target: String, fir: FieldIR)(body: Tree => Tree): List[Tree] = reflectively(newTermName(target), fir)(body)
366377

367378
/**
368379
* requires: !fir.accessor.isEmpty
@@ -382,8 +393,8 @@ abstract class Macro extends Reflection211Compat { self =>
382393
}
383394
}
384395
val field = fir.field.get
385-
val ownerSymbol = TermName(fir.name + "Owner")
386-
val firSymbol = TermName(fir.name + "Symbol")
396+
val ownerSymbol = newTermName(fir.name + "Owner")
397+
val firSymbol = newTermName(fir.name + "Symbol")
387398
// TODO: make sure this works for:
388399
// 1) private[this] fields
389400
// 2) inherited private[this] fields
@@ -427,6 +438,8 @@ trait PickleTools {
427438
}
428439

429440
trait CurrentMirrorMacro extends Macro {
441+
import scala.reflect.runtime.{universe => ru}
442+
430443
def impl: c.Tree = {
431444
import c.universe._
432445
c.inferImplicitValue(typeOf[ru.Mirror], silent = true) orElse {

core/src/main/scala/pickling/internal/package.scala

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@ package scala.pickling
33
import scala.language.experimental.macros
44
import scala.language.reflectiveCalls
55

6-
import scala.reflect.runtime.{universe => ru}
7-
import ru._
6+
import HasCompat._
87

98
package object internal {
109

10+
import scala.reflect.runtime.{universe => ru}
11+
import ru._
12+
import compat._
13+
1114
// TOGGLE DEBUGGING
1215
private val debugEnabled: Boolean = System.getProperty("pickling.debug", "false").toBoolean
1316
private[pickling] def debug(output: => String) = if (debugEnabled) println(output)

core/src/main/scala/pickling/ir/IRs.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@ package ir
33

44
import scala.reflect.api.Universe
55

6+
import HasCompat._
7+
68
class IRs[U <: Universe with Singleton](val uni: U) {
79
import uni._
10+
import compat._
811
import definitions._
912

1013
sealed abstract class PickleIR

project/Build.scala

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ object BuildSettings {
1212
val buildSettings = Defaults.defaultSettings ++ Seq(
1313
version := buildVersion,
1414
scalaVersion := buildScalaVersion,
15-
addCompilerPlugin("org.scala-lang.plugins" % "macro-paradise" % "2.0.0-SNAPSHOT" cross CrossVersion.full),
1615
resolvers += Resolver.sonatypeRepo("snapshots"),
1716
resolvers += Resolver.sonatypeRepo("releases"),
1817
scalacOptions ++= Seq("-feature")
@@ -73,8 +72,21 @@ object MyBuild extends Build {
7372
settings = buildSettings ++ Seq(
7473
scalacOptions ++= Seq("-optimise"),
7574
libraryDependencies <+= (scalaVersion)("org.scala-lang" % "scala-reflect" % _),
76-
libraryDependencies += "org.scalatest" %% "scalatest" % "2.1.2" % "test",
75+
libraryDependencies += "org.scalatest" %% "scalatest" % "2.1.3" % "test",
7776
libraryDependencies += "org.scalacheck" %% "scalacheck" % "1.11.3" % "test",
77+
libraryDependencies := {
78+
CrossVersion.partialVersion(scalaVersion.value) match {
79+
// if scala 2.11+ is used, quasiquotes are merged into scala-reflect
80+
case Some((2, scalaMajor)) if scalaMajor >= 11 =>
81+
libraryDependencies.value ++ Seq(
82+
"org.scala-lang.modules" %% "scala-parser-combinators" % "1.0.1")
83+
// in Scala 2.10, quasiquotes are provided by macro-paradise
84+
case Some((2, 10)) =>
85+
libraryDependencies.value ++ Seq(
86+
compilerPlugin("org.scalamacros" % "paradise" % "2.0.0-M8" cross CrossVersion.full),
87+
"org.scalamacros" %% "quasiquotes" % "2.0.0-M8")
88+
}
89+
},
7890
conflictWarning in ThisBuild := ConflictWarning.disable,
7991
parallelExecution in Test := false, // hello, reflection sync!!
8092
run <<= run in Compile in sandbox, // http://www.scala-sbt.org/release/docs/Detailed-Topics/Tasks
@@ -191,7 +203,7 @@ object MyBuild extends Build {
191203
settings = buildSettings ++ Seq(
192204
sourceDirectory in Compile <<= baseDirectory(root => root),
193205
sourceDirectory in Test <<= baseDirectory(root => root),
194-
libraryDependencies += "org.scalatest" %% "scalatest" % "2.1.2",
206+
libraryDependencies += "org.scalatest" %% "scalatest" % "2.1.3",
195207
parallelExecution in Test := false,
196208
// scalacOptions ++= Seq()
197209
// scalacOptions ++= Seq("-Xlog-implicits")

0 commit comments

Comments
 (0)