diff options
author | Felix Mulder <felix.mulder@gmail.com> | 2016-11-02 11:08:28 +0100 |
---|---|---|
committer | Guillaume Martres <smarter@ubuntu.com> | 2016-11-22 01:35:07 +0100 |
commit | 8a61ff432543a29234193cd1f7c14abd3f3d31a0 (patch) | |
tree | a8147561d307af862c295cfc8100d271063bb0dd /compiler/src/dotty/tools/dotc/ast/NavigateAST.scala | |
parent | 6a455fe6da5ff9c741d91279a2dc6fe2fb1b472f (diff) | |
download | dotty-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.scala | 82 |
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 |