diff options
Diffstat (limited to 'src/compiler/scala/tools/nsc/ast/TreeGen.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/ast/TreeGen.scala | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala new file mode 100644 index 0000000000..425cf9eac8 --- /dev/null +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -0,0 +1,158 @@ +/* NSC -- new scala compiler + * Copyright 2005 LAMP/EPFL + * @author Martin Odersky + */ +// $Id$ +package scala.tools.nsc.ast; + +import scala.tools.nsc.util.Position; +import symtab.Flags._; + +abstract class TreeGen { + + val global: Global; + + import global._; + import definitions._; + import posAssigner.atPos; + + /** Builds a reference to value whose type is given stable prefix. + */ + def mkQualifier(tpe: Type): Tree = tpe match { + case NoPrefix => + EmptyTree + case ThisType(clazz) => + if (clazz.isRoot || clazz.isEmptyPackageClass) EmptyTree else This(clazz) + case SingleType(pre, sym) => + if (sym.isThisSkolem) { + mkQualifier(ThisType(sym.deSkolemize)) + } else { + val qual = mkStableRef(pre, sym); + qual.tpe match { + case MethodType(List(), restpe) => + Apply(qual, List()) setType restpe + case _ => + qual + } + } + case TypeRef(pre, sym, args) => + assert(phase.erasedTypes); + if (sym.isModuleClass && !sym.isRoot) { + val qual = Select(mkQualifier(sym.owner.tpe), sym.sourceModule); + qual.tpe match { + case MethodType(List(), restpe) => + Apply(qual, List()) setType restpe + case _ => + qual + } + } else This(sym) + } + + /** Builds a reference to given symbol with given stable prefix. */ + def mkRef(pre: Type, sym: Symbol): Tree = { + val qual = mkQualifier(pre); + if (qual == EmptyTree) Ident(sym) else Select(qual, sym) + } + + /** Builds a reference to given symbol. */ + def mkRef(sym: Symbol): Tree = + if (sym.owner.isClass) mkRef(sym.owner.thisType, sym) else Ident(sym); + + /** Replaces tree type with a stable type if possible */ + def stabilize(tree: Tree): Tree = tree match { + case Ident(_) => + if (tree.symbol.isStable) tree.setType(singleType(tree.symbol.owner.thisType, tree.symbol)) + else tree + case Select(qual, _) => + if (tree.symbol.isStable && qual.tpe.isStable) tree.setType(singleType(qual.tpe, tree.symbol)) + else tree + case _ => + tree + } + + /** Cast `tree' to type `pt' */ + def cast(tree: Tree, pt: Type): Tree = { + if (settings.debug.value) log("casting " + tree + ":" + tree.tpe + " to " + pt); + assert(!tree.tpe.isInstanceOf[MethodType], tree); + typer.typed { + atPos(tree.pos) { + Apply(TypeApply(Select(tree, Object_asInstanceOf), List(TypeTree(pt))), List()) + } + } + } + + /** Builds a reference with stable type to given symbol */ + def mkStableRef(pre: Type, sym: Symbol): Tree = stabilize(mkRef(pre, sym)); + def mkStableRef(sym: Symbol): Tree = stabilize(mkRef(sym)); + + def This(sym: Symbol): Tree = + global.This(sym.name) setSymbol sym setType sym.thisType; + + def Ident(sym: Symbol): Tree = { + assert(sym.isTerm); + global.Ident(sym.name) setSymbol sym setType sym.tpe; + } + + def Select(qual: Tree, sym: Symbol): Tree = + if (qual.symbol != null && + (qual.symbol.name.toTermName == nme.ROOT || + qual.symbol.name.toTermName == nme.EMPTY_PACKAGE_NAME)) { + this.Ident(sym) + } else { + assert(sym.isTerm); + val result = global.Select(qual, sym.name) setSymbol sym; + if (qual.tpe != null) result setType qual.tpe.memberType(sym); + result + } + + /** Builds an instance test with given value and type. */ + def mkIsInstanceOf(value: Tree, tpe: Type, erased: Boolean): Tree = { + val sym = + if(erased) + definitions.Any_isInstanceOfErased + else + definitions.Any_isInstanceOf; + Apply( + TypeApply( + Select(value, sym), + List(TypeTree(tpe))), + List()) + } + + def mkIsInstanceOf(value: Tree, tpe: Type): Tree = { + mkIsInstanceOf(value, tpe, global.phase.erasedTypes); + } + + /** Builds a cast with given value and type. */ + def mkAsInstanceOf(value: Tree, tpe: Type, erased: Boolean): Tree = { + val sym = + if(erased) + definitions.Any_asInstanceOfErased + else + definitions.Any_asInstanceOf; + + Apply( + TypeApply( + Select(value, sym), + List(TypeTree(tpe))), + List()) + } + + def mkAsInstanceOf(value: Tree, tpe: Type): Tree = { + mkAsInstanceOf(value, tpe, global.phase.erasedTypes); + } + + + /** Builds a list with given head and tail. */ + def mkNewCons(head: Tree, tail: Tree): Tree = + New(Apply(mkRef(definitions.ConsClass), List(head,tail))); + + /** Builds a list with given head and tail. */ + def mkNil: Tree = + mkRef(definitions.NilModule); + + /** Builds a pair */ + def mkNewPair(left: Tree, right: Tree) = + New(Apply(mkRef(definitions.TupleClass(2)), List(left,right))); + +} |