summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/ast/TreeGen.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/scala/tools/nsc/ast/TreeGen.scala')
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeGen.scala158
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)));
+
+}