diff options
Diffstat (limited to 'sources/scalac/ast/printer/TextTreePrinter.java')
-rw-r--r-- | sources/scalac/ast/printer/TextTreePrinter.java | 683 |
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); + } + } +} |