diff options
author | Adriaan Moors <adriaan.moors@typesafe.com> | 2014-02-23 10:01:24 -0600 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@typesafe.com> | 2014-02-23 10:01:24 -0600 |
commit | efa99c01974febe227937f090afbb93b9a6a59a5 (patch) | |
tree | a5656dda5c063d10c9d72f614a39ceb8a7828b1c /test/files/neg/macro-bundle-whitebox-use-refined/Macros_1.scala | |
parent | 6a9767b95216badc5cc8080f430d6a517fbdac4a (diff) | |
parent | dded01b234542501fa62821376a4d853e24250d4 (diff) | |
download | scala-efa99c01974febe227937f090afbb93b9a6a59a5.tar.gz scala-efa99c01974febe227937f090afbb93b9a6a59a5.tar.bz2 scala-efa99c01974febe227937f090afbb93b9a6a59a5.zip |
Merge pull request #3571 from xeno-by/ticket/8321
SI-8321 bundles can't be whitebox
Diffstat (limited to 'test/files/neg/macro-bundle-whitebox-use-refined/Macros_1.scala')
-rw-r--r-- | test/files/neg/macro-bundle-whitebox-use-refined/Macros_1.scala | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/test/files/neg/macro-bundle-whitebox-use-refined/Macros_1.scala b/test/files/neg/macro-bundle-whitebox-use-refined/Macros_1.scala new file mode 100644 index 0000000000..1866044221 --- /dev/null +++ b/test/files/neg/macro-bundle-whitebox-use-refined/Macros_1.scala @@ -0,0 +1,108 @@ +import scala.reflect.macros.blackbox.Context +import scala.language.experimental.macros + +// whitebox use case #1: return type refinement + +class ReturnTypeRefinementBundle(val c: Context { type PrefixType = Nothing }) { + import c.universe._ + def impl = { + q""" + trait Foo { + def x = 2 + } + new Foo {} + """ + } +} + +object ReturnTypeRefinement { + def foo: Any = macro ReturnTypeRefinementBundle.impl +} + +// whitebox use case #2: fundep materialization + +trait FundepMaterialization[T, U] { + def to(t : T) : U + // def from(u : U) : T +} + +class FundepMaterializationBundle(val c: Context { type PrefixType = Nothing }) { + import c.universe._ + import definitions._ + import Flag._ + + def impl[T: c.WeakTypeTag, U: c.WeakTypeTag]: c.Expr[FundepMaterialization[T, U]] = { + val sym = c.weakTypeOf[T].typeSymbol + if (!sym.isClass || !sym.asClass.isCaseClass) c.abort(c.enclosingPosition, s"$sym is not a case class") + val fields = sym.info.decls.toList.collect{ case x: TermSymbol if x.isVal && x.isCaseAccessor => x } + + def mkTpt() = { + val core = Ident(TupleClass(fields.length) orElse UnitClass) + if (fields.length == 0) core + else AppliedTypeTree(core, fields map (f => TypeTree(f.info))) + } + + def mkFrom() = { + if (fields.length == 0) Literal(Constant(Unit)) + else Apply(Ident(newTermName("Tuple" + fields.length)), fields map (f => Select(Ident(newTermName("f")), newTermName(f.name.toString.trim)))) + } + + val evidenceClass = ClassDef(Modifiers(FINAL), newTypeName("$anon"), List(), Template( + List(AppliedTypeTree(Ident(newTypeName("FundepMaterialization")), List(Ident(sym), mkTpt()))), + emptyValDef, + List( + DefDef(Modifiers(), termNames.CONSTRUCTOR, List(), List(List()), TypeTree(), Block(List(Apply(Select(Super(This(typeNames.EMPTY), typeNames.EMPTY), termNames.CONSTRUCTOR), List())), Literal(Constant(())))), + DefDef(Modifiers(), newTermName("to"), List(), List(List(ValDef(Modifiers(PARAM), newTermName("f"), Ident(sym), EmptyTree))), TypeTree(), mkFrom())))) + c.Expr[FundepMaterialization[T, U]](Block(List(evidenceClass), Apply(Select(New(Ident(newTypeName("$anon"))), termNames.CONSTRUCTOR), List()))) + } +} + +object FundepMaterialization { + implicit def materializeIso[T, U]: FundepMaterialization[T, U] = macro FundepMaterializationBundle.impl[T, U] +} + +// whitebox use case #3: dynamic materialization + +trait DynamicMaterialization[T] + +class C1(val x: Int) +class C2(val x: String) + +trait LowPriority { + implicit def lessSpecific[T]: DynamicMaterialization[T] = null +} + +object DynamicMaterialization extends LowPriority { + implicit def moreSpecific[T]: DynamicMaterialization[T] = macro DynamicMaterializationBundle.impl[T] +} + +class DynamicMaterializationBundle(val c: Context { type PrefixType = Nothing }) { + import c.universe._ + def impl[T: c.WeakTypeTag] = { + val tpe = weakTypeOf[T] + if (tpe.members.exists(_.info =:= typeOf[Int])) + c.abort(c.enclosingPosition, "I don't like classes that contain integers") + q"new DynamicMaterialization[$tpe]{ override def toString = ${tpe.toString} }" + } +} + +// whitebox use case #4: extractor macros + +object ExtractorMacro { + def unapply(x: Int): Any = macro ExtractorBundle.unapplyImpl +} + +class ExtractorBundle(val c: Context { type PrefixType = Nothing }) { + import c.universe._ + def unapplyImpl(x: Tree) = { + q""" + new { + class Match(x: Int) { + def isEmpty = false + def get = x + } + def unapply(x: Int) = new Match(x) + }.unapply($x) + """ + } +} |