diff options
author | Felix Mulder <felix.mulder@gmail.com> | 2016-11-02 11:08:28 +0100 |
---|---|---|
committer | Guillaume Martres <smarter@ubuntu.com> | 2016-11-22 01:35:07 +0100 |
commit | 8a61ff432543a29234193cd1f7c14abd3f3d31a0 (patch) | |
tree | a8147561d307af862c295cfc8100d271063bb0dd /compiler/src/dotty/tools/dotc/core/Definitions.scala | |
parent | 6a455fe6da5ff9c741d91279a2dc6fe2fb1b472f (diff) | |
download | dotty-8a61ff432543a29234193cd1f7c14abd3f3d31a0.tar.gz dotty-8a61ff432543a29234193cd1f7c14abd3f3d31a0.tar.bz2 dotty-8a61ff432543a29234193cd1f7c14abd3f3d31a0.zip |
Move compiler and compiler tests to compiler dir
Diffstat (limited to 'compiler/src/dotty/tools/dotc/core/Definitions.scala')
-rw-r--r-- | compiler/src/dotty/tools/dotc/core/Definitions.scala | 807 |
1 files changed, 807 insertions, 0 deletions
diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala new file mode 100644 index 000000000..4b090d9b1 --- /dev/null +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -0,0 +1,807 @@ +package dotty.tools +package dotc +package core + +import Types._, Contexts._, Symbols._, Denotations._, SymDenotations._, StdNames._, Names._ +import Flags._, Scopes._, Decorators._, NameOps._, util.Positions._, Periods._ +import unpickleScala2.Scala2Unpickler.ensureConstructor +import scala.annotation.{ switch, meta } +import scala.collection.{ mutable, immutable } +import PartialFunction._ +import collection.mutable +import scala.reflect.api.{ Universe => ApiUniverse } + +object Definitions { + val MaxTupleArity, MaxAbstractFunctionArity = 22 + val MaxFunctionArity = 30 + // Awaiting a definite solution that drops the limit altogether, 30 gives a safety + // margin over the previous 22, so that treecopiers in miniphases are allowed to + // temporarily create larger closures. This is needed in lambda lift where large closures + // are first formed by treecopiers before they are split apart into parameters and + // environment in the lambdalift transform itself. +} + +/** A class defining symbols and types of standard definitions + * + * Note: There's a much nicer design possible once we have implicit functions. + * The idea is explored to some degree in branch wip-definitions (#929): Instead of a type + * and a separate symbol definition, we produce in one line an implicit function from + * Context to Symbol, and possibly also the corresponding type. This cuts down on all + * the duplication encountered here. + * + * wip-definitions tries to do the same with an implicit conversion from a SymbolPerRun + * type to a symbol type. The problem with that is universal equality. Comparisons will + * not trigger the conversion and will therefore likely return false results. + * + * So the branch is put on hold, until we have implicit functions, which will always + * automatically be dereferenced. + */ +class Definitions { + import Definitions._ + + private implicit var ctx: Context = _ + + private def newSymbol[N <: Name](owner: Symbol, name: N, flags: FlagSet, info: Type) = + ctx.newSymbol(owner, name, flags | Permanent, info) + + private def newClassSymbol(owner: Symbol, name: TypeName, flags: FlagSet, infoFn: ClassSymbol => Type) = + ctx.newClassSymbol(owner, name, flags | Permanent, infoFn).entered + + private def newCompleteClassSymbol(owner: Symbol, name: TypeName, flags: FlagSet, parents: List[TypeRef], decls: Scope = newScope) = + ctx.newCompleteClassSymbol(owner, name, flags | Permanent, parents, decls).entered + + private def newTopClassSymbol(name: TypeName, flags: FlagSet, parents: List[TypeRef]) = + completeClass(newCompleteClassSymbol(ScalaPackageClass, name, flags, parents)) + + private def newTypeField(cls: ClassSymbol, name: TypeName, flags: FlagSet, scope: MutableScope) = + scope.enter(newSymbol(cls, name, flags, TypeBounds.empty)) + + private def newTypeParam(cls: ClassSymbol, name: TypeName, flags: FlagSet, scope: MutableScope) = + newTypeField(cls, name, flags | ClassTypeParamCreationFlags, scope) + + private def newSyntheticTypeParam(cls: ClassSymbol, scope: MutableScope, paramFlags: FlagSet, suffix: String = "T0") = + newTypeParam(cls, suffix.toTypeName.expandedName(cls), ExpandedName | paramFlags, scope) + + // NOTE: Ideally we would write `parentConstrs: => Type*` but SIP-24 is only + // implemented in Dotty and not in Scala 2. + // See <http://docs.scala-lang.org/sips/pending/repeated-byname.html>. + private def specialPolyClass(name: TypeName, paramFlags: FlagSet, parentConstrs: => Seq[Type]): ClassSymbol = { + val completer = new LazyType { + def complete(denot: SymDenotation)(implicit ctx: Context): Unit = { + val cls = denot.asClass.classSymbol + val paramDecls = newScope + val typeParam = newSyntheticTypeParam(cls, paramDecls, paramFlags) + def instantiate(tpe: Type) = + if (tpe.typeParams.nonEmpty) tpe.appliedTo(typeParam.typeRef) + else tpe + val parents = parentConstrs.toList map instantiate + val parentRefs: List[TypeRef] = ctx.normalizeToClassRefs(parents, cls, paramDecls) + denot.info = ClassInfo(ScalaPackageClass.thisType, cls, parentRefs, paramDecls) + } + } + newClassSymbol(ScalaPackageClass, name, EmptyFlags, completer) + } + + private def newMethod(cls: ClassSymbol, name: TermName, info: Type, flags: FlagSet = EmptyFlags): TermSymbol = + newSymbol(cls, name.encode, flags | Method, info).entered.asTerm + + private def newAliasType(name: TypeName, tpe: Type, flags: FlagSet = EmptyFlags): TypeSymbol = { + val sym = newSymbol(ScalaPackageClass, name, flags, TypeAlias(tpe)) + ScalaPackageClass.currentPackageDecls.enter(sym) + sym + } + + private def newPolyMethod(cls: ClassSymbol, name: TermName, typeParamCount: Int, + resultTypeFn: PolyType => Type, flags: FlagSet = EmptyFlags) = { + val tparamNames = tpnme.syntheticTypeParamNames(typeParamCount) + val tparamBounds = tparamNames map (_ => TypeBounds.empty) + val ptype = PolyType(tparamNames)(_ => tparamBounds, resultTypeFn) + newMethod(cls, name, ptype, flags) + } + + private def newT1ParameterlessMethod(cls: ClassSymbol, name: TermName, resultTypeFn: PolyType => Type, flags: FlagSet) = + newPolyMethod(cls, name, 1, resultTypeFn, flags) + + private def newT1EmptyParamsMethod(cls: ClassSymbol, name: TermName, resultTypeFn: PolyType => Type, flags: FlagSet) = + newPolyMethod(cls, name, 1, pt => MethodType(Nil, resultTypeFn(pt)), flags) + + private def mkArityArray(name: String, arity: Int, countFrom: Int): Array[TypeRef] = { + val arr = new Array[TypeRef](arity + 1) + for (i <- countFrom to arity) arr(i) = ctx.requiredClassRef(name + i) + arr + } + + private def completeClass(cls: ClassSymbol): ClassSymbol = { + ensureConstructor(cls, EmptyScope) + if (cls.linkedClass.exists) cls.linkedClass.info = NoType + cls + } + + lazy val RootClass: ClassSymbol = ctx.newPackageSymbol( + NoSymbol, nme.ROOT, (root, rootcls) => ctx.rootLoader(root)).moduleClass.asClass + lazy val RootPackage: TermSymbol = ctx.newSymbol( + NoSymbol, nme.ROOTPKG, PackageCreationFlags, TypeRef(NoPrefix, RootClass)) + + lazy val EmptyPackageVal = ctx.newPackageSymbol( + RootClass, nme.EMPTY_PACKAGE, (emptypkg, emptycls) => ctx.rootLoader(emptypkg)).entered + lazy val EmptyPackageClass = EmptyPackageVal.moduleClass.asClass + + /** A package in which we can place all methods that are interpreted specially by the compiler */ + lazy val OpsPackageVal = ctx.newCompletePackageSymbol(RootClass, nme.OPS_PACKAGE).entered + lazy val OpsPackageClass = OpsPackageVal.moduleClass.asClass + + lazy val ScalaPackageVal = ctx.requiredPackage("scala") + lazy val ScalaMathPackageVal = ctx.requiredPackage("scala.math") + lazy val ScalaPackageClass = ScalaPackageVal.moduleClass.asClass + lazy val JavaPackageVal = ctx.requiredPackage("java") + lazy val JavaLangPackageVal = ctx.requiredPackage("java.lang") + // fundamental modules + lazy val SysPackage = ctx.requiredModule("scala.sys.package") + lazy val Sys_errorR = SysPackage.moduleClass.requiredMethodRef(nme.error) + def Sys_error(implicit ctx: Context) = Sys_errorR.symbol + + /** The `scalaShadowing` package is used to safely modify classes and + * objects in scala so that they can be used from dotty. They will + * be visible as members of the `scala` package, replacing any objects + * or classes with the same name. But their binary artifacts are + * in `scalaShadowing` so they don't clash with the same-named `scala` + * members at runtime. + */ + lazy val ScalaShadowingPackageVal = ctx.requiredPackage("scalaShadowing") + lazy val ScalaShadowingPackageClass = ScalaShadowingPackageVal.moduleClass.asClass + + /** Note: We cannot have same named methods defined in Object and Any (and AnyVal, for that matter) + * because after erasure the Any and AnyVal references get remapped to the Object methods + * which would result in a double binding assertion failure. + * Instead we do the following: + * + * - Have some methods exist only in Any, and remap them with the Erasure denotation + * transformer to be owned by Object. + * - Have other methods exist only in Object. + * To achieve this, we synthesize all Any and Object methods; Object methods no longer get + * loaded from a classfile. + * + * There's a remaining question about `getClass`. In Scala2.x `getClass` was handled by compiler magic. + * This is deemed too cumersome for Dotty and therefore right now `getClass` gets no special treatment; + * it's just a method on `Any` which returns the raw type `java.lang.Class`. An alternative + * way to get better `getClass` typing would be to treat `getClass` as a method of a generic + * decorator which gets remapped in a later phase to Object#getClass. Then we could give it + * the right type without changing the typechecker: + * + * implicit class AnyGetClass[T](val x: T) extends AnyVal { + * def getClass: java.lang.Class[T] = ??? + * } + */ + lazy val AnyClass: ClassSymbol = completeClass(newCompleteClassSymbol(ScalaPackageClass, tpnme.Any, Abstract, Nil)) + def AnyType = AnyClass.typeRef + lazy val AnyValClass: ClassSymbol = completeClass(newCompleteClassSymbol(ScalaPackageClass, tpnme.AnyVal, Abstract, List(AnyClass.typeRef))) + def AnyValType = AnyValClass.typeRef + + lazy val Any_== = newMethod(AnyClass, nme.EQ, methOfAny(BooleanType), Final) + lazy val Any_!= = newMethod(AnyClass, nme.NE, methOfAny(BooleanType), Final) + lazy val Any_equals = newMethod(AnyClass, nme.equals_, methOfAny(BooleanType)) + lazy val Any_hashCode = newMethod(AnyClass, nme.hashCode_, MethodType(Nil, IntType)) + lazy val Any_toString = newMethod(AnyClass, nme.toString_, MethodType(Nil, StringType)) + lazy val Any_## = newMethod(AnyClass, nme.HASHHASH, ExprType(IntType), Final) + lazy val Any_getClass = newMethod(AnyClass, nme.getClass_, MethodType(Nil, ClassClass.typeRef.appliedTo(TypeBounds.empty)), Final) + lazy val Any_isInstanceOf = newT1ParameterlessMethod(AnyClass, nme.isInstanceOf_, _ => BooleanType, Final) + lazy val Any_asInstanceOf = newT1ParameterlessMethod(AnyClass, nme.asInstanceOf_, PolyParam(_, 0), Final) + + def AnyMethods = List(Any_==, Any_!=, Any_equals, Any_hashCode, + Any_toString, Any_##, Any_getClass, Any_isInstanceOf, Any_asInstanceOf) + + lazy val ObjectClass: ClassSymbol = { + val cls = ctx.requiredClass("java.lang.Object") + assert(!cls.isCompleted, "race for completing java.lang.Object") + cls.info = ClassInfo(cls.owner.thisType, cls, AnyClass.typeRef :: Nil, newScope) + + // The companion object doesn't really exist, `NoType` is the general + // technique to do that. Here we need to set it before completing + // attempt to load Object's classfile, which causes issue #1648. + val companion = JavaLangPackageVal.info.decl(nme.Object).symbol + companion.info = NoType // to indicate that it does not really exist + + completeClass(cls) + } + def ObjectType = ObjectClass.typeRef + + lazy val AnyRefAlias: TypeSymbol = newAliasType(tpnme.AnyRef, ObjectType) + def AnyRefType = AnyRefAlias.typeRef + + lazy val Object_eq = newMethod(ObjectClass, nme.eq, methOfAnyRef(BooleanType), Final) + lazy val Object_ne = newMethod(ObjectClass, nme.ne, methOfAnyRef(BooleanType), Final) + lazy val Object_synchronized = newPolyMethod(ObjectClass, nme.synchronized_, 1, + pt => MethodType(List(PolyParam(pt, 0)), PolyParam(pt, 0)), Final) + lazy val Object_clone = newMethod(ObjectClass, nme.clone_, MethodType(Nil, ObjectType), Protected) + lazy val Object_finalize = newMethod(ObjectClass, nme.finalize_, MethodType(Nil, UnitType), Protected) + lazy val Object_notify = newMethod(ObjectClass, nme.notify_, MethodType(Nil, UnitType)) + lazy val Object_notifyAll = newMethod(ObjectClass, nme.notifyAll_, MethodType(Nil, UnitType)) + lazy val Object_wait = newMethod(ObjectClass, nme.wait_, MethodType(Nil, UnitType)) + lazy val Object_waitL = newMethod(ObjectClass, nme.wait_, MethodType(LongType :: Nil, UnitType)) + lazy val Object_waitLI = newMethod(ObjectClass, nme.wait_, MethodType(LongType :: IntType :: Nil, UnitType)) + + def ObjectMethods = List(Object_eq, Object_ne, Object_synchronized, Object_clone, + Object_finalize, Object_notify, Object_notifyAll, Object_wait, Object_waitL, Object_waitLI) + + /** Dummy method needed by elimByName */ + lazy val dummyApply = newPolyMethod( + OpsPackageClass, nme.dummyApply, 1, + pt => MethodType(List(FunctionOf(Nil, PolyParam(pt, 0))), PolyParam(pt, 0))) + + /** Method representing a throw */ + lazy val throwMethod = newMethod(OpsPackageClass, nme.THROWkw, + MethodType(List(ThrowableType), NothingType)) + + lazy val NothingClass: ClassSymbol = newCompleteClassSymbol( + ScalaPackageClass, tpnme.Nothing, AbstractFinal, List(AnyClass.typeRef)) + def NothingType = NothingClass.typeRef + lazy val NullClass: ClassSymbol = newCompleteClassSymbol( + ScalaPackageClass, tpnme.Null, AbstractFinal, List(ObjectClass.typeRef)) + def NullType = NullClass.typeRef + + lazy val ScalaPredefModuleRef = ctx.requiredModuleRef("scala.Predef") + def ScalaPredefModule(implicit ctx: Context) = ScalaPredefModuleRef.symbol + + lazy val Predef_conformsR = ScalaPredefModule.requiredMethodRef("$conforms") + def Predef_conforms(implicit ctx: Context) = Predef_conformsR.symbol + lazy val Predef_classOfR = ScalaPredefModule.requiredMethodRef("classOf") + def Predef_classOf(implicit ctx: Context) = Predef_classOfR.symbol + + lazy val ScalaRuntimeModuleRef = ctx.requiredModuleRef("scala.runtime.ScalaRunTime") + def ScalaRuntimeModule(implicit ctx: Context) = ScalaRuntimeModuleRef.symbol + def ScalaRuntimeClass(implicit ctx: Context) = ScalaRuntimeModule.moduleClass.asClass + + def runtimeMethodRef(name: PreName) = ScalaRuntimeModule.requiredMethodRef(name) + def ScalaRuntime_dropR(implicit ctx: Context) = runtimeMethodRef(nme.drop) + def ScalaRuntime_drop(implicit ctx: Context) = ScalaRuntime_dropR.symbol + + lazy val BoxesRunTimeModuleRef = ctx.requiredModuleRef("scala.runtime.BoxesRunTime") + def BoxesRunTimeModule(implicit ctx: Context) = BoxesRunTimeModuleRef.symbol + def BoxesRunTimeClass(implicit ctx: Context) = BoxesRunTimeModule.moduleClass.asClass + lazy val ScalaStaticsModuleRef = ctx.requiredModuleRef("scala.runtime.Statics") + def ScalaStaticsModule(implicit ctx: Context) = ScalaStaticsModuleRef.symbol + def ScalaStaticsClass(implicit ctx: Context) = ScalaStaticsModule.moduleClass.asClass + + def staticsMethodRef(name: PreName) = ScalaStaticsModule.requiredMethodRef(name) + def staticsMethod(name: PreName) = ScalaStaticsModule.requiredMethod(name) + + lazy val DottyPredefModuleRef = ctx.requiredModuleRef("dotty.DottyPredef") + def DottyPredefModule(implicit ctx: Context) = DottyPredefModuleRef.symbol + + def Predef_eqAny(implicit ctx: Context) = DottyPredefModule.requiredMethod(nme.eqAny) + + lazy val DottyArraysModuleRef = ctx.requiredModuleRef("dotty.runtime.Arrays") + def DottyArraysModule(implicit ctx: Context) = DottyArraysModuleRef.symbol + def newGenericArrayMethod(implicit ctx: Context) = DottyArraysModule.requiredMethod("newGenericArray") + def newArrayMethod(implicit ctx: Context) = DottyArraysModule.requiredMethod("newArray") + + lazy val NilModuleRef = ctx.requiredModuleRef("scala.collection.immutable.Nil") + def NilModule(implicit ctx: Context) = NilModuleRef.symbol + + lazy val SingletonClass: ClassSymbol = + // needed as a synthetic class because Scala 2.x refers to it in classfiles + // but does not define it as an explicit class. + newCompleteClassSymbol( + ScalaPackageClass, tpnme.Singleton, PureInterfaceCreationFlags | Final, + List(AnyClass.typeRef), EmptyScope) + + lazy val SeqType: TypeRef = ctx.requiredClassRef("scala.collection.Seq") + def SeqClass(implicit ctx: Context) = SeqType.symbol.asClass + + lazy val Seq_applyR = SeqClass.requiredMethodRef(nme.apply) + def Seq_apply(implicit ctx: Context) = Seq_applyR.symbol + lazy val Seq_headR = SeqClass.requiredMethodRef(nme.head) + def Seq_head(implicit ctx: Context) = Seq_headR.symbol + + lazy val ArrayType: TypeRef = ctx.requiredClassRef("scala.Array") + def ArrayClass(implicit ctx: Context) = ArrayType.symbol.asClass + lazy val Array_applyR = ArrayClass.requiredMethodRef(nme.apply) + def Array_apply(implicit ctx: Context) = Array_applyR.symbol + lazy val Array_updateR = ArrayClass.requiredMethodRef(nme.update) + def Array_update(implicit ctx: Context) = Array_updateR.symbol + lazy val Array_lengthR = ArrayClass.requiredMethodRef(nme.length) + def Array_length(implicit ctx: Context) = Array_lengthR.symbol + lazy val Array_cloneR = ArrayClass.requiredMethodRef(nme.clone_) + def Array_clone(implicit ctx: Context) = Array_cloneR.symbol + lazy val ArrayConstructorR = ArrayClass.requiredMethodRef(nme.CONSTRUCTOR) + def ArrayConstructor(implicit ctx: Context) = ArrayConstructorR.symbol + lazy val ArrayModuleType = ctx.requiredModuleRef("scala.Array") + def ArrayModule(implicit ctx: Context) = ArrayModuleType.symbol.moduleClass.asClass + + + lazy val UnitType: TypeRef = valueTypeRef("scala.Unit", BoxedUnitType, java.lang.Void.TYPE, UnitEnc) + def UnitClass(implicit ctx: Context) = UnitType.symbol.asClass + lazy val BooleanType = valueTypeRef("scala.Boolean", BoxedBooleanType, java.lang.Boolean.TYPE, BooleanEnc) + def BooleanClass(implicit ctx: Context) = BooleanType.symbol.asClass + lazy val Boolean_notR = BooleanClass.requiredMethodRef(nme.UNARY_!) + def Boolean_! = Boolean_notR.symbol + lazy val Boolean_andR = BooleanClass.requiredMethodRef(nme.ZAND) // ### harmonize required... calls + def Boolean_&& = Boolean_andR.symbol + lazy val Boolean_orR = BooleanClass.requiredMethodRef(nme.ZOR) + def Boolean_|| = Boolean_orR.symbol + + lazy val ByteType: TypeRef = valueTypeRef("scala.Byte", BoxedByteType, java.lang.Byte.TYPE, ByteEnc) + def ByteClass(implicit ctx: Context) = ByteType.symbol.asClass + lazy val ShortType: TypeRef = valueTypeRef("scala.Short", BoxedShortType, java.lang.Short.TYPE, ShortEnc) + def ShortClass(implicit ctx: Context) = ShortType.symbol.asClass + lazy val CharType: TypeRef = valueTypeRef("scala.Char", BoxedCharType, java.lang.Character.TYPE, CharEnc) + def CharClass(implicit ctx: Context) = CharType.symbol.asClass + lazy val IntType: TypeRef = valueTypeRef("scala.Int", BoxedIntType, java.lang.Integer.TYPE, IntEnc) + def IntClass(implicit ctx: Context) = IntType.symbol.asClass + lazy val Int_minusR = IntClass.requiredMethodRef(nme.MINUS, List(IntType)) + def Int_- = Int_minusR.symbol + lazy val Int_plusR = IntClass.requiredMethodRef(nme.PLUS, List(IntType)) + def Int_+ = Int_plusR.symbol + lazy val Int_divR = IntClass.requiredMethodRef(nme.DIV, List(IntType)) + def Int_/ = Int_divR.symbol + lazy val Int_mulR = IntClass.requiredMethodRef(nme.MUL, List(IntType)) + def Int_* = Int_mulR.symbol + lazy val Int_eqR = IntClass.requiredMethodRef(nme.EQ, List(IntType)) + def Int_== = Int_eqR.symbol + lazy val Int_geR = IntClass.requiredMethodRef(nme.GE, List(IntType)) + def Int_>= = Int_geR.symbol + lazy val Int_leR = IntClass.requiredMethodRef(nme.LE, List(IntType)) + def Int_<= = Int_leR.symbol + lazy val LongType: TypeRef = valueTypeRef("scala.Long", BoxedLongType, java.lang.Long.TYPE, LongEnc) + def LongClass(implicit ctx: Context) = LongType.symbol.asClass + lazy val Long_XOR_Long = LongType.member(nme.XOR).requiredSymbol( + x => (x is Method) && (x.info.firstParamTypes.head isRef defn.LongClass) + ) + lazy val Long_LSR_Int = LongType.member(nme.LSR).requiredSymbol( + x => (x is Method) && (x.info.firstParamTypes.head isRef defn.IntClass) + ) + lazy val FloatType: TypeRef = valueTypeRef("scala.Float", BoxedFloatType, java.lang.Float.TYPE, FloatEnc) + def FloatClass(implicit ctx: Context) = FloatType.symbol.asClass + lazy val DoubleType: TypeRef = valueTypeRef("scala.Double", BoxedDoubleType, java.lang.Double.TYPE, DoubleEnc) + def DoubleClass(implicit ctx: Context) = DoubleType.symbol.asClass + + lazy val BoxedUnitType: TypeRef = ctx.requiredClassRef("scala.runtime.BoxedUnit") + def BoxedUnitClass(implicit ctx: Context) = BoxedUnitType.symbol.asClass + + def BoxedUnit_UNIT(implicit ctx: Context) = BoxedUnitClass.linkedClass.requiredValue("UNIT") + + lazy val BoxedBooleanType: TypeRef = ctx.requiredClassRef("java.lang.Boolean") + def BoxedBooleanClass(implicit ctx: Context) = BoxedBooleanType.symbol.asClass + lazy val BoxedByteType: TypeRef = ctx.requiredClassRef("java.lang.Byte") + def BoxedByteClass(implicit ctx: Context) = BoxedByteType.symbol.asClass + lazy val BoxedShortType: TypeRef = ctx.requiredClassRef("java.lang.Short") + def BoxedShortClass(implicit ctx: Context) = BoxedShortType.symbol.asClass + lazy val BoxedCharType: TypeRef = ctx.requiredClassRef("java.lang.Character") + def BoxedCharClass(implicit ctx: Context) = BoxedCharType.symbol.asClass + lazy val BoxedIntType: TypeRef = ctx.requiredClassRef("java.lang.Integer") + def BoxedIntClass(implicit ctx: Context) = BoxedIntType.symbol.asClass + lazy val BoxedLongType: TypeRef = ctx.requiredClassRef("java.lang.Long") + def BoxedLongClass(implicit ctx: Context) = BoxedLongType.symbol.asClass + lazy val BoxedFloatType: TypeRef = ctx.requiredClassRef("java.lang.Float") + def BoxedFloatClass(implicit ctx: Context) = BoxedFloatType.symbol.asClass + lazy val BoxedDoubleType: TypeRef = ctx.requiredClassRef("java.lang.Double") + def BoxedDoubleClass(implicit ctx: Context) = BoxedDoubleType.symbol.asClass + + lazy val BoxedBooleanModule = ctx.requiredModule("java.lang.Boolean") + lazy val BoxedByteModule = ctx.requiredModule("java.lang.Byte") + lazy val BoxedShortModule = ctx.requiredModule("java.lang.Short") + lazy val BoxedCharModule = ctx.requiredModule("java.lang.Character") + lazy val BoxedIntModule = ctx.requiredModule("java.lang.Integer") + lazy val BoxedLongModule = ctx.requiredModule("java.lang.Long") + lazy val BoxedFloatModule = ctx.requiredModule("java.lang.Float") + lazy val BoxedDoubleModule = ctx.requiredModule("java.lang.Double") + lazy val BoxedUnitModule = ctx.requiredModule("java.lang.Void") + + lazy val ByNameParamClass2x = specialPolyClass(tpnme.BYNAME_PARAM_CLASS, Covariant, Seq(AnyType)) + lazy val EqualsPatternClass = specialPolyClass(tpnme.EQUALS_PATTERN, EmptyFlags, Seq(AnyType)) + + lazy val RepeatedParamClass = specialPolyClass(tpnme.REPEATED_PARAM_CLASS, Covariant, Seq(ObjectType, SeqType)) + + // fundamental classes + lazy val StringClass = ctx.requiredClass("java.lang.String") + def StringType: Type = StringClass.typeRef + lazy val StringModule = StringClass.linkedClass + + lazy val String_+ = newMethod(StringClass, nme.raw.PLUS, methOfAny(StringType), Final) + lazy val String_valueOf_Object = StringModule.info.member(nme.valueOf).suchThat(_.info.firstParamTypes match { + case List(pt) => (pt isRef AnyClass) || (pt isRef ObjectClass) + case _ => false + }).symbol + + lazy val JavaCloneableClass = ctx.requiredClass("java.lang.Cloneable") + lazy val NullPointerExceptionClass = ctx.requiredClass("java.lang.NullPointerException") + lazy val ClassClass = ctx.requiredClass("java.lang.Class") + lazy val BoxedNumberClass = ctx.requiredClass("java.lang.Number") + lazy val ThrowableClass = ctx.requiredClass("java.lang.Throwable") + lazy val ClassCastExceptionClass = ctx.requiredClass("java.lang.ClassCastException") + lazy val JavaSerializableClass = ctx.requiredClass("java.lang.Serializable") + lazy val ComparableClass = ctx.requiredClass("java.lang.Comparable") + + // in scalac modified to have Any as parent + + lazy val SerializableType: TypeRef = ctx.requiredClassRef("scala.Serializable") + def SerializableClass(implicit ctx: Context) = SerializableType.symbol.asClass + lazy val StringBuilderType: TypeRef = ctx.requiredClassRef("scala.collection.mutable.StringBuilder") + def StringBuilderClass(implicit ctx: Context) = StringBuilderType.symbol.asClass + lazy val MatchErrorType: TypeRef = ctx.requiredClassRef("scala.MatchError") + def MatchErrorClass(implicit ctx: Context) = MatchErrorType.symbol.asClass + + lazy val StringAddType: TypeRef = ctx.requiredClassRef("scala.runtime.StringAdd") + def StringAddClass(implicit ctx: Context) = StringAddType.symbol.asClass + + lazy val StringAdd_plusR = StringAddClass.requiredMethodRef(nme.raw.PLUS) + def StringAdd_+(implicit ctx: Context) = StringAdd_plusR.symbol + + lazy val PartialFunctionType: TypeRef = ctx.requiredClassRef("scala.PartialFunction") + def PartialFunctionClass(implicit ctx: Context) = PartialFunctionType.symbol.asClass + lazy val AbstractPartialFunctionType: TypeRef = ctx.requiredClassRef("scala.runtime.AbstractPartialFunction") + def AbstractPartialFunctionClass(implicit ctx: Context) = AbstractPartialFunctionType.symbol.asClass + lazy val SymbolType: TypeRef = ctx.requiredClassRef("scala.Symbol") + def SymbolClass(implicit ctx: Context) = SymbolType.symbol.asClass + lazy val DynamicType: TypeRef = ctx.requiredClassRef("scala.Dynamic") + def DynamicClass(implicit ctx: Context) = DynamicType.symbol.asClass + lazy val OptionType: TypeRef = ctx.requiredClassRef("scala.Option") + def OptionClass(implicit ctx: Context) = OptionType.symbol.asClass + lazy val ProductType: TypeRef = ctx.requiredClassRef("scala.Product") + def ProductClass(implicit ctx: Context) = ProductType.symbol.asClass + lazy val Product_canEqualR = ProductClass.requiredMethodRef(nme.canEqual_) + def Product_canEqual(implicit ctx: Context) = Product_canEqualR.symbol + lazy val Product_productArityR = ProductClass.requiredMethodRef(nme.productArity) + def Product_productArity(implicit ctx: Context) = Product_productArityR.symbol + lazy val Product_productPrefixR = ProductClass.requiredMethodRef(nme.productPrefix) + def Product_productPrefix(implicit ctx: Context) = Product_productPrefixR.symbol + lazy val LanguageModuleRef = ctx.requiredModule("scala.language") + def LanguageModuleClass(implicit ctx: Context) = LanguageModuleRef.symbol.moduleClass.asClass + lazy val NonLocalReturnControlType: TypeRef = ctx.requiredClassRef("scala.runtime.NonLocalReturnControl") + + lazy val ClassTagType = ctx.requiredClassRef("scala.reflect.ClassTag") + def ClassTagClass(implicit ctx: Context) = ClassTagType.symbol.asClass + def ClassTagModule(implicit ctx: Context) = ClassTagClass.companionModule + + lazy val EqType = ctx.requiredClassRef("scala.Eq") + def EqClass(implicit ctx: Context) = EqType.symbol.asClass + + // Annotation base classes + lazy val AnnotationType = ctx.requiredClassRef("scala.annotation.Annotation") + def AnnotationClass(implicit ctx: Context) = AnnotationType.symbol.asClass + lazy val ClassfileAnnotationType = ctx.requiredClassRef("scala.annotation.ClassfileAnnotation") + def ClassfileAnnotationClass(implicit ctx: Context) = ClassfileAnnotationType.symbol.asClass + lazy val StaticAnnotationType = ctx.requiredClassRef("scala.annotation.StaticAnnotation") + def StaticAnnotationClass(implicit ctx: Context) = StaticAnnotationType.symbol.asClass + + // Annotation classes + lazy val AliasAnnotType = ctx.requiredClassRef("scala.annotation.internal.Alias") + def AliasAnnot(implicit ctx: Context) = AliasAnnotType.symbol.asClass + lazy val AnnotationDefaultAnnotType = ctx.requiredClassRef("scala.annotation.internal.AnnotationDefault") + def AnnotationDefaultAnnot(implicit ctx: Context) = AnnotationDefaultAnnotType.symbol.asClass + lazy val BodyAnnotType = ctx.requiredClassRef("scala.annotation.internal.Body") + def BodyAnnot(implicit ctx: Context) = BodyAnnotType.symbol.asClass + lazy val ChildAnnotType = ctx.requiredClassRef("scala.annotation.internal.Child") + def ChildAnnot(implicit ctx: Context) = ChildAnnotType.symbol.asClass + lazy val CovariantBetweenAnnotType = ctx.requiredClassRef("scala.annotation.internal.CovariantBetween") + def CovariantBetweenAnnot(implicit ctx: Context) = CovariantBetweenAnnotType.symbol.asClass + lazy val ContravariantBetweenAnnotType = ctx.requiredClassRef("scala.annotation.internal.ContravariantBetween") + def ContravariantBetweenAnnot(implicit ctx: Context) = ContravariantBetweenAnnotType.symbol.asClass + lazy val DeprecatedAnnotType = ctx.requiredClassRef("scala.deprecated") + def DeprecatedAnnot(implicit ctx: Context) = DeprecatedAnnotType.symbol.asClass + lazy val ImplicitNotFoundAnnotType = ctx.requiredClassRef("scala.annotation.implicitNotFound") + def ImplicitNotFoundAnnot(implicit ctx: Context) = ImplicitNotFoundAnnotType.symbol.asClass + lazy val InlineAnnotType = ctx.requiredClassRef("scala.inline") + def InlineAnnot(implicit ctx: Context) = InlineAnnotType.symbol.asClass + lazy val InlineParamAnnotType = ctx.requiredClassRef("scala.annotation.internal.InlineParam") + def InlineParamAnnot(implicit ctx: Context) = InlineParamAnnotType.symbol.asClass + lazy val InvariantBetweenAnnotType = ctx.requiredClassRef("scala.annotation.internal.InvariantBetween") + def InvariantBetweenAnnot(implicit ctx: Context) = InvariantBetweenAnnotType.symbol.asClass + lazy val MigrationAnnotType = ctx.requiredClassRef("scala.annotation.migration") + def MigrationAnnot(implicit ctx: Context) = MigrationAnnotType.symbol.asClass + lazy val NativeAnnotType = ctx.requiredClassRef("scala.native") + def NativeAnnot(implicit ctx: Context) = NativeAnnotType.symbol.asClass + lazy val RemoteAnnotType = ctx.requiredClassRef("scala.remote") + def RemoteAnnot(implicit ctx: Context) = RemoteAnnotType.symbol.asClass + lazy val RepeatedAnnotType = ctx.requiredClassRef("scala.annotation.internal.Repeated") + def RepeatedAnnot(implicit ctx: Context) = RepeatedAnnotType.symbol.asClass + lazy val SourceFileAnnotType = ctx.requiredClassRef("scala.annotation.internal.SourceFile") + def SourceFileAnnot(implicit ctx: Context) = SourceFileAnnotType.symbol.asClass + lazy val ScalaSignatureAnnotType = ctx.requiredClassRef("scala.reflect.ScalaSignature") + def ScalaSignatureAnnot(implicit ctx: Context) = ScalaSignatureAnnotType.symbol.asClass + lazy val ScalaLongSignatureAnnotType = ctx.requiredClassRef("scala.reflect.ScalaLongSignature") + def ScalaLongSignatureAnnot(implicit ctx: Context) = ScalaLongSignatureAnnotType.symbol.asClass + lazy val ScalaStrictFPAnnotType = ctx.requiredClassRef("scala.annotation.strictfp") + def ScalaStrictFPAnnot(implicit ctx: Context) = ScalaStrictFPAnnotType.symbol.asClass + lazy val ScalaStaticAnnotType = ctx.requiredClassRef("scala.annotation.static") + def ScalaStaticAnnot(implicit ctx: Context) = ScalaStaticAnnotType.symbol.asClass + lazy val SerialVersionUIDAnnotType = ctx.requiredClassRef("scala.SerialVersionUID") + def SerialVersionUIDAnnot(implicit ctx: Context) = SerialVersionUIDAnnotType.symbol.asClass + lazy val TASTYSignatureAnnotType = ctx.requiredClassRef("scala.annotation.internal.TASTYSignature") + def TASTYSignatureAnnot(implicit ctx: Context) = TASTYSignatureAnnotType.symbol.asClass + lazy val TASTYLongSignatureAnnotType = ctx.requiredClassRef("scala.annotation.internal.TASTYLongSignature") + def TASTYLongSignatureAnnot(implicit ctx: Context) = TASTYLongSignatureAnnotType.symbol.asClass + lazy val TailrecAnnotType = ctx.requiredClassRef("scala.annotation.tailrec") + def TailrecAnnot(implicit ctx: Context) = TailrecAnnotType.symbol.asClass + lazy val SwitchAnnotType = ctx.requiredClassRef("scala.annotation.switch") + def SwitchAnnot(implicit ctx: Context) = SwitchAnnotType.symbol.asClass + lazy val ThrowsAnnotType = ctx.requiredClassRef("scala.throws") + def ThrowsAnnot(implicit ctx: Context) = ThrowsAnnotType.symbol.asClass + lazy val TransientAnnotType = ctx.requiredClassRef("scala.transient") + def TransientAnnot(implicit ctx: Context) = TransientAnnotType.symbol.asClass + lazy val UncheckedAnnotType = ctx.requiredClassRef("scala.unchecked") + def UncheckedAnnot(implicit ctx: Context) = UncheckedAnnotType.symbol.asClass + lazy val UncheckedStableAnnotType = ctx.requiredClassRef("scala.annotation.unchecked.uncheckedStable") + def UncheckedStableAnnot(implicit ctx: Context) = UncheckedStableAnnotType.symbol.asClass + lazy val UncheckedVarianceAnnotType = ctx.requiredClassRef("scala.annotation.unchecked.uncheckedVariance") + def UncheckedVarianceAnnot(implicit ctx: Context) = UncheckedVarianceAnnotType.symbol.asClass + lazy val UnsafeNonvariantAnnotType = ctx.requiredClassRef("scala.annotation.internal.UnsafeNonvariant") + def UnsafeNonvariantAnnot(implicit ctx: Context) = UnsafeNonvariantAnnotType.symbol.asClass + lazy val VolatileAnnotType = ctx.requiredClassRef("scala.volatile") + def VolatileAnnot(implicit ctx: Context) = VolatileAnnotType.symbol.asClass + lazy val FieldMetaAnnotType = ctx.requiredClassRef("scala.annotation.meta.field") + def FieldMetaAnnot(implicit ctx: Context) = FieldMetaAnnotType.symbol.asClass + lazy val GetterMetaAnnotType = ctx.requiredClassRef("scala.annotation.meta.getter") + def GetterMetaAnnot(implicit ctx: Context) = GetterMetaAnnotType.symbol.asClass + lazy val SetterMetaAnnotType = ctx.requiredClassRef("scala.annotation.meta.setter") + def SetterMetaAnnot(implicit ctx: Context) = SetterMetaAnnotType.symbol.asClass + + // convenient one-parameter method types + def methOfAny(tp: Type) = MethodType(List(AnyType), tp) + def methOfAnyVal(tp: Type) = MethodType(List(AnyValType), tp) + def methOfAnyRef(tp: Type) = MethodType(List(ObjectType), tp) + + // Derived types + + def RepeatedParamType = RepeatedParamClass.typeRef + def ThrowableType = ThrowableClass.typeRef + + def ClassType(arg: Type)(implicit ctx: Context) = { + val ctype = ClassClass.typeRef + if (ctx.phase.erasedTypes) ctype else ctype.appliedTo(arg) + } + + /** The enumeration type, goven a value of the enumeration */ + def EnumType(sym: Symbol)(implicit ctx: Context) = + // given (in java): "class A { enum E { VAL1 } }" + // - sym: the symbol of the actual enumeration value (VAL1) + // - .owner: the ModuleClassSymbol of the enumeration (object E) + // - .linkedClass: the ClassSymbol of the enumeration (class E) + sym.owner.linkedClass.typeRef + + object FunctionOf { + def apply(args: List[Type], resultType: Type)(implicit ctx: Context) = + FunctionType(args.length).appliedTo(args ::: resultType :: Nil) + def unapply(ft: Type)(implicit ctx: Context)/*: Option[(List[Type], Type)]*/ = { + // -language:keepUnions difference: unapply needs result type because inferred type + // is Some[(List[Type], Type)] | None, which is not a legal unapply type. + val tsym = ft.typeSymbol + lazy val targs = ft.argInfos + val numArgs = targs.length - 1 + if (numArgs >= 0 && numArgs <= MaxFunctionArity && + (FunctionType(numArgs).symbol == tsym)) Some(targs.init, targs.last) + else None + } + } + + object ArrayOf { + def apply(elem: Type)(implicit ctx: Context) = + if (ctx.erasedTypes) JavaArrayType(elem) + else ArrayType.appliedTo(elem :: Nil) + def unapply(tp: Type)(implicit ctx: Context): Option[Type] = tp.dealias match { + case at: RefinedType if (at isRef ArrayType.symbol) && at.argInfos.length == 1 => Some(at.argInfos.head) + case _ => None + } + } + + /** An extractor for multi-dimensional arrays. + * Note that this will also extract the high bound if an + * element type is a wildcard. E.g. + * + * Array[_ <: Array[_ <: Number]] + * + * would match + * + * MultiArrayOf(<Number>, 2) + */ + object MultiArrayOf { + def apply(elem: Type, ndims: Int)(implicit ctx: Context): Type = + if (ndims == 0) elem else ArrayOf(apply(elem, ndims - 1)) + def unapply(tp: Type)(implicit ctx: Context): Option[(Type, Int)] = tp match { + case ArrayOf(elemtp) => + def recur(elemtp: Type): Option[(Type, Int)] = elemtp.dealias match { + case TypeBounds(lo, hi) => recur(hi) + case MultiArrayOf(finalElemTp, n) => Some(finalElemTp, n + 1) + case _ => Some(elemtp, 1) + } + recur(elemtp) + case _ => + None + } + } + + // ----- Symbol sets --------------------------------------------------- + + lazy val AbstractFunctionType = mkArityArray("scala.runtime.AbstractFunction", MaxAbstractFunctionArity, 0) + val AbstractFunctionClassPerRun = new PerRun[Array[Symbol]](implicit ctx => AbstractFunctionType.map(_.symbol.asClass)) + def AbstractFunctionClass(n: Int)(implicit ctx: Context) = AbstractFunctionClassPerRun()(ctx)(n) + lazy val FunctionType = mkArityArray("scala.Function", MaxFunctionArity, 0) + def FunctionClassPerRun = new PerRun[Array[Symbol]](implicit ctx => FunctionType.map(_.symbol.asClass)) + def FunctionClass(n: Int)(implicit ctx: Context) = FunctionClassPerRun()(ctx)(n) + lazy val Function0_applyR = FunctionType(0).symbol.requiredMethodRef(nme.apply) + def Function0_apply(implicit ctx: Context) = Function0_applyR.symbol + + lazy val TupleType = mkArityArray("scala.Tuple", MaxTupleArity, 2) + lazy val ProductNType = mkArityArray("scala.Product", MaxTupleArity, 0) + + private lazy val FunctionTypes: Set[TypeRef] = FunctionType.toSet + private lazy val TupleTypes: Set[TypeRef] = TupleType.toSet + private lazy val ProductTypes: Set[TypeRef] = ProductNType.toSet + + /** If `cls` is a class in the scala package, its name, otherwise EmptyTypeName */ + def scalaClassName(cls: Symbol)(implicit ctx: Context): TypeName = + if (cls.isClass && cls.owner == ScalaPackageClass) cls.asClass.name else EmptyTypeName + + /** If type `ref` refers to a class in the scala package, its name, otherwise EmptyTypeName */ + def scalaClassName(ref: Type)(implicit ctx: Context): TypeName = scalaClassName(ref.classSymbol) + + private def isVarArityClass(cls: Symbol, prefix: Name) = { + val name = scalaClassName(cls) + name.startsWith(prefix) && name.drop(prefix.length).forall(_.isDigit) + } + + def isBottomClass(cls: Symbol) = + cls == NothingClass || cls == NullClass + def isBottomType(tp: Type) = + tp.derivesFrom(NothingClass) || tp.derivesFrom(NullClass) + + def isFunctionClass(cls: Symbol) = isVarArityClass(cls, tpnme.Function) + def isAbstractFunctionClass(cls: Symbol) = isVarArityClass(cls, tpnme.AbstractFunction) + def isTupleClass(cls: Symbol) = isVarArityClass(cls, tpnme.Tuple) + def isProductClass(cls: Symbol) = isVarArityClass(cls, tpnme.Product) + + val StaticRootImportFns = List[() => TermRef]( + () => JavaLangPackageVal.termRef, + () => ScalaPackageVal.termRef + ) + + val PredefImportFns = List[() => TermRef]( + () => ScalaPredefModuleRef, + () => DottyPredefModuleRef + ) + + lazy val RootImportFns = + if (ctx.settings.YnoImports.value) List.empty[() => TermRef] + else if (ctx.settings.YnoPredef.value) StaticRootImportFns + else StaticRootImportFns ++ PredefImportFns + + lazy val RootImportTypes = RootImportFns.map(_()) + + /** Modules whose members are in the default namespace and their module classes */ + lazy val UnqualifiedOwnerTypes: Set[NamedType] = + RootImportTypes.toSet[NamedType] ++ RootImportTypes.map(_.symbol.moduleClass.typeRef) + + lazy val PhantomClasses = Set[Symbol](AnyClass, AnyValClass, NullClass, NothingClass) + + def isPolymorphicAfterErasure(sym: Symbol) = + (sym eq Any_isInstanceOf) || (sym eq Any_asInstanceOf) + + def isTupleType(tp: Type)(implicit ctx: Context) = { + val arity = tp.dealias.argInfos.length + arity <= MaxTupleArity && TupleType(arity) != null && (tp isRef TupleType(arity).symbol) + } + + def tupleType(elems: List[Type]) = { + TupleType(elems.size).appliedTo(elems) + } + + def isProductSubType(tp: Type)(implicit ctx: Context) = + (tp derivesFrom ProductType.symbol) && tp.baseClasses.exists(isProductClass) + + def isFunctionType(tp: Type)(implicit ctx: Context) = { + val arity = functionArity(tp) + 0 <= arity && arity <= MaxFunctionArity && (tp isRef FunctionType(arity).symbol) + } + + def functionArity(tp: Type)(implicit ctx: Context) = tp.dealias.argInfos.length - 1 + + // ----- primitive value class machinery ------------------------------------------ + + /** This class would also be obviated by the implicit function type design */ + class PerRun[T](generate: Context => T) { + private var current: RunId = NoRunId + private var cached: T = _ + def apply()(implicit ctx: Context): T = { + if (current != ctx.runId) { + cached = generate(ctx) + current = ctx.runId + } + cached + } + } + + lazy val ScalaNumericValueTypeList = List( + ByteType, ShortType, CharType, IntType, LongType, FloatType, DoubleType) + + private lazy val ScalaNumericValueTypes: collection.Set[TypeRef] = ScalaNumericValueTypeList.toSet + private lazy val ScalaValueTypes: collection.Set[TypeRef] = ScalaNumericValueTypes + UnitType + BooleanType + private lazy val ScalaBoxedTypes = ScalaValueTypes map (t => boxedTypes(t.name)) + + val ScalaNumericValueClasses = new PerRun[collection.Set[Symbol]](implicit ctx => ScalaNumericValueTypes.map(_.symbol)) + val ScalaValueClasses = new PerRun[collection.Set[Symbol]](implicit ctx => ScalaValueTypes.map(_.symbol)) + val ScalaBoxedClasses = new PerRun[collection.Set[Symbol]](implicit ctx => ScalaBoxedTypes.map(_.symbol)) + + private val boxedTypes = mutable.Map[TypeName, TypeRef]() + private val valueTypeEnc = mutable.Map[TypeName, PrimitiveClassEnc]() + +// private val unboxedTypeRef = mutable.Map[TypeName, TypeRef]() +// private val javaTypeToValueTypeRef = mutable.Map[Class[_], TypeRef]() +// private val valueTypeNameToJavaType = mutable.Map[TypeName, Class[_]]() + + private def valueTypeRef(name: String, boxed: TypeRef, jtype: Class[_], enc: Int): TypeRef = { + val vcls = ctx.requiredClassRef(name) + boxedTypes(vcls.name) = boxed + valueTypeEnc(vcls.name) = enc +// unboxedTypeRef(boxed.name) = vcls +// javaTypeToValueTypeRef(jtype) = vcls +// valueTypeNameToJavaType(vcls.name) = jtype + vcls + } + + /** The type of the boxed class corresponding to primitive value type `tp`. */ + def boxedType(tp: Type)(implicit ctx: Context): TypeRef = boxedTypes(scalaClassName(tp)) + + def wrapArrayMethodName(elemtp: Type): TermName = { + val cls = elemtp.classSymbol + if (cls.isPrimitiveValueClass) nme.wrapXArray(cls.name) + else if (cls.derivesFrom(ObjectClass) && !cls.isPhantomClass) nme.wrapRefArray + else nme.genericWrapArray + } + + type PrimitiveClassEnc = Int + + val ByteEnc = 2 + val ShortEnc = ByteEnc * 3 + val CharEnc = 5 + val IntEnc = ShortEnc * CharEnc + val LongEnc = IntEnc * 7 + val FloatEnc = LongEnc * 11 + val DoubleEnc = FloatEnc * 13 + val BooleanEnc = 17 + val UnitEnc = 19 + + def isValueSubType(tref1: TypeRef, tref2: TypeRef)(implicit ctx: Context) = + valueTypeEnc(tref2.name) % valueTypeEnc(tref1.name) == 0 + def isValueSubClass(sym1: Symbol, sym2: Symbol) = + valueTypeEnc(sym2.asClass.name) % valueTypeEnc(sym1.asClass.name) == 0 + + // ----- Initialization --------------------------------------------------- + + /** Lists core classes that don't have underlying bytecode, but are synthesized on-the-fly in every reflection universe */ + lazy val syntheticScalaClasses = List( + AnyClass, + AnyRefAlias, + RepeatedParamClass, + ByNameParamClass2x, + AnyValClass, + NullClass, + NothingClass, + SingletonClass, + EqualsPatternClass) + + lazy val syntheticCoreClasses = syntheticScalaClasses ++ List( + EmptyPackageVal, + OpsPackageClass) + + /** Lists core methods that don't have underlying bytecode, but are synthesized on-the-fly in every reflection universe */ + lazy val syntheticCoreMethods = AnyMethods ++ ObjectMethods ++ List(String_+, throwMethod) + + lazy val reservedScalaClassNames: Set[Name] = syntheticScalaClasses.map(_.name).toSet + + private[this] var _isInitialized = false + private def isInitialized = _isInitialized + + def init()(implicit ctx: Context) = { + this.ctx = ctx + if (!_isInitialized) { + // force initialization of every symbol that is synthesized or hijacked by the compiler + val forced = syntheticCoreClasses ++ syntheticCoreMethods ++ ScalaValueClasses() + + // Enter all symbols from the scalaShadowing package in the scala package + for (m <- ScalaShadowingPackageClass.info.decls) + ScalaPackageClass.enter(m) + + _isInitialized = true + } + } +} |