Skip to content

Commit

Permalink
rethinks tags
Browse files Browse the repository at this point in the history
* introduces ArrayTag and ErasureTag
* all type tags now feature erasure
  • Loading branch information
xeno-by committed Apr 23, 2012
1 parent 14df5d7 commit 2b09d8c
Show file tree
Hide file tree
Showing 82 changed files with 1,394 additions and 1,178 deletions.
2 changes: 1 addition & 1 deletion lib/scala-compiler.jar.desired.sha1
@@ -1 +1 @@
5d99e65aaa8e00c4815e011a8dfc495cb38bdfcc ?scala-compiler.jar
c020eccb8cf37963725985f36b44d070915cf4d2 ?scala-compiler.jar
2 changes: 1 addition & 1 deletion lib/scala-library.jar.desired.sha1
@@ -1 +1 @@
53ddaba2c7d56b360eda1a56c3eef5ec23ef14ca ?scala-library.jar
31c7188cef85c28b84b9ce35bc6780996e5dd139 ?scala-library.jar
16 changes: 13 additions & 3 deletions src/compiler/scala/reflect/internal/Definitions.scala
Expand Up @@ -380,6 +380,8 @@ trait Definitions extends reflect.api.StandardDefinitions {
def arrayCloneMethod = getMember(ScalaRunTimeModule, nme.array_clone)
def ensureAccessibleMethod = getMember(ScalaRunTimeModule, nme.ensureAccessible)
def scalaRuntimeSameElements = getMember(ScalaRunTimeModule, nme.sameElements)
def arrayClassMethod = getMember(ScalaRunTimeModule, nme.arrayClass)
def arrayElementClassMethod = getMember(ScalaRunTimeModule, nme.arrayElementClass)

// classes with special meanings
lazy val StringAddClass = getRequiredClass("scala.runtime.StringAdd")
Expand Down Expand Up @@ -409,7 +411,7 @@ trait Definitions extends reflect.api.StandardDefinitions {
lazy val EqualsPatternClass = specialPolyClass(tpnme.EQUALS_PATTERN_NAME, 0L)(_ => AnyClass.tpe)
lazy val JavaRepeatedParamClass = specialPolyClass(tpnme.JAVA_REPEATED_PARAM_CLASS_NAME, COVARIANT)(tparam => arrayType(tparam.tpe))
lazy val RepeatedParamClass = specialPolyClass(tpnme.REPEATED_PARAM_CLASS_NAME, COVARIANT)(tparam => seqType(tparam.tpe))

lazy val MarkerCPSTypes = getClassIfDefined("scala.util.continuations.cpsParam")

def isByNameParamType(tp: Type) = tp.typeSymbol == ByNameParamClass
Expand Down Expand Up @@ -479,7 +481,9 @@ trait Definitions extends reflect.api.StandardDefinitions {
// scala.reflect
lazy val ReflectPackageClass = getMember(ScalaPackageClass, nme.reflect)
lazy val ReflectPackage = getPackageObject("scala.reflect")
def Reflect_mirror = getMember(ReflectPackage, nme.mirror)
def ReflectMirror = getMember(ReflectPackage, nme.mirror)
// [Eugene] is this a good place for ReflectMirrorPrefix?
def ReflectMirrorPrefix = gen.mkAttributedRef(ReflectMirror) setType singleType(ReflectMirror.owner.thisPrefix, ReflectMirror)

lazy val ExprClass = getMember(getRequiredClass("scala.reflect.api.Exprs"), tpnme.Expr)
def ExprTree = getMemberClass(ExprClass, nme.tree)
Expand All @@ -488,6 +492,8 @@ trait Definitions extends reflect.api.StandardDefinitions {
def ExprValue = getMember(ExprClass, nme.value)
lazy val ExprModule = getMember(getRequiredClass("scala.reflect.api.Exprs"), nme.Expr)

lazy val ArrayTagClass = requiredClass[scala.reflect.ArrayTag[_]]
lazy val ErasureTagClass = requiredClass[scala.reflect.ErasureTag[_]]
lazy val ClassTagModule = requiredModule[scala.reflect.ClassTag[_]]
lazy val ClassTagClass = requiredClass[scala.reflect.ClassTag[_]]
lazy val TypeTagsClass = requiredClass[scala.reflect.api.TypeTags]
Expand All @@ -496,7 +502,9 @@ trait Definitions extends reflect.api.StandardDefinitions {
lazy val ConcreteTypeTagClass = getMemberClass(TypeTagsClass, tpnme.ConcreteTypeTag)
lazy val ConcreteTypeTagModule = getMemberModule(TypeTagsClass, nme.ConcreteTypeTag)

def ClassTagErasure = getMemberMethod(ClassTagClass, nme.erasure)
def ArrayTagWrap = getMemberMethod(ArrayTagClass, nme.wrap)
def ArrayTagNewArray = getMemberMethod(ArrayTagClass, nme.newArray)
def ErasureTagErasure = getMemberMethod(ErasureTagClass, nme.erasure)
def ClassTagTpe = getMemberMethod(ClassTagClass, nme.tpe)
def TypeTagTpe = getMemberMethod(TypeTagClass, nme.tpe)

Expand All @@ -507,6 +515,8 @@ trait Definitions extends reflect.api.StandardDefinitions {
def MacroContextReify = getMember(MacroContextClass, nme.reify)
lazy val MacroImplAnnotation = getRequiredClass("scala.reflect.makro.internal.macroImpl")
lazy val MacroInternalPackage = getPackageObject("scala.reflect.makro.internal")
def MacroInternal_materializeArrayTag = getMemberMethod(MacroInternalPackage, nme.materializeArrayTag)
def MacroInternal_materializeErasureTag = getMemberMethod(MacroInternalPackage, nme.materializeErasureTag)
def MacroInternal_materializeClassTag = getMemberMethod(MacroInternalPackage, nme.materializeClassTag)
def MacroInternal_materializeTypeTag = getMemberMethod(MacroInternalPackage, nme.materializeTypeTag)
def MacroInternal_materializeConcreteTypeTag = getMemberMethod(MacroInternalPackage, nme.materializeConcreteTypeTag)
Expand Down
42 changes: 25 additions & 17 deletions src/compiler/scala/reflect/internal/StdNames.scala
Expand Up @@ -562,6 +562,8 @@ trait StdNames {
val applyOrElse: NameType = "applyOrElse"
val args : NameType = "args"
val argv : NameType = "argv"
val arrayClass: NameType = "arrayClass"
val arrayElementClass: NameType = "arrayElementClass"
val arrayValue: NameType = "arrayValue"
val array_apply : NameType = "array_apply"
val array_clone : NameType = "array_clone"
Expand Down Expand Up @@ -628,9 +630,11 @@ trait StdNames {
val main: NameType = "main"
val manifest: NameType = "manifest"
val map: NameType = "map"
val materializeArrayTag: NameType = "materializeArrayTag"
val materializeClassTag: NameType = "materializeClassTag"
val materializeTypeTag: NameType = "materializeTypeTag"
val materializeConcreteTypeTag: NameType = "materializeConcreteTypeTag"
val materializeErasureTag: NameType= "materializeErasureTag"
val materializeTypeTag: NameType = "materializeTypeTag"
val mirror : NameType = "mirror"
val moduleClass : NameType = "moduleClass"
val name: NameType = "name"
Expand Down Expand Up @@ -813,10 +817,11 @@ trait StdNames {
val ROOTPKG: TermName = "_root_"
val EQEQ_LOCAL_VAR: TermName = "eqEqTemp$"

def getCause = sn.GetCause
def getClass_ = sn.GetClass
def getMethod_ = sn.GetMethod
def invoke_ = sn.Invoke
def getCause = sn.GetCause
def getClass_ = sn.GetClass
def getComponentType = sn.GetComponentType
def getMethod_ = sn.GetMethod
def invoke_ = sn.Invoke

val ADD = encode("+")
val AND = encode("&")
Expand Down Expand Up @@ -1005,6 +1010,7 @@ trait StdNames {
val ForName : TermName
val GetCause : TermName
val GetClass : TermName
val GetComponentType : TermName
val GetMethod : TermName
val Invoke : TermName
val JavaLang : TermName
Expand Down Expand Up @@ -1090,12 +1096,13 @@ trait StdNames {
final val Throwable: TypeName = "java.lang.Throwable"
final val ValueType: TypeName = tpnme.NO_NAME

final val ForName: TermName = newTermName("forName")
final val GetCause: TermName = newTermName("getCause")
final val GetClass: TermName = newTermName("getClass")
final val GetMethod: TermName = newTermName("getMethod")
final val Invoke: TermName = newTermName("invoke")
final val JavaLang: TermName = newTermName("java.lang")
final val ForName: TermName = newTermName("forName")
final val GetCause: TermName = newTermName("getCause")
final val GetClass: TermName = newTermName("getClass")
final val GetComponentType: TermName = newTermName("getComponentType")
final val GetMethod: TermName = newTermName("getMethod")
final val Invoke: TermName = newTermName("invoke")
final val JavaLang: TermName = newTermName("java.lang")

val Boxed = immutable.Map[TypeName, TypeName](
tpnme.Boolean -> BoxedBoolean,
Expand Down Expand Up @@ -1127,12 +1134,13 @@ trait StdNames {
final val Throwable: TypeName = "System.Exception"
final val ValueType: TypeName = "System.ValueType"

final val ForName: TermName = newTermName("GetType")
final val GetCause: TermName = newTermName("InnerException") /* System.Reflection.TargetInvocationException.InnerException */
final val GetClass: TermName = newTermName("GetType")
final val GetMethod: TermName = newTermName("GetMethod")
final val Invoke: TermName = newTermName("Invoke")
final val JavaLang: TermName = newTermName("System")
final val ForName: TermName = newTermName("GetType")
final val GetCause: TermName = newTermName("InnerException") /* System.Reflection.TargetInvocationException.InnerException */
final val GetClass: TermName = newTermName("GetType")
final val GetComponentType: TermName = newTermName("GetElementType")
final val GetMethod: TermName = newTermName("GetMethod")
final val Invoke: TermName = newTermName("Invoke")
final val JavaLang: TermName = newTermName("System")

val Boxed = immutable.Map[TypeName, TypeName](
tpnme.Boolean -> "System.Boolean",
Expand Down
6 changes: 3 additions & 3 deletions src/compiler/scala/reflect/internal/TreeInfo.scala
Expand Up @@ -676,14 +676,14 @@ abstract class TreeInfo {
case ValDef(_, name, _, Apply(Select(mrRef1 @ Ident(_), newFreeType), List(_, _, value, Literal(Constant(flags: Long)), Literal(Constant(origin: String)))))
if mrRef1.name == nme.MIRROR_SHORT && (newFreeType == newFreeTypeMethod.name || newFreeType == newFreeExistentialMethod.name) =>
value match {
case Apply(TypeApply(Select(Select(mrRef2 @ Ident(_), typeTag), apply), List(binding)), List(Literal(Constant(null))))
case Apply(TypeApply(Select(Select(mrRef2 @ Ident(_), typeTag), apply), List(binding)), List(Literal(Constant(null)), _))
if mrRef2.name == nme.MIRROR_SHORT && typeTag == nme.TypeTag && apply == nme.apply =>
Some(mrRef1, name, binding, flags, origin)
case Apply(TypeApply(Select(mrRef2 @ Ident(_), typeTag), List(binding)), List(Literal(Constant(null))))
case Apply(TypeApply(Select(mrRef2 @ Ident(_), typeTag), List(binding)), List(Literal(Constant(null)), _))
if mrRef2.name == nme.MIRROR_SHORT && typeTag == nme.TypeTag =>
Some(mrRef1, name, binding, flags, origin)
case _ =>
throw new Error("unsupported free type def: " + showRaw(tree))
throw new Error("unsupported free type def: %s%n%s".format(value, showRaw(value)))
}
case _ =>
None
Expand Down
21 changes: 19 additions & 2 deletions src/compiler/scala/reflect/internal/Types.scala
Expand Up @@ -264,7 +264,23 @@ trait Types extends api.Types { self: SymbolTable =>
def nonPrivateDeclaration(name: Name): Symbol = nonPrivateDecl(name)
def declarations = decls
def typeArguments = typeArgs
def erasure = transformedType(this)
def erasure = this match {
case ConstantType(value) => widen.erasure // [Eugene to Martin] constant types are unaffected by erasure. weird.
case _ =>
var result = transformedType(this)
result = result.normalize match { // necessary to deal with erasures of HK types, typeConstructor won't work
case PolyType(undets, underlying) => existentialAbstraction(undets, underlying) // we don't want undets in the result
case _ => result
}
// [Eugene] erasure screws up all ThisTypes for modules into PackageTypeRefs
// we need to unscrew them, or certain typechecks will fail mysteriously
// http://groups.google.com/group/scala-internals/browse_thread/thread/6d3277ae21b6d581
result = result.map(tpe => tpe match {
case tpe: PackageTypeRef => ThisType(tpe.sym)
case _ => tpe
})
result
}
def substituteTypes(from: List[Symbol], to: List[Type]): Type = subst(from, to)

// [Eugene] to be discussed and refactored
Expand Down Expand Up @@ -1342,7 +1358,8 @@ trait Types extends api.Types { self: SymbolTable =>
if (period != currentPeriod) {
tpe.underlyingPeriod = currentPeriod
if (!isValid(period)) {
tpe.underlyingCache = tpe.pre.memberType(tpe.sym).resultType;
// [Eugene to Paul] needs review
tpe.underlyingCache = if (tpe.sym == NoSymbol) ThisType(RootClass) else tpe.pre.memberType(tpe.sym).resultType;
assert(tpe.underlyingCache ne tpe, tpe)
}
}
Expand Down
123 changes: 11 additions & 112 deletions src/compiler/scala/reflect/makro/runtime/Reifiers.scala
Expand Up @@ -12,124 +12,23 @@ trait Reifiers {
import mirror._
import definitions._

private lazy val ClassTagModule = ClassTagClass.companionSymbol
lazy val reflectMirrorPrefix: Tree = ReflectMirrorPrefix

// [Eugene] imho this logic should be moved into `erasure`
private def calculateTagErasure(tpe: Type) = tpe match {
case tpe if tpe.typeSymbol.isDerivedValueClass => tpe // [Eugene to Martin] is this correct?
case ConstantType(value) => tpe.widen.erasure
case _ =>
// [Eugene] magikz. needs review
// necessary to deal with erasures of HK types, typeConstructor won't work
tpe.erasure.normalize match {
// we don't want undets in the result
case PolyType(undets, underlying) => existentialAbstraction(undets, underlying)
case result => result
}
}
private def classTagFromArgument(tpe: Type, arg: Tree) = {
gen.mkMethodCall(ClassTagModule, nme.apply, List(tpe), List(arg))
// val factory = TypeApply(Select(Ident(ClassTagModule), nme.apply), List(TypeTree(tpe)))
// Apply(factory, List(typeArg))
}
private def classTagFromErasure(tpe: Type) = {
val erasure = calculateTagErasure(tpe)
classTagFromArgument(tpe, gen.mkNullaryCall(Predef_classOf, List(erasure)))
// val targ = TypeApply(Select(Ident(PredefModule), nme.classOf), List(TypeTree(erasure)))
// classTagFromArgument(tpe, targ)
}
private def typetagIsSynthetic(tree: Tree) = tree match {
case Block(_, _) => true
case _ => tree exists (_ hasSymbolWhich Set(TypeTagModule, ConcreteTypeTagModule))
def reifyTree(prefix: Tree, tree: Tree): Tree = {
val result = scala.reflect.reify.`package`.reifyTree(mirror)(callsiteTyper, prefix, tree)
logFreeVars(enclosingPosition, result)
result
}

lazy val reflectMirrorPrefix: Tree = {
// [Eugene] how do I typecheck this without undergoing this tiresome (and, in general, incorrect) procedure?
val prefix: Tree = Select(Select(Ident(definitions.ScalaPackage), newTermName("reflect")), newTermName("mirror"))
val prefixTpe = typeCheck(TypeApply(Select(prefix, newTermName("asInstanceOf")), List(SingletonTypeTree(prefix)))).tpe
typeCheck(prefix) setType prefixTpe
def reifyType(prefix: Tree, tpe: Type, dontSpliceAtTopLevel: Boolean = false, concrete: Boolean = false): Tree = {
val result = scala.reflect.reify.`package`.reifyType(mirror)(callsiteTyper, prefix, tpe, dontSpliceAtTopLevel, concrete)
logFreeVars(enclosingPosition, result)
result
}

def reifyTree(prefix: Tree, tree: Tree): Tree =
reifyTopLevel(prefix, tree)

def reifyType(prefix: Tree, tpe: Type, dontSpliceAtTopLevel: Boolean = false, requireConcreteTypeTag: Boolean = false): Tree =
reifyTopLevel(prefix, tpe, dontSpliceAtTopLevel, requireConcreteTypeTag)

def reifyErasure(tpe: Type): Tree = {
val positionBearer = (enclosingMacros.find(_.macroApplication.pos != NoPosition) match {
case None => EmptyTree
case Some(m) => m.macroApplication
}).asInstanceOf[Tree]

val typetagInScope = callsiteTyper.context.withMacrosDisabled(
callsiteTyper.resolveTypeTag(
positionBearer,
singleType(Reflect_mirror.owner.thisPrefix, Reflect_mirror),
tpe,
full = true
)
)
typetagInScope match {
case success if !success.isEmpty && !typetagIsSynthetic(success) =>
classTagFromArgument(tpe, typetagInScope)
case _ =>
if (tpe.typeSymbol == ArrayClass) {
val componentTpe = tpe.typeArguments(0)
val componentTag = callsiteTyper.resolveClassTag(positionBearer, componentTpe)
Select(componentTag, nme.wrap)
}
// [Eugene] what's the intended behavior? there's no spec on ClassManifests
// for example, should we ban Array[T] or should we tag them with Array[AnyRef]?
// if its the latter, what should be the result of tagging Array[T] where T <: Int?
else if (tpe.isSpliceable) {
throw new ReificationError(enclosingPosition,
"tpe %s is an unresolved spliceable type".format(tpe))
}
else classTagFromErasure(tpe)
}
}
def reifyErasure(tpe: Type, concrete: Boolean = true): Tree =
scala.reflect.reify.`package`.reifyErasure(mirror)(callsiteTyper, tpe, concrete)

def unreifyTree(tree: Tree): Tree =
Select(tree, definitions.ExprEval)

def reifyTopLevel(prefix: Tree, reifee: Any, dontSpliceAtTopLevel: Boolean = false, requireConcreteTypeTag: Boolean = false): Tree = {
// [Eugene] the plumbing is not very pretty, but anyways factoring out the reifier seems like a necessary step to me
import scala.reflect.reify._
val reifier = mkReifier(mirror)(callsiteTyper, prefix, reifee, dontSpliceAtTopLevel, requireConcreteTypeTag)

try {
val result = reifier.reified
logFreeVars(enclosingPosition, result)
result
} catch {
case ex: reifier.ReificationError =>
// // this is a "soft" exception - it will normally be caught by the macro
// // consequently, we need to log the stack trace here, so that it doesn't get lost
// if (settings.Yreifydebug.value) {
// val message = new java.io.StringWriter()
// ex.printStackTrace(new java.io.PrintWriter(message))
// println(scala.compat.Platform.EOL + message)
// }
val xlated = new ReificationError(ex.pos, ex.msg)
xlated.setStackTrace(ex.getStackTrace)
throw xlated
case ex: reifier.UnexpectedReificationError =>
val xlated = new UnexpectedReificationError(ex.pos, ex.msg, ex.cause)
xlated.setStackTrace(ex.getStackTrace)
throw xlated
}
}

class ReificationError(var pos: Position, val msg: String) extends Throwable(msg)

object ReificationError extends ReificationErrorExtractor {
def unapply(error: ReificationError): Option[(Position, String)] = Some((error.pos, error.msg))
}

class UnexpectedReificationError(val pos: Position, val msg: String, val cause: Throwable = null) extends Throwable(msg, cause)

object UnexpectedReificationError extends UnexpectedReificationErrorExtractor {
def unapply(error: UnexpectedReificationError): Option[(Position, String, Throwable)] = Some((error.pos, error.msg, error.cause))
}
}
8 changes: 3 additions & 5 deletions src/compiler/scala/reflect/reify/Errors.scala
@@ -1,17 +1,15 @@
package scala.reflect
package reify

import scala.tools.nsc.Global
import scala.reflect.makro.ReificationError
import scala.reflect.makro.UnexpectedReificationError

trait Errors {
self: Reifier =>

import mirror._
import definitions._

class ReificationError(var pos: Position, val msg: String) extends Throwable(msg)
class UnexpectedReificationError(val pos: Position, val msg: String, val cause: Throwable = null) extends Throwable(msg)

lazy val defaultErrorPosition: Position =
mirror.analyzer.openMacros.find(c => c.macroApplication.pos != NoPosition).map(_.macroApplication.pos).getOrElse(NoPosition)

Expand Down Expand Up @@ -60,4 +58,4 @@ trait Errors {
val msg = "internal error: erroneous reifees are not supported, make sure that your reifee has typechecked successfully before passing it to the reifier"
throw new UnexpectedReificationError(defaultErrorPosition, msg)
}
}
}

0 comments on commit 2b09d8c

Please sign in to comment.