view sema/AstAction.d @ 102:cd066f3b539a new_gen

Parsing methods in structs - error on semantics though.
author Anders Johnsen <skabet@gmail.com>
date Thu, 08 May 2008 10:32:41 +0200
parents 857f0d530789
children 7ff4bc2accf2
line wrap: on
line source

module sema.AstAction;

import Integer = tango.text.convert.Integer;

import lexer.Token;

import misc.Error,
       basic.SourceManager;

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 Identifier handleType(Id type)
    {
        if(auto t = cast(PointerId)type)
            return new PointerIdentifier(handleType(t.id));
        if(auto t = cast(ArrayId)type)
            return new ArrayIdentifier(handleType(t.id), cast(IntegerLit)t.number);
        else
            return identifierFromTok(type.tok);
    }

    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);
    }

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

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

    // -- Declarations --
    override 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;
    }

    override 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];
    }

    override DeclT actOnDeclarator(ref Id type, ref Id id, ExprT init)
    {
        Exp exp = cast(Exp)init;
        if(type.tok.type == Tok.Struct)
            return new StructDecl(identifierFromTok(id.tok));
        else
            return new VarDecl(handleType(type), identifierFromTok(id.tok), exp);
    }
    
    override 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);
    }

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

    override DeclT actOnStartOfFunctionDef(ref Id type, ref Id name)
    {
        return new FuncDecl(identifierFromTok(type.tok), identifierFromTok(name.tok));
    }

    override 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(identifierFromTok(type.tok));
    }

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

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

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

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

    override 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);
    }

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

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

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

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

    override ExprT actOnBinaryOp(SLoc op_loc, Operator op, ExprT l, ExprT r)
    {
        Exp left = cast(Exp)l;
        Exp right = cast(Exp)r;
        if (op == Operator.Assign)
            return new AssignExp(op_loc, left, right);
        else
        {
            BinaryExp.Operator bin_op = cast(BinaryExp.Operator)op;
            return new BinaryExp(op_loc, bin_op, left, right);
        }
    }

    override 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);
        assert(0, "Only valid unary expressions are -x and *x");
    }

    override 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);
    }

    override 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);
    }

    override ExprT
        actOnIndexEpr(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);
    }
}