Mercurial > projects > ddmd
view dmd/PowExp.d @ 178:e3afd1303184
Many small bugs fixed
Made all classes derive from TObject to detect memory leaks (functionality is disabled for now)
Began work on overriding backend memory allocations (to avoid memory leaks)
author | korDen |
---|---|
date | Sun, 17 Oct 2010 07:42:00 +0400 |
parents | 96c0fff6897d |
children | cd48cb899aee |
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.Global; 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) { register(); 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; } if (!global.importMathChecked) { global.importMathChecked = true; auto amodules = global.amodules; for (int i = 0; i < amodules.dim; i++) { auto mi = cast(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; } } }