From e32ba9c54a32c5198a5aac3b950b05b00d67abda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bjo=CC=88rn=20Antonsson?= Date: Wed, 25 Jun 2014 14:32:29 +0200 Subject: [PATCH] +pro,hco,par Make sure that things build on both 2.10 and 2.11 --- .../docs/http/HttpServerExampleSpec.scala | 2 +- .../main/java/akka/http/model/japi/Host.java | 2 +- .../main/java/akka/http/model/japi/Uri.java | 6 +- .../main/java/akka/http/model/japi/Util.java | 4 +- .../model/japi/headers/CacheDirectives.java | 4 +- .../src/main/scala/akka/http/model/Uri.scala | 11 + .../http/model/headers/CacheDirective.scala | 8 +- .../src/test/scala/akka/http/TestServer.scala | 20 +- .../akka/shapeless/poly.scala | 4 + .../main/scala-2.11/akka/shapeless/poly.scala | 396 ++++++++++++++++++ .../main/scala/akka/shapeless/generic.scala | 10 + .../scala/akka/shapeless/singletons.scala | 3 + 12 files changed, 450 insertions(+), 20 deletions(-) rename akka-parsing/src/main/{scala => scala-2.10}/akka/shapeless/poly.scala (99%) create mode 100644 akka-parsing/src/main/scala-2.11/akka/shapeless/poly.scala diff --git a/akka-docs-dev/rst/scala/code/docs/http/HttpServerExampleSpec.scala b/akka-docs-dev/rst/scala/code/docs/http/HttpServerExampleSpec.scala index 815ae8c8cb..e98cb37913 100644 --- a/akka-docs-dev/rst/scala/code/docs/http/HttpServerExampleSpec.scala +++ b/akka-docs-dev/rst/scala/code/docs/http/HttpServerExampleSpec.scala @@ -64,7 +64,7 @@ class HttpServerExampleSpec case HttpRequest(GET, Uri.Path("/"), _, _, _) ⇒ HttpResponse( entity = HttpEntity(MediaTypes.`text/html`, - Hello world!.toString)) + "Hello world!")) case HttpRequest(GET, Uri.Path("/ping"), _, _, _) ⇒ HttpResponse(entity = "PONG!") case HttpRequest(GET, Uri.Path("/crash"), _, _, _) ⇒ sys.error("BOOM!") diff --git a/akka-http-core/src/main/java/akka/http/model/japi/Host.java b/akka-http-core/src/main/java/akka/http/model/japi/Host.java index d225a9fdba..b00387286b 100644 --- a/akka-http-core/src/main/java/akka/http/model/japi/Host.java +++ b/akka-http-core/src/main/java/akka/http/model/japi/Host.java @@ -34,7 +34,7 @@ public abstract class Host { /** * The constant representing an empty Host. */ - public static final Host EMPTY = akka.http.model.Uri$Host$Empty$.MODULE$; + public static final Host EMPTY = akka.http.model.Uri.getHostEmpty(); /** * Parse the given Host string using the default charset and parsing-mode. diff --git a/akka-http-core/src/main/java/akka/http/model/japi/Uri.java b/akka-http-core/src/main/java/akka/http/model/japi/Uri.java index 5960aa887d..e57f2f23ad 100644 --- a/akka-http-core/src/main/java/akka/http/model/japi/Uri.java +++ b/akka-http-core/src/main/java/akka/http/model/japi/Uri.java @@ -156,9 +156,9 @@ public abstract class Uri { */ public abstract Uri fragment(Option fragment); - public static final akka.http.model.Uri.ParsingMode STRICT = akka.http.model.Uri$ParsingMode$Strict$.MODULE$; - public static final akka.http.model.Uri.ParsingMode RELAXED = akka.http.model.Uri$ParsingMode$Relaxed$.MODULE$; - public static final akka.http.model.Uri.ParsingMode RELAXED_WITH_RAW_QUERY = akka.http.model.Uri$ParsingMode$RelaxedWithRawQuery$.MODULE$; + public static final akka.http.model.Uri.ParsingMode STRICT = akka.http.model.Uri.getParsingModeStrict(); + public static final akka.http.model.Uri.ParsingMode RELAXED = akka.http.model.Uri.getParsingModeRelaxed(); + public static final akka.http.model.Uri.ParsingMode RELAXED_WITH_RAW_QUERY = akka.http.model.Uri.getParsingModeRelaxedWithRawQuery(); /** * Creates a default Uri to be modified using the modification methods. diff --git a/akka-http-core/src/main/java/akka/http/model/japi/Util.java b/akka-http-core/src/main/java/akka/http/model/japi/Util.java index f8d05a4247..f26c41e7fc 100644 --- a/akka-http-core/src/main/java/akka/http/model/japi/Util.java +++ b/akka-http-core/src/main/java/akka/http/model/japi/Util.java @@ -35,7 +35,7 @@ public abstract class Util { } @SuppressWarnings("unchecked") public static scala.collection.immutable.Map convertMapToScala(Map map) { - return Map$.MODULE$.apply(scala.collection.JavaConverters.asScalaMapConverter(map).asScala().toSeq()); + return Map$.MODULE$.apply(scala.collection.JavaConverters.mapAsScalaMapConverter(map).asScala().toSeq()); } @SuppressWarnings("unchecked") // contains an upcast public static scala.Option convertOptionToScala(Option o) { @@ -53,7 +53,7 @@ public abstract class Util { @SuppressWarnings("unchecked") public static Seq convertIterable(Iterable els) { - return scala.collection.JavaConverters.asScalaIterableConverter((Iterable)els).asScala().toVector(); + return scala.collection.JavaConverters.iterableAsScalaIterableConverter((Iterable)els).asScala().toVector(); } @SuppressWarnings("unchecked") public static Seq convertArray(T[] els) { diff --git a/akka-http-core/src/main/java/akka/http/model/japi/headers/CacheDirectives.java b/akka-http-core/src/main/java/akka/http/model/japi/headers/CacheDirectives.java index f4d1e6ba59..d7936de125 100644 --- a/akka-http-core/src/main/java/akka/http/model/japi/headers/CacheDirectives.java +++ b/akka-http-core/src/main/java/akka/http/model/japi/headers/CacheDirectives.java @@ -29,9 +29,9 @@ public final class CacheDirectives { public static CacheDirective NO_CACHE(String... fieldNames) { return akka.http.model.headers.CacheDirectives.no$minuscache$.MODULE$.apply(fieldNames); } - public static final CacheDirective PUBLIC = akka.http.model.headers.CacheDirectives.public$.MODULE$; + public static final CacheDirective PUBLIC = akka.http.model.headers.CacheDirectives.getPublic(); public static CacheDirective PRIVATE(String... fieldNames) { - return akka.http.model.headers.CacheDirectives.private$.MODULE$.apply(fieldNames); + return akka.http.model.headers.CacheDirectives.createPrivate(fieldNames); } public static final CacheDirective PROXY_REVALIDATE = akka.http.model.headers.CacheDirectives.proxy$minusrevalidate$.MODULE$; public static CacheDirective S_MAXAGE(long deltaSeconds) { diff --git a/akka-http-core/src/main/scala/akka/http/model/Uri.scala b/akka-http-core/src/main/scala/akka/http/model/Uri.scala index 1044ce7dbc..fc98e5ced2 100644 --- a/akka-http-core/src/main/scala/akka/http/model/Uri.scala +++ b/akka-http-core/src/main/scala/akka/http/model/Uri.scala @@ -345,6 +345,10 @@ object Uri { def apply(address: Inet4Address): IPv4Host = IPv4Host(address.getAddress, address.getHostAddress) def apply(address: Inet6Address): IPv6Host = IPv6Host(address.getAddress, address.getHostAddress) } + + /** Java API */ + def getHostEmpty: Host = Host.Empty + sealed abstract class NonEmptyHost extends Host { def isEmpty = false def toOption = Some(this) @@ -596,6 +600,13 @@ object Uri { } } + /** Java API */ + def getParsingModeStrict: ParsingMode = ParsingMode.Strict + /** Java API */ + def getParsingModeRelaxed: ParsingMode = ParsingMode.Relaxed + /** Java API */ + def getParsingModeRelaxedWithRawQuery: ParsingMode = ParsingMode.RelaxedWithRawQuery + // http://tools.ietf.org/html/rfc3986#section-5.2.2 private[http] def resolve(scheme: String, userinfo: String, host: Host, port: Int, path: Path, query: Query, fragment: Option[String], base: Uri): Uri = { diff --git a/akka-http-core/src/main/scala/akka/http/model/headers/CacheDirective.scala b/akka-http-core/src/main/scala/akka/http/model/headers/CacheDirective.scala index 45f8da5260..6aaeb3e5a8 100644 --- a/akka-http-core/src/main/scala/akka/http/model/headers/CacheDirective.scala +++ b/akka-http-core/src/main/scala/akka/http/model/headers/CacheDirective.scala @@ -17,7 +17,7 @@ object CacheDirective { sealed trait RequestDirective extends CacheDirective sealed trait ResponseDirective extends CacheDirective - private final case class CustomCacheDirective(name: String, content: Option[String]) + final case class CustomCacheDirective(name: String, content: Option[String]) extends RequestDirective with ResponseDirective with ValueRenderable { def render[R <: Rendering](r: R): r.type = content match { case Some(s) ⇒ r ~~ name ~~ '=' ~~# s @@ -91,12 +91,18 @@ object CacheDirectives { // http://tools.ietf.org/html/rfc7234#section-5.2.2.5 case object `public` extends SingletonValueRenderable with ResponseDirective + /** Java API */ + def getPublic: ResponseDirective = `public` + // http://tools.ietf.org/html/rfc7234#section-5.2.2.6 final case class `private`(fieldNames: immutable.Seq[String]) extends FieldNamesDirective with ResponseDirective object `private` { @varargs def apply(fieldNames: String*): `private` = apply(immutable.Seq(fieldNames: _*)) } + /** Java API */ + @varargs def createPrivate(fieldNames: String*): ResponseDirective = `private`.apply(immutable.Seq(fieldNames: _*)) + // http://tools.ietf.org/html/rfc7234#section-5.2.2.7 case object `proxy-revalidate` extends SingletonValueRenderable with ResponseDirective diff --git a/akka-http-core/src/test/scala/akka/http/TestServer.scala b/akka-http-core/src/test/scala/akka/http/TestServer.scala index 21da0c552d..564d994dc9 100644 --- a/akka-http-core/src/test/scala/akka/http/TestServer.scala +++ b/akka-http-core/src/test/scala/akka/http/TestServer.scala @@ -52,14 +52,14 @@ object TestServer extends App { lazy val index = HttpResponse( entity = HttpEntity(MediaTypes.`text/html`, - - -

Say hello to akka-http-core!

-

Defined resources:

- - - .toString())) + """| + | + |

Say hello to akka-http-core!

+ |

Defined resources:

+ | + | + |""".stripMargin)) } diff --git a/akka-parsing/src/main/scala/akka/shapeless/poly.scala b/akka-parsing/src/main/scala-2.10/akka/shapeless/poly.scala similarity index 99% rename from akka-parsing/src/main/scala/akka/shapeless/poly.scala rename to akka-parsing/src/main/scala-2.10/akka/shapeless/poly.scala index d0512eabbc..78af5ad446 100644 --- a/akka-parsing/src/main/scala/akka/shapeless/poly.scala +++ b/akka-parsing/src/main/scala-2.10/akka/shapeless/poly.scala @@ -21,6 +21,8 @@ import language.experimental.macros import reflect.macros.Context +import HasCompat._ + // Typically the contents of this object will be imported via val alias `poly` in the shapeless package object. object PolyDefns extends Cases { /** @@ -52,6 +54,7 @@ object PolyDefns extends Cases { def materializeFromValueImpl[P: c.WeakTypeTag, FT: c.WeakTypeTag, T: c.WeakTypeTag](c: Context): c.Expr[Case[P, FT :: HNil]] = { import c.universe._ + import compat._ val pTpe = weakTypeOf[P] val ftTpe = weakTypeOf[FT] @@ -227,6 +230,7 @@ object Poly extends PolyInst { def liftFnImpl(c: Context)(f: c.Expr[Any]): c.Expr[Poly] = { import c.universe._ + import compat._ import Flag._ val pendingSuperCall = Apply(Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR), List()) diff --git a/akka-parsing/src/main/scala-2.11/akka/shapeless/poly.scala b/akka-parsing/src/main/scala-2.11/akka/shapeless/poly.scala new file mode 100644 index 0000000000..23986026c8 --- /dev/null +++ b/akka-parsing/src/main/scala-2.11/akka/shapeless/poly.scala @@ -0,0 +1,396 @@ +/* + * Copyright (c) 2011-13 Miles Sabin + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package akka.shapeless + +import language.existentials +import language.experimental.macros + +import reflect.macros.Context + +import HasCompat._ + +// Typically the contents of this object will be imported via val alias `poly` in the shapeless package object. +object PolyDefns extends Cases { + /** + * Type-specific case of a polymorphic function. + * + * @author Miles Sabin + */ + abstract class Case[P, L <: HList] { + type Result + val value: L ⇒ Result + + def apply(t: L) = value(t) + def apply()(implicit ev: HNil =:= L) = value(HNil) + def apply[T](t: T)(implicit ev: (T :: HNil) =:= L) = value(t :: HNil) + def apply[T, U](t: T, u: U)(implicit ev: (T :: U :: HNil) =:= L) = value(t :: u :: HNil) + } + + object Case extends CaseInst { + type Aux[P, L <: HList, Result0] = Case[P, L] { type Result = Result0 } + type Hom[P, T] = Aux[P, T :: HNil, T] + + def apply[P, L <: HList, R](v: L ⇒ R): Aux[P, L, R] = new Case[P, L] { + type Result = R + val value = v + } + + implicit def materializeFromValue1[P, F[_], T]: Case[P, F[T] :: HNil] = macro materializeFromValueImpl[P, F[T], T] + implicit def materializeFromValue2[P, T]: Case[P, T :: HNil] = macro materializeFromValueImpl[P, T, T] + + def materializeFromValueImpl[P: c.WeakTypeTag, FT: c.WeakTypeTag, T: c.WeakTypeTag](c: Context): c.Expr[Case[P, FT :: HNil]] = { + import c.universe._ + import compat._ + + val pTpe = weakTypeOf[P] + val ftTpe = weakTypeOf[FT] + val tTpe = weakTypeOf[T] + + val recTpe = weakTypeOf[Case[P, FT :: HNil]] + if (c.openImplicits.tail.exists(_.pt =:= recTpe)) + c.abort(c.enclosingPosition, s"Diverging implicit expansion for Case.Aux[$pTpe, $ftTpe :: HNil]") + + val value = pTpe match { + case SingleType(_, f) ⇒ f + case other ⇒ c.abort(c.enclosingPosition, "Can only materialize cases from singleton values") + } + + c.Expr[Case[P, FT :: HNil]] { + TypeApply(Select(Ident(value), newTermName("caseUniv")), List(TypeTree(tTpe))) + } + } + } + + type Case0[P] = Case[P, HNil] + object Case0 { + type Aux[P, T] = Case.Aux[P, HNil, T] + def apply[P, T](v: T): Aux[P, T] = new Case[P, HNil] { + type Result = T + val value = (l: HNil) ⇒ v + } + } + + /** + * Represents the composition of two polymorphic function values. + * + * @author Miles Sabin + */ + class Compose[F, G](f: F, g: G) extends Poly + + object Compose { + implicit def composeCase[C, F <: Poly, G <: Poly, T, U, V](implicit unpack: Unpack2[C, Compose, F, G], cG: Case1.Aux[G, T, U], cF: Case1.Aux[F, U, V]) = new Case[C, T :: HNil] { + type Result = V + val value = (t: T :: HNil) ⇒ cF(cG.value(t)) + } + } + + /** + * Base class for lifting a `Function1` to a `Poly1` + */ + class ->[T, R](f: T ⇒ R) extends Poly1 { + implicit def subT[U <: T] = at[U](f) + } + + trait LowPriorityLiftFunction1 extends Poly1 { + implicit def default[T] = at[T](_ ⇒ HNil: HNil) + } + + /** + * Base class for lifting a `Function1` to a `Poly1` over the universal domain, yielding an `HList` with the result as + * its only element if the argument is in the original functions domain, `HNil` otherwise. + */ + class >->[T, R](f: T ⇒ R) extends LowPriorityLiftFunction1 { + implicit def subT[U <: T] = at[U](f(_) :: HNil) + } + + trait LowPriorityLiftU extends Poly { + implicit def default[L <: HList] = new ProductCase[L] { + type Result = HNil + val value = (l: L) ⇒ HNil + } + } + + /** + * Base class for lifting a `Poly` to a `Poly` over the universal domain, yielding an `HList` with the result as it's + * only element if the argument is in the original functions domain, `HNil` otherwise. + */ + class LiftU[P <: Poly](p: P) extends LowPriorityLiftU { + implicit def defined[L <: HList](implicit caseT: Case[P, L]) = new ProductCase[L] { + type Result = caseT.Result :: HNil + val value = (l: L) ⇒ caseT(l) :: HNil + } + } + + /** + * Base trait for natural transformations. + * + * @author Miles Sabin + */ + trait ~>[F[_], G[_]] extends Poly1 { + def apply[T](f: F[T]): G[T] + implicit def caseUniv[T]: Case.Aux[F[T], G[T]] = at[F[T]](apply(_)) + } + + object ~> { + implicit def inst1[F[_], G[_], T](f: F ~> G): F[T] ⇒ G[T] = f(_) + implicit def inst2[G[_], T](f: Id ~> G): T ⇒ G[T] = f(_) + implicit def inst3[F[_], T](f: F ~> Id): F[T] ⇒ T = f(_) + implicit def inst4[T](f: Id ~> Id): T ⇒ T = f[T](_) // Explicit type argument needed here to prevent recursion? + implicit def inst5[F[_], G, T](f: F ~> Const[G]#λ): F[T] ⇒ G = f(_) + implicit def inst6[G, T](f: Id ~> Const[G]#λ): T ⇒ G = f(_) + implicit def inst7[F, G](f: Const[F]#λ ~> Const[G]#λ): F ⇒ G = f(_) + } + + /** Natural transformation with a constant type constructor on the right hand side. */ + type ~>>[F[_], R] = ~>[F, Const[R]#λ] + + /** Polymorphic identity function. */ + object identity extends (Id ~> Id) { + def apply[T](t: T) = t + } +} + +/** + * Base trait for polymorphic values. + * + * @author Miles Sabin + */ +trait Poly extends PolyApply { + import poly._ + + def compose(f: Poly) = new Compose[this.type, f.type](this, f) + + def andThen(f: Poly) = new Compose[f.type, this.type](f, this) + + /** The type of the case representing this polymorphic function at argument types `L`. */ + type ProductCase[L <: HList] = Case[this.type, L] + object ProductCase { + /** The type of a case of this polymorphic function of the form `L => R` */ + type Aux[L <: HList, Result0] = ProductCase[L] { type Result = Result0 } + + /** The type of a case of this polymorphic function of the form `T => T` */ + type Hom[T] = Aux[T :: HNil, T] + + def apply[L <: HList, R](v: L ⇒ R) = new ProductCase[L] { + type Result = R + val value = v + } + } + + def use[T, L <: HList, R](t: T)(implicit cb: CaseBuilder[T, L, R]) = cb(t) + + trait CaseBuilder[T, L <: HList, R] { + def apply(t: T): ProductCase.Aux[L, R] + } + + trait LowPriorityCaseBuilder { + implicit def valueCaseBuilder[T]: CaseBuilder[T, HNil, T] = + new CaseBuilder[T, HNil, T] { + def apply(t: T) = ProductCase((_: HNil) ⇒ t) + } + } + + object CaseBuilder extends LowPriorityCaseBuilder { + import ops.function.FnToProduct + implicit def fnCaseBuilder[F, H, T <: HList, Result](implicit fntp: FnToProduct.Aux[F, ((H :: T) ⇒ Result)]): CaseBuilder[F, H :: T, Result] = + new CaseBuilder[F, H :: T, Result] { + def apply(f: F) = ProductCase((l: H :: T) ⇒ fntp(f)(l)) + } + } + + def caseAt[L <: HList](implicit c: ProductCase[L]) = c + + def apply[R](implicit c: ProductCase.Aux[HNil, R]): R = c() +} + +/** + * Provides implicit conversions from polymorphic function values to monomorphic function values, eg. for use as + * arguments to ordinary higher order functions. + * + * @author Miles Sabin + */ +object Poly extends PolyInst { + implicit def inst0(p: Poly)(implicit cse: p.ProductCase[HNil]): cse.Result = cse() + + implicit def apply(f: Any): Poly = macro liftFnImpl + + def liftFnImpl(c: Context)(f: c.Expr[Any]): c.Expr[Poly] = { + import c.universe._ + import compat._ + import Flag._ + + val pendingSuperCall = Apply(Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR), List()) + + val moduleName = newTermName(c.fresh) + + val anySym = c.mirror.staticClass("scala.Any") + val anyTpe = anySym.asType.toType + val nothingSym = c.mirror.staticClass("scala.Nothing") + val nothingTpe = nothingSym.asType.toType + + val typeOpsSym = c.mirror.staticPackage("shapeless") + val idSym = typeOpsSym.newTypeSymbol(newTypeName("Id")) + val constSym = typeOpsSym.newTypeSymbol(newTypeName("Const")) + + val natTSym = c.mirror.staticClass("shapeless.PolyDefns.$tilde$greater") + val natTTpe = natTSym.asClass.toTypeConstructor + + def mkApply(fSym: Symbol, gSym: Symbol, targ: TypeName, arg: TermName, body: Tree) = { + def mkTargRef(sym: Symbol) = + if (sym == idSym) + Ident(targ) + else if (sym.asType.typeParams.isEmpty) + Ident(sym.name) + else + AppliedTypeTree(Ident(sym.name), List(Ident(targ))) + + DefDef( + Modifiers(), newTermName("apply"), + List(TypeDef(Modifiers(PARAM), targ, List(), TypeBoundsTree(TypeTree(nothingTpe), TypeTree(anyTpe)))), + List(List(ValDef(Modifiers(PARAM), arg, mkTargRef(fSym), EmptyTree))), + mkTargRef(gSym), + body) + } + + def destructureMethod(methodSym: MethodSymbol) = { + val paramSym = methodSym.paramss match { + case List(List(ps)) ⇒ ps + case _ ⇒ c.abort(c.enclosingPosition, "Expression $f has the wrong shape to be converted to a polymorphic function value") + } + + def extractTc(tpe: Type): Symbol = { + val owner = tpe.typeSymbol.owner + if (owner == methodSym) idSym + else tpe.typeConstructor.typeSymbol + } + + (extractTc(paramSym.typeSignature), extractTc(methodSym.returnType)) + } + + def stripSymbolsAndTypes(tree: Tree, internalSyms: List[Symbol]) = { + // Adapted from https://github.com/scala/async/blob/master/src/main/scala/scala/async/TransformUtils.scala#L226 + final class StripSymbolsAndTypes extends Transformer { + override def transform(tree: Tree): Tree = super.transform { + tree match { + case TypeApply(fn, args) if args.map(t ⇒ transform(t)) exists (_.isEmpty) ⇒ transform(fn) + case EmptyTree ⇒ tree + case _ ⇒ + val hasSymbol: Boolean = { + val reflectInternalTree = tree.asInstanceOf[symtab.Tree forSome { val symtab: reflect.internal.SymbolTable }] + reflectInternalTree.hasSymbol + } + val dupl = tree.duplicate + if (hasSymbol) + dupl.symbol = NoSymbol + dupl.tpe = null + dupl + } + } + } + + (new StripSymbolsAndTypes).transform(tree) + } + + val (fSym, gSym, dd) = + f.tree match { + case Block(List(), Function(List(_), Apply(TypeApply(fun, _), _))) ⇒ + val methodSym = fun.symbol.asMethod + + val (fSym1, gSym1) = destructureMethod(methodSym) + val body = Apply(TypeApply(Ident(methodSym), List(Ident(newTypeName("T")))), List(Ident(newTermName("t")))) + + (fSym1, gSym1, mkApply(fSym1, gSym1, newTypeName("T"), newTermName("t"), body)) + + case Block(List(), Function(List(_), Apply(fun, _))) ⇒ + val methodSym = fun.symbol.asMethod + + val (fSym1, gSym1) = destructureMethod(methodSym) + val body = Apply(Ident(methodSym), List(Ident(newTermName("t")))) + + (fSym1, gSym1, mkApply(fSym1, gSym1, newTypeName("T"), newTermName("t"), body)) + + case Block(List(df @ DefDef(mods, _, List(tp), List(List(vp)), tpt, rhs)), Literal(Constant(()))) ⇒ + val methodSym = df.symbol.asMethod + + val (fSym1, gSym1) = destructureMethod(methodSym) + + val body = mkApply(fSym1, gSym1, tp.name, vp.name, stripSymbolsAndTypes(rhs, List())) + + (fSym1, gSym1, body) + + case Block(List(df @ DefDef(_, _, List(), List(List(vp)), tpt, rhs)), Literal(Constant(()))) ⇒ + val methodSym = df.symbol.asMethod + + val (fSym1, gSym1) = destructureMethod(methodSym) + + val body = mkApply(fSym1, gSym1, newTypeName("T"), vp.name, stripSymbolsAndTypes(rhs, List())) + (fSym1, gSym1, body) + + case _ ⇒ + c.abort(c.enclosingPosition, s"Unable to convert expression $f to a polymorphic function value") + } + + def mkTargTree(sym: Symbol) = + if (sym == idSym) + Select(Ident(newTermName("shapeless")), newTypeName("Id")) + else if (sym.asType.typeParams.isEmpty) + SelectFromTypeTree( + AppliedTypeTree( + Select(Ident(newTermName("shapeless")), newTypeName("Const")), + List(Ident(sym.name))), + newTypeName("λ")) + else + Ident(sym.name) + + val liftedTypeTree = + AppliedTypeTree( + Ident(natTSym), + List(mkTargTree(fSym), mkTargTree(gSym))) + + val moduleDef = + ModuleDef(Modifiers(), moduleName, + Template( + List(liftedTypeTree), + emptyValDef, + List( + DefDef( + Modifiers(), nme.CONSTRUCTOR, List(), + List(List()), + TypeTree(), + Block(List(pendingSuperCall), Literal(Constant(())))), + + dd))) + + c.Expr[Poly] { + Block( + List(moduleDef), + Ident(moduleName)) + } + } +} + +/** + * Trait simplifying the creation of polymorphic values. + */ +trait Poly0 extends Poly { + type Case0[T] = ProductCase.Aux[HNil, T] + + def at[T](t: T) = new ProductCase[HNil] { + type Result = T + val value = (l: HNil) ⇒ t + } +} diff --git a/akka-parsing/src/main/scala/akka/shapeless/generic.scala b/akka-parsing/src/main/scala/akka/shapeless/generic.scala index 14a01b4b58..4f3b7f6c6d 100644 --- a/akka-parsing/src/main/scala/akka/shapeless/generic.scala +++ b/akka-parsing/src/main/scala/akka/shapeless/generic.scala @@ -22,6 +22,15 @@ import scala.collection.breakOut import scala.collection.immutable.ListMap import scala.reflect.macros.Context +// provides a source compatibility stub +// in Scala 2.10.x, it will make `import compat._` compile just fine, +// even though `c.universe` doesn't have `compat` +// in Scala 2.11.0, it will be ignored, becase `import c.universe._` +// brings its own `compat` in scope and that one takes precedence +private[shapeless] object HasCompat { val compat = ??? } + +import HasCompat._ + trait Generic[T] { type Repr def to(t: T): Repr @@ -131,6 +140,7 @@ object GenericMacros { import c.universe._ import Flag._ + import compat._ def unitValueTree = reify { () }.tree def absurdValueTree = reify { ??? }.tree diff --git a/akka-parsing/src/main/scala/akka/shapeless/singletons.scala b/akka-parsing/src/main/scala/akka/shapeless/singletons.scala index c7958367af..4aa48ea895 100644 --- a/akka-parsing/src/main/scala/akka/shapeless/singletons.scala +++ b/akka-parsing/src/main/scala/akka/shapeless/singletons.scala @@ -23,6 +23,8 @@ import scala.reflect.macros.Context import tag.@@ +import HasCompat._ + trait Witness { type T val value: T {} @@ -73,6 +75,7 @@ trait SingletonTypeMacros[C <: Context] { import c.universe._ import Flag._ + import compat._ def mkWitnessT(sTpe: Type, s: Any): Tree = mkWitness(TypeTree(sTpe), Literal(Constant(s)))