Skip to content

Commit 96196c9

Browse files
committed
Names and definitions for Lambdas
Adding names and definitions for the Lambda scheme to hk types. Also add HigherKinded flag for HK type parameters and abstract types.
1 parent 51563ae commit 96196c9

File tree

4 files changed

+81
-13
lines changed

4 files changed

+81
-13
lines changed

src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,7 @@ class Definitions {
422422
def functionArity(tp: Type) = tp.dealias.argInfos.length - 1
423423

424424
// ----- Higher kinds machinery ------------------------------------------
425-
425+
// tbr
426426
private var _hkTraits: Set[Symbol] = Set()
427427

428428
/** The set of HigherKindedXYZ traits encountered so far */
@@ -476,6 +476,66 @@ class Definitions {
476476
hkTraitOfArity.getOrElseUpdate(vcs, createTrait)
477477
}
478478

479+
// ----- LambdaXYZ traits ------------------------------------------
480+
481+
private var myLambdaTraits: Set[Symbol] = Set()
482+
483+
/** The set of HigherKindedXYZ traits encountered so far */
484+
def lambdaTraits: Set[Symbol] = myLambdaTraits
485+
486+
private var lambdaTraitForVariances = mutable.Map[List[Int], ClassSymbol]()
487+
488+
/** The HigherKinded trait corresponding to symbols `boundSyms` (which are assumed
489+
* to be the type parameters of a higher-kided type). This is a class symbol that
490+
* would be generated by the following schema.
491+
*
492+
* class LambdaXYZ { type v_1 Arg1; ...; type v_N ArgN; type Apply }
493+
*
494+
* Here:
495+
*
496+
* - XYZ is a string of length N with one letter for each variant of a bound symbols,
497+
* using `P` (positive variance), `N` (negative variance), `I` (invariant).
498+
* - v_i are the variances of the bound symbols (i.e. +, -, or empty).
499+
*/
500+
def lambdaTrait(vcs: List[Int]): ClassSymbol = {
501+
assert(vcs.nonEmpty)
502+
503+
def varianceFlags(v: Int) = v match {
504+
case -1 => Contravariant
505+
case 0 => EmptyFlags
506+
case 1 => Covariant
507+
}
508+
509+
val completer = new LazyType {
510+
def complete(denot: SymDenotation)(implicit ctx: Context): Unit = {
511+
val cls = denot.asClass.classSymbol
512+
val paramDecls = newScope
513+
for (i <- 0 until vcs.length)
514+
newTypeParam(cls, tpnme.lambdaArgName(i), varianceFlags(vcs(i)), paramDecls)
515+
newTypeParam(cls, tpnme.Apply, EmptyFlags, paramDecls)
516+
val parentTraitRefs =
517+
for (i <- 0 until vcs.length if vcs(i) != 0)
518+
yield lambdaTrait(vcs.updated(i, 0)).typeRef
519+
denot.info = ClassInfo(
520+
ScalaPackageClass.thisType, cls, ObjectClass.typeRef :: parentTraitRefs.toList, paramDecls)
521+
}
522+
}
523+
524+
val traitName = tpnme.lambdaTraitName(vcs)
525+
526+
def createTrait = {
527+
val cls = newClassSymbol(
528+
ScalaPackageClass,
529+
traitName,
530+
Trait | Interface | Synthetic,
531+
completer)
532+
myLambdaTraits += cls
533+
cls
534+
}
535+
536+
lambdaTraitForVariances.getOrElseUpdate(vcs, createTrait)
537+
}
538+
479539
// ----- primitive value class machinery ------------------------------------------
480540

481541
lazy val ScalaNumericValueClasses: collection.Set[Symbol] = Set(

src/dotty/tools/dotc/core/Flags.scala

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -198,8 +198,9 @@ object Flags {
198198
final val Final = commonFlag(6, "final")
199199

200200
/** A method symbol. */
201-
final val MethodCommon = commonFlag(7, "<method>")
202-
final val Method = MethodCommon.toTermFlags
201+
final val MethodOrHKCommon = commonFlag(7, "<method>")
202+
final val Method = MethodOrHKCommon.toTermFlags
203+
final val HigherKinded = MethodOrHKCommon.toTypeFlags
203204

204205
/** A (term or type) parameter to a class or method */
205206
final val Param = commonFlag(8, "<param>")
@@ -411,7 +412,7 @@ object Flags {
411412

412413
/** Flags guaranteed to be set upon symbol creation */
413414
final val FromStartFlags =
414-
AccessFlags | Module | Package | Deferred | MethodCommon | Param | Scala2ExistentialCommon | Touched |
415+
AccessFlags | Module | Package | Deferred | MethodOrHKCommon | Param | Scala2ExistentialCommon | Touched |
415416
Static | CovariantCommon | ContravariantCommon | ExpandedName | AccessorOrSealed |
416417
CaseAccessorOrTypeArgument | Frozen | Erroneous | ImplicitCommon | Permanent | SelfNameOrImplClass
417418

src/dotty/tools/dotc/core/NameOps.scala

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,15 @@ object NameOps {
8787
name.last == '=' && name.head != '=' && isOperatorPart(name.head)
8888
}
8989

90-
/** Is this the name of a higher-kinded type parameter? */
91-
def isHkParamName: Boolean = name(0) == '_' && name.startsWith(HK_PARAM_PREFIX)
90+
/** Is this the name of a higher-kinded type parameter of a Lambda? */
91+
def isLambdaArgName = name.startsWith(tpnme.LAMBDA_ARG_PREFIX)
92+
def isHkParamName: Boolean = name(0) == '_' && name.startsWith(HK_PARAM_PREFIX) // tbr
9293

9394
/** The index of the higher-kinded type parameter with this name.
94-
* Pre: isHkParamName.
95+
* Pre: isLambdaArgName.
9596
*/
96-
def hkParamIndex: Int = name.drop(name.lastIndexOf('$') + 1).toString.toInt
97+
def lambdaArgIndex: Int = name.drop(name.lastIndexOf('$') + 1).toString.toInt
98+
def hkParamIndex: Int = name.drop(name.lastIndexOf('$') + 1).toString.toInt // tbr
9799

98100
/** If the name ends with $nn where nn are
99101
* all digits, strip the $ and the digits.
@@ -181,7 +183,7 @@ object NameOps {
181183
* by this name.
182184
* @pre The name is a higher-kinded trait name, i.e. it starts with HK_TRAIT_PREFIX
183185
*/
184-
def hkVariances: List[Int] = {
186+
def hkVariances: List[Int] = { // tbr
185187
def varianceOfSuffix(suffix: Char): Int = {
186188
val idx = tpnme.varianceSuffixes.indexOf(suffix)
187189
assert(idx >= 0)

src/dotty/tools/dotc/core/StdNames.scala

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ object StdNames {
166166
final val WILDCARD_STAR: N = "_*"
167167
final val REIFY_TREECREATOR_PREFIX: N = "$treecreator"
168168
final val REIFY_TYPECREATOR_PREFIX: N = "$typecreator"
169+
final val LAMBDA_ARG_PREFIX: N = "$hkArg$"
169170

170171
final val Any: N = "Any"
171172
final val AnyVal: N = "AnyVal"
@@ -249,8 +250,8 @@ object StdNames {
249250
val SKOLEM: N = "<skolem>"
250251
val SPECIALIZED_INSTANCE: N = "specInstance$"
251252
val THIS: N = "_$this"
252-
val HK_PARAM_PREFIX: N = "_$hk$"
253-
val HK_TRAIT_PREFIX: N = "$HigherKinded$"
253+
val HK_PARAM_PREFIX: N = "_$hk$" // tbr
254+
val HK_TRAIT_PREFIX: N = "$HigherKinded$" // tbr
254255

255256
final val Nil: N = "Nil"
256257
final val Predef: N = "Predef"
@@ -286,6 +287,7 @@ object StdNames {
286287
val Flag : N = "Flag"
287288
val Ident: N = "Ident"
288289
val Import: N = "Import"
290+
val LambdaPrefix: N = "Lambda$"
289291
val Literal: N = "Literal"
290292
val LiteralAnnotArg: N = "LiteralAnnotArg"
291293
val Modifiers: N = "Modifiers"
@@ -645,8 +647,11 @@ object StdNames {
645647
def syntheticTypeParamNames(num: Int): List[TypeName] =
646648
(0 until num).map(syntheticTypeParamName)(breakOut)
647649

648-
def higherKindedTraitName(vcs: List[Int]): TypeName = HK_TRAIT_PREFIX ++ vcs.map(varianceSuffix).mkString
649-
def higherKindedParamName(n: Int) = HK_PARAM_PREFIX ++ n.toString
650+
def higherKindedTraitName(vcs: List[Int]): TypeName = HK_TRAIT_PREFIX ++ vcs.map(varianceSuffix).mkString // tbr
651+
def higherKindedParamName(n: Int) = HK_PARAM_PREFIX ++ n.toString //tbr
652+
653+
def lambdaTraitName(vcs: List[Int]): TypeName = LambdaPrefix ++ vcs.map(varianceSuffix).mkString
654+
def lambdaArgName(n: Int) = LAMBDA_ARG_PREFIX ++ n.toString
650655

651656
final val Conforms = encode("<:<")
652657

0 commit comments

Comments
 (0)