view sema/AstAction.d @ 185:7b274cfdc1dc

Added support for array literals. Codegen is broken, though.
author Anders Johnsen <skabet@gmail.com>
date Fri, 25 Jul 2008 12:18:05 +0200
parents 29324df1d649
children 08f68d684047
line wrap: on
line source

module sema.AstAction;

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

import lexer.Token;

import basic.SourceManager,
       basic.Attribute;

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

public
import parser.Action;

/**
  This class implements the default actions for Dang, by building up an AST
  with the data needed in a compiler.
 */
class AstAction : Action
{
    this(SourceManager sm)
    {
        this.sm = sm;
    }
    private SourceManager sm;

    private IdentifierTypeExp handleType(Id type)
    {
        if(auto t = cast(PointerTypeId)type)
            return new PointerTypeExp(handleType(t.id));
        if(auto t = cast(StaticArrayTypeId)type)
            return new StaticArrayTypeExp(handleType(t.id), cast(IntegerLit)t.number);
        if(auto t = cast(FunctionTypeId)type)
            return new FunctionTypeExp(handleType(t.id), cast(VarDecl[])t.decls);
        
        return new IdentifierTypeExp(type.tok.location, sm.getText(type.tok.asRange));
    }

    private Identifier identifierFromTok(Token t)
    {
        return new Identifier(t.location, sm.getText(t.asRange));
    }
override
{
    ModuleT actOnModule(ref Token _module, char[] name)
    {
        return new Module(name);
    }

    ModuleT actOnImplicitModule(SLoc startLoc, char[] name)
    {
        return new Module(name);
    }

    void actOnModuleDecl(ModuleT m, DeclT d)
    {
        (cast(Module)m).addDecl(cast(Decl)d);
    }

    // -- Declarations --
    DeclT actOnImport(ref Token _, ref ModuleName target, Id* name)
    {
        auto res = new ImportDecl;
        Identifier[] packages = new Identifier[target.packages.length];
        foreach (i, v; target.packages)
            packages[i] = identifierFromTok(v.tok);
        res.packages = packages;

        res.name = identifierFromTok(target.id.tok);
        if (name !is null)
            res.aliasedName = identifierFromTok(name.tok);
        return res;
    }

    void addSelectiveImport(DeclT _import, ref Id target, Id* name)
    {
        auto d = cast(ImportDecl)_import;
        Identifier t = identifierFromTok(target.tok);
        Identifier n = t;
        if (name !is null)
            n = identifierFromTok(name.tok);
        d.explicitSymbols ~= [t, n];
    }

    DeclT actOnDeclarator(ref Id type, ref Id id, ExprT init, Attribute att)
    {
        Decl d;
        Exp exp = cast(Exp)init;
        if (type.tok.type == Tok.Struct)
            d = new StructDecl(identifierFromTok(id.tok));
        else if (type.tok.type == Tok.Class)
            d = new ClassDecl(identifierFromTok(id.tok));
        else if (type.tok.type == Tok.Interface)
            d = new InterfaceDecl(identifierFromTok(id.tok));
        else
            d = new VarDecl(handleType(type), id ? identifierFromTok(id.tok) : null, exp);

        d.att = att;
        return d;
    }
    
    void actOnStructMember(DeclT st_decl, DeclT m_decl) //ref Id type, ref Id name, ExprT init)
    {
        StructDecl st = cast(StructDecl)st_decl;
        st.addMember(cast(Decl)m_decl);
    }

    void actOnClassMember(DeclT cl_decl, DeclT m_decl) 
    {
        ClassDecl cl = cast(ClassDecl)cl_decl;
        cl.addMember(cast(Decl)m_decl);
    }

    void actOnClassBaseClass(DeclT cl_decl, ref Id name)
    {
        ClassDecl cl = cast(ClassDecl)cl_decl;
        cl.addBaseClass(identifierFromTok(name.tok));
    }

    void actOnInterfaceMember(DeclT if_decl, DeclT m_decl)
    {
        InterfaceDecl inf = cast(InterfaceDecl)if_decl;
        inf.addMember(cast(Decl)m_decl);
    }

    void actOnInterfaceBaseClass(DeclT if_decl, ref Id name)
    {
        InterfaceDecl inf = cast(InterfaceDecl)if_decl;
        inf.addBaseClass(identifierFromTok(name.tok));
    }

    ExprT actOnMemberReference(ExprT lhs, SLoc op, Id member)
    {
        Exp exp = cast(Exp)lhs;
        Identifier id = identifierFromTok(member.tok);
        return new MemberReference(op, exp, id);
    }

    DeclT actOnStartOfFunctionDef(ref Id type, ref Id name, Attribute att)
    {
        auto res = new FuncDecl(handleType(type), identifierFromTok(name.tok));
        res.att = att;
        return res;
    }

    void addFuncArg(DeclT func, Id type, Id name)
    {
        FuncDecl fd = cast(FuncDecl)func;
        if(name)
            fd.addParam(handleType(type), identifierFromTok(name.tok));
        else
            fd.addParam(handleType(type));
    }

    DeclT actOnEndOfFunction(DeclT func, StmtT stmts)
    {
        FuncDecl fd = cast(FuncDecl)func;
        fd.setBody(cast(CompoundStatement)stmts);
        return fd;
    }

    // -- Statements --
    StmtT actOnCompoundStmt(ref Token l, ref Token r, StmtT[] stmts)
    {
        Stmt[] statements = cast(Stmt[])stmts;
        return new CompoundStatement(statements.dup);
    }

    StmtT actOnExprStmt(ExprT exp)
    {
        return new ExpStmt(cast(Exp)exp);
    }

    StmtT actOnReturnStmt(ref Token loc, ExprT exp)
    {
        Exp e = cast(Exp)exp;
        auto res = new ReturnStmt;
        res.exp = e;
        return res;
    }

    StmtT actOnIfStmt(ref Token ifTok, ExprT cond, StmtT thenBody,
                               ref Token elseTok, StmtT elseBody)
    {
        Exp c = cast(Exp)cond;
        Stmt t = cast(Stmt)thenBody;
        Stmt e = cast(Stmt)elseBody;
        return new IfStmt(c, t, e);
    }

    StmtT actOnWhileStmt(ref Token tok, ExprT cond, StmtT whileBody)
    {
        Exp c = cast(Exp)cond;
        Stmt b = cast(Stmt)whileBody;
        return new WhileStmt(c, b);
    }

    StmtT actOnForStmt(ref Token tok, StmtT init, ExprT cond, ExprT incre, StmtT forBody)
    {
        Stmt i = cast(Stmt)init;
        Exp c = cast(Exp)cond;
        Exp inc = cast(Exp)incre;
        Stmt b = cast(Stmt)forBody;
        return new ForStmt(i, c, inc, b);
    }

    StmtT actOnDeclStmt(DeclT decl)
    {
        Decl d = cast(Decl)decl;
        return new DeclStmt(d);
    }

    StmtT actOnStartOfSwitchStmt(Token _switch, ExprT exp)
    {
        return new SwitchStmt(_switch.location, cast(Exp)exp);
    }

    void actOnCaseStmt(StmtT stmt, Token _case, ExprT[] exps, StmtT[] stmts)
    {
        auto sw = cast(SwitchStmt)stmt;
        sw.addCase(_case.location, cast(Exp[])exps, cast(Stmt[])stmts);
    }

    void actOnDefaultStmt(StmtT stmt, Token _default, StmtT[] stmts)
    {
        auto sw = cast(SwitchStmt)stmt;
        sw.setDefault(_default.location, cast(Stmt[])stmts);
    }

    // -- Expressions --
    ExprT actOnNumericConstant(Token c)
    {
        return new IntegerLit(c.location, sm.getText(c.asRange));
    }

    ExprT actOnStringExp(Token s)
    {
        return new StringExp(s.location, sm.getText(s.asRange));
    }

    ExprT actOnIdentifierExp(Id id)
    {
        return identifierFromTok(id.tok);
    }

    ExprT actOnBinaryOp(SLoc op_loc, Operator op, ExprT l, ExprT r)
    {
        Exp left = cast(Exp)l;
        Exp right = cast(Exp)r;
        switch(op)
        {
            case Operator.Assign:
            case Operator.AddAssign:
            case Operator.SubAssign:
            case Operator.MulAssign:
            case Operator.DivAssign:
            case Operator.ModAssign:
                return new AssignExp(op_loc, cast(BinaryExp.Operator)op, left, right);
            default:
                BinaryExp.Operator bin_op = cast(BinaryExp.Operator)op;
                return new BinaryExp(op_loc, bin_op, left, right);
        }
    }

    ExprT actOnUnaryOp(Token op, ExprT operand)
    {
        Exp target = cast(Exp)operand;
        if (op.type == Tok.Minus)
            return new NegateExp(op.location, target);
        if (op.type == Tok.Star)
            return new DerefExp(op.location, target);
        if (op.type == Tok.And)
            return new AddressOfExp(op.location, target);
        assert(0, "Only valid unary expressions are -x and *x");
    }

    ExprT actOnCallExpr(ExprT fn, ref Token, ExprT[] args, ref Token)
    {
        Exp f = cast(Exp)fn;
        Exp[] arguments = cast(Exp[])args.dup;
        return new CallExp(f, arguments);
    }

    ExprT actOnCastExpr(ref Token _cast, Id id, ExprT exp)
    {
        Exp target = cast(Exp)exp;
        Identifier target_type = identifierFromTok(id.tok);
        return new CastExp(_cast.location, target_type, target);
    }

    ExprT actOnIndexExpr(ExprT arr, ref Token lb, ExprT index, ref Token rb)
    {
        Exp target = cast(Exp)arr;
        Exp idx = cast(Exp)index;
        return new IndexExp(target, lb.location, idx, rb.location);
    }

    ExprT actOnNewExpr(ref Id type, ExprT[] a_args, ExprT[] c_args)
    {
        auto id = identifierFromTok(type.tok);
        Exp[] _a_args = cast(Exp[])a_args;
        Exp[] _c_args = cast(Exp[])c_args;
        return new NewExp(id, _a_args, _c_args);
    }

    ExprT actOnArrayLiteralExpr(ExprT[] exps, SLoc start, SLoc end)
    {
        return new ArrayLiteralExp(cast(Exp[])exps, start, end);
    }
}
}