diff options
author | Paul Phillips <paulp@improving.org> | 2009-06-28 14:36:34 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2009-06-28 14:36:34 +0000 |
commit | 979e774ef861656c40effd3ab973a54529844c78 (patch) | |
tree | 897cf033901b0af262d169f2cef5ef387bf1bb27 /src | |
parent | b3924e660b9644b20714d71673f3ebfb6e0db4af (diff) | |
download | scala-979e774ef861656c40effd3ab973a54529844c78.tar.gz scala-979e774ef861656c40effd3ab973a54529844c78.tar.bz2 scala-979e774ef861656c40effd3ab973a54529844c78.zip |
More fleshing out of code generation DSL.
consistent and reasonably aesthetic naming scheme for operators. Making
progress on consolidating the several different places where code
generation logic has been partially encapsulated.
Diffstat (limited to 'src')
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 )) |