/* ____ ____ ____ ____ ______ *\ ** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** ** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** ** /_____/\____/\___/\____/____/ ** \* */ // $Id$ package scalac.symtab; import java.io.StringWriter; import ch.epfl.lamp.util.CodePrinter; import scalac.Global; import scalac.atree.AConstant; import scalac.symtab.Type.Constraint; import scalac.symtab.Scope.SymbolIterator; import scalac.util.Name; import scalac.util.NameTransformer; import scalac.util.Debug; /** This class provides methods to print symbols and types. */ public class SymbolTablePrinter { //######################################################################## // Private Fields /** The global environment */ private final Global global; /** The underlying code printer */ private final CodePrinter printer; //######################################################################## // Public Constructors /** Creates a new instance */ public SymbolTablePrinter() { this((String)null); } /** Creates a new instance */ public SymbolTablePrinter(String step) { this(Global.instance, new CodePrinter(step)); } /** Creates a new instance */ public SymbolTablePrinter(CodePrinter printer) { this(Global.instance, printer); } /** Creates a new instance */ public SymbolTablePrinter(Global global, CodePrinter printer) { this.global = global; this.printer = printer; } //######################################################################## // Public Methods - Getting & Setting /** Returns the underlying code printer. */ public CodePrinter getCodePrinter() { return printer; } //######################################################################## // Public Methods - Formatting /** Increases the indentation level by one. */ public SymbolTablePrinter indent() { printer.indent(); return this; } /** Decreases the indentation level by one. */ public SymbolTablePrinter undent() { printer.undent(); return this; } /** Inserts a new line. */ public SymbolTablePrinter line() { printer.line(); return this; } /** Inserts a white space. */ public SymbolTablePrinter space() { printer.space(); return this; } //######################################################################## // Public Methods - Printing simple values /** Prints a new line. */ public SymbolTablePrinter println() { printer.println(); return this; } /** Prints the boolean value followed by a new line. */ public SymbolTablePrinter println(boolean value) { printer.println(value); return this; } /** Prints the byte value followed by a new line. */ public SymbolTablePrinter println(byte value) { printer.println(value); return this; } /** Prints the short value followed by a new line. */ public SymbolTablePrinter println(short value) { printer.println(value); return this; } /** Prints the char value followed by a new line. */ public SymbolTablePrinter println(char value) { printer.println(value); return this; } /** Prints the int value followed by a new line. */ public SymbolTablePrinter println(int value) { printer.println(value); return this; } /** Prints the long value followed by a new line. */ public SymbolTablePrinter println(long value) { printer.println(value); return this; } /** Prints the float value followed by a new line. */ public SymbolTablePrinter println(float value) { printer.println(value); return this; } /** Prints the double value followed by a new line. */ public SymbolTablePrinter println(double value) { printer.println(value); return this; } /** Prints the string followed by a new line. */ public SymbolTablePrinter println(String value) { printer.println(value); return this; } /** Prints the boolean value. */ public SymbolTablePrinter print(boolean value) { printer.print(value); return this; } /** Prints the byte value. */ public SymbolTablePrinter print(byte value) { printer.print(value); return this; } /** Prints the short value. */ public SymbolTablePrinter print(short value) { printer.print(value); return this; } /** Prints the char value. */ public SymbolTablePrinter print(char value) { printer.print(value); return this; } /** Prints the int value. */ public SymbolTablePrinter print(int value) { printer.print(value); return this; } /** Prints the long value. */ public SymbolTablePrinter print(long value) { printer.print(value); return this; } /** Prints the float value. */ public SymbolTablePrinter print(float value) { printer.print(value); return this; } /** Prints the long value. */ public SymbolTablePrinter print(double value) { printer.print(value); return this; } /** Prints the string. */ public SymbolTablePrinter print(String value) { printer.print(value); return this; } //######################################################################## // Public Methods - Printing scopes /** Prints the members of the given scope. */ public SymbolTablePrinter printScope(Scope scope) { return printScope(scope, false); } /** Prints the members of the given scope. */ public SymbolTablePrinter printScope(Scope scope, boolean lazy) { boolean first = true; for (SymbolIterator i = scope.iterator(); i.hasNext(); ) { Symbol member = i.next(); if (!mustShowMember(member)) continue; if (first) print("{").indent(); else print(", "); first = false; line().printSignature(member); } if (!first) line().undent().print("}"); else if (!lazy) print("{}"); return this; } /** * Returns true iff the given member must be printed. The default * implementation always returns true. */ public boolean mustShowMember(Symbol member) { return true; } //######################################################################## // Public Methods - Printing symbols /** * Returns the string representation of the kind of the given * symbol or null if there is no such representation. */ public String getSymbolKind(Symbol symbol) { switch (symbol.kind) { case Kinds.NONE: return null; case Kinds.CLASS: if (symbol.isPackageClass()) return "package class"; if (symbol.isModuleClass()) return "object class"; if (symbol.isTrait()) return "trait"; return "class"; case Kinds.TYPE: case Kinds.ALIAS: return "type"; case Kinds.VAL: if (symbol.isVariable()) return "variable"; if (symbol.isPackage()) return "package"; if (symbol.isModule()) return "object"; if (symbol.isConstructor()) return "constructor"; if (symbol.isInitializedMethod()) if (global.debug || (symbol.flags & Modifiers.STABLE) == 0) return "method"; return "value"; default: throw Debug.abort("unknown kind " + symbol.kind); } } /** * Returns the definition keyword associated to the given symbol * or null if there is no such keyword. */ public String getSymbolKeyword(Symbol symbol) { if (symbol.isParameter()) return null; switch (symbol.kind) { case Kinds.NONE: return null; case Kinds.CLASS: if (symbol.isTrait()) return "trait"; return "class"; case Kinds.TYPE: case Kinds.ALIAS: return "type"; case Kinds.VAL: if (symbol.isVariable()) return "var"; if (symbol.isPackage()) return "package"; if (symbol.isModule()) return "object"; if (symbol.isInitializedMethod()) return "def"; return "val"; default: throw Debug.abort("unknown kind " + symbol.kind); } } /** Returns the name of the given symbol. */ public String getSymbolName(Symbol symbol) { String name = symbol.simpleName().toString(); if (!global.debug) name = NameTransformer.decode(name); return name; } /** Returns the inner string of the given symbol. */ public String getSymbolInnerString(Symbol symbol) { switch (symbol.kind) { case Kinds.NONE : return ":"; case Kinds.ALIAS: return "="; case Kinds.CLASS: return "extends"; case Kinds.TYPE : return "<:"; case Kinds.VAL : return symbol.isModule() ? "extends" : ":"; default : throw Debug.abort("unknown kind " + symbol.kind); } } /** Prints the unique identifier of the given symbol */ public SymbolTablePrinter printSymbolUniqueId(Symbol symbol) { if (global.uniqid) print('#').print(global.uniqueID.id(symbol)); return this; } /** Prints the name of the given symbol */ public SymbolTablePrinter printSymbolName(Symbol symbol) { print(getSymbolName(symbol)); return printSymbolUniqueId(symbol); } /** Prints the kind and the name of the given symbol. */ public SymbolTablePrinter printSymbolKindAndName(Symbol symbol) { if (symbol.isAnonymousClass()) { print("