diff dmd/PowExp.d @ 130:60bb0fe4563e

dmdfe 2.037 first main iteration
author Eldar Insafutdinov <e.insafutdinov@gmail.com>
date Thu, 09 Sep 2010 22:51:44 +0100
parents
children 206db751bd4c
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/PowExp.d	Thu Sep 09 22:51:44 2010 +0100
@@ -0,0 +1,96 @@
+module dmd.PowExp;
+
+import dmd.BinExp;
+import dmd.Scope;
+import dmd.Loc;
+import dmd.Identifier;
+import dmd.Expression;
+
+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;
+    }
+}
+
+}
\ No newline at end of file