From 96196c9ffa9939acd7437103d1621dac96e9abc6 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 12 Jun 2014 14:50:05 +0200 Subject: 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. --- src/dotty/tools/dotc/core/Definitions.scala | 62 ++++++++++++++++++++++++++++- src/dotty/tools/dotc/core/Flags.scala | 7 ++-- src/dotty/tools/dotc/core/NameOps.scala | 12 +++--- src/dotty/tools/dotc/core/StdNames.scala | 13 ++++-- 4 files changed, 81 insertions(+), 13 deletions(-) (limited to 'src/dotty') diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala index 6f34efc8b..3f567d87a 100644 --- a/src/dotty/tools/dotc/core/Definitions.scala +++ b/src/dotty/tools/dotc/core/Definitions.scala @@ -422,7 +422,7 @@ class Definitions { def functionArity(tp: Type) = tp.dealias.argInfos.length - 1 // ----- Higher kinds machinery ------------------------------------------ - + // tbr private var _hkTraits: Set[Symbol] = Set() /** The set of HigherKindedXYZ traits encountered so far */ @@ -476,6 +476,66 @@ class Definitions { hkTraitOfArity.getOrElseUpdate(vcs, createTrait) } + // ----- LambdaXYZ traits ------------------------------------------ + + private var myLambdaTraits: Set[Symbol] = Set() + + /** The set of HigherKindedXYZ traits encountered so far */ + def lambdaTraits: Set[Symbol] = myLambdaTraits + + private var lambdaTraitForVariances = mutable.Map[List[Int], ClassSymbol]() + + /** The HigherKinded trait corresponding to symbols `boundSyms` (which are assumed + * to be the type parameters of a higher-kided type). This is a class symbol that + * would be generated by the following schema. + * + * class LambdaXYZ { type v_1 Arg1; ...; type v_N ArgN; type Apply } + * + * Here: + * + * - XYZ is a string of length N with one letter for each variant of a bound symbols, + * using `P` (positive variance), `N` (negative variance), `I` (invariant). + * - v_i are the variances of the bound symbols (i.e. +, -, or empty). + */ + def lambdaTrait(vcs: List[Int]): ClassSymbol = { + assert(vcs.nonEmpty) + + def varianceFlags(v: Int) = v match { + case -1 => Contravariant + case 0 => EmptyFlags + case 1 => Covariant + } + + val completer = new LazyType { + def complete(denot: SymDenotation)(implicit ctx: Context): Unit = { + val cls = denot.asClass.classSymbol + val paramDecls = newScope + for (i <- 0 until vcs.length) + newTypeParam(cls, tpnme.lambdaArgName(i), varianceFlags(vcs(i)), paramDecls) + newTypeParam(cls, tpnme.Apply, EmptyFlags, paramDecls) + val parentTraitRefs = + for (i <- 0 until vcs.length if vcs(i) != 0) + yield lambdaTrait(vcs.updated(i, 0)).typeRef + denot.info = ClassInfo( + ScalaPackageClass.thisType, cls, ObjectClass.typeRef :: parentTraitRefs.toList, paramDecls) + } + } + + val traitName = tpnme.lambdaTraitName(vcs) + + def createTrait = { + val cls = newClassSymbol( + ScalaPackageClass, + traitName, + Trait | Interface | Synthetic, + completer) + myLambdaTraits += cls + cls + } + + lambdaTraitForVariances.getOrElseUpdate(vcs, createTrait) + } + // ----- primitive value class machinery ------------------------------------------ lazy val ScalaNumericValueClasses: collection.Set[Symbol] = Set( diff --git a/src/dotty/tools/dotc/core/Flags.scala b/src/dotty/tools/dotc/core/Flags.scala index 9f87120f8..40da7525d 100644 --- a/src/dotty/tools/dotc/core/Flags.scala +++ b/src/dotty/tools/dotc/core/Flags.scala @@ -198,8 +198,9 @@ object Flags { final val Final = commonFlag(6, "final") /** A method symbol. */ - final val MethodCommon = commonFlag(7, "") - final val Method = MethodCommon.toTermFlags + final val MethodOrHKCommon = commonFlag(7, "") + final val Method = MethodOrHKCommon.toTermFlags + final val HigherKinded = MethodOrHKCommon.toTypeFlags /** A (term or type) parameter to a class or method */ final val Param = commonFlag(8, "") @@ -411,7 +412,7 @@ object Flags { /** Flags guaranteed to be set upon symbol creation */ final val FromStartFlags = - AccessFlags | Module | Package | Deferred | MethodCommon | Param | Scala2ExistentialCommon | Touched | + AccessFlags | Module | Package | Deferred | MethodOrHKCommon | Param | Scala2ExistentialCommon | Touched | Static | CovariantCommon | ContravariantCommon | ExpandedName | AccessorOrSealed | CaseAccessorOrTypeArgument | Frozen | Erroneous | ImplicitCommon | Permanent | SelfNameOrImplClass diff --git a/src/dotty/tools/dotc/core/NameOps.scala b/src/dotty/tools/dotc/core/NameOps.scala index 22a7e5734..187946590 100644 --- a/src/dotty/tools/dotc/core/NameOps.scala +++ b/src/dotty/tools/dotc/core/NameOps.scala @@ -87,13 +87,15 @@ object NameOps { name.last == '=' && name.head != '=' && isOperatorPart(name.head) } - /** Is this the name of a higher-kinded type parameter? */ - def isHkParamName: Boolean = name(0) == '_' && name.startsWith(HK_PARAM_PREFIX) + /** Is this the name of a higher-kinded type parameter of a Lambda? */ + def isLambdaArgName = name.startsWith(tpnme.LAMBDA_ARG_PREFIX) + def isHkParamName: Boolean = name(0) == '_' && name.startsWith(HK_PARAM_PREFIX) // tbr /** The index of the higher-kinded type parameter with this name. - * Pre: isHkParamName. + * Pre: isLambdaArgName. */ - def hkParamIndex: Int = name.drop(name.lastIndexOf('$') + 1).toString.toInt + def lambdaArgIndex: Int = name.drop(name.lastIndexOf('$') + 1).toString.toInt + def hkParamIndex: Int = name.drop(name.lastIndexOf('$') + 1).toString.toInt // tbr /** If the name ends with $nn where nn are * all digits, strip the $ and the digits. @@ -181,7 +183,7 @@ object NameOps { * by this name. * @pre The name is a higher-kinded trait name, i.e. it starts with HK_TRAIT_PREFIX */ - def hkVariances: List[Int] = { + def hkVariances: List[Int] = { // tbr def varianceOfSuffix(suffix: Char): Int = { val idx = tpnme.varianceSuffixes.indexOf(suffix) assert(idx >= 0) diff --git a/src/dotty/tools/dotc/core/StdNames.scala b/src/dotty/tools/dotc/core/StdNames.scala index 593feb909..3b1cb63f1 100644 --- a/src/dotty/tools/dotc/core/StdNames.scala +++ b/src/dotty/tools/dotc/core/StdNames.scala @@ -166,6 +166,7 @@ object StdNames { final val WILDCARD_STAR: N = "_*" final val REIFY_TREECREATOR_PREFIX: N = "$treecreator" final val REIFY_TYPECREATOR_PREFIX: N = "$typecreator" + final val LAMBDA_ARG_PREFIX: N = "$hkArg$" final val Any: N = "Any" final val AnyVal: N = "AnyVal" @@ -249,8 +250,8 @@ object StdNames { val SKOLEM: N = "" val SPECIALIZED_INSTANCE: N = "specInstance$" val THIS: N = "_$this" - val HK_PARAM_PREFIX: N = "_$hk$" - val HK_TRAIT_PREFIX: N = "$HigherKinded$" + val HK_PARAM_PREFIX: N = "_$hk$" // tbr + val HK_TRAIT_PREFIX: N = "$HigherKinded$" // tbr final val Nil: N = "Nil" final val Predef: N = "Predef" @@ -286,6 +287,7 @@ object StdNames { val Flag : N = "Flag" val Ident: N = "Ident" val Import: N = "Import" + val LambdaPrefix: N = "Lambda$" val Literal: N = "Literal" val LiteralAnnotArg: N = "LiteralAnnotArg" val Modifiers: N = "Modifiers" @@ -645,8 +647,11 @@ object StdNames { def syntheticTypeParamNames(num: Int): List[TypeName] = (0 until num).map(syntheticTypeParamName)(breakOut) - def higherKindedTraitName(vcs: List[Int]): TypeName = HK_TRAIT_PREFIX ++ vcs.map(varianceSuffix).mkString - def higherKindedParamName(n: Int) = HK_PARAM_PREFIX ++ n.toString + def higherKindedTraitName(vcs: List[Int]): TypeName = HK_TRAIT_PREFIX ++ vcs.map(varianceSuffix).mkString // tbr + def higherKindedParamName(n: Int) = HK_PARAM_PREFIX ++ n.toString //tbr + + def lambdaTraitName(vcs: List[Int]): TypeName = LambdaPrefix ++ vcs.map(varianceSuffix).mkString + def lambdaArgName(n: Int) = LAMBDA_ARG_PREFIX ++ n.toString final val Conforms = encode("<:<") -- cgit v1.2.3