view sema/BuildTypes.d @ 195:4e1a7265d620

Made a BuildTypes pass, to give all exp's a type.
author Anders Johnsen <skabet@gmail.com>
date Tue, 29 Jul 2008 15:50:24 +0200
parents
children
line wrap: on
line source

module sema.BuildTypes;

import basic.LiteralParsing,
       basic.Message;

import sema.Visitor,
       sema.Symbol,
       sema.DType;

import tango.io.Stdout;


class BuildTypes : Visitor!(void)
{
    this(MessageHandler messages)
    {
        this.messages = messages;
    }

    override void visitCallExp(CallExp exp)
    {
        super.visitCallExp(exp);
        DFunction f = exp.exp.type.asCallable();
        assert(f !is null, "Can only call functions");
        exp.type = f.returnType;
    }

    override void visitAssignExp(AssignExp exp)
    {
        super.visitAssignExp(exp);
        exp.type = exp.identifier.type;
    }

    override void visitBinaryExp(BinaryExp exp)
    {
        super.visitBinaryExp(exp);
        if (exp.op == BinaryExp.Operator.Eq || 
            exp.op == BinaryExp.Operator.Ne ||
            exp.op == BinaryExp.Operator.Lt ||
            exp.op == BinaryExp.Operator.Le ||
            exp.op == BinaryExp.Operator.Gt ||
            exp.op == BinaryExp.Operator.Ge)
        {
            exp.type = DType.Bool;
            return;
        }

        DType l = exp.left.type;
        DType r = exp.right.type;
        if (l.isSame(r))
            exp.type = l;
        else if (l.hasImplicitConversionTo(r))
            exp.type = r;
        else if (r.hasImplicitConversionTo(l))
            exp.type = l;
        else
            exp.type = DType.Int; //FIXME: Throw error here.
    }

    override void visitNegateExp(NegateExp exp) 
    { 
        super.visitNegateExp(exp);
        exp.type = exp.exp.type; 
    }

    override void visitDerefExp(DerefExp exp)
    {
        super.visitDerefExp(exp);
        exp.type = exp.exp.type.asPointer().pointerOf; 
    }

    override void visitAddressOfExp(AddressOfExp exp)
    {
        super.visitAddressOfExp(exp);
        exp.type = exp.exp.type.getPointerTo; 
    }

    override void visitIntegerLit(IntegerLit exp)
    {
        super.visitIntegerLit(exp);
        switch(exp.number.type)
        {
            case NumberType.Int:
                exp.type = DType.Int;
                break;
            case NumberType.Long:
                exp.type = DType.Long;
                break;
            case NumberType.ULong:
                exp.type = DType.ULong;
                break;
            case NumberType.Double:
                exp.type = DType.Double;
                break;
            case NumberType.Real:
                exp.type = DType.Real;
                break;
        }
    }

    override void visitMemberReference(MemberReference exp)
    {
        super.visitMemberReference(exp);
        if ( exp.target.type.isStruct )
        {
            Symbol st = exp.target.getSymbol;
            if (auto t = st.findMembers(exp.child.name))
                exp.type = t[0].type;
//            else assert(0, "Referencing non-existant member");
        }
        else if ( exp.target.type.isClass )
        {
            Symbol cl = exp.target.getSymbol;
            if (auto t = cl.findMembers(exp.child.name))
                exp.type = t[0].type;
//            else assert(0, "Referencing non-existant member");
        }
        else
            assert(0, "Only structs and classes have members");
        // no error reporting here
    }

    override void visitIndexExp(IndexExp exp)
    {
        super.visitIndexExp(exp);
        DType type = exp.target.type;
        if (type.isStaticArray())
            exp.type = type.asStaticArray().arrayOf;
        else if (type.isPointer())
            exp.type = type.asPointer().pointerOf;
        else assert(0, "Can only index pointers and arrays");
    }

    override void visitCastExp(CastExp exp)
    {
        super.visitCastExp(exp);
        exp.type = exp.env.findType(exp.castType.get);
    }

    override void visitStringExp(StringExp exp)
    {
        super.visitStringExp(exp);
        switch (exp.data.type)
        {
            case StringType.Char:
                exp.type = DType.Char.getAsStaticArray(exp.data.data.length); 
                break;
            case StringType.WChar:
                exp.type = DType.WChar.getAsStaticArray(exp.data.data.length/2); 
                break;
            case StringType.DChar:
                exp.type = DType.DChar.getAsStaticArray(exp.data.data.length/4); 
                break;
        }
    }

    override void visitNewExp(NewExp exp)
    {
        super.visitNewExp(exp);
        exp.type = exp.env.findType(exp.newType.get); 
    }

    override void visitNullExp(NullExp exp)
    {
        super.visitNullExp(exp);
        exp.type = new DPointer(DType.Int);
    }

    override void visitIdentifier(Identifier exp)
    {
        super.visitIdentifier(exp);
        if (auto sym = exp.getSymbol)
            exp.type = sym.type;
        else
            exp.type = DType.Int;
    }

/*    override void visitIdentifierTypeExp(IdentifierTypeExp exp)
    {
        if (auto sym = exp.getSymbol)
            exp.type = sym.type;
        else
            exp.type = DType.Int;
    }*/

    override void visitPointerTypeExp(PointerTypeExp exp)
    {
        super.visitPointerTypeExp(exp);
        exp.type = exp.pointerOf.type.getPointerTo();
    }

    override void visitStaticArrayTypeExp(StaticArrayTypeExp exp)
    {
        super.visitStaticArrayTypeExp(exp);
        exp.type = exp.arrayOf.type.getAsStaticArray(exp.size);
    }

/*    override void visitArrayTypeExp(ArrayTypeExp exp)
    {
        exp.type = arrayOf.type.getAsArray();
    }*/

    override void visitFunctionTypeExp(FunctionTypeExp exp)
    {
        super.visitFunctionTypeExp(exp);
        auto t  = new DFunction(exp.returnType);
        t.returnType = exp.returnType.type;
        foreach (decl ; exp.decls)
            t.params ~= decl.varType.type;

        exp.type = t.getPointerTo;
    }

    override void visitArrayLiteralExp(ArrayLiteralExp exp)
    {
        super.visitArrayLiteralExp(exp);
        exp.type = exp.exps[0].type.getAsStaticArray(exp.exps.length);
    }

    MessageHandler messages;
}