view sema/ImplicitCast.d @ 88:eb5b2c719a39 new_gen

Major change to locations, tokens and expressions. A location (now SourceLocation or SLoc) is only 32 bit in size - disadvantage is that it can't find its own text. You have to go through the new SourceManager to do that. This has caused changes to a lot of stuff and removal of DataSource and the old Location Additionally Exp has gotten some location stuff, so we can give proper error messages. Not in Decl and Stmt yet, but thats coming too.
author Anders Halager <halager@gmail.com>
date Sun, 04 May 2008 18:13:46 +0200
parents 9a35a973175a
children
line wrap: on
line source

module sema.ImplicitCast;

import sema.Visitor,
       sema.DType;

import tango.io.Stdout;

import misc.Error,
       basic.SourceLocation;

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(
                    SLoc.Invalid,
                    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(
                    SLoc.Invalid,
                    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(
                        SLoc.Invalid,
                        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)
        {
            if(!expType.hasImplicitConversionTo(identifierType))
                throw error(__LINE__, "Cannot make implicit cast between");

            auto castExp = new CastExp(
                    SLoc.Invalid,
                    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(
                        SLoc.Invalid,
                        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(
                        SLoc.Invalid,
                        new Identifier(varType.name),
                        decl.init);
                castExp.env = decl.init.env;
                decl.init = castExp;
            }
        }
    }
}