@@ -13,99 +13,133 @@ import dotty.tools.dotc.core.Constants.*
1313
1414class AddReifiedTypes extends MiniPhase with InfoTransformer {
1515 import ast .tpd .*
16+
17+ final val DEBUG = false
1618
1719 override def phaseName : String = " addReifiedTypes"
1820 override def description : String = " add reified type values to methods"
1921
20- override def transformInfo (tp : Type , sym : Symbol )(using Context ): Type = tp match {
21- case pt : PolyType =>
22- pt.derivedLambdaType(
23- pt.paramNames,
24- pt.paramInfos,
25- addReifiedParams(pt.resType, pt.paramNames)
26- )
27- case _ => tp
28- }
22+ override def transformInfo (tp : Type , sym : Symbol )(using Context ): Type =
23+ if (sym.is(Flags .Method )) then {
24+ val res = addReifiedParams(tp)
25+ // println(s"Transforming method info for ${sym.name}, from: ${tp.show} to: ${res.show}")
26+ res
27+ }
28+ else tp
2929
30- def addReifiedParams (tp : Type , typeParamNames : List [Name ])(using Context ): Type = tp match {
30+ def addReifiedParams (tp : Type )(using Context ): Type = tp match {
31+ case pt : PolyType =>
32+ val reifiedParamNames = pt.paramNames.map(name => termName(s " reified_ $name" ))
33+ val reifiedParamTypes = reifiedParamNames.map(_ => defn.ReifiedValueType )
34+ pt.resType match {
35+ case mt : MethodType =>
36+ // println(s"Adding reified params to method pt. method type $mt: ${pt.show}")
37+ val rest = addReifiedParams(mt.resType)
38+ val reifiedList = MethodType (reifiedParamNames, reifiedParamTypes, rest)
39+ pt.derivedLambdaType(
40+ pt.paramNames,
41+ pt.paramInfos,
42+ mt.derivedLambdaType(
43+ mt.paramNames,
44+ mt.paramInfos,
45+ reifiedList
46+ )
47+ )
48+ case other =>
49+ // println(s"Adding reified params to method pt. other $other: ${pt.show}")
50+ val rest = addReifiedParams(other)
51+ val reifiedList = MethodType (reifiedParamNames, reifiedParamTypes, rest)
52+ pt.derivedLambdaType(
53+ pt.paramNames,
54+ pt.paramInfos,
55+ reifiedList
56+ )
57+ }
3158 case mt : MethodType =>
32- val newParamNames = typeParamNames.map(name => termName(s " reified_ $name" ))
33- val newParamTypes = newParamNames.map(_ => defn.ReifiedValueType )
59+ // println(s"Adding reified params to method mt. method type $mt: ${tp.show}")
3460 mt.derivedLambdaType(
35- mt.paramNames ++ newParamNames,
36- mt.paramInfos ++ newParamTypes,
37- mt.resultType
38- )
39- case pt : PolyType =>
40- pt.derivedLambdaType(
41- pt.paramNames,
42- pt.paramInfos,
43- addReifiedParams(pt.resType, typeParamNames)
61+ mt.paramNames,
62+ mt.paramInfos,
63+ addReifiedParams(mt.resType)
4464 )
4565 case _ => tp
4666 }
4767
4868 override def transformDefDef (tree : DefDef )(using Context ): Tree = {
4969 val sym = tree.symbol
50- val typeParams = tree.paramss.collectFirst {
51- case tparams : List [? ] if tparams.nonEmpty && tparams.head.isInstanceOf [TypeDef ] =>
52- tparams.asInstanceOf [List [TypeDef ]]
53- }.getOrElse(Nil )
70+ // if there are no type parameters, no need to add reified params
71+ if (! tree.paramss.exists(_.exists(_.isInstanceOf [TypeDef ]))) return tree
5472
55- if (typeParams.nonEmpty) {
56- val newParamDefs = typeParams.map { tparam =>
57- val paramName = termName(s " reified_ ${tparam.name}" )
58- val paramSym = newSymbol(
59- sym,
60- paramName,
61- Flags .Param ,
62- defn.ReifiedValueType ,
63- ).asTerm
64- ValDef (paramSym)
65- }
66-
67- var added = false
68- val newParamss = tree.paramss.map { clause =>
69- val isTypeClause = clause.nonEmpty && clause.head.isInstanceOf [TypeDef ]
70- if (! isTypeClause && ! added) {
71- added = true
72- val newClause : ParamClause = clause.asInstanceOf [List [ValDef ]] ++ newParamDefs
73- newClause
74- } else {
75- clause
76- }
73+ var newParamss = List .empty[ParamClause ]
74+ var typeParams = List .empty[TypeDef ]
75+ for (clause <- tree.paramss){
76+ clause match {
77+ // def A[U, V](u: U, v: V)
78+ // case [U, V]
79+ case tparams : List [? ] if tparams.nonEmpty && tparams.head.isInstanceOf [TypeDef ] =>
80+ newParamss = newParamss :+ clause.asInstanceOf [ParamClause ]
81+ typeParams = tparams.asInstanceOf [List [TypeDef ]]
82+ case vparams : List [? ] =>
83+ newParamss = newParamss :+ clause.asInstanceOf [ParamClause ]
84+ if (typeParams.nonEmpty) {
85+ println(s " TransformDefDef for tree: ${tree.show} Adding reified value at end for method ${sym.name} with type params: ${typeParams.map(_.name)}" )
86+ newParamss = newParamss :+ createReifiedClause(typeParams, sym)
87+ typeParams = Nil
88+ }
7789 }
78-
79- if (added) cpy.DefDef (tree)(paramss = newParamss)
80- else tree
81- } else tree
90+ }
91+ if (typeParams.nonEmpty) {
92+ println(s " TransformDefDef for tree: ${tree.show} Adding reified value at end for method ${sym.name} with type params: ${typeParams.map(_.name)}" )
93+ newParamss = newParamss :+ createReifiedClause(typeParams, sym)
94+ }
95+ cpy.DefDef (tree)(paramss = newParamss)
96+ }
97+
98+ def createReifiedClause (typeParams : List [TypeDef ], sym : Symbol )(using Context ): ParamClause = {
99+ typeParams.map {
100+ tparam =>
101+ val reifiedName = termName(s " reified_ ${tparam.name}" )
102+ val reifiedSym = newSymbol(sym, reifiedName, Flags .Param , defn.ReifiedValueType )
103+ ValDef (reifiedSym.asTerm)
104+ }
82105 }
83106
84107 override def transformApply (tree : Apply )(using Context ): Tree = {
85- val sym = tree.fun.symbol
86- if (sym.exists && sym.info.isInstanceOf [PolyType ]) {
87- val poly = sym.info.asInstanceOf [PolyType ]
88- val methodType = poly.resultType match {
89- case mt : MethodType => mt
90- case _ => null
91- }
92-
93- if (methodType != null ) {
94- val expectedParams = methodType.paramInfos.length
95- val currentArgs = tree.args.length
96-
97- if (currentArgs < expectedParams) {
98- val reifiedArgs = tree.fun match {
99- case TypeApply (_, targs) =>
100- targs.map(targ => createReifiedValue(targ.tpe))
101- case _ =>
102- poly.paramNames.map(_ => createReifiedValue(defn.ReifiedValueType ))
103- }
104- return cpy.Apply (tree)(tree.fun, tree.args ++ reifiedArgs)
105- }
108+ val fun = tree.fun
109+ val args = tree.args
110+ val funType = fun.tpe.widen
111+ val resType = funType match {
112+ case mt : MethodType =>
113+ println(s " TransformApply tree type: ${tree.tpe.show}, method type: ${mt.resType.show}" )
114+ mt.resType
115+ case _ => tree.tpe
116+ }
117+ if (isReifiedParamMethod(resType)){
118+ val reifiedArgs = collectReifiedArgs(fun)
119+ val innerApply = cpy.Apply (tree)(fun, args).withType(resType)
120+ val outerResType = resType match {
121+ case mt : MethodType => mt.resType
122+ case _ => resType
106123 }
124+ println(s " Transforming Apply: ${tree.show}, fun type: ${funType.show}, res type: ${resType.show}, with reified args: ${reifiedArgs.map(_.show)}" )
125+ Apply (innerApply, reifiedArgs).withType(outerResType)
126+ } else tree
127+ }
128+
129+ def isReifiedParamMethod (tpe : Type )(using Context ): Boolean = tpe match {
130+ case mt : MethodType =>
131+ mt.paramNames.nonEmpty && mt.paramNames.head.toString.startsWith(" reified_" )
132+ case _ => false
133+ }
134+
135+ def collectReifiedArgs (tree : Tree )(using Context ): List [Tree ] = {
136+ tree match {
137+ case ta : TypeApply =>
138+ ta.args.map(arg => createReifiedValue(arg.tpe))
139+ case a : Apply =>
140+ collectReifiedArgs(a.fun)
141+ case _ => Nil
107142 }
108- tree
109143 }
110144
111145 def createReifiedValue (tpe : Type )(using Context ): Tree = {
0 commit comments