diff options
12 files changed, 196 insertions, 218 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreeDSL.scala b/src/compiler/scala/tools/nsc/ast/TreeDSL.scala index 1ef0a1bc69..884e54a21d 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeDSL.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeDSL.scala @@ -18,7 +18,9 @@ trait TreeDSL { import definitions._ object CODE { - def LIT(x: Any) = Literal(Constant(x)) + def LIT(x: Any) = Literal(Constant(x)) + def ID(sym: Symbol) = Ident(sym) setType sym.tpe + def TRUE = LIT(true) def FALSE = LIT(false) def NULL = LIT(null) @@ -26,13 +28,10 @@ trait TreeDSL { def ZERO = LIT(0) def WILD = Ident(nme.WILDCARD) - case class ExpectApply(target: Tree) { - def apply(args: Tree*) = Apply(target, args.toList) - } + def fn(lhs: Tree, op: Name, args: Tree*) = Apply(Select(lhs, op), args.toList) + def fn(lhs: Tree, op: Symbol, args: Tree*) = Apply(Select(lhs, op), 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: Symbol, rhs: Tree) = Apply(Select(lhs, op), List(rhs)) private def toAnyRef(x: Tree) = x setType AnyRefClass.tpe /** logical/comparison ops **/ @@ -46,19 +45,27 @@ 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) + def NE_REF(other: Tree) = fn(target, nme.ne, other) + def EQEQ(other: Tree) = fn(target, nme.EQ, other) + + def ANY_EQ (other: Tree) = fn(target, nme.eq, toAnyRef(other)) + def ANY_== (other: Tree) = fn(target, Any_==, other) + def OBJ_!= (other: Tree) = fn(target, Object_ne, other) + + def INT_| (other: Tree) = fn(target, getMember(IntClass, nme.OR), other) + def INT_& (other: Tree) = fn(target, getMember(IntClass, nme.AND), other) + def INT_== (other: Tree) = fn(target, getMember(IntClass, nme.EQ), other) + def INT_!= (other: Tree) = fn(target, getMember(IntClass, nme.NE), other) + + def BOOL_&& (other: Tree) = fn(target, getMember(BooleanClass, nme.ZAND), other) + def BOOL_|| (other: Tree) = fn(target, getMember(BooleanClass, nme.ZOR), other) /** Apply, Select, Match **/ + def APPLY(params: Tree*) = Apply(target, params.toList) def APPLY(params: List[Tree]) = Apply(target, params) def MATCH(cases: CaseDef*) = Match(target, cases.toList) - def DOT(member: Name) = ExpectApply(Select(target, member)) - def DOT(sym: Symbol) = ExpectApply(Select(target, sym)) + def DOT(member: Name) = SelectStart(Select(target, member)) + def DOT(sym: Symbol) = SelectStart(Select(target, sym)) /** Assignment */ def ===(rhs: Tree) = Assign(target, rhs) @@ -67,13 +74,18 @@ trait TreeDSL { * what differs between the different forms of IS and AS. */ def AS(tpe: Type) = TypeApply(Select(target, Any_asInstanceOf), List(TypeTree(tpe))) + def AS_ANY(tpe: Type) = gen.mkAsInstanceOf(target, 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) + def TOSTRING() = fn(target, nme.toString_) + def GETCLASS() = fn(target, Object_getClass) + } + + case class SelectStart(tree: Select) { + def apply(args: Tree*) = Apply(tree, args.toList) } class CaseStart(pat: Tree, guard: Tree) { @@ -110,7 +122,11 @@ trait TreeDSL { class SymbolMethods(target: Symbol) { def BIND(body: Tree) = Bind(target, body) - // def DOT(member: Symbol) = new TreeMethods(Ident(target)) DOT member + + // Option + def IS_DEFINED() = + if (target.tpe.typeSymbol == SomeClass) TRUE // is Some[_] + else NOT(ID(target) DOT nme.isEmpty) // is Option[_] // name of nth indexed argument to a method (first parameter list), defaults to 1st def ARG(idx: Int = 0) = Ident(target.paramss.head(idx)) @@ -135,6 +151,14 @@ trait TreeDSL { 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) + def NOT(tree: Tree) = Select(tree, getMember(BooleanClass, nme.UNARY_!)) + + // + // Unused, from the pattern matcher: + // def SEQELEM(tpe: Type): Type = (tpe.widen baseType SeqClass) match { + // case NoType => Predef.error("arg " + tpe + " not subtype of Seq[A]") + // case t => t typeArgs 0 + // } /** Implicits - some of these should probably disappear **/ implicit def mkTreeMethods(target: Tree): TreeMethods = new TreeMethods(target) @@ -146,5 +170,13 @@ trait TreeDSL { implicit def mkNameMethodsFromString(target: String): NameMethods = new NameMethods(target) implicit def mkSymbolMethodsFromSymbol(target: Symbol): SymbolMethods = new SymbolMethods(target) + + /** (foo DOT bar) might be simply a Select, but more likely it is to be immediately + * followed by an Apply. We don't want to add an actual apply method to arbitrary + * trees, so SelectStart is created with an apply - and if apply is not the next + * thing called, the implicit from SelectStart -> Tree will provide the tree. + */ + implicit def mkTreeFromSelectStart(ss: SelectStart): Select = ss.tree + implicit def mkTreeMethodsFromSelectStart(ss: SelectStart): TreeMethods = mkTreeMethods(ss.tree) } }
\ No newline at end of file diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala index dcdb284af2..ed3c842201 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -10,6 +10,9 @@ import scala.collection.mutable.ListBuffer import symtab.Flags._ import symtab.SymbolTable +/** XXX to resolve: TreeGen only assumes global is a SymbolTable, but + * TreeDSL at the moment expects a Global. Can we get by with SymbolTable? + */ abstract class TreeGen { val global: SymbolTable @@ -102,9 +105,9 @@ abstract class TreeGen { def mkAttributedRef(pre: Type, sym: Symbol): Tree = { val qual = mkAttributedQualifier(pre) qual match { - case EmptyTree => mkAttributedIdent(sym) + case EmptyTree => mkAttributedIdent(sym) case This(clazz) if (qual.symbol.isRoot || qual.symbol.isEmptyPackageClass) => mkAttributedIdent(sym) - case _ => mkAttributedSelect(qual, sym) + case _ => mkAttributedSelect(qual, sym) } } @@ -119,8 +122,7 @@ abstract class TreeGen { if (tree.symbol.isStable) tree.setType(singleType(tree.symbol.owner.thisType, tree.symbol)) else tree case Select(qual, _) => - assert(tree.symbol ne null) - assert(qual.tpe ne null) + assert((tree.symbol ne null) && (qual.tpe ne null)) if (tree.symbol.isStable && qual.tpe.isStable) tree.setType(singleType(qual.tpe, tree.symbol)) else tree @@ -135,9 +137,7 @@ abstract class TreeGen { assert(!pt.typeSymbol.isPackageClass) assert(!pt.typeSymbol.isPackageObjectClass) assert(pt eq pt.normalize) //@MAT only called during erasure, which already takes care of that - atPos(tree.pos) { - Apply(TypeApply(mkAttributedSelect(tree, Object_asInstanceOf), List(TypeTree(pt))), List()) - } + atPos(tree.pos)(mkAsInstanceOf(tree, pt, false)) } /** Builds a reference with stable type to given symbol */ @@ -150,59 +150,60 @@ abstract class TreeGen { def mkAttributedThis(sym: Symbol): Tree = This(sym.name) setSymbol sym setType sym.thisType - def mkAttributedIdent(sym: Symbol): Tree = { + def mkAttributedIdent(sym: Symbol): Tree = Ident(sym.name) setSymbol sym setType sym.tpe - } - def mkAttributedSelect(qual: Tree, sym: Symbol): Tree = - if ((qual.symbol ne null) && - (qual.symbol.name.toTermName == nme.ROOT || - qual.symbol.name.toTermName == nme.EMPTY_PACKAGE_NAME)) { - mkAttributedIdent(sym) - } else { - val qual1 = - if ((qual.tpe ne null) && - sym.owner.isPackageObjectClass && - sym.owner.owner == qual.tpe.typeSymbol) { - //println("insert package for "+qual+"/"+sym) - val pkgobj = sym.owner.sourceModule - Select(qual, nme.PACKAGEkw) setSymbol pkgobj setType singleType(qual.tpe, pkgobj) - } else qual - val result = Select(qual1, sym.name) setSymbol sym - if (qual1.tpe ne null) result setType qual.tpe.memberType(sym) - result + /** XXX this method needs a close analysis to identify its essential logical + * units - this attempt at modularization verges on the arbitrary. + */ + def mkAttributedSelect(qual: Tree, sym: Symbol): Tree = { + def tpe = qual.tpe + def isUnqualified(s: Symbol) = + s != null && (List(nme.ROOT, nme.EMPTY_PACKAGE_NAME) contains s.name.toTermName) + def isInPkgObject(s: Symbol) = + tpe != null && s.owner.isPackageObjectClass && s.owner.owner == tpe.typeSymbol + def getQualifier() = + if (!isInPkgObject(sym)) qual + else { + val pkgobj = sym.owner.sourceModule + Select(qual, nme.PACKAGEkw) setSymbol pkgobj setType singleType(tpe, pkgobj) + } + + if (isUnqualified(qual.symbol)) mkAttributedIdent(sym) + else { + val newQualifier = getQualifier() + def verifyType(tree: Tree) = + if (newQualifier.tpe == null) tree + else tree setType (tpe memberType sym) + + verifyType( Select(newQualifier, sym.name) setSymbol sym ) } + } - /** Builds an instance test with given value and type. */ - def mkIsInstanceOf(value: Tree, tpe: Type, any: Boolean = true): Tree = { - val sym = if (any) Any_isInstanceOf else Object_isInstanceOf + private def mkTypeApply(value: Tree, tpe: Type, what: Symbol) = Apply( TypeApply( - mkAttributedSelect(value, sym), + mkAttributedSelect(value, what), List(TypeTree(tpe.normalize)) ), Nil ) - } + /** Builds an instance test with given value and type. */ + def mkIsInstanceOf(value: Tree, tpe: Type, any: Boolean = true): Tree = + mkTypeApply(value, tpe, (if (any) Any_isInstanceOf else Object_isInstanceOf)) /** Builds a cast with given value and type. */ - def mkAsInstanceOf(value: Tree, tpe: Type, any: Boolean = true): Tree = { - val sym = if (any) Any_asInstanceOf else Object_asInstanceOf - Apply( - TypeApply( - mkAttributedSelect(value, sym), - List(TypeTree(tpe.normalize)) - ), - Nil - ) - } + def mkAsInstanceOf(value: Tree, tpe: Type, any: Boolean = true): Tree = + mkTypeApply(value, tpe, (if (any) Any_asInstanceOf else Object_asInstanceOf)) def mkClassOf(tp: Type): Tree = Literal(Constant(tp)) setType Predef_classOfType(tp) def mkCheckInit(tree: Tree): Tree = { - var tpe = tree.tpe - if (tpe == null && tree.hasSymbol) tpe = tree.symbol.tpe + val tpe = + if (tree.tpe != null || !tree.hasSymbol) tree.tpe + else tree.symbol.tpe + if (!global.phase.erasedTypes && settings.Xchecknull.value && tpe <:< NotNullClass.tpe && !tpe.isNotNull) mkRuntimeCall(nme.checkInitialized, List(tree)) @@ -212,23 +213,24 @@ abstract class TreeGen { /** Builds a list with given head and tail. */ def mkNewCons(head: Tree, tail: Tree): Tree = - New(Apply(mkAttributedRef(definitions.ConsClass), List(head, tail))) + New(Apply(mkAttributedRef(ConsClass), List(head, tail))) /** Builds a list with given head and tail. */ - def mkNil: Tree = - mkAttributedRef(definitions.NilModule) + def mkNil: Tree = mkAttributedRef(NilModule) /** Builds a tuple */ def mkTuple(elems: List[Tree]): Tree = if (elems.isEmpty) Literal(()) else Apply( - Select(mkAttributedRef(definitions.TupleClass(elems.length).caseModule), nme.apply), + Select(mkAttributedRef(TupleClass(elems.length).caseModule), nme.apply), elems) - def mkAnd(tree1: Tree, tree2: Tree) = + // tree1 AND tree2 + def mkAnd(tree1: Tree, tree2: Tree): Tree = Apply(Select(tree1, Boolean_and), List(tree2)) - def mkOr(tree1: Tree, tree2: Tree) = + // tree1 OR tree2 + def mkOr(tree1: Tree, tree2: Tree): Tree = Apply(Select(tree1, Boolean_or), List(tree2)) def mkCached(cvar: Symbol, expr: Tree): Tree = { @@ -278,7 +280,7 @@ abstract class TreeGen { /** Make a synchronized block on 'monitor'. */ def mkSynchronized(monitor: Tree, body: Tree): Tree = - Apply(Select(monitor, definitions.Object_synchronized), List(body)) + Apply(Select(monitor, Object_synchronized), List(body)) def wildcardStar(tree: Tree) = atPos(tree.pos) { Typed(tree, Ident(nme.WILDCARD_STAR.toTypeName)) } diff --git a/src/compiler/scala/tools/nsc/backend/ScalaPrimitives.scala b/src/compiler/scala/tools/nsc/backend/ScalaPrimitives.scala index fdaa1ad42c..3f53b2e77c 100644 --- a/src/compiler/scala/tools/nsc/backend/ScalaPrimitives.scala +++ b/src/compiler/scala/tools/nsc/backend/ScalaPrimitives.scala @@ -235,15 +235,12 @@ abstract class ScalaPrimitives { // scala.Boolean addPrimitives(BooleanClass, nme.EQ, EQ) addPrimitives(BooleanClass, nme.NE, NE) - addPrimitive(Boolean_not, ZNOT) - addPrimitive(Boolean_or, ZOR) - addPrimitive(Boolean_and, ZAND) + addPrimitives(BooleanClass, nme.UNARY_!, ZNOT) + addPrimitives(BooleanClass, nme.ZOR, ZOR) + addPrimitives(BooleanClass, nme.ZAND, ZAND) addPrimitives(BooleanClass, nme.OR, OR) addPrimitives(BooleanClass, nme.AND, AND) addPrimitives(BooleanClass, nme.XOR, XOR) -// addPrimitives(BooleanClass, nme.ADD, CONCAT) - // unary ! -// addPrimitives(BooleanClass, nme.UNARY_!, ZNOT) // scala.Byte addPrimitives(ByteClass, nme.EQ, EQ) diff --git a/src/compiler/scala/tools/nsc/matching/CodeFactory.scala b/src/compiler/scala/tools/nsc/matching/CodeFactory.scala index ece4518703..f62c5a0c7a 100644 --- a/src/compiler/scala/tools/nsc/matching/CodeFactory.scala +++ b/src/compiler/scala/tools/nsc/matching/CodeFactory.scala @@ -12,29 +12,21 @@ import scala.tools.nsc.util.Position * * @author Burak Emir */ -trait CodeFactory { +trait CodeFactory extends ast.TreeDSL +{ self: transform.ExplicitOuter with PatternNodes => import global.{typer => _, _} - import analyzer.Typer; + import analyzer.Typer - import definitions._ // standard classes and methods + import definitions._ import Code._ + import CODE._ /** Methods to simplify code generation */ object Code { - // function application - def fn(lhs: Tree, op: Name, args: Tree*) = Apply(Select(lhs, op), args.toList) - def fn(lhs: Tree, op: Symbol, args: Tree*) = Apply(Select(lhs, op), args.toList) - - val AND = definitions.Boolean_and - val NOT = definitions.Boolean_not - val SEQ = definitions.SeqClass - val SOME = definitions.SomeClass - val TRUE = Const(true) - val FALSE = Const(false) - val NULL = Const(null) + // val SOME = definitions.SomeClass object Const { def apply(x: Any) = Literal(Constant(x)) @@ -57,21 +49,6 @@ trait CodeFactory { final def mkIdent(sym: Symbol) = Ident(sym) setType sym.tpe final def mk_(tpe: Type) = Ident(nme.WILDCARD) setType tpe - /** returns A for T <: Sequence[ A ] - */ - final def getElemType_Sequence(tpe: Type): Type = { - val tpe1 = tpe.widen.baseType(SEQ) - if (tpe1 == NoType) - Predef.error("arg " + tpe + " not subtype of Seq[A]") - - tpe1.typeArgs(0) - } - - // Option fullness check - final def nonEmptinessCheck(vsym: Symbol) = - if (vsym.tpe.typeSymbol == SOME) TRUE // is Some[_] - else Not(Select(mkIdent(vsym), nme.isEmpty)) // is Option[_] - /** for tree of sequence type, returns tree that drops first i elements */ final def seqDrop(sel:Tree, ix: Int)(implicit typer : Typer) = if (ix == 0) sel else @@ -95,8 +72,6 @@ trait CodeFactory { final def Equals (left: Tree, right: Tree): Tree = fn(left, nme.EQ, right) final def Eq (left: Tree, right: Tree): Tree = fn(left, nme.eq, right) final def GTE (left: Tree, right: Tree): Tree = fn(left, nme.GE, right) // >= - final def And (terms: Tree*): Tree = terms.reduceLeft((left, right) => fn(left, AND, right)) - final def Not (arg: Tree): Tree = Select(arg, NOT) final def ThrowMatchError(pos: Position, obj: Tree) = atPos(pos) { Throw( New(TypeTree(MatchErrorClass.tpe), List(List(obj))) ) diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala index d821bc4956..b497dcf185 100644 --- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala +++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala @@ -30,14 +30,15 @@ import MatchUtil._ * * @author Burak Emir */ -trait ParallelMatching { +trait ParallelMatching extends ast.TreeDSL { self: transform.ExplicitOuter with PatternNodes with CodeFactory => import global.{typer => _, _} import analyzer.Typer; import symtab.Flags import Types._ - import Code.{ fn, Const } + import Code.Const + import CODE._ /** * Encapsulates a symbol being matched on. @@ -56,7 +57,7 @@ trait ParallelMatching { def mkList(prefix: List[Symbol], suffix: List[Symbol]) = prefix ::: sym :: suffix def isDefined = sym ne NoSymbol def accessors = sym.caseFieldAccessors - def id = mkIdent(sym) + def id = ID(sym) def tpe = sym.tpe def pos = sym.pos def isChar = tpe.widen.isChar @@ -292,10 +293,11 @@ trait ParallelMatching { val (branches, defaultV, defaultRep) = this.getTransition // tag body pairs val cases = for ((tag, r) <- branches) yield { val r2 = rep.make(r.temp, r.row.map(x => x.rebind(bindVars(tag, x.subst)))) - CaseDef(Literal(tag), EmptyTree, r2.toTree) + + CASE(Literal(tag)) ==> r2.toTree } - lazy val ndefault = defaultRep.map(_.toTree) getOrElse failTree - lazy val casesWithDefault = cases ::: List(CaseDef(mk_(definitions.IntClass.tpe), EmptyTree, ndefault)) + lazy val ndefault = defaultRep.map(_.toTree) getOrElse failTree + lazy val casesWithDefault = cases ::: List(CASE(mk_(definitions.IntClass.tpe)) ==> ndefault) cases match { case CaseDef(lit,_,body) :: Nil => If(Equals(scrut.id, lit), body, ndefault) @@ -354,19 +356,19 @@ trait ParallelMatching { val vtpe = app.tpe.typeArgs(0) val vsym = newVarCapture(ua.pos, vtpe) val nrows = mkNewRows((xs) => List(xs.head), 1) - val vdef = typedValDef(vsym, Get(mkIdent(ures))) + val vdef = typedValDef(vsym, Get(ID(ures))) mkTransition(List(vdef), List(vsym), nrows) case _ => // app.tpe is Option[? <: ProductN[T1,...,Tn]] val uresGet = newVarCapture(ua.pos, app.tpe.typeArgs(0)) - val vdefHead = typedValDef(uresGet, Get(mkIdent(ures))) + val vdefHead = typedValDef(uresGet, Get(ID(ures))) val ts = definitions.getProductArgs(uresGet.tpe).get val nrows = mkNewRows(identity, ts.size) val (vdefs: List[Tree], vsyms: List[Symbol]) = List.unzip( for ((vtpe, i) <- ts.zip((1 to ts.size).toList)) yield { val vchild = newVarCapture(ua.pos, vtpe) val accSym = definitions.productProj(uresGet, i) - val rhs = typer.typed(Code.fn(mkIdent(uresGet), accSym)) + val rhs = typer.typed(fn(ID(uresGet), accSym)) (typedValDef(vchild, rhs), vchild) }) @@ -379,8 +381,8 @@ trait ParallelMatching { val succ = srep.toTree val fail = frep.map(_.toTree) getOrElse failTree val cond = - if (uacall.symbol.tpe.isBoolean) typer.typed(mkIdent(uacall.symbol)) - else nonEmptinessCheck(uacall.symbol) + if (uacall.symbol.tpe.isBoolean) typer.typed(ID(uacall.symbol)) + else uacall.symbol IS_DEFINED typer.typed( squeezedBlock(List(rep.handleOuter(uacall)), If(cond,squeezedBlock(vdefs,succ),fail)) ) } @@ -609,7 +611,7 @@ trait ParallelMatching { val caseTemps = srep.temp match { case x :: xs if x == casted.sym => xs ; case x => x } var vdefs = for ((tmp, accessorMethod) <- caseTemps.zip(cfa)) yield { - val untypedAccess = Code.fn(casted.id, accessorMethod) + val untypedAccess = fn(casted.id, accessorMethod) val typedAccess = typer.typed(untypedAccess) typedValDef(tmp, typedAccess) } @@ -701,10 +703,9 @@ trait ParallelMatching { case If(cond, Const(true), Const(false)) => super.transform(cond) case If(cond1, If(cond2, thenp, elsep1), elsep2) if (elsep1 equalsStructure elsep2) => - super.transform(If(And(cond1,cond2), thenp, elsep1)) + super.transform( IF (cond1 AND cond2) THEN thenp ELSE elsep1 ) case If(cond1, If(cond2, thenp, Apply(jmp,List())), ld:LabelDef) if (jmp.symbol eq ld.symbol) => - super.transform(If(And(cond1,cond2), thenp, ld)) - + super.transform( IF (cond1 AND cond2) THEN thenp ELSE ld ) case t => super.transform(t) } } @@ -731,7 +732,7 @@ trait ParallelMatching { final def requestBody(bx: Int, subst: Bindings)(implicit theOwner: Symbol): Tree = { if (bx < 0) { // is shortcut val jlabel = shortCuts(-bx-1) - return Apply(mkIdent(jlabel), Nil) + return Apply(ID(jlabel), Nil) } if (!isReached(bx)) { // first time this bx is requested // might be bound elsewhere ( see `x @ unapply' ) <-- this comment refers to null check @@ -777,7 +778,7 @@ trait ParallelMatching { val vdefs = for (v <- vss(bx) ; substv <- subst(v)) yield typedValDef(v, substv) squeezedBlock(vdefs, body.duplicate setType resultType) case _ => - Apply(mkIdent(label),args) + Apply(ID(label), args) } } @@ -1015,7 +1016,7 @@ trait ParallelMatching { outerAccessor(tpe2test.typeSymbol) match { case NoSymbol => if (settings.debug.value) cunit.warning(scrut.pos, "no outer acc for "+tpe2test.typeSymbol) ; cond - case outerAcc => And(cond, Eq(Code.fn(gen.mkAsInstanceOf(scrut, tpe2test), outerAcc), theRef)) + case outerAcc => cond AND (((scrut AS_ANY tpe2test) DOT outerAcc)() ANY_EQ theRef) } } diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala index 56c19e8fc7..4254ec4800 100644 --- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala +++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala @@ -86,14 +86,10 @@ trait Definitions { lazy val FloatClass = newValueClass(nme.Float, 'F') lazy val DoubleClass = newValueClass(nme.Double, 'D') - // some value class conveniences - def Boolean_not = getMember(BooleanClass, nme.UNARY_!) + // XXX the class-specific member symbols need to be grouped somewhere + // associated with that class. def Boolean_and = getMember(BooleanClass, nme.ZAND) def Boolean_or = getMember(BooleanClass, nme.ZOR) - def Int_Or = getMember(IntClass, nme.OR) - def Int_And = getMember(IntClass, nme.AND) - def Int_== = getMember(IntClass, nme.EQ) - def Int_!= = getMember(IntClass, nme.NE) // the scala reference classes lazy val ScalaObjectClass: Symbol = getClass("scala.ScalaObject") diff --git a/src/compiler/scala/tools/nsc/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala index f1c6641dd0..4313ec5f8e 100644 --- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala +++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala @@ -267,7 +267,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { BLOCK( VAL(methodSym) === ((REF(reflPolyCacheSym) DOT methodCache_find)(REF(forReceiverSym))) , - IF (REF(methodSym) NOT_== NULL) . + IF (REF(methodSym) OBJ_!= NULL) . THEN (Return(REF(methodSym))) ELSE { def methodSymRHS = ((REF(forReceiverSym) DOT Class_getMethod)(LIT(method), REF(reflParamsCacheSym))) @@ -366,7 +366,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { 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))) + IF (NULL ANY_== REF(sym)) THEN NULL ELSE gen.mkRuntimeCall(nme.boxArray, List(REF(sym))) ) } resType.typeSymbol match { @@ -394,7 +394,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { BLOCK( VAL(sym) === param, - IF (NULL EQANY REF(sym)) . + IF (NULL ANY_== REF(sym)) . THEN (NULL) . ELSE ( IF (REF(sym) IS_OBJ BoxedArrayClass.tpe) . diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala index 2d3edf3a0e..0331766b80 100644 --- a/src/compiler/scala/tools/nsc/transform/Constructors.scala +++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala @@ -136,7 +136,7 @@ abstract class Constructors extends Transform with ast.TreeDSL { result = atPos(to.pos) { localTyper.typed { - IF (from EQREF NULL) THEN THROW(NullPointerExceptionClass) ELSE result + IF (from ANY_EQ NULL) THEN THROW(NullPointerExceptionClass) ELSE result } } diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala index 6cdadc758a..1a8c52c118 100644 --- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala +++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala @@ -16,7 +16,14 @@ import matching.{TransMatcher, PatternNodes, CodeFactory, ParallelMatching} * @author Martin Odersky * @version 1.0 */ -abstract class ExplicitOuter extends InfoTransform with TransMatcher with PatternNodes with CodeFactory with ParallelMatching with TypingTransformers { +abstract class ExplicitOuter extends InfoTransform + with TransMatcher + with PatternNodes + with CodeFactory + with ParallelMatching + with TypingTransformers + with ast.TreeDSL +{ import global._ import definitions._ diff --git a/src/compiler/scala/tools/nsc/transform/LazyVals.scala b/src/compiler/scala/tools/nsc/transform/LazyVals.scala index 9707baf392..21370c3176 100644 --- a/src/compiler/scala/tools/nsc/transform/LazyVals.scala +++ b/src/compiler/scala/tools/nsc/transform/LazyVals.scala @@ -28,8 +28,6 @@ abstract class LazyVals extends Transform with ast.TreeDSL { * Transform local lazy accessors to check for the initialized bit. */ class LazyValues(unit: CompilationUnit) extends Transformer { - - import definitions.{Int_And, Int_Or, Int_==} /** map from method symbols to the number of lazy values it defines. */ private val lazyVals = new HashMap[Symbol, Int] { override def default(meth: Symbol) = 0 @@ -106,6 +104,8 @@ abstract class LazyVals extends Transform with ast.TreeDSL { } } + import CODE._ + /** return a 'lazified' version of rhs. Rhs should conform to the * following schema: * { @@ -146,18 +146,14 @@ abstract class LazyVals extends Transform with ast.TreeDSL { (Block(List(rhs, mkSetFlag(bitmapSym, mask)), Literal(Constant(()))), Literal(())) } - import CODE._ - val result = atPos(tree.pos) { - IF ((Ident(bitmapSym) BIT_AND mask) EQINT ZERO) THEN block ENDIF + IF ((Ident(bitmapSym) INT_& mask) INT_== ZERO) THEN block ENDIF } typed(Block(List(result), res)) } private def mkSetFlag(bmp: Symbol, mask: Tree): Tree = - Assign(Ident(bmp), - Apply(Select(Ident(bmp), Int_Or), List(mask))) - + Ident(bmp) === (Ident(bmp) INT_| mask) final val FLAGS_PER_WORD = 32 val bitmaps = new HashMap[Symbol, List[Symbol]] { diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index 3dc9588208..56bcd34cd2 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -12,9 +12,10 @@ import scala.collection.mutable.ListBuffer import scala.tools.nsc.util.{Position,NoPosition} import scala.collection.mutable.HashMap -abstract class Mixin extends InfoTransform { +abstract class Mixin extends InfoTransform with ast.TreeDSL { import global._ import definitions._ + import CODE._ /** The name of the phase: */ val phaseName: String = "mixin" @@ -381,6 +382,7 @@ abstract class Mixin extends InfoTransform { /** The typer */ private var localTyper: erasure.Typer = _ + private def typedPos(pos: Position)(tree: Tree) = localTyper typed { atPos(pos)(tree) } import scala.collection._ @@ -489,7 +491,7 @@ abstract class Mixin extends InfoTransform { /** Attribute given tree and anchor at given position */ def attributedDef(pos: Position, tree: Tree): Tree = { if (settings.debug.value) log("add new def to " + clazz + ": " + tree) - localTyper.typed { atPos(pos) { tree } } + typedPos(pos)(tree) } /** The position of given symbol, or, if this is undefined, @@ -576,19 +578,20 @@ abstract class Mixin extends InfoTransform { /** Return an (untyped) tree of the form 'Clazz.this.bmp = Clazz.this.bmp | mask'. */ def mkSetFlag(clazz: Symbol, offset: Int): Tree = { val bmp = bitmapFor(clazz, offset) - val mask = Literal(Constant(1 << (offset % FLAGS_PER_WORD))) + val mask = LIT(1 << (offset % FLAGS_PER_WORD)) + def x = This(clazz) DOT bmp - Assign(Select(This(clazz), bmp), - Apply(Select(Select(This(clazz), bmp), Int_Or), List(mask))) + x === (x INT_| mask) } /** Return an (untyped) tree of the form 'clazz.this.bitmapSym & mask (==|!=) 0', the * precise comparison operator depending on the value of 'equalToZero'. */ - def mkTest(clazz: Symbol, mask: Tree, bitmapSym: Symbol, equalToZero: Boolean): Tree = - Apply(Select(Apply(Select(Select(This(clazz), bitmapSym), Int_And), List(mask)), - if (equalToZero) Int_== else Int_!=), - List(Literal(Constant(0)))) + def mkTest(clazz: Symbol, mask: Tree, bitmapSym: Symbol, equalToZero: Boolean): Tree = { + def lhs = (This(clazz) DOT bitmapSym) INT_& mask + if (equalToZero) lhs INT_== ZERO + else lhs INT_!= ZERO + } /** return a 'lazified' version of rhs. * @param clazz The class symbol @@ -612,31 +615,30 @@ abstract class Mixin extends InfoTransform { * the 'n' is (offset / 32), the MASK is (1 << (offset % 32)). */ def mkLazyDef(clazz: Symbol, init: List[Tree], retVal: Tree, offset: Int): Tree = { - val bitmapSym = bitmapFor(clazz, offset) + val mask = LIT(1 << (offset % FLAGS_PER_WORD)) + def cond = mkTest(clazz, mask, bitmapSym, true) + def syncBody = init ::: List(mkSetFlag(clazz, offset), UNIT) + + val result = + IF (cond) THEN gen.mkSynchronized( + gen mkAttributedThis clazz, + IF (cond) THEN BLOCK(syncBody: _*) ENDIF + ) ENDIF - val mask = Literal(Constant(1 << (offset % FLAGS_PER_WORD))) - val result = - If(mkTest(clazz, mask, bitmapSym, true), - gen.mkSynchronized(gen.mkAttributedThis(clazz), - If(mkTest(clazz, mask, bitmapSym, true), - Block(init ::: - List(mkSetFlag(clazz, offset)), - Literal(Constant(()))), - EmptyTree)), - EmptyTree) - localTyper.typed(atPos(init.head.pos)(Block(List(result), retVal))) + typedPos(init.head.pos)(BLOCK(result, retVal)) } def mkCheckedAccessor(clazz: Symbol, retVal: Tree, offset: Int, pos: Position): Tree = { val bitmapSym = bitmapFor(clazz, offset) - val mask = Literal(Constant(1 << (offset % FLAGS_PER_WORD))) - val msg = "Uninitialized field: " + unit.source + ": " + pos.line.get - val result = - If(mkTest(clazz, mask, bitmapSym, false), - retVal, - Throw(New(TypeTree(definitions.UninitializedErrorClass.tpe), List(List(Literal(Constant(msg))))))) - localTyper.typed(atPos(pos)(Block(List(result), retVal))) + val mask = LIT(1 << (offset % FLAGS_PER_WORD)) + val msg = "Uninitialized field: " + unit.source + ": " + pos.line.get + val result = + IF (mkTest(clazz, mask, bitmapSym, false)) . + THEN (retVal) . + ELSE (THROW(UninitializedErrorClass, LIT(msg))) + + typedPos(pos)(BLOCK(result, retVal)) } /** Complete lazy field accessors. Applies only to classes, for it's own (non inherited) lazy fields. @@ -911,11 +913,8 @@ abstract class Mixin extends InfoTransform { def staticCall(target: Symbol) = { if (target == NoSymbol) assert(false, "" + sym + ":" + sym.tpe + " " + sym.owner + " " + implClass(sym.owner) + " " + implClass(sym.owner).info.member(sym.name) + " " + atPhase(phase.prev)(implClass(sym.owner).info.member(sym.name).tpe) + " " + phase);//debug - localTyper.typed { - atPos(tree.pos) { - Apply(staticRef(target), transformSuper(qual) :: args) - } - } + + typedPos(tree.pos)(Apply(staticRef(target), transformSuper(qual) :: args)) } if (isStaticOnly(sym)) { // change calls to methods which are defined only in implementation @@ -934,12 +933,9 @@ abstract class Mixin extends InfoTransform { if (sym.hasFlag(ACCESSOR)) { assert(args.isEmpty) val sym1 = sym.overridingSymbol(currentOwner.enclClass) - localTyper.typed { - atPos(tree.pos) { - Apply(Select(transformSuper(qual), sym1), List()) - } - } - } else { + typedPos(tree.pos)((transformSuper(qual) DOT sym1)()) + } + else { staticCall(atPhase(phase.prev)(sym.overridingSymbol(implClass(sym.owner)))) } } else { @@ -959,49 +955,25 @@ abstract class Mixin extends InfoTransform { tree case Select(qual, name) if sym.owner.isImplClass && !isStaticOnly(sym) => + assert(!sym.isMethod, "no method allowed here: %s%s %s".format(sym, sym.isImplOnly, flagsToString(sym.flags))) + // refer to fields in some implementation class via an abstract // getter in the interface. - - if (sym.isMethod) - assert(false, "no method allowed here: " + sym + sym.isImplOnly + - " " + flagsToString(sym.flags)) val iface = toInterface(sym.owner.tpe).typeSymbol val getter = sym.getter(iface) assert(getter != NoSymbol) - localTyper.typed { - atPos(tree.pos) { - Apply(Select(qual, getter), List()) - } - } + typedPos(tree.pos)((qual DOT getter)()) case Assign(Apply(lhs @ Select(qual, _), List()), rhs) => // assign to fields in some implementation class via an abstract // setter in the interface. - localTyper.typed { -/* - println(lhs.symbol) - println(lhs.symbol.owner.info.decls) - println(needsExpandedSetterName(lhs.symbol)) - println(toInterface(lhs.symbol.owner.tpe).typeSymbol) - println(toInterface(lhs.symbol.owner.tpe).typeSymbol.info.decls) - util.trace("generating tree: ") { -*/ - atPos(tree.pos) { - Apply( - Select( - qual, - lhs.symbol.setter( - toInterface(lhs.symbol.owner.tpe).typeSymbol, - needsExpandedSetterName(lhs.symbol))) setPos lhs.pos, - List(rhs)) - } -// } - } -/* //DEBUG - case Ident(name) if (name.toString == "xxx") => - println(tree+":"+tree.tpe+"/"+tree.tpe.baseClasses) - tree -*/ + def setter = lhs.symbol.setter( + toInterface(lhs.symbol.owner.tpe).typeSymbol, + needsExpandedSetterName(lhs.symbol) + ) setPos lhs.pos + + typedPos(tree.pos) { (qual DOT setter)(rhs) } + case _ => tree } diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala index 5809b56f30..010171effe 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala @@ -116,7 +116,7 @@ trait SyntheticMethods extends ast.TreeDSL { name, 0, makeTypeConstructor(paramtypes, target.tpe.resultType) ) - typer.typed { + typer typed { DEF(method) === { Apply(gen.mkAttributedRef(target), This(clazz) :: (method ARGNAMES)) } @@ -171,11 +171,11 @@ trait SyntheticMethods extends ast.TreeDSL { val (guards, params) = List.map2(clazz.caseFieldAccessors, constrParamTypes)(makeTrees) unzip // Pattern is classname applied to parameters, and guards are all logical and-ed - val (guard, pat) = (AND(guards : _*), clazz.name.toTermName APPLY params) + val (guard, pat) = (AND(guards: _*), clazz.name.toTermName APPLY params) localTyper typed { DEF(method) === { - (This(clazz) EQREF that) OR (that MATCH( + (This(clazz) ANY_EQ that) OR (that MATCH( (CASE(pat) IF guard) ==> TRUE , DEFAULT ==> FALSE )) |