view sema/ImplicitCast.d @ 80:682e20aa224f new_gen

Pointers working now - big YAY
author Anders Johnsen <skabet@gmail.com>
date Fri, 02 May 2008 17:33:50 +0200
parents 70a002b3fba4
children 9a35a973175a
line wrap: on
line source

module sema.ImplicitCast;

import sema.Visitor,
       sema.DType;

import tango.io.Stdout;

import misc.Error;

class ImplicitCast : Visitor!(void)
{
    private Error error(uint line, char[] msg)
    {
        return new Error(msg);
    }

    override void visitBinaryExp(BinaryExp exp)
    {
        super.visitBinaryExp(exp);

        if(exp.left.type.byteSize > exp.right.type.byteSize)
        {
            if(!exp.right.type.hasImplicitConversionTo(exp.left.type))
                throw error(__LINE__, "Cannot make implicit cast");

            auto castExp = new CastExp(
                    new Identifier(exp.left.type.name),
                    exp.right);
            castExp.env = exp.env;
            exp.right = castExp;
        }

        if(exp.left.type.byteSize < exp.right.type.byteSize)
        {
            if(!exp.left.type.hasImplicitConversionTo(exp.right.type))
                throw error(__LINE__, "Cannot make implicit cast");

            auto castExp = new CastExp(
                    new Identifier(exp.right.type.name),
                    exp.left);
            castExp.env = exp.env;
            exp.left = castExp;
        }

    }

    override void visitCallExp(CallExp exp)
    {
        super.visitCallExp(exp);

        Exp[] newArgs;

        foreach(i, arg; exp.args)
        {
            auto argType = (cast(DFunction)exp.exp.type).params[i];
            auto expType = arg.type;
            if(argType.byteSize != expType.byteSize)
            {
                if(!expType.hasImplicitConversionTo(argType))
                    throw error(__LINE__, "Cannot make implicit cast");

                auto castExp = new CastExp(
                        new Identifier(argType.name),
                        arg);
                castExp.env = exp.exp.env;
                newArgs ~= castExp;
            }
            else
                newArgs ~= arg;
        }

        exp.args = newArgs;
    }

    override void visitAssignExp(AssignExp exp)
    {
        super.visitAssignExp(exp);

        auto identifierType = exp.identifier.type;
        auto expType = exp.exp.type;

        if(identifierType != expType)
        {
            Stdout(&identifierType)(identifierType).newline;
            Stdout(&expType)(expType).newline;
            if(!expType.hasImplicitConversionTo(identifierType))
                throw error(__LINE__, "Cannot make implicit cast between");

            auto castExp = new CastExp(
                    new Identifier(expType.name),
                    exp.exp);
            castExp.env = exp.exp.env;
            exp.exp = castExp;
        }
    }

    override void visitReturnStmt(ReturnStmt stmt)
    {
        super.visitReturnStmt(stmt);

        if(stmt.exp)
        {
            auto returnType = stmt.env.parentFunction.type.asFunction.returnType;
            auto expType = stmt.exp.type;
            if(returnType != expType)
            {
                if(!expType.hasImplicitConversionTo(returnType))
                    throw error(__LINE__, "Cannot make implicit cast");

                auto castExp = new CastExp(
                        new Identifier(returnType.name),
                        stmt.exp);
                castExp.env = stmt.exp.env;
                stmt.exp = castExp;
            }
        }
    }

    override void visitVarDecl(VarDecl decl)
    {
        super.visitVarDecl(decl);

        if(decl.init)
        {
            auto varType = decl.type;
            auto expType = decl.init.type;
            if(varType.byteSize != expType.byteSize)
            {
                if(!expType.hasImplicitConversionTo(varType))
                    throw error(__LINE__, "Cannot make implicit cast");

                auto castExp = new CastExp(
                        new Identifier(varType.name),
                        decl.init);
                castExp.env = decl.init.env;
                decl.init = castExp;
            }
        }
    }
}