@@ -5,28 +5,22 @@ import dotty.tools.dotc.ast.Trees.SeqLiteral
5
5
import dotty .tools .dotc .ast .tpd ._
6
6
import dotty .tools .dotc .core .Annotations .Annotation
7
7
import dotty .tools .dotc .core .Contexts .Context
8
+ import dotty .tools .dotc .core .Decorators .StringDecorator
9
+ import dotty .tools .dotc .core .DenotTransformers .InfoTransformer
10
+ import dotty .tools .dotc .core .Names .TermName
11
+ import dotty .tools .dotc .core .Symbols .Symbol
8
12
import dotty .tools .dotc .core .{Symbols , Flags }
9
13
import dotty .tools .dotc .core .Types ._
10
14
import dotty .tools .dotc .transform .TreeTransforms .{TransformerInfo , MiniPhaseTransform }
11
- import dotty .tools .dotc .core .Decorators ._
12
15
import scala .collection .mutable
13
16
14
- class TypeSpecializer extends MiniPhaseTransform {
17
+ class TypeSpecializer extends MiniPhaseTransform with InfoTransformer {
15
18
16
19
override def phaseName = " specialize"
17
20
18
21
final val maxTparamsToSpecialize = 2
19
22
20
- private val specializationRequests : mutable.HashMap [Symbols .Symbol , List [List [Type ]]] = mutable.HashMap .empty
21
-
22
- def registerSpecializationRequest (method : Symbols .Symbol )(arguments : List [Type ])(implicit ctx : Context ) = {
23
- if (ctx.phaseId > this .treeTransformPhase.id)
24
- assert(ctx.phaseId <= this .treeTransformPhase.id)
25
- val prev = specializationRequests.getOrElse(method, List .empty)
26
- specializationRequests.put(method, arguments :: prev)
27
- }
28
-
29
- private final def name2SpecialisedType (implicit ctx : Context ) =
23
+ private final def nameToSpecialisedType (implicit ctx : Context ) =
30
24
Map (" Byte" -> ctx.definitions.ByteType ,
31
25
" Boolean" -> ctx.definitions.BooleanType ,
32
26
" Short" -> ctx.definitions.ShortType ,
@@ -37,19 +31,71 @@ class TypeSpecializer extends MiniPhaseTransform {
37
31
" Char" -> ctx.definitions.CharType ,
38
32
" Unit" -> ctx.definitions.UnitType )
39
33
40
- private final def specialisedType2Suffix (implicit ctx : Context ) =
34
+ private final def specialisedTypeToSuffix (implicit ctx : Context ) =
41
35
Map (ctx.definitions.ByteType -> " $mcB$sp" ,
42
- ctx.definitions.BooleanType -> " $mcZ$sp" ,
43
- ctx.definitions.ShortType -> " $mcS$sp" ,
44
- ctx.definitions.IntType -> " $mcI$sp" ,
45
- ctx.definitions.LongType -> " $mcJ$sp" ,
46
- ctx.definitions.FloatType -> " $mcF$sp" ,
47
- ctx.definitions.DoubleType -> " $mcD$sp" ,
48
- ctx.definitions.CharType -> " $mcC$sp" ,
49
- ctx.definitions.UnitType -> " $mcV$sp" )
36
+ ctx.definitions.BooleanType -> " $mcZ$sp" ,
37
+ ctx.definitions.ShortType -> " $mcS$sp" ,
38
+ ctx.definitions.IntType -> " $mcI$sp" ,
39
+ ctx.definitions.LongType -> " $mcJ$sp" ,
40
+ ctx.definitions.FloatType -> " $mcF$sp" ,
41
+ ctx.definitions.DoubleType -> " $mcD$sp" ,
42
+ ctx.definitions.CharType -> " $mcC$sp" ,
43
+ ctx.definitions.UnitType -> " $mcV$sp" )
44
+
45
+ private val specializationRequests : mutable.HashMap [Symbols .Symbol , List [List [Type ]]] = mutable.HashMap .empty
46
+
47
+ private val newSymbolMap : mutable.HashMap [TermName , (List [Symbols .TermSymbol ], List [Type ])] = mutable.HashMap .empty // Why does the typechecker require TermSymbol ?
48
+
49
+ override def transformInfo (tp : Type , sym : Symbol )(implicit ctx : Context ): Type = {
50
+
51
+ tp.widen match {
52
+ case poly : PolyType if ! (sym.isPrimaryConstructor
53
+ || (sym is Flags .Label )) =>
54
+
55
+ def generateSpecializations (remainingTParams : List [Type ], remainingBounds : List [TypeBounds ])
56
+ (instantiations : List [Type ], names : List [String ])(implicit ctx : Context ): Unit = {
57
+ if (remainingTParams.nonEmpty) {
58
+ val typeToSpecialize = remainingTParams.head
59
+ val bounds = remainingBounds.head
60
+ val a = shouldSpecializeFor(typeToSpecialize.typeSymbol) // TODO returns Nil because no annotations are found - elucidate
61
+ a.flatten
62
+ .filter { tpe =>
63
+ bounds.contains(tpe)
64
+ }.foreach({ tpe =>
65
+ val nme = specialisedTypeToSuffix(ctx)(tpe)
66
+ generateSpecializations(remainingTParams.tail, remainingBounds.tail)(tpe :: instantiations, nme :: names)
67
+ })
68
+ }
69
+ else {
70
+ generateSpecializedSymbols(instantiations.reverse, names.reverse)
71
+ }
72
+ }
73
+
74
+ def generateSpecializedSymbols (instantiations : List [Type ], names : List [String ])(implicit ctx : Context ): Unit = {
75
+ val newSym = ctx.newSymbol(sym.owner, (sym.name + names.mkString).toTermName, sym.flags | Flags .Synthetic , poly.instantiate(instantiations.toList))
76
+ ctx.enter(newSym) // TODO check frozen flag ?
77
+ val prev = newSymbolMap.getOrElse(sym.name.toTermName, (Nil , Nil ))
78
+ val newSyms = newSym :: prev._1
79
+ newSymbolMap.put(sym.name.toTermName, (newSyms, instantiations)) // Could `.put(...)` bring up (mutability) issues ?
80
+ }
81
+ val origTParams = poly.resType.paramTypess.flatten // Is this really what is needed ?
82
+ val bounds = poly.paramBounds
83
+ generateSpecializations(origTParams, bounds)(List .empty, List .empty)
84
+ tp
85
+ case _ =>
86
+ tp
87
+ }
88
+ }
89
+
90
+ def registerSpecializationRequest (method : Symbols .Symbol )(arguments : List [Type ])(implicit ctx : Context ) = {
91
+ if (ctx.phaseId > this .treeTransformPhase.id)
92
+ assert(ctx.phaseId <= this .treeTransformPhase.id)
93
+ val prev = specializationRequests.getOrElse(method, List .empty)
94
+ specializationRequests.put(method, arguments :: prev)
95
+ }
50
96
51
97
def specializeForAll (sym : Symbols .Symbol )(implicit ctx : Context ): List [List [Type ]] = {
52
- registerSpecializationRequest(sym)(specialisedType2Suffix .keys.toList)
98
+ registerSpecializationRequest(sym)(specialisedTypeToSuffix .keys.toList)
53
99
println(" Specializing for all primitive types" )
54
100
specializationRequests.getOrElse(sym, Nil )
55
101
}
@@ -66,7 +112,7 @@ class TypeSpecializer extends MiniPhaseTransform {
66
112
annot.arguments match {
67
113
case List (SeqLiteral (types)) =>
68
114
specializeForSome(sym)(types.map(tpeTree =>
69
- name2SpecialisedType (ctx)(tpeTree.tpe.asInstanceOf [TermRef ].name.toString())))
115
+ nameToSpecialisedType (ctx)(tpeTree.tpe.asInstanceOf [TermRef ].name.toString())))
70
116
case List () => specializeForAll(sym)
71
117
}
72
118
case nil =>
@@ -80,46 +126,43 @@ class TypeSpecializer extends MiniPhaseTransform {
80
126
tree.tpe.widen match {
81
127
82
128
case poly : PolyType if ! (tree.symbol.isPrimaryConstructor
83
- || (tree.symbol is Flags .Label )) => {
129
+ || (tree.symbol is Flags .Label )) =>
84
130
val origTParams = tree.tparams.map(_.symbol)
85
131
val origVParams = tree.vparamss.flatten.map(_.symbol)
86
132
println(s " specializing ${tree.symbol} for Tparams: $origTParams" )
87
133
88
- def specialize (instatiations : List [Type ], names : List [String ]): Tree = {
89
- val newSym = ctx.newSymbol(tree.symbol.owner, (tree.name + names.mkString).toTermName, tree.symbol.flags | Flags .Synthetic , poly.instantiate(instatiations.toList))
90
- polyDefDef(newSym, { tparams => vparams => {
91
- assert(tparams.isEmpty)
92
- new TreeTypeMap (
93
- typeMap = _
94
- .substDealias(origTParams, instatiations.toList)
95
- .subst(origVParams, vparams.flatten.map(_.tpe)),
96
- oldOwners = tree.symbol :: Nil ,
97
- newOwners = newSym :: Nil
98
- ).transform(tree.rhs)
134
+ def specialize (instantiations : List [Type ]): List [Tree ] = {
135
+ newSymbolMap(tree.name) match {
136
+ case newSyms : (List [Symbol ], List [Type ]) =>
137
+ newSyms._1.map{newSym =>
138
+ polyDefDef(newSym, { tparams => vparams => {
139
+ assert(tparams.isEmpty)
140
+ new TreeTypeMap (
141
+ typeMap = _
142
+ .substDealias(origTParams, instantiations.toList)
143
+ .subst(origVParams, vparams.flatten.map(_.tpe)),
144
+ oldOwners = tree.symbol :: Nil ,
145
+ newOwners = newSym :: Nil
146
+ ).transform(tree.rhs)
147
+ }
148
+ })}
149
+ case nil =>
150
+ List ()
99
151
}
100
- })
101
152
}
102
153
103
- def generateSpecializations (remainingTParams : List [TypeDef ], remainingBounds : List [TypeBounds ])
104
- (instatiations : List [Type ],
105
- names : List [String ]): Iterable [Tree ] = {
106
- if (remainingTParams.nonEmpty) {
107
- val typeToSpecialize = remainingTParams.head
108
- val bounds = remainingBounds.head
109
- shouldSpecializeFor(typeToSpecialize.symbol)
110
- .flatten
111
- .filter{ tpe =>
112
- bounds.contains(tpe)
113
- }.flatMap { tpe =>
114
- val nme = specialisedType2Suffix(ctx)(tpe)
115
- generateSpecializations(remainingTParams.tail, remainingBounds.tail)(tpe :: instatiations, nme :: names)
116
- }
117
- } else
118
- List (specialize(instatiations.reverse, names.reverse))
119
- }
120
- Thicket (tree :: generateSpecializations(tree.tparams, poly.paramBounds)(List .empty, List .empty).toList)
121
- }
154
+ val specializedMethods : List [Tree ] = (for (inst <- newSymbolMap.keys) yield specialize(newSymbolMap(inst)._2)).flatten.toList
155
+ Thicket (tree :: specializedMethods)
156
+
122
157
case _ => tree
123
158
}
124
159
}
160
+
161
+ def transformTypeOfTree (tree : Tree ): Tree = {
162
+ tree
163
+ }
164
+
165
+ override def transformIdent (tree : Ident )(implicit ctx : Context , info : TransformerInfo ): Tree = transformTypeOfTree(tree)
166
+ override def transformSelect (tree : Select )(implicit ctx : Context , info : TransformerInfo ): Tree = transformTypeOfTree(tree)
167
+
125
168
}
0 commit comments