view tools/DotPrinter.d @ 88:eb5b2c719a39 new_gen

Major change to locations, tokens and expressions. A location (now SourceLocation or SLoc) is only 32 bit in size - disadvantage is that it can't find its own text. You have to go through the new SourceManager to do that. This has caused changes to a lot of stuff and removal of DataSource and the old Location Additionally Exp has gotten some location stuff, so we can give proper error messages. Not in Decl and Stmt yet, but thats coming too.
author Anders Halager <halager@gmail.com>
date Sun, 04 May 2008 18:13:46 +0200
parents 9f8131676242
children 48bb2287c035
line wrap: on
line source

module tools.DotPrinter;

import tango.io.Stdout,
       Int = tango.text.convert.Integer;

import ast.Decl,
       ast.Stmt,
       ast.Exp;

class DotPrinter
{
    this()
    {
    }

    private char[][void*] identifiers;
    private int current_id = 0;

    void print(Decl[] decls)
    {
        Stdout("digraph {").newline;
        foreach(decl ; decls)
        {
            printDecl(decl);
        }
        Stdout("}").newline;
    }

    void printDecl(Decl decl)
    {
        switch(decl.declType)
        {
            case DeclType.FuncDecl:
                FuncDecl funcDecl = cast(FuncDecl)decl;

                //printIdentifier(funcDecl.identifier);
                //printFuncArgs(funcDecl.funcArgs);
                Stdout(dotId(decl))(` [label="function`);
                Stdout(`\n name: `)(text(funcDecl.identifier));
                Stdout(`\n return type: `)(text(funcDecl.returnType));
                Stdout(`", shape=box, fillcolor=lightblue, style=filled]`);
                Stdout.newline;
                //Stdout(`"`);
                foreach(stmt ; funcDecl.statements)
                    printStatement(dotId(decl), stmt);
                break;

            case DeclType.VarDecl:
                VarDecl varDecl = cast(VarDecl)decl;

                //printIdentifier(funcDecl.identifier);
                //printFuncArgs(funcDecl.funcArgs);
                Stdout(dotId(decl))(` [label="var`);
                Stdout(`\n name: `)(text(varDecl.identifier));
                Stdout(`\n type: `)(text(varDecl.varType));
                Stdout(`"]`).newline;

                if (varDecl.init !is null)
                    printExpression(dotId(decl), varDecl.init);
                break;
        }
    }

    void printStatement(char[] parent, Stmt stmt)
    {
        auto id = dotId(stmt);
        switch (stmt.stmtType)
        {
            case StmtType.Stmt:
                Stdout(id)(` [label="Statement"]`).newline;
                Stdout(parent)(` -> `)(id).newline;
                break;

            case StmtType.Decl:
                Stdout(id)(` [label="Decl"]`).newline;
                Stdout(parent)(` -> `)(id).newline;
                auto decl = (cast(DeclStmt)stmt).decl;
                printDecl(decl);
                Stdout(id)(` -> `)(dotId(decl)).newline;
                break;

            case StmtType.Return:
                Stdout(id)(` [label="Return"]`).newline;
                Stdout(parent)(` -> `)(id).newline;
                printExpression(id, (cast(ReturnStmt)stmt).exp);
                break;

            case StmtType.Exp:
                Stdout(parent)(` -> `)(id).newline;
                printExpression(id, (cast(ExpStmt)stmt).exp);
                break;
        }
    }

    void printExpression(char[] parent, Exp exp)
    {
        auto id = dotId(exp);

        switch(exp.expType)
        {
            case ExpType.Binary:
                auto bin = cast(BinaryExp)exp;
                Stdout(id)(` [label="`)(bin.op)(`"]`).newline;
                printExpression(id, bin.left);
                printExpression(id, bin.right);
                break;

            case ExpType.Negate:
                auto neg = cast(NegateExp)exp;
                Stdout(id)(` [label="Negate"]`).newline;
                printExpression(id, neg.exp);
                break;

            case ExpType.IntegerLit:
                auto e = cast(IntegerLit)exp;
                Stdout(id)(` [label="`)(text(e.get))(`"]`).newline;
                break;
        
            case ExpType.Identifier:
                auto e = cast(Identifier)exp;
                Stdout(id)(` [label="`)(text(e))(`"]`).newline;
                break;

            case ExpType.AssignExp:
                auto ass = cast(AssignExp)exp;
                Stdout(parent)(` [label="Assign"]`).newline;
//                Stdout(id)(` [label="`)(text(ass.identifier))(`"]`).newline;
                printExpression(parent, ass.exp);
                break;

            case ExpType.CallExp:
                break;
        }
        Stdout(parent)(` -> `)(id).newline;
    }

    char[] dotId(Decl d) { return dotId(cast(void*)d); }
    char[] dotId(Stmt s) { return dotId(cast(void*)s); }
    char[] dotId(Exp e)  { return dotId(cast(void*)e); }

    char[] dotId(void* o)
    {
        auto id = o in identifiers;
        if (id is null)
        {
            ++current_id;
            identifiers[o] = Int.toString(current_id);
            id = o in identifiers;
        }
        return *id;
    }

    char[] text(Identifier identifier)
    {
        return identifier.get;
    }
    char[] text(char[] t)
    {
        return t;
    }
}