@@ -128,7 +128,59 @@ class KindRewriter(plugin: Plugin, val global: Global)
128128 def makeTypeParamContra (name : Name , bounds : TypeBoundsTree = DefaultBounds ): TypeDef =
129129 TypeDef (Modifiers (PARAM | CONTRAVARIANT ), makeTypeName(name), Nil , bounds)
130130
131- def polyLambda (tree : Tree ): Tree = tree match {
131+ // Given a name, e.g. A or `+A` or `A <: Foo`, build a type
132+ // parameter tree using the given name, bounds, variance, etc.
133+ def makeTypeParamFromName (ident : Ident ): TypeDef = {
134+ val decoded = NameTransformer .decode(ident.name.toString)
135+ val src = s " type _X_[ $decoded] = Unit "
136+ sp.parse(src) match {
137+ case Some (TypeDef (_, _, List (tpe), _)) => tpe.duplicate
138+ case None => reporter.error(ident.pos, s " Can't parse param: ${ident.name}" ); null
139+ }
140+ }
141+
142+ // Like makeTypeParam, but can be used recursively in the case of types
143+ // that are themselves parameterized.
144+ def makeComplexTypeParam (t : Tree ): TypeDef = t match {
145+ case id @ Ident (_) =>
146+ makeTypeParamFromName(id)
147+
148+ case TypeDef (m, nm, ps, bs) =>
149+ TypeDef (Modifiers (PARAM ), nm, ps.map(makeComplexTypeParam), bs)
150+
151+ case ExistentialTypeTree (AppliedTypeTree (Ident (name), ps), _) =>
152+ val tparams = ps.map(makeComplexTypeParam)
153+ TypeDef (Modifiers (PARAM ), makeTypeName(name), tparams, DefaultBounds )
154+
155+ case x =>
156+ reporter.error(x.pos, " Can't parse %s (%s)" format (x, x.getClass.getName))
157+ null .asInstanceOf [TypeDef ]
158+ }
159+
160+ def typeArgsToTypeParams (args : List [Tree ]): List [TypeDef ] = args.map {
161+ case id @ Ident (_) =>
162+ makeTypeParamFromName(id)
163+
164+ case AppliedTypeTree (Ident (Plus ), Ident (name) :: Nil ) =>
165+ makeTypeParamCo(name)
166+
167+ case AppliedTypeTree (Ident (Minus ), Ident (name) :: Nil ) =>
168+ makeTypeParamContra(name)
169+
170+ case AppliedTypeTree (Ident (name), ps) =>
171+ val tparams = ps.map(makeComplexTypeParam)
172+ TypeDef (Modifiers (PARAM ), makeTypeName(name), tparams, DefaultBounds )
173+
174+ case ExistentialTypeTree (AppliedTypeTree (Ident (name), ps), _) =>
175+ val tparams = ps.map(makeComplexTypeParam)
176+ TypeDef (Modifiers (PARAM ), makeTypeName(name), tparams, DefaultBounds )
177+
178+ case x =>
179+ reporter.error(x.pos, " Can't parse %s (%s)" format (x, x.getClass.getName))
180+ null .asInstanceOf [TypeDef ]
181+ }
182+
183+ def polyTerm (tree : Tree ): Tree = tree match {
132184 case PolyLambda (methodName, (arrowType @ UnappliedType (_ :: targs)) :: Nil , Function1Tree (name, body)) =>
133185 val (f, g) = targs match {
134186 case a :: b :: Nil => (a, b)
@@ -139,41 +191,21 @@ class KindRewriter(plugin: Plugin, val global: Global)
139191 atPos(tree.pos.makeTransparent)(
140192 q " new $arrowType { def $methodName[ $TParam]( $name: $f[ $TParam]): $g[ $TParam] = $body } "
141193 )
194+ case PolyVal (targetType, methodName, tArgs, body) =>
195+ atPos(tree.pos.makeTransparent)(tArgs match {
196+ case Nil =>
197+ val tParam = newTypeName(freshName(" A" ))
198+ q " new $targetType { def $methodName[ $tParam] = $body } "
199+ case _ =>
200+ val tParams = typeArgsToTypeParams(tArgs)
201+ q " new $targetType { def $methodName[.. $tParams] = $body } "
202+ })
142203 case _ => tree
143204 }
144205
145206 // The transform method -- this is where the magic happens.
146207 override def transform (tree : Tree ): Tree = {
147208
148- // Given a name, e.g. A or `+A` or `A <: Foo`, build a type
149- // parameter tree using the given name, bounds, variance, etc.
150- def makeTypeParamFromName (name : Name ): TypeDef = {
151- val decoded = NameTransformer .decode(name.toString)
152- val src = s " type _X_[ $decoded] = Unit "
153- sp.parse(src) match {
154- case Some (TypeDef (_, _, List (tpe), _)) => tpe
155- case None => reporter.error(tree.pos, s " Can't parse param: $name" ); null
156- }
157- }
158-
159- // Like makeTypeParam, but can be used recursively in the case of types
160- // that are themselves parameterized.
161- def makeComplexTypeParam (t : Tree ): TypeDef = t match {
162- case Ident (name) =>
163- makeTypeParamFromName(name)
164-
165- case TypeDef (m, nm, ps, bs) =>
166- TypeDef (Modifiers (PARAM ), nm, ps.map(makeComplexTypeParam), bs)
167-
168- case ExistentialTypeTree (AppliedTypeTree (Ident (name), ps), _) =>
169- val tparams = ps.map(makeComplexTypeParam)
170- TypeDef (Modifiers (PARAM ), makeTypeName(name), tparams, DefaultBounds )
171-
172- case x =>
173- reporter.error(x.pos, " Can't parse %s (%s)" format (x, x.getClass.getName))
174- null .asInstanceOf [TypeDef ]
175- }
176-
177209 // Given the list a::as, this method finds the last argument in the list
178210 // (the "subtree") and returns that separately from the other arguments.
179211 // The stack is just used to enable tail recursion, and a and as are
@@ -204,28 +236,7 @@ class KindRewriter(plugin: Plugin, val global: Global)
204236 // Lambda[(A, B) => Function2[A, Int, B]] case.
205237 def handleLambda (a : Tree , as : List [Tree ]): Tree = {
206238 val (args, subtree) = parseLambda(a, as, Nil )
207- val innerTypes = args.map {
208- case Ident (name) =>
209- makeTypeParamFromName(name)
210-
211- case AppliedTypeTree (Ident (Plus ), Ident (name) :: Nil ) =>
212- makeTypeParamCo(name)
213-
214- case AppliedTypeTree (Ident (Minus ), Ident (name) :: Nil ) =>
215- makeTypeParamContra(name)
216-
217- case AppliedTypeTree (Ident (name), ps) =>
218- val tparams = ps.map(makeComplexTypeParam)
219- TypeDef (Modifiers (PARAM ), makeTypeName(name), tparams, DefaultBounds )
220-
221- case ExistentialTypeTree (AppliedTypeTree (Ident (name), ps), _) =>
222- val tparams = ps.map(makeComplexTypeParam)
223- TypeDef (Modifiers (PARAM ), makeTypeName(name), tparams, DefaultBounds )
224-
225- case x =>
226- reporter.error(x.pos, " Can't parse %s (%s)" format (x, x.getClass.getName))
227- null .asInstanceOf [TypeDef ]
228- }
239+ val innerTypes = typeArgsToTypeParams(args)
229240 makeTypeProjection(innerTypes, subtree)
230241 }
231242
@@ -321,7 +332,7 @@ class KindRewriter(plugin: Plugin, val global: Global)
321332 // given a tree, see if it could possibly be a type lambda
322333 // (either placeholder syntax or lambda syntax). if so, handle
323334 // it, and if not, transform it in the normal way.
324- val result = polyLambda (tree match {
335+ val result = polyTerm (tree match {
325336
326337 // Lambda[A => Either[A, Int]] case.
327338 case AppliedTypeTree (Ident (TypeLambda1 ), AppliedTypeTree (target, a :: as) :: Nil ) =>
0 commit comments