1
+ package dotty .tools .dotc .transform
2
+
3
+ import dotty .tools .dotc .ast .TreeTypeMap
4
+ import dotty .tools .dotc .ast .tpd ._
5
+ import dotty .tools .dotc .core .Contexts .Context
6
+ import dotty .tools .dotc .core .Flags
7
+ import dotty .tools .dotc .core .Types ._
8
+ import dotty .tools .dotc .transform .TreeTransforms .{TransformerInfo , MiniPhaseTransform }
9
+ import dotty .tools .dotc .core .Decorators ._
10
+ import scala .collection .mutable .{ListBuffer , ArrayBuffer }
11
+
12
+ class TypeSpecializer extends MiniPhaseTransform {
13
+
14
+ override def phaseName = " Type Specializer"
15
+
16
+ final val maxTparamsToSpecialize = 2
17
+
18
+ private final def specialisedTypes (implicit ctx : Context ) =
19
+ Map (ctx.definitions.ByteType -> " $mcB$sp" ,
20
+ ctx.definitions.BooleanType -> " $mcZ$sp" ,
21
+ ctx.definitions.ShortType -> " $mcS$sp" ,
22
+ ctx.definitions.IntType -> " $mcI$sp" ,
23
+ ctx.definitions.LongType -> " $mcJ$sp" ,
24
+ ctx.definitions.FloatType -> " $mcF$sp" ,
25
+ ctx.definitions.DoubleType -> " $mcD$sp" ,
26
+ ctx.definitions.CharType -> " $mcC$sp" ,
27
+ ctx.definitions.UnitType -> " $mcV$sp" )
28
+
29
+ override def transformDefDef (tree : DefDef )(implicit ctx : Context , info : TransformerInfo ): Tree = {
30
+
31
+ def rewireType (tpe : Type ) = tpe match {
32
+ case tpe : TermRef => tpe.widen
33
+ case _ => tpe
34
+ }
35
+
36
+ tree.tpe.widen match {
37
+
38
+ case poly : PolyType if ! (tree.symbol.isPrimaryConstructor
39
+ || (tree.symbol is Flags .Label )
40
+ || (tree.tparams.length > maxTparamsToSpecialize)) => {
41
+ val origTParams = tree.tparams.map(_.symbol)
42
+ val origVParams = tree.vparamss.flatten.map(_.symbol)
43
+ println(s " specializing ${tree.symbol} for Tparams: ${origTParams.length}" )
44
+
45
+ def specialize (instatiations : collection.mutable.ListBuffer [Type ], names : collection.mutable.ArrayBuffer [String ]): Tree = {
46
+
47
+ val newSym = ctx.newSymbol(tree.symbol.owner, (tree.name + names.mkString).toTermName, tree.symbol.flags | Flags .Synthetic , poly.instantiate(instatiations.toList))
48
+ polyDefDef(newSym, { tparams => vparams => {
49
+ assert(tparams.isEmpty)
50
+ new TreeTypeMap (
51
+ typeMap = _
52
+ .substDealias(origTParams, instatiations.toList)
53
+ .subst(origVParams, vparams.flatten.map(_.tpe)),
54
+ oldOwners = tree.symbol :: Nil ,
55
+ newOwners = newSym :: Nil
56
+ ).transform(tree.rhs)
57
+ }
58
+ })
59
+ }
60
+
61
+ def generateSpecializations (remainingTParams : List [TypeDef ])
62
+ (instatiated : ArrayBuffer [TypeDef ], instatiations : ListBuffer [Type ],
63
+ names : ArrayBuffer [String ]): Iterable [Tree ] = {
64
+ if (remainingTParams.nonEmpty) {
65
+ val typeToSpecialize = remainingTParams.head
66
+ specialisedTypes.flatMap { tpnme =>
67
+ val tpe = tpnme._1
68
+ val nme = tpnme._2
69
+ instatiated.+= (typeToSpecialize)
70
+ instatiations.+= (tpe)
71
+ names.+= (nme)
72
+ val r = generateSpecializations(remainingTParams.tail)(instatiated, instatiations, names)
73
+ instatiated.drop(1 )
74
+ instatiations.drop(1 )
75
+ names.drop(1 )
76
+ r
77
+ }
78
+ } else
79
+ List (specialize(instatiations, names))
80
+ }
81
+
82
+
83
+ Thicket (tree :: generateSpecializations(tree.tparams)(ArrayBuffer .empty, ListBuffer .empty, ArrayBuffer .empty).toList)
84
+ }
85
+ case _ => tree
86
+ }
87
+ }
88
+ }
0 commit comments