aboutsummaryrefslogtreecommitdiff
path: root/compiler/src/dotty/tools/dotc/ast/NavigateAST.scala
diff options
context:
space:
mode:
authorFelix Mulder <felix.mulder@gmail.com>2016-11-02 11:08:28 +0100
committerGuillaume Martres <smarter@ubuntu.com>2016-11-22 01:35:07 +0100
commit8a61ff432543a29234193cd1f7c14abd3f3d31a0 (patch)
treea8147561d307af862c295cfc8100d271063bb0dd /compiler/src/dotty/tools/dotc/ast/NavigateAST.scala
parent6a455fe6da5ff9c741d91279a2dc6fe2fb1b472f (diff)
downloaddotty-8a61ff432543a29234193cd1f7c14abd3f3d31a0.tar.gz
dotty-8a61ff432543a29234193cd1f7c14abd3f3d31a0.tar.bz2
dotty-8a61ff432543a29234193cd1f7c14abd3f3d31a0.zip
Move compiler and compiler tests to compiler dir
Diffstat (limited to 'compiler/src/dotty/tools/dotc/ast/NavigateAST.scala')
-rw-r--r--compiler/src/dotty/tools/dotc/ast/NavigateAST.scala82
1 files changed, 82 insertions, 0 deletions
diff --git a/compiler/src/dotty/tools/dotc/ast/NavigateAST.scala b/compiler/src/dotty/tools/dotc/ast/NavigateAST.scala
new file mode 100644
index 000000000..33aa87d8e
--- /dev/null
+++ b/compiler/src/dotty/tools/dotc/ast/NavigateAST.scala
@@ -0,0 +1,82 @@
+package dotty.tools.dotc
+package ast
+
+import core.Contexts.Context
+import core.Decorators._
+import util.Positions._
+import Trees.{MemberDef, DefTree}
+
+/** Utility functions to go from typed to untyped ASTs */
+object NavigateAST {
+
+ /** The untyped tree corresponding to typed tree `tree` in the compilation
+ * unit specified by `ctx`
+ */
+ def toUntyped(tree: tpd.Tree)(implicit ctx: Context): untpd.Tree =
+ untypedPath(tree, exactMatch = true) match {
+ case (utree: untpd.Tree) :: _ =>
+ utree
+ case _ =>
+ val loosePath = untypedPath(tree, exactMatch = false)
+ throw new
+ Error(i"""no untyped tree for $tree, pos = ${tree.pos}
+ |best matching path =\n$loosePath%\n====\n%
+ |path positions = ${loosePath.map(_.pos)}""")
+ }
+
+ /** The reverse path of untyped trees starting with a tree that closest matches
+ * `tree` and ending in the untyped tree at the root of the compilation unit
+ * specified by `ctx`.
+ * @param exactMatch If `true`, the path must start with a node that exactly
+ * matches `tree`, or `Nil` is returned.
+ * If `false` the path might start with a node enclosing
+ * the logical position of `tree`.
+ * Note: A complication concerns member definitions. ValDefs and DefDefs
+ * have after desugaring a position that spans just the name of the symbol being
+ * defined and nothing else. So we look instead for an untyped tree approximating the
+ * envelope of the definition, and declare success if we find another DefTree.
+ */
+ def untypedPath(tree: tpd.Tree, exactMatch: Boolean = false)(implicit ctx: Context): List[Positioned] =
+ tree match {
+ case tree: MemberDef[_] =>
+ untypedPath(tree.pos) match {
+ case path @ (last: DefTree[_]) :: _ => path
+ case path if !exactMatch => path
+ case _ => Nil
+ }
+ case _ =>
+ untypedPath(tree.pos) match {
+ case (path @ last :: _) if last.pos == tree.pos || !exactMatch => path
+ case _ => Nil
+ }
+ }
+
+ /** The reverse part of the untyped root of the compilation unit of `ctx` to
+ * position `pos`.
+ */
+ def untypedPath(pos: Position)(implicit ctx: Context): List[Positioned] =
+ pathTo(pos, ctx.compilationUnit.untpdTree)
+
+
+ /** The reverse path from node `from` to the node that closest encloses position `pos`,
+ * or `Nil` if no such path exists. If a non-empty path is returned it starts with
+ * the node closest enclosing `pos` and ends with `from`.
+ */
+ def pathTo(pos: Position, from: Positioned)(implicit ctx: Context): List[Positioned] = {
+ def childPath(it: Iterator[Any], path: List[Positioned]): List[Positioned] = {
+ while (it.hasNext) {
+ val path1 = it.next match {
+ case p: Positioned => singlePath(p, path)
+ case xs: List[_] => childPath(xs.iterator, path)
+ case _ => path
+ }
+ if (path1 ne path) return path1
+ }
+ path
+ }
+ def singlePath(p: Positioned, path: List[Positioned]): List[Positioned] =
+ if (p.pos contains pos) childPath(p.productIterator, p :: path)
+ else path
+ singlePath(from, Nil)
+ }
+} \ No newline at end of file