view dmd/PowExp.d @ 131:206db751bd4c

dmdfe 2.037 compiles now
author Eldar Insafutdinov <e.insafutdinov@gmail.com>
date Fri, 10 Sep 2010 00:27:37 +0100
parents 60bb0fe4563e
children af1bebfd96a4
line wrap: on
line source

module dmd.PowExp;

import dmd.BinExp;
import dmd.Scope;
import dmd.Loc;
import dmd.Identifier;
import dmd.Expression;
import dmd.TOK;
import dmd.Module;
import dmd.Id;
import dmd.IdentifierExp;
import dmd.DotIdExp;
import dmd.CallExp;
import dmd.ErrorExp;

version(DMDV2) {

class PowExp : BinExp
{
    this(Loc loc, Expression e1, Expression e2)
    {
        super(loc, TOK.TOKpow, PowExp.sizeof, e1, e2);
    }
        
    Expression semantic(Scope sc)
    {
        Expression e;

        if (type)
	        return this;

        BinExp.semanticp(sc);
        e = op_overload(sc);
        if (e)
	        return e;

        static int importMathChecked = 0;
        if (!importMathChecked)
        {
	        importMathChecked = 1;
	        for (int i = 0; i < Module.amodules.dim; i++)
	        {
                auto mi = cast(Module)Module.amodules.data[i];
	            //printf("\t[%d] %s\n", i, mi->toChars());
	            if (mi.ident == Id.math &&
		        mi.parent.ident == Id.std &&
		        !mi.parent.parent)
		        goto L1;
	        }
	        error("must import std.math to use ^^ operator");

            L1: ;
        }

        assert(e1.type && e2.type);
        if ( (e1.type.isintegral() || e1.type.isfloating()) &&
	     (e2.type.isintegral() || e2.type.isfloating()))
        {
	        // For built-in numeric types, there are three cases:
	        // x ^^ 1   ----> x
	        // x ^^ 0.5 ----> sqrt(x)
	        // x ^^ y   ----> pow(x, y)
	        // TODO: backend support, especially for  e1 ^^ 2.
	        bool wantSqrt = false;	
	        e2 = e2.optimize(0);
	        if ((e2.op == TOK.TOKfloat64 && e2.toReal() == 1.0) ||
	            (e2.op == TOK.TOKint64 && e2.toInteger() == 1))
	        {
	            return e1;  // Replace x ^^ 1 with x.
	        }

	        e = new IdentifierExp(loc, Id.empty);
	        e = new DotIdExp(loc, e, Id.std);
	        e = new DotIdExp(loc, e, Id.math);
	        if (e2.op == TOKfloat64 && e2.toReal() == 0.5)
	        {   // Replace e1 ^^ 0.5 with .std.math.sqrt(x)
	            e = new CallExp(loc, new DotIdExp(loc, e, Id._sqrt), e1);
	        }
	        else 
	        {   // Replace e1 ^^ e2 with .std.math.pow(e1, e2)
 	            e = new CallExp(loc, new DotIdExp(loc, e, Id._pow), e1, e2);	
	        }	
	        e = e.semantic(sc);
	        return e;
        }
        error("%s ^^ %s is not supported", e1.type.toChars(), e2.type.toChars() );
        return new ErrorExp();
    }
   

    // For operator overloading
    Identifier opId()
    {
        return Id.pow;
    }
    
    Identifier opId_r()
    {
        return Id.pow_r;
    }
}

}