summaryrefslogtreecommitdiff
path: root/sources/scalac/ast/printer/TextTreePrinter.java
diff options
context:
space:
mode:
Diffstat (limited to 'sources/scalac/ast/printer/TextTreePrinter.java')
-rw-r--r--sources/scalac/ast/printer/TextTreePrinter.java683
1 files changed, 683 insertions, 0 deletions
diff --git a/sources/scalac/ast/printer/TextTreePrinter.java b/sources/scalac/ast/printer/TextTreePrinter.java
new file mode 100644
index 0000000000..c5138d025f
--- /dev/null
+++ b/sources/scalac/ast/printer/TextTreePrinter.java
@@ -0,0 +1,683 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+** **
+\* */
+
+// $Id$
+
+package scalac.ast.printer;
+
+import scalac.ast.*;
+import scalac.symtab.*;
+import scalac.util.Debug;
+import scalac.Global;
+import scalac.Unit;
+import scalac.util.Name;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * Text pretty printer for Scala abstract syntax trees.
+ *
+ * @author Michel Schinz, Matthias Zenger
+ * @version 1.0
+ */
+public class TextTreePrinter implements TreePrinter {
+ protected PrintWriter out;
+
+ protected int indent = 0;
+ protected final int INDENT_STEP = 2;
+ protected final String INDENT_STRING =
+ " ";
+ protected final int MAX_INDENT = INDENT_STRING.length();
+
+ public TextTreePrinter(OutputStream stream) {
+ out = new PrintWriter(stream);
+ }
+
+ public TextTreePrinter() {
+ this(System.out);
+ }
+
+ public void begin() { }
+
+ public void end() {
+ out.flush();
+ }
+
+ public void flush() {
+ out.flush();
+ }
+
+ public TreePrinter print(String str) {
+ out.print(str);
+ return this;
+ }
+
+ public TreePrinter println() {
+ out.println();
+ return this;
+ }
+
+ public void beginSection(int level, String title) {
+ out.println("[[" + title + "]]");
+ out.flush();
+ }
+
+ protected void indent() {
+ indent += Math.min(MAX_INDENT, INDENT_STEP);
+ }
+
+ protected void undent() {
+ indent -= Math.max(0, INDENT_STEP);
+ }
+
+ protected void printString(String str) {
+ out.print(str);
+ }
+
+ protected void printNewLine() {
+ out.println();
+ if (indent > 0)
+ out.write(INDENT_STRING, 0, indent);
+ }
+
+ public static class SymbolUsage {
+ public case Definition;
+ public case Use;
+ }
+
+ public static class Text {
+ public case None;
+ public case Space;
+ public case Newline;
+ public case Simple(String str);
+ public case Literal(String str);
+ public case Keyword(String name);
+ public case Identifier(Symbol symbol, String name, SymbolUsage usage);
+ public case Sequence(Text[] elements);
+ }
+
+ protected void print(Text text) {
+ switch (text) {
+ case None : break;
+ case Space : printString(" "); break;
+ case Newline : printNewLine(); break;
+ case Simple(String str) : printString(str); break;
+ case Literal(String str) : printString(str); break;
+ case Keyword(String name) : printString(name); break;
+ case Identifier(Symbol sym, String name, _) :
+ printString(name);
+ if (sym != null && Global.instance.uniqid)
+ printString("#" + Global.instance.uniqueID.id(sym));
+ break;
+ case Sequence(Text[] elements) : print(elements); break;
+ }
+ }
+
+ protected void print(Text[] texts) {
+ for (int i = 0; i < texts.length; ++i)
+ print(texts[i]);
+ }
+
+ protected static final Text KW_ABSTRACT = Text.Keyword("abstract");
+ protected static final Text KW_CASE = Text.Keyword("case");
+ protected static final Text KW_CLASS = Text.Keyword("class");
+ protected static final Text KW_CONSTR = Text.Keyword("constr");
+ protected static final Text KW_DEF = Text.Keyword("def");
+ protected static final Text KW_DO = Text.Keyword("do");
+ protected static final Text KW_ELSE = Text.Keyword("else");
+ protected static final Text KW_EXTENDS = Text.Keyword("extends");
+ protected static final Text KW_FINAL = Text.Keyword("final");
+ protected static final Text KW_FOR = Text.Keyword("for");
+ protected static final Text KW_IF = Text.Keyword("if");
+ protected static final Text KW_IMPORT = Text.Keyword("import");
+ protected static final Text KW_INTERFACE = Text.Keyword("interface");
+ protected static final Text KW_LET = Text.Keyword("let");
+ protected static final Text KW_MODULE = Text.Keyword("module");
+ protected static final Text KW_NEW = Text.Keyword("new");
+ protected static final Text KW_NULL = Text.Keyword("null");
+ protected static final Text KW_OUTER = Text.Keyword("outer");
+ protected static final Text KW_OVERRIDE = Text.Keyword("override");
+ protected static final Text KW_PACKAGE = Text.Keyword("package");
+ protected static final Text KW_PRIVATE = Text.Keyword("private");
+ protected static final Text KW_PROTECTED = Text.Keyword("protected");
+ protected static final Text KW_QUALIFIED = Text.Keyword("qualified");
+ protected static final Text KW_STATIC = Text.Keyword("static");
+ protected static final Text KW_SUPER = Text.Keyword("super");
+ protected static final Text KW_THIS = Text.Keyword("this");
+ protected static final Text KW_TYPE = Text.Keyword("type");
+ protected static final Text KW_VAL = Text.Keyword("val");
+ protected static final Text KW_VAR = Text.Keyword("var");
+ protected static final Text KW_WITH = Text.Keyword("with");
+ protected static final Text KW_YIELD = Text.Keyword("yield");
+
+ protected static final Text TXT_ERROR = Text.Simple("<error>");
+ protected static final Text TXT_UNKNOWN = Text.Simple("<unknown>");
+ protected static final Text TXT_NULL = Text.Simple("<null>");
+ protected static final Text TXT_MODULE_COMMENT
+ = Text.Simple("/*module*/ ");
+ protected static final Text TXT_EMPTY = Text.Simple("<empty>");
+
+ protected static final Text TXT_QUOTE = Text.Simple("\"");
+ protected static final Text TXT_PLUS = Text.Simple("+");
+ protected static final Text TXT_COLON = Text.Simple(":");
+ protected static final Text TXT_SEMICOLON = Text.Simple(";");
+ protected static final Text TXT_DOT = Text.Simple(".");
+ protected static final Text TXT_COMMA = Text.Simple(",");
+ protected static final Text TXT_EQUAL = Text.Simple("=");
+ protected static final Text TXT_SUBTYPE = Text.Simple("<:");
+ protected static final Text TXT_AT = Text.Simple("@");
+ protected static final Text TXT_HASH = Text.Simple("#");
+ protected static final Text TXT_RIGHT_ARROW = Text.Simple("=>");
+ protected static final Text TXT_LEFT_PAREN = Text.Simple("(");
+ protected static final Text TXT_RIGHT_PAREN = Text.Simple(")");
+ protected static final Text TXT_LEFT_BRACE = Text.Simple("{");
+ protected static final Text TXT_RIGHT_BRACE = Text.Simple("}");
+ protected static final Text TXT_LEFT_BRACKET = Text.Simple("[");
+ protected static final Text TXT_RIGHT_BRACKET = Text.Simple("]");
+
+ protected static final Text TXT_WITH_BLOCK_BEGIN =
+ Text.Sequence(new Text[] {
+ Text.Space, KW_WITH, Text.Space, TXT_LEFT_BRACE, Text.Newline
+ });
+ protected static final Text TXT_WITH_SP =
+ Text.Sequence(new Text[]{ Text.Space, KW_WITH, Text.Space });
+ protected static final Text TXT_BLOCK_BEGIN =
+ Text.Sequence(new Text[]{ TXT_LEFT_BRACE, Text.Newline });
+ protected static final Text TXT_BLOCK_END =
+ Text.Sequence(new Text[]{ Text.Newline, TXT_RIGHT_BRACE });
+ protected static final Text TXT_BLOCK_SEP =
+ Text.Sequence(new Text[]{ TXT_SEMICOLON, Text.Newline });
+ protected static final Text TXT_COMMA_SP =
+ Text.Sequence(new Text[]{ TXT_COMMA, Text.Space });
+ protected static final Text TXT_ELSE_NL =
+ Text.Sequence(new Text[]{ KW_ELSE, Text.Newline });
+
+ public void print(Unit unit) {
+ printUnitHeader(unit);
+ if (unit.body != null) {
+ for (int i = 0; i < unit.body.length; ++i) {
+ print(unit.body[i]);
+ print(TXT_BLOCK_SEP);
+ }
+ } else
+ print(TXT_NULL);
+ printUnitFooter(unit);
+
+ out.flush();
+ }
+
+ protected void printUnitHeader(Unit unit) {
+ print(Text.Simple("// Scala source: " + unit.source + "\n"));
+ }
+
+ protected void printUnitFooter(Unit unit) {
+ print(Text.Newline);
+ }
+
+ public TreePrinter print(Tree tree) {
+ switch (tree) {
+ case Bad():
+ print(TXT_ERROR);
+ break;
+
+ case Empty:
+ print(TXT_EMPTY);
+ break;
+
+ case ClassDef(int mods, // :
+ Name name,
+ Tree.TypeDef[] tparams,
+ Tree.ValDef[][] vparams,
+ Tree tpe,
+ Tree.Template impl):
+ printModifiers(mods);
+ print((mods & Modifiers.INTERFACE) != 0
+ ? KW_INTERFACE
+ : KW_CLASS);
+ print(Text.Space);
+ printSymbolDefinition(tree.symbol(), name);
+ printParams(tparams);
+ printParams(vparams);
+ printOpt(TXT_COLON, tpe, false);
+ printTemplate(KW_EXTENDS, impl, true);
+ break;
+
+ case PackageDef(Tree packaged, Tree.Template impl):
+ print(KW_PACKAGE);
+ print(Text.Space);
+ print(packaged);
+ print(Text.Space);
+ printTemplate(KW_WITH, impl, true);
+ break;
+
+ case ModuleDef(int mods, // :
+ Name name,
+ Tree tpe,
+ Tree.Template impl):
+ printModifiers(mods);
+ print(KW_MODULE);
+ print(Text.Space);
+ printSymbolDefinition(tree.symbol(), name);
+ printOpt(TXT_COLON, tpe, false);
+ printTemplate(KW_EXTENDS, impl, true);
+ break;
+
+ case ValDef(int mods, Name name, Tree tpe, Tree rhs):
+ printModifiers(mods);
+ if ((mods & Modifiers.MUTABLE) != 0) print(KW_VAR);
+ else {
+ if ((mods & Modifiers.MODUL) != 0) print(TXT_MODULE_COMMENT);
+ print(KW_VAL);
+ }
+ print(Text.Space);
+ printSymbolDefinition(tree.symbol(), name);
+ printOpt(TXT_COLON, tpe, false);
+ printOpt(TXT_EQUAL, rhs, true);
+ break;
+
+ case PatDef(int mods, Tree pat, Tree rhs):
+ printModifiers(mods);
+ print(KW_VAL);
+ print(Text.Space);
+ print(pat);
+ printOpt(TXT_EQUAL, rhs, true);
+ break;
+
+ case DefDef(int mods,
+ Name name,
+ Tree.TypeDef[] tparams,
+ Tree.ValDef[][] vparams,
+ Tree tpe,
+ Tree rhs):
+ printModifiers(mods);
+ if (name.isConstrName()) print(KW_CONSTR); else print(KW_DEF);
+ print(Text.Space);
+ printSymbolDefinition(tree.symbol(), name);
+ printParams(tparams);
+ printParams(vparams);
+ printOpt(TXT_COLON, tpe, false);
+ printOpt(TXT_EQUAL, rhs, true);
+ break;
+
+ case TypeDef(int mods,
+ Name name,
+ Tree.TypeDef[] tparams,
+ Tree rhs):
+ printModifiers(mods);
+ print(KW_TYPE);
+ print(Text.Space);
+ printSymbolDefinition(tree.symbol(), name);
+ printParams(tparams);
+ if ((mods & Modifiers.ABSTRACT) != 0) printOpt(TXT_SUBTYPE, rhs, true);
+ else printOpt(TXT_EQUAL, rhs, true);
+ break;
+
+ case Import(Tree expr, Name[] selectors):
+ print(KW_IMPORT);
+ print(Text.Space);
+ print(expr);
+ print(TXT_LEFT_BRACE);
+ for (int i = 0; i < selectors.length; i = i + 2) {
+ if (i > 0) print(TXT_COMMA_SP);
+ print(selectors[i].toString());
+ if (i + 1 < selectors.length && selectors[i] != selectors[i+1]) {
+ print(TXT_RIGHT_ARROW);
+ print(selectors[i+1].toString());
+ }
+ }
+ print(TXT_RIGHT_BRACE);
+ break;
+
+ case CaseDef(Tree pat, Tree guard, Tree body):
+ print(KW_CASE);
+ print(Text.Space);
+ print(pat);
+ printOpt(KW_IF, guard, true);
+ print(Text.Space);
+ print(TXT_RIGHT_ARROW);
+ print(Text.Space);
+ print(body);
+ break;
+
+ case LabelDef(Tree[] params, Tree rhs):
+ assert tree.symbol() != null;
+ printSymbolDefinition(tree.symbol(), null);
+ printArray(params, TXT_LEFT_PAREN, TXT_RIGHT_PAREN, TXT_COMMA_SP);
+ print(rhs);
+ break;
+
+ case Block(Tree[] stats):
+ printArray(stats, TXT_BLOCK_BEGIN, TXT_BLOCK_END, TXT_BLOCK_SEP);
+ break;
+
+ case Tuple(Tree[] trees):
+ printArray(trees, TXT_LEFT_BRACKET, TXT_RIGHT_BRACKET, TXT_COMMA_SP);
+ break;
+
+ case Visitor(Tree.CaseDef[] cases):
+ printArray(cases, TXT_BLOCK_BEGIN, TXT_BLOCK_END, Text.Newline);
+ break;
+
+ case Function(Tree.ValDef[] vparams, Tree body):
+ print(TXT_LEFT_BRACE);
+ printParams(vparams);
+ print(Text.Space);
+ print(TXT_RIGHT_ARROW);
+ print(Text.Space);
+ print(body);
+ print(TXT_RIGHT_BRACE);
+ break;
+
+ case Assign(Tree lhs, Tree rhs):
+ print(lhs);
+ print(Text.Space);
+ print(TXT_EQUAL);
+ print(Text.Space);
+ print(rhs);
+ break;
+
+ case If(Tree cond, Tree thenp, Tree elsep):
+ print(KW_IF);
+ print(Text.Space);
+ print(TXT_LEFT_PAREN);
+ print(cond);
+ print(TXT_RIGHT_PAREN);
+ indent(); print(Text.Newline);
+ print(thenp);
+ undent(); print(Text.Newline);
+ indent(); printOpt(TXT_ELSE_NL, elsep, false); undent();
+ printType(tree);
+ break;
+
+ case New(Tree.Template templ):
+ printTemplate(KW_NEW, templ, false);
+ printType(tree);
+ break;
+
+ case Typed(Tree expr, Tree tpe):
+ print(TXT_LEFT_PAREN);
+ print(expr);
+ print(TXT_RIGHT_PAREN);
+ print(Text.Space);
+ print(TXT_COLON);
+ print(Text.Space);
+ print(tpe);
+ printType(tree);
+ break;
+
+ case TypeApply(Tree fun, Tree[] targs):
+ print(fun);
+ print(TXT_AT);
+ printArray(targs, TXT_LEFT_BRACKET, TXT_RIGHT_BRACKET, TXT_COMMA_SP);
+ printType(tree);
+ break;
+
+ case Apply(Tree fun, Tree[] vargs):
+ print(fun);
+ printArray(vargs, TXT_LEFT_PAREN, TXT_RIGHT_PAREN, TXT_COMMA_SP);
+ printType(tree);
+ break;
+
+ case Super(Tree tpe):
+ if (tpe != Tree.Empty)
+ print(TXT_LEFT_PAREN);
+
+ print(KW_SUPER);
+
+ if (tpe != Tree.Empty) {
+ print(Text.Space);
+ print(TXT_COLON);
+ print(Text.Space);
+ print(tpe);
+ print(TXT_RIGHT_PAREN);
+ }
+ printType(tree);
+ break;
+
+ case This(Tree qualifier):
+ if (qualifier != Tree.Empty) {
+ print(qualifier);
+ print(TXT_DOT);
+ }
+ print(KW_THIS);
+ printType(tree);
+ break;
+
+ case Select(Tree qualifier, Name name):
+ print(qualifier);
+ print(TXT_DOT);
+ printSymbolUse(tree.symbol(), name);
+ printType(tree);
+ break;
+
+ case Ident(Name name):
+ printSymbolUse(tree.symbol(), name);
+ printType(tree);
+ break;
+
+ case Literal(Object obj):
+ String str;
+ if (obj instanceof String)
+ str = "\"" + obj + "\"";
+ else
+ str = String.valueOf(obj);
+ print(Text.Literal(str));
+ printType(tree);
+ break;
+
+ case SingletonType(Tree ref):
+ print(ref);
+ print(TXT_DOT); print(KW_TYPE);
+ break;
+
+ case SelectFromType(Tree qualifier, Name selector):
+ print(qualifier);
+ print(Text.Space); print(TXT_HASH); print(Text.Space);
+ printSymbolUse(tree.symbol(), selector);
+ break;
+
+ case FunType(Tree[] argtpes, Tree restpe):
+ printArray(argtpes, TXT_LEFT_PAREN, TXT_RIGHT_PAREN, TXT_COMMA_SP);
+ print(TXT_RIGHT_ARROW);
+ print(restpe);
+ break;
+
+ case CompoundType(Tree[] baseTypes, Tree[] refinements):
+ printArray(baseTypes, Text.None, Text.None, TXT_WITH_SP);
+ printArray(refinements, TXT_WITH_BLOCK_BEGIN, TXT_BLOCK_END, Text.Newline);
+ break;
+
+ case TupleType(Tree[] types):
+ printArray(types, TXT_LEFT_BRACKET, TXT_RIGHT_BRACKET, TXT_COMMA_SP);
+ break;
+
+ case AppliedType(Tree tpe, Tree[] args):
+ print(tpe);
+ indent();
+ print(TXT_LEFT_BRACKET);
+ for (int i = 0; i < args.length; ++i) {
+ if (i > 0) print(TXT_COMMA_SP);
+ print(args[i]);
+ }
+ undent();
+ print(TXT_RIGHT_BRACKET);
+ break;
+
+ case CovariantType(Tree tpe):
+ print(TXT_PLUS);
+ print(tpe);
+ break;
+
+ case Template(Tree[] parents, Tree[] body):
+ Debug.abort("unexpected case", tree);
+ break;
+
+ default:
+ print(TXT_UNKNOWN);
+ break;
+ }
+ return this;
+ }
+
+ // Printing helpers
+
+ protected void printArray(Tree[] trees, Text open, Text close, Text sep) {
+ indent();
+ print(open);
+ for (int i = 0; i < trees.length; ++i) {
+ if (i > 0) print(sep);
+ print(trees[i]);
+ }
+ undent();
+ print(close);
+ }
+
+ protected void printOpt(Text prefix, Tree tree, boolean spaceBefore) {
+ if (tree != Tree.Empty) {
+ if (spaceBefore)
+ print(Text.Space);
+ print(prefix);
+ print(Text.Space);
+ print(tree);
+ }
+ }
+
+ // Printing of symbols
+
+ protected String symbolString(Symbol symbol, Name name) {
+ if (symbol != null)
+ return symbol.name.toString();
+ else
+ return name.toString();
+ }
+
+ protected void printSymbolDefinition(Symbol symbol, Name name) {
+ print(Text.Identifier(symbol,
+ symbolString(symbol, name),
+ SymbolUsage.Definition));
+ }
+
+ protected void printSymbolUse(Symbol symbol, Name name) {
+ print(Text.Identifier(symbol,
+ symbolString(symbol, name),
+ SymbolUsage.Use));
+ }
+
+ // Printing of trees
+
+ protected void printType(Tree tree) {
+ if (Global.instance.printtypes) {
+ print(TXT_LEFT_BRACE);
+ if (tree.type != null)
+ print(Text.Simple(tree.type.toString()));
+ else
+ print(TXT_NULL);
+ print(TXT_RIGHT_BRACE);
+ }
+ }
+
+ protected void printModifiers(int flags) {
+ if ((flags & Modifiers.ABSTRACT) != 0) {
+ print(KW_ABSTRACT);
+ print(Text.Space);
+ }
+ if ((flags & Modifiers.FINAL) != 0) {
+ print(KW_FINAL);
+ print(Text.Space);
+ }
+ if ((flags & Modifiers.PRIVATE) != 0) {
+ print(KW_PRIVATE);
+ print(Text.Space);
+ }
+ if ((flags & Modifiers.PROTECTED) != 0) {
+ print(KW_PROTECTED);
+ print(Text.Space);
+ }
+ if ((flags & Modifiers.QUALIFIED) != 0) {
+ print(KW_QUALIFIED);
+ print(Text.Space);
+ }
+ if ((flags & Modifiers.OVERRIDE) != 0) {
+ print(KW_OVERRIDE);
+ print(Text.Space);
+ }
+ if ((flags & Modifiers.CASE) != 0) {
+ print(KW_CASE);
+ print(Text.Space);
+ }
+ if ((flags & Modifiers.DEF) != 0) {
+ print(KW_DEF);
+ print(Text.Space);
+ }
+ if ((flags & Modifiers.STATIC) != 0) {
+ print(KW_STATIC);
+ print(Text.Space);
+ }
+ }
+
+ protected void printTemplate(Text prefix,
+ Tree.Template templ,
+ boolean spaceBefore) {
+ if (! (templ.parents.length == 0
+ || (templ.parents.length == 1
+ && templ.parents[0] == Tree.Empty))) {
+ if (spaceBefore)
+ print(Text.Space);
+ print(prefix);
+ print(Text.Space);
+ printArray(templ.parents, Text.None, Text.None, TXT_WITH_SP);
+ }
+
+ if (templ.body.length > 0)
+ printArray(templ.body, TXT_WITH_BLOCK_BEGIN, TXT_BLOCK_END, TXT_BLOCK_SEP);
+ }
+
+ protected void printParams(Tree.TypeDef[] tparams) {
+ if (tparams.length > 0) {
+ print(TXT_LEFT_BRACKET);
+ for (int i = 0; i < tparams.length; i++) {
+ if (i > 0) print(TXT_COMMA_SP);
+ printParam(tparams[i]);
+ }
+ print(TXT_RIGHT_BRACKET);
+ }
+ }
+
+ protected void printParams(Tree.ValDef[][] vparamss) {
+ for (int i = 0; i < vparamss.length; ++i)
+ printParams(vparamss[i]);
+ }
+
+ protected void printParams(Tree.ValDef[] vparams) {
+ print(TXT_LEFT_PAREN);
+ for (int i = 0; i < vparams.length; ++i) {
+ if (i > 0) print(TXT_COMMA_SP);
+ printParam(vparams[i]);
+ }
+ print(TXT_RIGHT_PAREN);
+ }
+
+ protected void printParam(Tree tree) {
+ switch (tree) {
+ case TypeDef(int mods, Name name, _, Tree bound):
+ printModifiers(mods);
+ printSymbolDefinition(tree.symbol(), name);
+ printOpt(KW_EXTENDS, bound, true);
+ break;
+
+ case ValDef(int mods, Name name, Tree tpe, Tree.Empty):
+ printModifiers(mods);
+ printSymbolDefinition(tree.symbol(), name);
+ printOpt(TXT_COLON, tpe, false);
+ break;
+
+ default:
+ Debug.abort("bad parameter: " + tree);
+ }
+ }
+}