package com.redhat.ceylon.compiler.typechecker.util;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;

import com.redhat.ceylon.compiler.typechecker.model.ProducedType;
import com.redhat.ceylon.compiler.typechecker.tree.NaturalVisitor;
import com.redhat.ceylon.compiler.typechecker.tree.Node;
import com.redhat.ceylon.compiler.typechecker.tree.Tree;
import com.redhat.ceylon.compiler.typechecker.tree.Visitor;


public class PrintVisitor extends Visitor implements NaturalVisitor {
    
    int depth=0;
    Writer stream;

    public PrintVisitor() {
        stream = new OutputStreamWriter(System.out);
    }
    
    public PrintVisitor(Writer w) {
        stream = w;
    }
    
    protected void print(String str) {
        try {
            stream.write(str);
        }
        catch (IOException ioe) {
            throw new RuntimeException(ioe);
        }
    }

    void newline() {
        print("\n");
    }

    void indent() {
        for (int i = 0; i < depth; i++)
            print("|  ");
    }

    @Override
    public void visitAny(Node node) {
        if (depth>0) newline();
        indent();
        print("+ ");
        print(node);
        depth++;
        super.visitAny(node);
        depth--;
        if (depth==0) newline();
        try {
            stream.flush();
        }
        catch (IOException ioe) {
            throw new RuntimeException(ioe);
        }
    }

    private void print(Node node) {
        print(node.getText() + 
                " [" + node.getNodeType() + 
                "] (" + node.getAntlrTreeNode().getLine() + 
                ":" + node.getAntlrTreeNode().getCharPositionInLine()  + 
                ")");
        if (node instanceof Tree.Term) {
            ProducedType type = ((Tree.Term) node).getTypeModel();
            if (type!=null) {
                print(" -> " + type.getProducedTypeName());
            }
        }
        if (node instanceof Tree.Type) {
            ProducedType type = ((Tree.Type) node).getTypeModel();
            if (type!=null) {
                print(" -> " + type.getProducedTypeName());
            }
        }
        if (!node.getErrors().isEmpty()) {
            print(" <-- ** " + node.getErrors() + " **");
        }
    }
}
@@ -134,16 +134,81 @@
 riter;%0A%0A
+import com.redhat.ceylon.compiler.typechecker.model.Declaration;%0A
 import c
@@ -1766,24 +1766,639 @@
       %22)%22);%0A
+        if (node instanceof Tree.Primary) %7B%0A            Declaration d = ((Tree.Primary) node).getDeclaration();%0A            if (d!=null) %7B%0A                print(%22  #%22 + d);%0A            %7D%0A        %7D%0A        if (node instanceof Tree.Declaration) %7B%0A            Declaration d = ((Tree.Declaration) node).getDeclarationModel();%0A            if (d!=null) %7B%0A                print(%22  #%22 + d);%0A            %7D%0A        %7D%0A        if (node instanceof Tree.SimpleType) %7B%0A            Declaration d = ((Tree.SimpleType) node).getDeclarationModel();%0A            if (d!=null) %7B%0A                print(%22  #%22 + d);%0A            %7D%0A        %7D%0A
         if (

print out the model references