Mercurial > projects > ddmd
view dmd/PowExp.d @ 157:b7b61140701d
* added all missing default cases in switch statements
+ Lexer.getDocComment
+ Lexer.combineComments
author | trass3r |
---|---|
date | Thu, 16 Sep 2010 01:34:10 +0200 |
parents | af1bebfd96a4 |
children | e7769d53e750 |
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; import dmd.CommaExp; import dmd.AndExp; import dmd.CondExp; import dmd.IntegerExp; import dmd.Type; import dmd.Lexer; import dmd.VarDeclaration; import dmd.ExpInitializer; import dmd.VarExp; import dmd.DeclarationExp; import dmd.MulExp; import dmd.WANT; version(DMDV2) { class PowExp : BinExp { this(Loc loc, Expression e1, Expression e2) { super(loc, TOK.TOKpow, PowExp.sizeof, e1, e2); } override Expression semantic(Scope sc) { Expression e; if (type) return this; //printf("PowExp::semantic() %s\n", toChars()); BinExp.semanticp(sc); e = op_overload(sc); if (e) return e; 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 several cases. // TODO: backend support, especially for e1 ^^ 2. bool wantSqrt = false; e1 = e1.optimize(0); e2 = e2.optimize(0); // Replace 1 ^^ x or 1.0^^x by (x, 1) if ((e1.op == TOK.TOKint64 && e1.toInteger() == 1) || (e1.op == TOK.TOKfloat64 && e1.toReal() == 1.0)) { typeCombine(sc); e = new CommaExp(loc, e2, e1); e = e.semantic(sc); return e; } // Replace -1 ^^ x by (x&1) ? -1 : 1, where x is integral if (e2.type.isintegral() && e1.op == TOKint64 && cast(long)e1.toInteger() == -1) { typeCombine(sc); Type resultType = type; e = new AndExp(loc, e2, new IntegerExp(loc, 1, e2.type)); e = new CondExp(loc, e, new IntegerExp(loc, -1, resultType), new IntegerExp(loc, 1, resultType)); e = e.semantic(sc); return e; } // All other negative integral powers are illegal if ((e1.type.isintegral()) && (e2.op == TOK.TOKint64) && cast(long)e2.toInteger() < 0) { error("cannot raise %s to a negative integer power. Did you mean (cast(real)%s)^^%s ?", e1.type.toBasetype().toChars(), e1.toChars(), e2.toChars()); return new ErrorExp(); } // Deal with x^^2, x^^3 immediately, since they are of practical importance. // Don't bother if x is a literal, since it will be constant-folded anyway. if ( ( (e2.op == TOK.TOKint64 && (e2.toInteger() == 2 || e2.toInteger() == 3)) || (e2.op == TOK.TOKfloat64 && (e2.toReal() == 2.0 || e2.toReal() == 3.0)) ) && (e1.op == TOK.TOKint64 || e1.op == TOK.TOKfloat64) ) { typeCombine(sc); // Replace x^^2 with (tmp = x, tmp*tmp) // Replace x^^3 with (tmp = x, tmp*tmp*tmp) Identifier idtmp = Lexer.uniqueId("__tmp"); VarDeclaration tmp = new VarDeclaration(loc, e1.type.toBasetype(), idtmp, new ExpInitializer(Loc(0), e1)); VarExp ve = new VarExp(loc, tmp); Expression ae = new DeclarationExp(loc, tmp); Expression me = new MulExp(loc, ve, ve); if ( (e2.op == TOK.TOKint64 && e2.toInteger() == 3) || (e2.op == TOK.TOKfloat64 && e2.toReal() == 3.0)) me = new MulExp(loc, me, ve); e = new CommaExp(loc, ae, me); e = e.semantic(sc); 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: ; } e = new IdentifierExp(loc, Id.empty); e = new DotIdExp(loc, e, Id.std); e = new DotIdExp(loc, e, Id.math); if (e2.op == TOK.TOKfloat64 && e2.toReal() == 0.5) { // Replace e1 ^^ 0.5 with .std.math.sqrt(x) typeCombine(sc); e = new CallExp(loc, new DotIdExp(loc, e, Id._sqrt), e1); } else { // Replace e1 ^^ e2 with .std.math.pow(e1, e2) // We don't combine the types if raising to an integer power (because // integer powers are treated specially by std.math.pow). if (!e2.type.isintegral()) typeCombine(sc); e = new CallExp(loc, new DotIdExp(loc, e, Id._pow), e1, e2); } e = e.semantic(sc); // Always constant fold integer powers of literals. This will run the interpreter // on .std.math.pow if ((e1.op == TOK.TOKfloat64 || e1.op == TOK.TOKint64) && (e2.op == TOK.TOKint64)) e = e.optimize(WANT.WANTvalue | WANT.WANTinterpret); return e; } error("%s ^^ %s is not supported", e1.type.toChars(), e2.type.toChars() ); return new ErrorExp(); } // For operator overloading override Identifier opId() { return Id.pow; } override Identifier opId_r() { return Id.pow_r; } } }