typekinds.scala
来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 484 行
SCALA
484 行
/* NSC -- new Scala compiler * Copyright 2005-2008 LAMP/EPFL * @author Martin Odersky */// $Id: TypeKinds.scala 13902 2008-02-06 15:45:31Z odersky $package scala.tools.nsc.backend.icode/* A type case case UNIT => case BOOL => case BYTE => case SHORT => case CHAR => case INT => case LONG => case FLOAT => case DOUBLE => case REFERENCE(cls) => case ARRAY(elem) => */import scala.collection.mutable.{Map, HashMap}trait TypeKinds { self: ICodes => import global._ /** This class represents a type kind. Type kinds * represent the types that the VM know (or the ICode * view of what VMs know). */ sealed abstract class TypeKind { def toType: Type = this match { case UNIT => definitions.UnitClass.tpe case BOOL => definitions.BooleanClass.tpe case BYTE => definitions.ByteClass.tpe case SHORT => definitions.ShortClass.tpe case CHAR => definitions.CharClass.tpe case INT => definitions.IntClass.tpe case LONG => definitions.LongClass.tpe case FLOAT => definitions.FloatClass.tpe case DOUBLE => definitions.DoubleClass.tpe case REFERENCE(cls) => typeRef(cls.typeConstructor.prefix, cls, Nil) //case VALUE(cls) => typeRef(cls.typeConstructor.prefix, cls, Nil); case ARRAY(elem) => typeRef(definitions.ArrayClass.typeConstructor.prefix, definitions.ArrayClass, elem.toType :: Nil) case _ => abort("Unknown type kind.") } def isReferenceType: Boolean = false def isArrayType: Boolean = false def isValueType: Boolean = !isReferenceType && !isArrayType def isIntType: Boolean = this match { case BYTE | SHORT | INT | LONG | CHAR => true case _ => false } def isRealType: Boolean = this match { case FLOAT | DOUBLE => true case _ => false } def isNumericType: Boolean = isIntType | isRealType def maxType(other: TypeKind): TypeKind /** Simple subtyping check */ def <:<(other: TypeKind): Boolean = (this eq other) || (this match { case BOOL | BYTE | SHORT | CHAR => other match { case INT | LONG => true case _ => false } case _ => this eq other }) override def equals(other: Any): Boolean = this eq other.asInstanceOf[AnyRef] /** Is this type a category 2 type in JVM terms? */ def isWideType: Boolean = this match { case DOUBLE | LONG => true case _ => false } /** The number of dimensions for array types. */ def dimensions: Int = 0 } /** * The least upper bound of two typekinds. They have to be either * REFERENCE or ARRAY kinds. * * The lub is based on the lub of scala types. */ def lub(a: TypeKind, b: TypeKind): TypeKind = { def lub0(t1: Type, t2: Type): Type = { val lubTpe = global.lub(t1 :: t2 :: Nil) assert(lubTpe.typeSymbol.isClass, "Least upper bound of " + t1 + " and " + t2 + " is not a class: " + lubTpe) lubTpe } if ((a.isReferenceType || a.isArrayType) && (b.isReferenceType || b.isArrayType)) toTypeKind(lub0(a.toType, b.toType)) else if (a == b) a else if (a == REFERENCE(definitions.AllClass)) b else if (b == REFERENCE(definitions.AllClass)) a else (a, b) match { case (BOXED(a1), BOXED(b1)) => if (a1 == b1) a else REFERENCE(definitions.AnyRefClass) case (BOXED(_), REFERENCE(_)) | (REFERENCE(_), BOXED(_)) => REFERENCE(definitions.AnyRefClass) case (BOXED(_), ARRAY(_)) | (ARRAY(_), BOXED(_)) => REFERENCE(definitions.AnyRefClass) case (BYTE, INT) | (INT, BYTE) => INT case (SHORT, INT) | (INT, SHORT) => INT case (CHAR, INT) | (INT, CHAR) => INT case _ => throw new CheckerError("Incompatible types: " + a + " with " + b) } } /** The unit value */ case object UNIT extends TypeKind { def maxType(other: TypeKind): TypeKind = other match { case UNIT => UNIT case REFERENCE(a) if a == definitions.AllClass => UNIT case _ => abort("Uncomparable type kinds: UNIT with " + other) } } /** A boolean value */ case object BOOL extends TypeKind { override def maxType(other: TypeKind): TypeKind = other match { case BOOL => BOOL case REFERENCE(a) if a == definitions.AllClass => BOOL case _ => abort("Uncomparable type kinds: BOOL with " + other) } } /** A 1-byte signed integer */ case object BYTE extends TypeKind { override def maxType(other: TypeKind): TypeKind = other match { case BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE => other case REFERENCE(a) if a == definitions.AllClass => BYTE case _ => abort("Uncomparable type kinds: BYTE with " + other) } } /** A 2-byte signed integer */ case object SHORT extends TypeKind { override def maxType(other: TypeKind): TypeKind = other match { case BYTE | SHORT | CHAR => SHORT case REFERENCE(a) if a == definitions.AllClass => SHORT case INT | LONG | FLOAT | DOUBLE => other case _ => abort("Uncomparable type kinds: SHORT with " + other) } } /** A 2-byte signed integer */ case object CHAR extends TypeKind { override def maxType(other: TypeKind): TypeKind = other match { case BYTE | SHORT | CHAR => CHAR case REFERENCE(a) if a == definitions.AllClass => CHAR case INT | LONG | FLOAT | DOUBLE => other case _ => abort("Uncomparable type kinds: CHAR with " + other) } } /** A 4-byte signed integer */ case object INT extends TypeKind { override def maxType(other: TypeKind): TypeKind = other match { case BYTE | SHORT | CHAR | INT => INT case REFERENCE(a) if a == definitions.AllClass => INT case LONG | FLOAT | DOUBLE => other case _ => abort("Uncomparable type kinds: INT with " + other) } } /** An 8-byte signed integer */ case object LONG extends TypeKind { override def maxType(other: TypeKind): TypeKind = other match { case BYTE | SHORT | CHAR | INT | LONG => LONG case REFERENCE(a) if a == definitions.AllClass => LONG case FLOAT | DOUBLE => DOUBLE case _ => abort("Uncomparable type kinds: LONG with " + other) } } /** A 4-byte floating point number */ case object FLOAT extends TypeKind { override def maxType(other: TypeKind): TypeKind = other match { case BYTE | SHORT | CHAR | INT | LONG | FLOAT => FLOAT case REFERENCE(a) if a == definitions.AllClass => FLOAT case DOUBLE => DOUBLE case _ => abort("Uncomparable type kinds: FLOAT with " + other) } } /** An 8-byte floating point number */ case object DOUBLE extends TypeKind { override def maxType(other: TypeKind): TypeKind = if (other.isNumericType) DOUBLE else if (other == REFERENCE(definitions.AllClass)) DOUBLE else abort("Uncomparable type kinds: DOUBLE with " + other) } /** A string reference */ // case object STRING extends TypeKind { // override def maxType(other: TypeKind): TypeKind = other match { // case STRING => STRING; // case _ => // abort("Uncomparbale type kinds: STRING with " + other); // } // } /** A class type. */ final case class REFERENCE(cls: Symbol) extends TypeKind { assert(cls ne null, "REFERENCE to null class symbol.") assert(cls != definitions.ArrayClass, "REFERENCE to Array is not allowed, should be ARRAY[..] instead") assert(cls != NoSymbol, "REFERENCE to NoSymbol not allowed!") override def toString(): String = "REFERENCE(" + cls.fullNameString + ")" /** * Approximate `lub'. The common type of two references is * always AnyRef. For 'real' least upper bound wrt to subclassing * use method 'lub'. */ override def maxType(other: TypeKind): TypeKind = other match { case REFERENCE(_) => REFERENCE(definitions.AnyRefClass) case ARRAY(_) => REFERENCE(definitions.AnyRefClass) case _ => abort("Uncomparbale type kinds: REFERENCE with " + other) } /** Checks subtyping relationship. */ override def <:<(other: TypeKind): Boolean = if (cls == definitions.AllClass) true else other match { case REFERENCE(cls2) => cls.tpe <:< cls2.tpe case ARRAY(_) => cls == definitions.AllRefClass case _ => false } override def isReferenceType: Boolean = true; override def equals(other: Any): Boolean = other match { case REFERENCE(cls2) => cls == cls2 case _ => false } }// final case class VALUE(cls: Symbol) extends TypeKind {// override def equals(other: Any): Boolean = other match {// case VALUE(cls2) => cls == cls2;// case _ => false;// }// def maxType(other: TypeKind): TypeKind =// abort(toString() + " maxType " + other.toString());// override def toString(): String =// "VALUE(" + cls.fullNameString + ")";// } def ArrayN(elem: TypeKind, dims: Int): ARRAY = { assert(dims > 0) if (dims == 1) ARRAY(elem) else ARRAY(ArrayN(elem, dims - 1)) } final case class ARRAY(val elem: TypeKind) extends TypeKind { override def toString(): String = "ARRAY[" + elem + "]" override def isArrayType = true override def dimensions: Int = 1 + elem.dimensions /** The ultimate element type of this array. */ def elementKind: TypeKind = elem match { case a @ ARRAY(e1) => a.elementKind case k => k } /** * Approximate `lub'. The common type of two references is * always AnyRef. For 'real' least upper bound wrt to subclassing * use method 'lub'. */ override def maxType(other: TypeKind): TypeKind = other match { case REFERENCE(_) => REFERENCE(definitions.AnyRefClass) case ARRAY(elem2) => ARRAY(elem maxType elem2) case _ => abort("Uncomparbale type kinds: ARRAY with " + other) } /** Array subtyping is covariant, as in Java. Necessary for checking * code that interacts with Java. */ override def <:<(other: TypeKind): Boolean = other match { case ARRAY(elem2) => elem <:< elem2 case REFERENCE(sym) => (sym == definitions.AnyRefClass || sym == definitions.ObjectClass) // TODO: platform dependent! case _ => false } override def equals(other: Any): Boolean = other match { case ARRAY(elem2) => elem == elem2 case _ => false } } /** A boxed value. */ case class BOXED(kind: TypeKind) extends TypeKind { override def toString(): String = "BOXED(" + kind + ")" /** * Approximate `lub'. The common type of two references is * always AnyRef. For 'real' least upper bound wrt to subclassing * use method 'lub'. */ override def maxType(other: TypeKind): TypeKind = other match { case REFERENCE(_) | ARRAY(_) | BOXED(_) => REFERENCE(definitions.AnyRefClass) case _ => abort("Uncomparbale type kinds: ARRAY with " + other) } /** Checks subtyping relationship. */ override def <:<(other: TypeKind): Boolean = other match { case REFERENCE(sym) => (sym == definitions.AnyRefClass || sym == definitions.ObjectClass) // TODO: platform dependent! case BOXED(other) => kind == other case _ => false } override def equals(other: Any): Boolean = other match { case BOXED(kind2) => kind == kind2 case _ => false } } /** * Dummy TypeKind to represent the ConcatClass in a platform-independent * way. For JVM it would have been a REFERENCE to 'StringBuffer'. */ case object ConcatClass extends TypeKind { override def toString() = "ConcatClass" /** * Approximate `lub'. The common type of two references is * always AnyRef. For 'real' least upper bound wrt to subclassing * use method 'lub'. */ override def maxType(other: TypeKind): TypeKind = other match { case REFERENCE(_) => REFERENCE(definitions.AnyRefClass) case _ => abort("Uncomparbale type kinds: ConcatClass with " + other) } /** Checks subtyping relationship. */ override def <:<(other: TypeKind): Boolean = (this eq other) override def isReferenceType: Boolean = false } ////////////////// Conversions ////////////////////////////// /** Return the TypeKind of the given type */ def toTypeKind(t: Type): TypeKind = t.normalize match { case ThisType(sym) => REFERENCE(sym) case SingleType(pre, sym) => primitiveTypeMap get sym match { case Some(k) => k case None => REFERENCE(sym) } case ConstantType(value) => toTypeKind(value.tpe) case TypeRef(_, sym, args) => primitiveTypeMap get sym match { case Some(k) => k case None => if (sym == definitions.ArrayClass) ARRAY(toTypeKind(args.head)) else { if (sym.isClass) REFERENCE(sym) else { assert(sym.isType, sym) // it must be compiling Array[a] AnyRefReference } } } case ClassInfoType(_, _, sym) => primitiveTypeMap get sym match { case Some(k) => k case None => if (sym == definitions.ArrayClass) abort("ClassInfoType to ArrayClass!") else REFERENCE(sym) } case ExistentialType(tparams, t) => toTypeKind(t) //case WildcardType => // bq: useful hack when wildcard types come here // REFERENCE(definitions.ObjectClass) case _ => abort("Unknown type: " + t) } /** A map from scala primitive Types to ICode TypeKinds */ private var primitiveTypeMap: Map[Symbol, TypeKind] = null /** Initialize the map from scala primitive types to ICode types */ def initPrimitiveTypeMap = { log("Initializing primitive map") primitiveTypeMap = new HashMap() primitiveTypeMap += (definitions.UnitClass -> UNIT) primitiveTypeMap += (definitions.BooleanClass -> BOOL) primitiveTypeMap += (definitions.ByteClass -> BYTE) primitiveTypeMap += (definitions.ShortClass -> SHORT) primitiveTypeMap += (definitions.CharClass -> CHAR) primitiveTypeMap += (definitions.IntClass -> INT) primitiveTypeMap += (definitions.LongClass -> LONG) if (!forCLDC) { primitiveTypeMap += (definitions.FloatClass -> FLOAT) primitiveTypeMap += (definitions.DoubleClass -> DOUBLE) }// primitiveTypeMap += (definitions.StringClass -> STRING) } }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?