view sema/Visitor.d @ 37:858b9805843d new_gen

Bug-fixes Void can now be used and is recognized as a keyword by lexer Fixed a problem with casting on pointer types The expression is now optional for a ReturnStmt (only legal in void funcs)
author Anders Halager <halager@gmail.com>
date Sun, 20 Apr 2008 23:53:05 +0200
parents ce17bea8e9bd
children 495188f9078e
line wrap: on
line source

module sema.Visitor;

import tango.io.Stdout;

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

import lexer.Token;

class Visitor(FinalT = int, DeclT = FinalT, StmtT = DeclT, ExpT = StmtT)
{
public:
    FinalT visit(Decl[] decls)
    {
        foreach (decl; decls)
            visitDecl(decl);
        static if (is(FinalT == void))
            return;
        else
            return FinalT.init;
    }

    DeclT visitDecl(Decl decl)
    {
        switch(decl.declType)
        {
            case DeclType.FuncDecl:
                return visitFuncDecl(cast(FuncDecl)decl);
            case DeclType.VarDecl:
                return visitVarDecl(cast(VarDecl)decl);
            case DeclType.StructDecl:
                return visitStructDecl(cast(StructDecl)decl);
            default:
                throw new Exception("Unknown declaration type");
        }
    }

    StmtT visitStmt(Stmt stmt)
    {
        switch(stmt.stmtType)
        {
            case StmtType.Return:
                return visitReturnStmt(cast(ReturnStmt)stmt);
            case StmtType.Decl:
                return visitDeclStmt(cast(DeclStmt)stmt);
            case StmtType.Exp:
                return visitExpStmt(cast(ExpStmt)stmt);
            case StmtType.If:
                return visitIfStmt(cast(IfStmt)stmt);
            case StmtType.While:
                return visitWhileStmt(cast(WhileStmt)stmt);
            case StmtType.Switch:
                return visitSwitchStmt(cast(SwitchStmt)stmt);
            default:
                throw new Exception("Unknown statement type");
        }
    }

    ExpT visitExp(Exp exp)
    {
        switch(exp.expType)
        {
            case ExpType.Binary:
                return visitBinaryExp(cast(BinaryExp)exp);
            case ExpType.IntegerLit:
                return visitIntegerLit(cast(IntegerLit)exp);
            case ExpType.Negate:
                return visitNegateExp(cast(NegateExp)exp);
            case ExpType.AssignExp:
                return visitAssignExp(cast(AssignExp)exp);
            case ExpType.CallExp:
                return visitCallExp(cast(CallExp)exp);
            case ExpType.Identifier:
                return visitIdentifier(cast(Identifier)exp);
            case ExpType.MemberLookup:
                return visitMemberLookup(cast(MemberLookup)exp);
            default:
                throw new Exception("Unknown expression type");
        }
    }

    // Declarations:
    DeclT visitVarDecl(VarDecl d)
    {
        visitExp(d.type);
        visitExp(d.identifier);
        if (d.init)
            visitExp(d.init);

        static if (is(DeclT == void))
            return;
        else
            return DeclT.init;
    }

    DeclT visitFuncDecl(FuncDecl f)
    {
        visitExp(f.type);
        visitExp(f.identifier);
        foreach (arg; f.funcArgs)
            visitDecl(arg);
        foreach (stmt; f.statements)
            visitStmt(stmt);

        static if (is(DeclT == void))
            return;
        else
            return DeclT.init;
    }

    DeclT visitStructDecl(StructDecl s)
    {
        visitExp(s.identifier);

        foreach (arg; s.vars)
            visitDecl(arg);

        static if (is(DeclT == void))
            return;
        else
            return DeclT.init;
    }

    // Statements:
    StmtT visitReturnStmt(ReturnStmt s)
    {
        if (s.exp)
            visitExp(s.exp);
        static if (is(StmtT == void))
            return;
        else
            return StmtT.init;
    }

    StmtT visitDeclStmt(DeclStmt d)
    {
        visitDecl(d.decl);
        static if (is(StmtT == void))
            return;
        else
            return StmtT.init;
    }

    StmtT visitIfStmt(IfStmt s)
    {
        visitExp(s.cond);
        foreach (stmt; s.then_body)
            visitStmt(stmt);
        foreach (stmt; s.else_body)
            visitStmt(stmt);
        static if (is(StmtT == void))
            return;
        else
            return StmtT.init;
    }

    StmtT visitWhileStmt(WhileStmt s)
    {
        visitExp(s.cond);
        foreach (stmt; s.stmts)
            visitStmt(stmt);
        static if (is(StmtT == void))
            return;
        else
            return StmtT.init;
    }

    StmtT visitSwitchStmt(SwitchStmt s)
    {
        visitExp(s.cond);
        foreach(stmt; s.defaultBlock)
            visitStmt(stmt);
        foreach (c; s.cases)
        {
            foreach(lit; c.values)
                visitIntegerLit(lit);
            foreach(stmt; c.stmts)
                visitStmt(stmt);
        }
        static if (is(StmtT == void))
            return;
        else
            return StmtT.init;
    }

    StmtT visitExpStmt(ExpStmt s)
    {
        visitExp(s.exp);
        static if (is(StmtT == void))
            return;
        else
            return StmtT.init;
    }

    // Expressions:
    ExpT visitAssignExp(AssignExp exp)
    {
        visitExp(exp.identifier);
        visitExp(exp.exp);
        static if (is(ExpT == void))
            return;
        else
            return ExpT.init;
    }

    ExpT visitBinaryExp(BinaryExp exp)
    {
        visitExp(exp.left);
        visitExp(exp.right);
        static if (is(ExpT == void))
            return;
        else
            return ExpT.init;
    }

    ExpT visitCallExp(CallExp exp)
    {
        visitExp(exp.exp);
        foreach (arg; exp.args)
            visitExp(arg);
        static if (is(ExpT == void))
            return;
        else
            return ExpT.init;
    }

    ExpT visitNegateExp(NegateExp exp)
    {
        visitExp(exp.exp);
        static if (is(ExpT == void))
            return;
        else
            return ExpT.init;
    }

    ExpT visitIntegerLit(IntegerLit exp)
    {
        static if (is(ExpT == void))
            return;
        else
            return ExpT.init;
    }

    ExpT visitIdentifier(Identifier exp)
    {
        static if (is(ExpT == void))
            return;
        else
            return ExpT.init;
    }

    ExpT visitMemberLookup(MemberLookup mem)
    {
        visitExp(mem.target);
        visitExp(mem.child);

        static if (is(ExpT == void))
            return;
        else
            return ExpT.init;
    }
}