summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeDSL.scala73
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeGen.scala12
-rw-r--r--src/compiler/scala/tools/nsc/transform/CleanUp.scala577
-rw-r--r--src/compiler/scala/tools/nsc/transform/Constructors.scala11
-rw-r--r--src/compiler/scala/tools/nsc/transform/LazyVals.scala11
5 files changed, 291 insertions, 393 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreeDSL.scala b/src/compiler/scala/tools/nsc/ast/TreeDSL.scala
index 98a6919f27..1ef0a1bc69 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeDSL.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeDSL.scala
@@ -21,16 +21,20 @@ trait TreeDSL {
def LIT(x: Any) = Literal(Constant(x))
def TRUE = LIT(true)
def FALSE = LIT(false)
+ def NULL = LIT(null)
+ def UNIT = LIT(())
+ def ZERO = LIT(0)
def WILD = Ident(nme.WILDCARD)
+ case class ExpectApply(target: Tree) {
+ def apply(args: Tree*) = Apply(target, args.toList)
+ }
+
class TreeMethods(target: Tree) {
- private def binop(lhs: Tree, op: Name, rhs: Tree) = Apply(Select(lhs, op), List(rhs))
+ private def binop(lhs: Tree, op: Name, rhs: Tree) = Apply(Select(lhs, op), List(rhs))
+ private def binop(lhs: Tree, op: Symbol, rhs: Tree) = Apply(Select(lhs, op), List(rhs))
private def toAnyRef(x: Tree) = x setType AnyRefClass.tpe
- case class ExpectApply(target: Tree) {
- def apply(args: Tree*) = Apply(target, args.toList)
- }
-
/** logical/comparison ops **/
def OR(other: Tree) =
if (target == EmptyTree) other
@@ -42,8 +46,13 @@ trait TreeDSL {
else if (other == EmptyTree) target
else gen.mkAnd(target, other)
+ def BIT_AND(other: Tree) = binop(target, Int_And, other)
def EQREF(other: Tree) = binop(target, nme.eq, toAnyRef(other))
+ def NE_REF(other: Tree) = binop(target, nme.ne, other)
def EQEQ(other: Tree) = binop(target, nme.EQ, other)
+ def EQINT(other: Tree) = binop(target, Int_==, other)
+ def EQANY(other: Tree) = binop(target, Any_==, other)
+ def NOT_==(other: Tree) = binop(target, Object_ne, other)
/** Apply, Select, Match **/
def APPLY(params: List[Tree]) = Apply(target, params)
@@ -51,17 +60,45 @@ trait TreeDSL {
def DOT(member: Name) = ExpectApply(Select(target, member))
def DOT(sym: Symbol) = ExpectApply(Select(target, sym))
- /** Casting */
- def AS(tpe: Type) = TypeApply(Select(target, Any_asInstanceOf), List(TypeTree(tpe)))
- def TOSTRING() = Select(target, nme.toString_)
+ /** Assignment */
+ def ===(rhs: Tree) = Assign(target, rhs)
+
+ /** Casting & type tests -- working our way toward understanding exactly
+ * what differs between the different forms of IS and AS.
+ */
+ def AS(tpe: Type) = TypeApply(Select(target, Any_asInstanceOf), List(TypeTree(tpe)))
+ def AS_ATTR(tpe: Type) = gen.mkAttributedCast(target, tpe)
+
+ def IS(tpe: Type) = gen.mkIsInstanceOf(target, tpe, true)
+ def IS_OBJ(tpe: Type) = gen.mkIsInstanceOf(target, tpe, false)
+
+ def TOSTRING() = Apply(Select(target, nme.toString_), Nil)
+ def GETCLASS() = Apply(Select(target, Object_getClass), Nil)
}
class CaseStart(pat: Tree, guard: Tree) {
def IF(g: Tree): CaseStart = new CaseStart(pat, g)
- def ==>(body: Tree): CaseDef = CaseDef(pat, guard, body) // DSL for =>
+ def ==>(body: Tree): CaseDef = CaseDef(pat, guard, body)
+ }
+
+ abstract class ValOrDefStart(sym: Symbol) {
+ def ===(body: Tree): ValOrDefDef
+ }
+ class DefStart(sym: Symbol) extends ValOrDefStart(sym) {
+ def ===(body: Tree) = DefDef(sym, body)
+ }
+ class ValStart(sym: Symbol) extends ValOrDefStart(sym) {
+ def ===(body: Tree) = ValDef(sym, body)
+ }
+ class IfStart(cond: Tree, thenp: Tree) {
+ def THEN(x: Tree) = new IfStart(cond, x)
+ def ELSE(elsep: Tree) = If(cond, thenp, elsep)
+ def ENDIF = If(cond, thenp, EmptyTree)
}
- class DefStart(sym: Symbol) {
- def ===(body: Tree) = DefDef(sym, body) // DSL for =
+ class TryStart(body: Tree, catches: List[CaseDef], fin: Tree) {
+ def CATCH(xs: CaseDef*) = new TryStart(body, xs.toList, fin)
+ def FINALLY(x: Tree) = Try(body, catches, x)
+ def ENDTRY = Try(body, catches, fin)
}
def CASE(pat: Tree): CaseStart = new CaseStart(pat, EmptyTree)
@@ -73,6 +110,7 @@ trait TreeDSL {
class SymbolMethods(target: Symbol) {
def BIND(body: Tree) = Bind(target, body)
+ // def DOT(member: Symbol) = new TreeMethods(Ident(target)) DOT member
// name of nth indexed argument to a method (first parameter list), defaults to 1st
def ARG(idx: Int = 0) = Ident(target.paramss.head(idx))
@@ -81,12 +119,23 @@ trait TreeDSL {
}
/** Top level accessible. */
- def THROW(sym: Symbol, msg: Tree) = Throw(New(TypeTree(sym.tpe), List(List(msg.TOSTRING))))
+ def THROW(sym: Symbol, msg: Tree = null) = {
+ val arg = if (msg == null) Nil else List(msg.TOSTRING)
+ Throw(New(TypeTree(sym.tpe), List(arg)))
+ }
+ def NEW(tpe: Tree, args: Tree*) = New(tpe, List(args.toList))
+
+ def VAL(sym: Symbol) = new ValStart(sym)
def DEF(sym: Symbol) = new DefStart(sym)
def AND(guards: Tree*) =
if (guards.isEmpty) EmptyTree
else guards reduceLeft gen.mkAnd
+ def IF(tree: Tree) = new IfStart(tree, EmptyTree)
+ def TRY(tree: Tree) = new TryStart(tree, Nil, EmptyTree)
+ def REF(sym: Symbol) = gen.mkAttributedRef(sym)
+ def BLOCK(xs: Tree*) = Block(xs.init.toList, xs.last)
+
/** Implicits - some of these should probably disappear **/
implicit def mkTreeMethods(target: Tree): TreeMethods = new TreeMethods(target)
implicit def mkTreeMethodsFromSymbol(target: Symbol): TreeMethods = new TreeMethods(Ident(target))
diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala
index 221d08e824..dcdb284af2 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala
@@ -174,24 +174,28 @@ abstract class TreeGen {
}
/** Builds an instance test with given value and type. */
- def mkIsInstanceOf(value: Tree, tpe: Type): Tree = // buraq: we ignore erase, no rtt
+ def mkIsInstanceOf(value: Tree, tpe: Type, any: Boolean = true): Tree = {
+ val sym = if (any) Any_isInstanceOf else Object_isInstanceOf
Apply(
TypeApply(
- mkAttributedSelect(value, Any_isInstanceOf),
+ mkAttributedSelect(value, sym),
List(TypeTree(tpe.normalize))
),
Nil
)
+ }
/** Builds a cast with given value and type. */
- def mkAsInstanceOf(value: Tree, tpe: Type): Tree =
+ def mkAsInstanceOf(value: Tree, tpe: Type, any: Boolean = true): Tree = {
+ val sym = if (any) Any_asInstanceOf else Object_asInstanceOf
Apply(
TypeApply(
- mkAttributedSelect(value, Any_asInstanceOf),
+ mkAttributedSelect(value, sym),
List(TypeTree(tpe.normalize))
),
Nil
)
+ }
def mkClassOf(tp: Type): Tree =
Literal(Constant(tp)) setType Predef_classOfType(tp)
diff --git a/src/compiler/scala/tools/nsc/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala
index c1ac9e15aa..f1c6641dd0 100644
--- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala
+++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala
@@ -11,9 +11,10 @@ import Flags._
import scala.tools.nsc.util.Position
import scala.collection.mutable.{ListBuffer, HashMap}
-abstract class CleanUp extends Transform {
+abstract class CleanUp extends Transform with ast.TreeDSL {
import global._
import definitions._
+ import CODE._
/** the following two members override abstract members in Transform */
val phaseName: String = "cleanup"
@@ -22,7 +23,6 @@ abstract class CleanUp extends Transform {
new CleanUpTransformer(unit)
class CleanUpTransformer(unit: CompilationUnit) extends Transformer {
-
private val newDefs = new ListBuffer[Tree]
private val newInits = new ListBuffer[Tree]
@@ -46,40 +46,40 @@ abstract class CleanUp extends Transform {
private var localTyper: analyzer.Typer = null
- private def classConstantMethod(pos: Position, sig: String): Symbol = classConstantMeth.get(sig) match {
- case Some(meth) =>
- meth
- case None =>
+ private object MethodDispatchType extends scala.Enumeration {
+ val NO_CACHE, MONO_CACHE, POLY_CACHE = Value
+ }
+ import MethodDispatchType.{ NO_CACHE, MONO_CACHE, POLY_CACHE }
+ private def dispatchType() = settings.refinementMethodDispatch.value match {
+ case "no-cache" => NO_CACHE
+ case "mono-cache" => MONO_CACHE
+ case "poly-cache" => POLY_CACHE
+ }
+
+ private def typedWithPos(pos: Position)(tree: Tree) =
+ localTyper typed { atPos(pos)(tree) }
+
+ private def classConstantMethod(pos: Position, sig: String): Symbol =
+ (classConstantMeth get sig) getOrElse {
val forName = getMember(ClassClass.linkedModuleOfClass, nme.forName)
val owner = currentOwner.enclClass
val cvar = owner.newVariable(pos, unit.fresh.newName(pos, "class$Cache"))
.setFlag(PRIVATE | STATIC | MUTABLE | SYNTHETIC).setInfo(ClassClass.tpe)
- owner.info.decls.enter(cvar)
- val cdef =
- localTyper.typed {
- atPos(pos) {
- ValDef(cvar, Literal(Constant(null)))
- }
- }
+ owner.info.decls enter cvar
+ val cdef = typedWithPos(pos) { VAL(cvar) === NULL }
val meth = owner.newMethod(pos, unit.fresh.newName(pos, "class$Method"))
.setFlag(PRIVATE | STATIC | SYNTHETIC).setInfo(MethodType(List(), ClassClass.tpe))
- owner.info.decls.enter(meth)
- val mdef =
- localTyper.typed {
- atPos(pos) {
- DefDef(meth, gen.mkCached(
- cvar,
- Apply(
- gen.mkAttributedRef(forName), List(Literal(sig)))))
- }
- }
+ owner.info.decls enter meth
+ val mdef = typedWithPos(pos)(DEF(meth) ===
+ gen.mkCached(cvar, Apply(REF(forName), List(Literal(sig))))
+ )
- newDefs.append(cdef, mdef);
+ newDefs.append(cdef, mdef)
classConstantMeth.update(sig, meth)
meth
- }
+ }
override def transformUnit(unit: CompilationUnit) =
unit.body = transform(unit.body)
@@ -123,61 +123,55 @@ abstract class CleanUp extends Transform {
* refinement, where the refinement defines a parameter based on a
* type variable. */
case ad@ApplyDynamic(qual0, params) =>
+ def mkName(s: String = "") =
+ if (s == "") unit.fresh newName ad.pos
+ else unit.fresh.newName(ad.pos, s)
+ def mkTerm(s: String = "") = newTermName(mkName(s))
+ val typedPos = typedWithPos(ad.pos) _
+
assert(ad.symbol.isPublic)
var qual: Tree = qual0
/* ### CREATING THE METHOD CACHE ### */
def addStaticVariableToClass(forName: String, forType: Type, forInit: Tree): Symbol = {
- val varSym = currentClass.newVariable(ad.pos, unit.fresh.newName(ad.pos, forName))
+ val varSym = currentClass.newVariable(ad.pos, mkName(forName))
.setFlag(PRIVATE | STATIC | MUTABLE | SYNTHETIC)
.setInfo(forType)
- currentClass.info.decls.enter(varSym)
- val varDef =
- localTyper.typed {
- atPos(ad.pos) {
- ValDef(varSym, forInit)
- }
- }
- newDefs.append(transform(varDef))
- val varInit =
- localTyper.typed {
- atPos(ad.pos) {
- Assign(gen.mkAttributedRef(varSym), forInit)
- }
- }
- newInits.append(transform(varInit))
+ currentClass.info.decls enter varSym
+
+ val varDef = typedPos( VAL(varSym) === forInit )
+ newDefs append transform(varDef)
+
+ val varInit = typedPos( REF(varSym) === forInit )
+ newInits append transform(varInit)
+
varSym
}
def addStaticMethodToClass(forName: String, forArgsTypes: List[Type], forResultType: Type)
(forBody: Pair[Symbol, List[Symbol]] => Tree): Symbol = {
- val methSym = currentClass.newMethod(ad.pos, unit.fresh.newName(ad.pos, forName))
+ val methSym = currentClass.newMethod(ad.pos, mkName(forName))
.setFlag(STATIC | SYNTHETIC)
+
methSym.setInfo(MethodType(methSym.newSyntheticValueParams(forArgsTypes), forResultType))
- currentClass.info.decls.enter(methSym)
- val methDef =
- localTyper.typed {
- atPos(ad.pos) {
- DefDef(methSym, { forBody(Pair(methSym, methSym.paramss(0))) })
- }
- }
- newDefs.append(transform(methDef))
+ currentClass.info.decls enter methSym
+
+ val methDef = typedPos( DefDef(methSym, { forBody(Pair(methSym, methSym.paramss(0))) }) )
+ newDefs append transform(methDef)
+
methSym
}
def fromTypesToClassArrayLiteral(paramTypes: List[Type]): Tree =
- ArrayValue(TypeTree(ClassClass.tpe), paramTypes map { pt => Literal(Constant(pt)) })
+ ArrayValue(TypeTree(ClassClass.tpe), paramTypes map LIT)
def theTypeClassArray =
TypeRef(ArrayClass.tpe.prefix, ArrayClass, List(ClassClass.tpe))
/* ... */
- def reflectiveMethodCache(method: String, paramTypes: List[Type]): Symbol = {
-
- settings.refinementMethodDispatch.value match {
-
- case "no-cache" =>
+ def reflectiveMethodCache(method: String, paramTypes: List[Type]): Symbol = dispatchType match {
+ case NO_CACHE =>
/* Implementation of the cache is as follows for method "def xyz(a: A, b: B)":
@@ -191,21 +185,12 @@ abstract class CleanUp extends Transform {
val reflParamsCacheSym: Symbol =
addStaticVariableToClass("reflParams$Cache", theTypeClassArray, fromTypesToClassArrayLiteral(paramTypes))
- val reflMethodSym: Symbol =
- addStaticMethodToClass("reflMethod$Method", List(ClassClass.tpe), MethodClass.tpe)
- { case Pair(reflMethodSym, List(forReceiverSym)) =>
- Apply(
- Select(gen.mkAttributedRef(forReceiverSym), Class_getMethod),
- List(
- Literal(Constant(method)),
- gen.mkAttributedRef(reflParamsCacheSym)
- )
- )
- }
-
- reflMethodSym
+ addStaticMethodToClass("reflMethod$Method", List(ClassClass.tpe), MethodClass.tpe) {
+ case Pair(reflMethodSym, List(forReceiverSym)) =>
+ (REF(forReceiverSym) DOT Class_getMethod)(LIT(method), REF(reflParamsCacheSym))
+ }
- case "mono-cache" =>
+ case MONO_CACHE =>
/* Implementation of the cache is as follows for method "def xyz(a: A, b: B)":
@@ -229,47 +214,26 @@ abstract class CleanUp extends Transform {
addStaticVariableToClass("reflParams$Cache", theTypeClassArray, fromTypesToClassArrayLiteral(paramTypes))
val reflMethodCacheSym: Symbol =
- addStaticVariableToClass("reflMethod$Cache", MethodClass.tpe, Literal(Constant(null)))
+ addStaticVariableToClass("reflMethod$Cache", MethodClass.tpe, NULL)
val reflClassCacheSym: Symbol =
- addStaticVariableToClass("reflClass$Cache", ClassClass.tpe, Literal(Constant(null)))
-
-
- val reflMethodSym: Symbol =
- addStaticMethodToClass("reflMethod$Method", List(ClassClass.tpe), MethodClass.tpe)
- { case Pair(reflMethodSym, List(forReceiverSym)) =>
- Block(
- List(
- If(Apply(Select(gen.mkAttributedRef(reflClassCacheSym), nme.ne), List(gen.mkAttributedRef(forReceiverSym))),
- Block(
- List(
- Assign(
- gen.mkAttributedRef(reflMethodCacheSym),
- Apply(
- Select(
- gen.mkAttributedRef(forReceiverSym),
- ClassClass.tpe.member(nme.getMethod_)
- ),
- List(
- Literal(Constant(method)),
- gen.mkAttributedRef(reflParamsCacheSym)
- )
- )
- ),
- Assign(gen.mkAttributedRef(reflClassCacheSym), gen.mkAttributedRef(forReceiverSym))
- ),
- Literal(Constant(()))
- ),
- EmptyTree
- )
- ),
- gen.mkAttributedRef(reflMethodCacheSym)
- )
- }
-
- reflMethodSym
+ addStaticVariableToClass("reflClass$Cache", ClassClass.tpe, NULL)
+
+ def getMethodSym = ClassClass.tpe member nme.getMethod_
+
+ addStaticMethodToClass("reflMethod$Method", List(ClassClass.tpe), MethodClass.tpe) {
+ case Pair(reflMethodSym, List(forReceiverSym)) =>
+ BLOCK(
+ IF (REF(reflClassCacheSym) NE_REF REF(forReceiverSym)) THEN BLOCK(
+ REF(reflMethodCacheSym) === ((REF(forReceiverSym) DOT getMethodSym)(LIT(method), REF(reflParamsCacheSym))) ,
+ REF(reflClassCacheSym) === REF(forReceiverSym),
+ UNIT
+ ) ENDIF,
+ REF(reflMethodCacheSym)
+ )
+ }
- case "poly-cache" =>
+ case POLY_CACHE =>
/* Implementation of the cache is as follows for method "def xyz(a: A, b: B)":
@@ -294,53 +258,31 @@ abstract class CleanUp extends Transform {
addStaticVariableToClass("reflParams$Cache", theTypeClassArray, fromTypesToClassArrayLiteral(paramTypes))
val reflPolyCacheSym: Symbol =
- addStaticVariableToClass("reflPoly$Cache", MethodCacheClass.tpe, New(TypeTree(EmptyMethodCacheClass.tpe), List(Nil)))
+ addStaticVariableToClass("reflPoly$Cache", MethodCacheClass.tpe, NEW(TypeTree(EmptyMethodCacheClass.tpe)))
val reflMethodSym: Symbol =
addStaticMethodToClass("reflMethod$Method", List(ClassClass.tpe), MethodClass.tpe)
{ case Pair(reflMethodSym, List(forReceiverSym)) =>
- val methodSym = reflMethodSym.newVariable(ad.pos, newTermName(unit.fresh.newName(ad.pos, "method"))) setInfo MethodClass.tpe
- Block(
- List(
- ValDef(
- methodSym,
- Apply(
- Select(gen.mkAttributedRef(reflPolyCacheSym), methodCache_find),
- List(gen.mkAttributedRef(forReceiverSym))
- )
+ val methodSym = reflMethodSym.newVariable(ad.pos, mkTerm("method")) setInfo MethodClass.tpe
+
+ BLOCK(
+ VAL(methodSym) === ((REF(reflPolyCacheSym) DOT methodCache_find)(REF(forReceiverSym))) ,
+ IF (REF(methodSym) NOT_== NULL) .
+ THEN (Return(REF(methodSym)))
+ ELSE {
+ def methodSymRHS = ((REF(forReceiverSym) DOT Class_getMethod)(LIT(method), REF(reflParamsCacheSym)))
+ def cacheRHS = ((REF(reflPolyCacheSym) DOT methodCache_add)(REF(forReceiverSym), REF(methodSym)))
+ BLOCK(
+ REF(methodSym) === methodSymRHS,
+ REF(reflPolyCacheSym) === cacheRHS,
+ Return(REF(methodSym))
)
- ),
- If(
- Apply(Select(gen.mkAttributedRef(methodSym), Object_ne), List(Literal(Constant(null)))),
- Return(gen.mkAttributedRef(methodSym)),
- Block(
- List(
- Assign(gen.mkAttributedRef(methodSym),
- Apply(
- Select(gen.mkAttributedRef(forReceiverSym), Class_getMethod),
- List(
- Literal(Constant(method)),
- gen.mkAttributedRef(reflParamsCacheSym)
- )
- )
- ),
- Assign(
- gen.mkAttributedRef(reflPolyCacheSym),
- Apply(
- Select(gen.mkAttributedRef(reflPolyCacheSym), methodCache_add),
- List(gen.mkAttributedRef(forReceiverSym), gen.mkAttributedRef(methodSym))
- )
- )
- ),
- Return(gen.mkAttributedRef(methodSym))
- )
- )
+ }
)
}
reflMethodSym
- }
}
/* ### HANDLING METHODS NORMALLY COMPILED TO OPERATORS ### */
@@ -356,102 +298,55 @@ abstract class CleanUp extends Transform {
}
- val testForNumber: Tree =
- gen.mkOr(
- Apply(
- TypeApply(
- gen.mkAttributedSelect(qual, definitions.Object_isInstanceOf),
- List(TypeTree(BoxedNumberClass.tpe.normalize))
- ),
- List()
- ),
- Apply(
- TypeApply(
- gen.mkAttributedSelect(qual, definitions.Object_isInstanceOf),
- List(TypeTree(BoxedCharacterClass.tpe.normalize))
- ),
- List()
- )
+ val testForNumber: Tree = (qual IS_OBJ BoxedNumberClass.tpe) OR (qual IS_OBJ BoxedCharacterClass.tpe)
+ val testForBoolean: Tree = (qual IS_OBJ BoxedBooleanClass.tpe)
+ val testForNumberOrBoolean = testForNumber OR testForBoolean
+
+ val getPrimitiveReplacementForStructuralCall: PartialFunction[Name, (Symbol, Tree)] = {
+ val testsForNumber = Map() ++ List(
+ nme.UNARY_+ -> "positive",
+ nme.UNARY_- -> "negate",
+ nme.UNARY_~ -> "complement",
+ nme.ADD -> "add",
+ nme.SUB -> "subtract",
+ nme.MUL -> "multiply",
+ nme.DIV -> "divide",
+ nme.MOD -> "takeModulo",
+ nme.LSL -> "shiftSignedLeft",
+ nme.LSR -> "shiftLogicalRight",
+ nme.ASR -> "shiftSignedRight",
+ nme.LT -> "testLessThan",
+ nme.LE -> "testLessOrEqualThan",
+ nme.GE -> "testGreaterOrEqualThan",
+ nme.GT -> "testGreaterThan",
+ nme.toByte -> "toByte",
+ nme.toShort -> "toShort",
+ nme.toChar -> "toCharacter",
+ nme.toInt -> "toInteger",
+ nme.toLong -> "toLong",
+ nme.toFloat -> "toFloat",
+ nme.toDouble-> "toDouble"
)
-
- val testForBoolean: Tree =
- Apply(
- TypeApply(
- gen.mkAttributedSelect(qual, definitions.Object_isInstanceOf),
- List(TypeTree(BoxedBooleanClass.tpe.normalize))
- ),
- List()
+ val testsForBoolean = Map() ++ List(
+ nme.UNARY_! -> "takeNot",
+ nme.ZOR -> "takeConditionalOr",
+ nme.ZAND -> "takeConditionalAnd"
+ )
+ val testsForNumberOrBoolean = Map() ++ List(
+ nme.OR -> "takeOr",
+ nme.XOR -> "takeXor",
+ nme.AND -> "takeAnd",
+ nme.EQ -> "testEqual",
+ nme.NE -> "testNotEqual"
)
+ def get(name: String) = getMember(BoxesRunTimeClass, name)
- val testForNumberOrBoolean: Tree = gen.mkOr(testForNumber, testForBoolean)
-
- def getPrimitiveReplacementForStructuralCall: PartialFunction[Name, (Symbol, Tree)] = {
- /* Unary arithmetic */
- case nme.UNARY_+ =>
- (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("positive")), testForNumber)
- case nme.UNARY_- =>
- (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("negate")), testForNumber)
- /* Unary logic */
- case nme.UNARY_~ =>
- (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("complement")), testForNumber)
- case nme.UNARY_! =>
- (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("takeNot")), testForBoolean)
- /* Binary arithmetic */
- case nme.ADD =>
- (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("add")), testForNumber)
- case nme.SUB =>
- (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("subtract")), testForNumber)
- case nme.MUL =>
- (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("multiply")), testForNumber)
- case nme.DIV =>
- (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("divide")), testForNumber)
- case nme.MOD =>
- (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("takeModulo")), testForNumber)
- /* Binary logic */
- case nme.OR =>
- (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("takeOr")), testForNumberOrBoolean)
- case nme.XOR =>
- (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("takeXor")), testForNumberOrBoolean)
- case nme.AND =>
- (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("takeAnd")), testForNumberOrBoolean)
- case nme.ZOR =>
- (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("takeConditionalOr")), testForBoolean)
- case nme.ZAND =>
- (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("takeConditionalAnd")), testForBoolean)
- /* Shifting */
- case nme.LSL =>
- (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("shiftSignedLeft")), testForNumber)
- case nme.LSR =>
- (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("shiftLogicalRight")), testForNumber)
- case nme.ASR =>
- (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("shiftSignedRight")), testForNumber)
- case nme.EQ =>
- (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("testEqual")), testForNumberOrBoolean)
- case nme.NE =>
- (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("testNotEqual")), testForNumberOrBoolean)
- case nme.LT =>
- (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("testLessThan")), testForNumber)
- case nme.LE =>
- (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("testLessOrEqualThan")), testForNumber)
- case nme.GE =>
- (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("testGreaterOrEqualThan")), testForNumber)
- case nme.GT =>
- (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("testGreaterThan")), testForNumber)
- /* Conversions */
- case nme.toByte =>
- (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("toByte")), testForNumber)
- case nme.toShort =>
- (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("toShort")), testForNumber)
- case nme.toChar =>
- (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("toCharacter")), testForNumber)
- case nme.toInt =>
- (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("toInteger")), testForNumber)
- case nme.toLong =>
- (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("toLong")), testForNumber)
- case nme.toFloat =>
- (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("toFloat")), testForNumber)
- case nme.toDouble =>
- (definitions.getMember(definitions.BoxesRunTimeClass, newTermName("toDouble")), testForNumber)
+ /** Begin partial function. */
+ {
+ case x if testsForNumber contains x => (get(testsForNumber(x)), testForNumber)
+ case x if testsForBoolean contains x => (get(testsForBoolean(x)), testForBoolean)
+ case x if testsForNumberOrBoolean contains x => (get(testsForNumberOrBoolean(x)), testForNumberOrBoolean)
+ }
}
/* ### BOXING PARAMS & UNBOXING RESULTS ### */
@@ -466,35 +361,21 @@ abstract class CleanUp extends Transform {
* - otherwise, the value is simply casted to the expected type. This
* is enough even for value (int et al.) values as the result of
* a dynamic call will box them as a side-effect. */
- def fixResult(resType: Type)(tree: Tree): Tree =
- localTyper.typed {
- if (resType.typeSymbol == UnitClass)
- Block (
- List(tree),
- gen.mkAttributedRef(BoxedUnit_UNIT)
- )
- else if (resType.typeSymbol == ArrayClass) {
- val sym = currentOwner.newValue(ad.pos, newTermName(unit.fresh.newName(ad.pos))) setInfo ObjectClass.tpe
- Block(
- List(ValDef(sym, tree)),
- If(
- Apply(Select(Literal(Constant(null)), Any_==), List(gen.mkAttributedRef(sym))),
- Literal(Constant(null)),
- Apply(
- Select(
- gen.mkAttributedRef(ScalaRunTimeModule),
- ScalaRunTimeModule.tpe.member(nme.boxArray)
- ),
- List(gen.mkAttributedRef(sym))
- )
- )
- )
- }
- else if (resType.typeSymbol == ObjectClass) // TODO: remove the cast always when unnecessary.
- tree
- else
- gen.mkAttributedCast(tree, resType)
+ def fixResult(resType: Type)(tree: Tree): Tree = localTyper typed {
+ def boxArray = {
+ val sym = currentOwner.newValue(ad.pos, mkTerm()) setInfo ObjectClass.tpe
+ BLOCK(
+ VAL(sym) === tree,
+ IF (NULL EQANY REF(sym)) THEN NULL ELSE gen.mkRuntimeCall(nme.boxArray, List(REF(sym)))
+ )
}
+ resType.typeSymbol match {
+ case UnitClass => BLOCK(tree, REF(BoxedUnit_UNIT))
+ case ArrayClass => boxArray
+ case ObjectClass => tree
+ case _ => tree AS_ATTR resType
+ }
+ }
/* Transforms the parameters of a dynamic apply (always AnyRefs) to
* something compatible with reclective calls. The transformation depends
@@ -503,33 +384,23 @@ abstract class CleanUp extends Transform {
* type. If it is a boxed array, the array is unboxed. If it is an
* unboxed array, it is left alone. */
def fixParams(params: List[Tree], paramTypes: List[Type]): List[Tree] =
- (params zip paramTypes) map { case (param, paramType) =>
- localTyper.typed {
+ for ((param, paramType) <- params zip paramTypes) yield {
+ localTyper typed {
if (paramType.typeSymbol == ArrayClass) {
- val sym = currentOwner.newValue(ad.pos, newTermName(unit.fresh.newName(ad.pos))) setInfo ObjectClass.tpe
- val arrayType = {
- assert(paramType.typeArgs.length == 1)
- paramType.typeArgs(0).normalize
- }
- Block(
- List(ValDef(sym, param)),
- If(
- Apply(Select(Literal(Constant(null)), Any_==), List(gen.mkAttributedRef(sym))),
- Literal(Constant(null)),
- If(
- Apply(
- TypeApply(
- gen.mkAttributedSelect(gen.mkAttributedRef(sym), definitions.Object_isInstanceOf),
- List(TypeTree(BoxedArrayClass.tpe.normalize))
- ),
- List()
- ),
- Apply(
- Select(gen.mkAttributedCast(gen.mkAttributedRef(sym), BoxedArrayClass.tpe), getMember(BoxedArrayClass, nme.unbox)),
- List(Literal(Constant(arrayType)))
- ),
- gen.mkAttributedRef(sym)
- )
+ val sym = currentOwner.newValue(ad.pos, mkTerm()) setInfo ObjectClass.tpe
+ assert(paramType.typeArgs.length == 1)
+ val arrayType = paramType.typeArgs(0).normalize
+ lazy val unboxMethod = getMember(BoxedArrayClass, nme.unbox)
+
+ BLOCK(
+ VAL(sym) === param,
+ IF (NULL EQANY REF(sym)) .
+ THEN (NULL) .
+ ELSE (
+ IF (REF(sym) IS_OBJ BoxedArrayClass.tpe) .
+ THEN (((REF(sym) AS_ATTR BoxedArrayClass.tpe) DOT unboxMethod)(LIT(arrayType)))
+ ELSE
+ REF(sym)
)
)
}
@@ -539,50 +410,35 @@ abstract class CleanUp extends Transform {
}
/* ### CALLING THE APPLY -> one for operators (see above), one for normal methods ### */
-
- def callAsOperator(paramTypes: List[Type], resType: Type): Tree = localTyper.typed {
+ def callAsOperator(paramTypes: List[Type], resType: Type): Tree = localTyper typed {
+ def default = callAsMethod(paramTypes, resType)
if (getPrimitiveReplacementForStructuralCall isDefinedAt ad.symbol.name) {
- val (operator, test) = getPrimitiveReplacementForStructuralCall(ad.symbol.name)
- If(
- test,
- Apply(
- gen.mkAttributedRef(operator),
- qual :: fixParams(params, paramTypes)
- ),
- callAsMethod(paramTypes, resType)
- )
+ val (operator, test) = getPrimitiveReplacementForStructuralCall(ad.symbol.name)
+ def args = qual :: fixParams(params, paramTypes)
+
+ IF (test) THEN (REF(operator) APPLY args) ELSE default
}
- else callAsMethod(paramTypes, resType)
+ else default
}
def callAsMethod(paramTypes: List[Type], resType: Type): Tree = localTyper.typed {
- val invokeExc =
- currentOwner.newValue(ad.pos, newTermName(unit.fresh.newName(ad.pos))) setInfo InvocationTargetExceptionClass.tpe
- Try(
- Apply(
- Select(
- Apply(
- gen.mkAttributedRef(reflectiveMethodCache(ad.symbol.name.toString, paramTypes)),
- List(Apply(Select(qual, ObjectClass.tpe.member(nme.getClass_)), Nil))
- ),
- MethodClass.tpe.member(nme.invoke_)
- ),
- List(
- qual,
- ArrayValue(TypeTree(ObjectClass.tpe), fixParams(params, paramTypes))
- )
- ),
- List(CaseDef(
- Bind(invokeExc, Typed(Ident(nme.WILDCARD), TypeTree(InvocationTargetExceptionClass.tpe))),
- EmptyTree,
- Throw(Apply(Select(Ident(invokeExc), nme.getCause), Nil))
- )),
- EmptyTree
- )
+ // reflective method call machinery
+ val invokeName = MethodClass.tpe member nme.invoke_ // reflect.Method.invoke(...)
+ def cache = REF(reflectiveMethodCache(ad.symbol.name.toString, paramTypes)) // cache Symbol
+ def lookup = Apply(cache, List(qual GETCLASS)) // get Method object from cache
+ def args = ArrayValue(TypeTree(ObjectClass.tpe), fixParams(params, paramTypes)) // args for invocation
+ def invocation = (lookup DOT invokeName)(qual, args) // .invoke(qual, ...)
+
+ // exception catching machinery
+ val invokeExc = currentOwner.newValue(ad.pos, mkTerm()) setInfo InvocationTargetExceptionClass.tpe
+ def catchVar = Bind(invokeExc, Typed(Ident(nme.WILDCARD), TypeTree(InvocationTargetExceptionClass.tpe)))
+ def catchBody = Throw(Apply(Select(Ident(invokeExc), nme.getCause), Nil))
+
+ // try { method.invoke } catch { case e: InvocationTargetExceptionClass => throw e.getCause() }
+ TRY (invocation) CATCH { CASE (catchVar) ==> catchBody } ENDTRY
}
- def getClass(q: Tree): Tree =
- Apply(Select(q, nme.getClass_), List())
+ def getClass(q: Tree): Tree = (q DOT nme.getClass_)()
if (settings.refinementMethodDispatch.value == "invoke-dynamic") {
/* val guardCallSite: Tree = {
@@ -626,42 +482,39 @@ abstract class CleanUp extends Transform {
val t: Tree = ad.symbol.tpe match {
case MethodType(mparams, resType) =>
assert(params.length == mparams.length)
- atPos(ad.pos)(localTyper.typed {
- val t1 = newTermName(unit.fresh.newName(ad.pos, "qual"))
- val sym = currentOwner.newValue(ad.pos, t1) setInfo qual0.tpe
- qual = gen.mkAttributedRef(sym)
- Block(
- List(ValDef(sym, qual0)),
- fixResult(if (isValueClass(resType.typeSymbol)) boxedClass(resType.typeSymbol).tpe else resType) {
- if (mayRequirePrimitiveReplacement)
- callAsOperator(mparams map (_.tpe), resType)
- else
- callAsMethod(mparams map (_.tpe), resType)
- }
+ typedPos {
+ val sym = currentOwner.newValue(ad.pos, mkTerm("qual")) setInfo qual0.tpe
+ qual = REF(sym)
+
+ def resTypeForFix = if (isValueClass(resType.typeSymbol)) boxedClass(resType.typeSymbol).tpe else resType
+ def call = if (mayRequirePrimitiveReplacement) (callAsOperator _) else (callAsMethod _)
+ BLOCK(
+ VAL(sym) === qual0,
+ fixResult(resTypeForFix)(call(mparams map (_.tpe), resType))
)
- })
+ }
}
/* For testing purposes, the dynamic application's condition
* can be printed-out in great detail. Remove? */
if (settings.debug.value) {
- Console.println(
- "Dynamically applying '" + qual + "." + ad.symbol.name +
- "(" + params.map(_.toString).mkString(", ") + ")' with"
- )
- ad.symbol.tpe match {
+ def paramsToString(xs: Any*) = xs map (_.toString) mkString ", "
+ val mstr = ad.symbol.tpe match {
case MethodType(mparams, resType) =>
- Console.println(
- " - declared parameters' types: " +
- (mparams.map(_.toString)).mkString("'",", ","'"))
- Console.println(
- " - passed arguments' types: " +
- (params.map(_.toString)).mkString("'",", ","'"))
- Console.println(
- " - result type: '" +
- resType.toString + "'")
+ """| with
+ | - declared parameter types: '%s'
+ | - passed argument types: '%s'
+ | - result type: '%s'""" .
+ stripMargin.format(
+ paramsToString(mparams),
+ paramsToString(params),
+ resType.toString
+ )
+ case _ => ""
}
- Console.println(" - resulting code: '" + t + "'")
+ Console.printf("""Dynamically application '%s.%s(%s)' %s - resulting code: '%s'""",
+ List(qual, ad.symbol.name, paramsToString(params), mstr, t) map (_.toString) : _*
+ )
}
/* We return the dynamic call tree, after making sure no other
@@ -707,12 +560,10 @@ abstract class CleanUp extends Transform {
case Literal(c) if (c.tag == ClassTag) && !forMSIL=>
val tpe = c.typeValue
- atPos(tree.pos) {
- localTyper.typed {
- if (isValueClass(tpe.typeSymbol) || tpe.typeSymbol == definitions.UnitClass)
- Select(gen.mkAttributedRef(javaBoxClassModule(tpe.typeSymbol)), "TYPE")
- else tree
- }
+ typedWithPos(tree.pos) {
+ if (isValueClass(tpe.typeSymbol) || tpe.typeSymbol == definitions.UnitClass)
+ Select(REF(javaBoxClassModule(tpe.typeSymbol)), "TYPE")
+ else tree
}
/* MSIL requires that the stack is empty at the end of a try-block.
diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala
index d5ace3c4f6..2d3edf3a0e 100644
--- a/src/compiler/scala/tools/nsc/transform/Constructors.scala
+++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala
@@ -13,7 +13,7 @@ import util.TreeSet
/** This phase converts classes with parameters into Java-like classes with
* fields, which are assigned to from constructors.
*/
-abstract class Constructors extends Transform {
+abstract class Constructors extends Transform with ast.TreeDSL {
import global._
import definitions._
@@ -130,19 +130,16 @@ abstract class Constructors extends Transform {
// Create code to copy parameter to parameter accessor field.
// If parameter is $outer, check that it is not null.
def copyParam(to: Symbol, from: Symbol): Tree = {
+ import CODE._
var result = mkAssign(to, Ident(from))
if (from.name == nme.OUTER)
result =
atPos(to.pos) {
localTyper.typed {
- If(
- Apply(
- Select(Ident(from), nme.eq),
- List(Literal(Constant(null)))),
- Throw(New(TypeTree(NullPointerExceptionClass.tpe), List(List()))),
- result)
+ IF (from EQREF NULL) THEN THROW(NullPointerExceptionClass) ELSE result
}
}
+
result
}
diff --git a/src/compiler/scala/tools/nsc/transform/LazyVals.scala b/src/compiler/scala/tools/nsc/transform/LazyVals.scala
index ce5329e532..9707baf392 100644
--- a/src/compiler/scala/tools/nsc/transform/LazyVals.scala
+++ b/src/compiler/scala/tools/nsc/transform/LazyVals.scala
@@ -3,7 +3,7 @@ package scala.tools.nsc.transform;
import scala.tools.nsc._
import scala.collection.mutable.HashMap
-abstract class LazyVals extends Transform {
+abstract class LazyVals extends Transform with ast.TreeDSL {
// inherits abstract value `global' and class `Phase' from Transform
import global._ // the global environment
@@ -146,13 +146,10 @@ abstract class LazyVals extends Transform {
(Block(List(rhs, mkSetFlag(bitmapSym, mask)), Literal(Constant(()))), Literal(()))
}
+ import CODE._
+
val result = atPos(tree.pos) {
- If(Apply(
- Select(
- Apply(Select(Ident(bitmapSym), Int_And),
- List(mask)),
- Int_==),
- List(Literal(Constant(0)))), block, EmptyTree)
+ IF ((Ident(bitmapSym) BIT_AND mask) EQINT ZERO) THEN block ENDIF
}
typed(Block(List(result), res))
}