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.AbsTypeDef[] 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(tree.symbol(), KW_EXTENDS, impl, true); break;  case PackageDef(Tree packaged, Tree.Template impl): print(KW_PACKAGE); print(Text.Space); print(packaged); printTemplate(null, KW_WITH, impl, true); break;  case ModuleDef(int mods, Name name, Tree tpe, Tree.Template impl): printModifiers(mods); print(KW_OBJECT); print(Text.Space); printSymbolDefinition(tree.symbol(), name); printOpt(TXT_COLON, tpe, false); printTemplate(null, 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_OBJECT_COMMENT); print(KW_VAL); } print(Text.Space); printSymbolDefinition(tree.symbol(), name); printOpt(TXT_COLON, tpe, false); if ((mods & Modifiers.DEFERRED) == 0) { print(Text.Space); print(TXT_EQUAL); print(Text.Space); if (rhs == Tree.Empty) print("_"); else print(rhs); } 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.AbsTypeDef[] tparams, Tree.ValDef[][] vparams, Tree tpe, Tree rhs): printModifiers(mods); print(KW_DEF); print(Text.Space); if (name.isTypeName()) print(KW_THIS); else printSymbolDefinition(tree.symbol(), name); printParams(tparams); printParams(vparams); printOpt(TXT_COLON, tpe, false); printOpt(TXT_EQUAL, rhs, true); break;  case AbsTypeDef(int mods, Name name, Tree rhs, Tree lobound): printModifiers(mods); print(KW_TYPE); print(Text.Space); printSymbolDefinition(tree.symbol(), name); printBounds(lobound, rhs); break;  case AliasTypeDef(int mods, Name name, Tree.AbsTypeDef[] tparams, Tree rhs): printModifiers(mods); print(KW_TYPE); print(Text.Space); printSymbolDefinition(tree.symbol(), name); printParams(tparams); printOpt(TXT_EQUAL, rhs, true); break;  case Import(Tree expr, Name[] selectors): print(KW_IMPORT); print(Text.Space); print(expr); print(TXT_DOT); 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(Name name, Tree.Ident[] params, Tree rhs): printSymbolDefinition(tree.symbol(), name); 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); printType(tree); break;  case Sequence(Tree[] trees): printArray(trees, TXT_LEFT_BRACKET, TXT_RIGHT_BRACKET, TXT_COMMA_SP); break;   case Alternative(Tree[] trees): printArray(trees, TXT_LEFT_PAREN, TXT_RIGHT_PAREN, TXT_BAR_SP); break;  case Bind(Name name, Tree t): printSymbolDefinition(tree.symbol(), name); print(Text.Space); print(TXT_AT); print(Text.Space); print(TXT_LEFT_PAREN); print( t ); print(TXT_RIGHT_PAREN); printType(tree); 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_PAREN); printParams(vparams); print(Text.Space); print(TXT_RIGHT_ARROW); print(Text.Space); print(body); print(TXT_RIGHT_PAREN); 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 Switch(Tree expr, int[] tags, Tree[] bodies, Tree defaultBody): print("<switch>"); print(Text.Space); print(TXT_LEFT_PAREN); print(expr); print(TXT_RIGHT_PAREN); print(Text.Space); indent(); print(TXT_BLOCK_BEGIN); for (int i = 0; i < tags.length; i++) { print(KW_CASE); print(Text.Space); print("" + tags[i]); print(Text.Space); print(TXT_RIGHT_ARROW); print(Text.Space); print(bodies[i]); print(Text.Newline); } print("<default> => "); print(defaultBody); undent(); print(TXT_BLOCK_END); break;  case Return(Tree expr): print(KW_RETURN); print(Text.Space); print(expr); break;  case New(Tree.Template templ): printTemplate(null, 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); printArray(targs, TXT_LEFT_BRACKET, TXT_RIGHT_BRACKET, TXT_COMMA_SP); printType(tree); break;  case Apply(Tree fun, Tree[] vargs): if (fun instanceof Tree.TypeTerm) print(fun.type.resultType().symbol().fullName().toString()); else print(fun); printArray(vargs, TXT_LEFT_PAREN, TXT_RIGHT_PAREN, TXT_COMMA_SP); printType(tree); break;  case Super(Name qualifier, Name mixin): if (qualifier != TypeNames.EMPTY) { printSymbolUse(tree.symbol(), qualifier); print(TXT_DOT); } print(KW_SUPER); if (mixin != TypeNames.EMPTY) { print(TXT_LEFT_PAREN); print(mixin.toString()); print(TXT_RIGHT_PAREN); } printType(tree); break;  case This(Name name): if (name != TypeNames.EMPTY) { printSymbolUse(tree.symbol(), name); 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(AConstant value): print(Text.Literal(value.toString())); printType(tree); break;  case TypeTerm(): print(tree.type.toString()); 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_BLOCK_BEGIN, TXT_BLOCK_END, Text.Newline); 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 Template(Tree[] parents, Tree[] body): Debug.abort("unexpected case: template"); break;  default: print(TXT_UNKNOWN); break; }
public TreePrinter print(String str) { out.print(str);
    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.AbsTypeDef[] 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(tree.symbol(), KW_EXTENDS, impl, true);            break;        case PackageDef(Tree packaged, Tree.Template impl):            print(KW_PACKAGE);            print(Text.Space);            print(packaged);            printTemplate(null, KW_WITH, impl, true);            break;        case ModuleDef(int mods, // :                       Name name,                       Tree tpe,                       Tree.Template impl):            printModifiers(mods);            print(KW_OBJECT);            print(Text.Space);            printSymbolDefinition(tree.symbol(), name);            printOpt(TXT_COLON, tpe, false);            printTemplate(null, 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_OBJECT_COMMENT);                print(KW_VAL);            }            print(Text.Space);            printSymbolDefinition(tree.symbol(), name);            printOpt(TXT_COLON, tpe, false);            if ((mods & Modifiers.DEFERRED) == 0) {                print(Text.Space); print(TXT_EQUAL); print(Text.Space);                if (rhs == Tree.Empty) print("_");                else print(rhs);            }            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.AbsTypeDef[] tparams,		    Tree.ValDef[][] vparams,		    Tree tpe,		    Tree rhs):	    printModifiers(mods);            print(KW_DEF);            print(Text.Space);            if (name.isTypeName()) print(KW_THIS);            else printSymbolDefinition(tree.symbol(), name);            printParams(tparams);            printParams(vparams);            printOpt(TXT_COLON, tpe, false);            printOpt(TXT_EQUAL, rhs, true);            break;            case AbsTypeDef(int mods,                            Name name,                            Tree rhs,                            Tree lobound):                printModifiers(mods);            print(KW_TYPE);            print(Text.Space);            printSymbolDefinition(tree.symbol(), name);            printBounds(lobound, rhs);            break;            case AliasTypeDef(int mods,                              Name name,                              Tree.AbsTypeDef[] tparams,                              Tree rhs):                printModifiers(mods);            print(KW_TYPE);            print(Text.Space);            printSymbolDefinition(tree.symbol(), name);            printParams(tparams);            printOpt(TXT_EQUAL, rhs, true);            break;        case Import(Tree expr, Name[] selectors):            print(KW_IMPORT);            print(Text.Space);            print(expr);            print(TXT_DOT);            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(Name name, Tree.Ident[] params, Tree rhs):            printSymbolDefinition(tree.symbol(), name);            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);            printType(tree);            break;        case Sequence(Tree[] trees): // sure ? was Tuple before...            printArray(trees, TXT_LEFT_BRACKET, TXT_RIGHT_BRACKET, TXT_COMMA_SP);            break;            /*              case Subsequence(Tree[] trees):              if( trees.length > 0 )              printArray(trees, TXT_LEFT_PAREN, TXT_RIGHT_PAREN, TXT_COMMA_SP);              else              {              print( TXT_LEFT_PAREN );              print( TXT_COMMA );              print( TXT_RIGHT_PAREN );              }              break;            */        case Alternative(Tree[] trees):            printArray(trees, TXT_LEFT_PAREN, TXT_RIGHT_PAREN, TXT_BAR_SP);            break;        case Bind(Name name, Tree t):            printSymbolDefinition(tree.symbol(), name);            print(Text.Space);            print(TXT_AT);            print(Text.Space);            print(TXT_LEFT_PAREN);            print( t );            print(TXT_RIGHT_PAREN);            printType(tree);            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_PAREN);            printParams(vparams);            print(Text.Space);            print(TXT_RIGHT_ARROW);            print(Text.Space);            print(body);            print(TXT_RIGHT_PAREN);            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 Switch(Tree expr, int[] tags, Tree[] bodies, Tree defaultBody):            print("<switch>");            print(Text.Space);            print(TXT_LEFT_PAREN);            print(expr);            print(TXT_RIGHT_PAREN);            print(Text.Space);            indent();            print(TXT_BLOCK_BEGIN);            for (int i = 0; i < tags.length; i++) {                print(KW_CASE);                print(Text.Space);                print("" + tags[i]);                print(Text.Space);                print(TXT_RIGHT_ARROW);                print(Text.Space);                print(bodies[i]);                print(Text.Newline);            }            print("<default> => ");            print(defaultBody);            undent();            print(TXT_BLOCK_END);            break;        case Return(Tree expr):            print(KW_RETURN);            print(Text.Space);            print(expr);            break;        case New(Tree.Template templ):            printTemplate(null, 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);            printArray(targs, TXT_LEFT_BRACKET, TXT_RIGHT_BRACKET, TXT_COMMA_SP);            printType(tree);            break;        case Apply(Tree fun, Tree[] vargs):            if (fun instanceof Tree.TypeTerm)                print(fun.type.resultType().symbol().fullName().toString());            else                print(fun);            printArray(vargs, TXT_LEFT_PAREN, TXT_RIGHT_PAREN, TXT_COMMA_SP);            printType(tree);            break;        case Super(Name qualifier, Name mixin):            if (qualifier != TypeNames.EMPTY) {                printSymbolUse(tree.symbol(), qualifier);                print(TXT_DOT);            }            print(KW_SUPER);            if (mixin != TypeNames.EMPTY) {                print(TXT_LEFT_PAREN);                print(mixin.toString());                print(TXT_RIGHT_PAREN);            }            printType(tree);            break;        case This(Name name):            if (name != TypeNames.EMPTY) {                printSymbolUse(tree.symbol(), name);                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(AConstant value):            print(Text.Literal(value.toString()));            printType(tree);            break;        case TypeTerm():            print(tree.type.toString());            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_BLOCK_BEGIN, TXT_BLOCK_END, Text.Newline);            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 Template(Tree[] parents, Tree[] body):            Debug.abort("unexpected case: template");            break;        default:            print(TXT_UNKNOWN);            break;        }        //print("{" + tree.type + "}");//DEBUG        return this;    }