Mercurial > projects > ddmd
annotate 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 |
rev | line source |
---|---|
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
1 module dmd.PowExp; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
2 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
3 import dmd.BinExp; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
4 import dmd.Scope; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
5 import dmd.Loc; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
6 import dmd.Identifier; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
7 import dmd.Expression; |
131
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
8 import dmd.TOK; |
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
9 import dmd.Module; |
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
10 import dmd.Id; |
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
11 import dmd.IdentifierExp; |
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
12 import dmd.DotIdExp; |
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
13 import dmd.CallExp; |
206db751bd4c
dmdfe 2.037 compiles now
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
130
diff
changeset
|
14 import dmd.ErrorExp; |
135 | 15 import dmd.CommaExp; |
16 import dmd.AndExp; | |
17 import dmd.CondExp; | |
169 | 18 import dmd.Global; |
135 | 19 import dmd.IntegerExp; |
20 import dmd.Type; | |
21 import dmd.Lexer; | |
22 import dmd.VarDeclaration; | |
23 import dmd.ExpInitializer; | |
24 import dmd.VarExp; | |
25 import dmd.DeclarationExp; | |
26 import dmd.MulExp; | |
27 import dmd.WANT; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
28 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
29 version(DMDV2) { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
30 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
31 class PowExp : BinExp |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
32 { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
33 this(Loc loc, Expression e1, Expression e2) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
34 { |
178 | 35 register(); |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
36 super(loc, TOK.TOKpow, PowExp.sizeof, e1, e2); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
37 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
38 |
135 | 39 override Expression semantic(Scope sc) |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
40 { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
41 Expression e; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
42 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
43 if (type) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
44 return this; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
45 |
135 | 46 //printf("PowExp::semantic() %s\n", toChars()); |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
47 BinExp.semanticp(sc); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
48 e = op_overload(sc); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
49 if (e) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
50 return e; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
51 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
52 assert(e1.type && e2.type); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
53 if ( (e1.type.isintegral() || e1.type.isfloating()) && |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
54 (e2.type.isintegral() || e2.type.isfloating())) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
55 { |
135 | 56 // For built-in numeric types, there are several cases. |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
57 // TODO: backend support, especially for e1 ^^ 2. |
135 | 58 |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
59 bool wantSqrt = false; |
135 | 60 e1 = e1.optimize(0); |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
61 e2 = e2.optimize(0); |
135 | 62 |
63 // Replace 1 ^^ x or 1.0^^x by (x, 1) | |
64 if ((e1.op == TOK.TOKint64 && e1.toInteger() == 1) || | |
65 (e1.op == TOK.TOKfloat64 && e1.toReal() == 1.0)) | |
66 { | |
67 typeCombine(sc); | |
68 e = new CommaExp(loc, e2, e1); | |
69 e = e.semantic(sc); | |
70 return e; | |
71 } | |
72 // Replace -1 ^^ x by (x&1) ? -1 : 1, where x is integral | |
73 if (e2.type.isintegral() && e1.op == TOKint64 && cast(long)e1.toInteger() == -1) | |
74 { | |
75 typeCombine(sc); | |
76 Type resultType = type; | |
77 e = new AndExp(loc, e2, new IntegerExp(loc, 1, e2.type)); | |
78 e = new CondExp(loc, e, new IntegerExp(loc, -1, resultType), new IntegerExp(loc, 1, resultType)); | |
79 e = e.semantic(sc); | |
80 return e; | |
81 } | |
82 // All other negative integral powers are illegal | |
83 if ((e1.type.isintegral()) && (e2.op == TOK.TOKint64) && cast(long)e2.toInteger() < 0) | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
84 { |
135 | 85 error("cannot raise %s to a negative integer power. Did you mean (cast(real)%s)^^%s ?", |
86 e1.type.toBasetype().toChars(), e1.toChars(), e2.toChars()); | |
87 return new ErrorExp(); | |
88 } | |
89 | |
90 // Deal with x^^2, x^^3 immediately, since they are of practical importance. | |
91 // Don't bother if x is a literal, since it will be constant-folded anyway. | |
92 if ( ( (e2.op == TOK.TOKint64 && (e2.toInteger() == 2 || e2.toInteger() == 3)) | |
93 || (e2.op == TOK.TOKfloat64 && (e2.toReal() == 2.0 || e2.toReal() == 3.0)) | |
94 ) && (e1.op == TOK.TOKint64 || e1.op == TOK.TOKfloat64) | |
95 ) | |
96 { | |
97 typeCombine(sc); | |
98 // Replace x^^2 with (tmp = x, tmp*tmp) | |
99 // Replace x^^3 with (tmp = x, tmp*tmp*tmp) | |
100 Identifier idtmp = Lexer.uniqueId("__tmp"); | |
101 VarDeclaration tmp = new VarDeclaration(loc, e1.type.toBasetype(), idtmp, new ExpInitializer(Loc(0), e1)); | |
102 VarExp ve = new VarExp(loc, tmp); | |
103 Expression ae = new DeclarationExp(loc, tmp); | |
104 Expression me = new MulExp(loc, ve, ve); | |
105 if ( (e2.op == TOK.TOKint64 && e2.toInteger() == 3) | |
106 || (e2.op == TOK.TOKfloat64 && e2.toReal() == 3.0)) | |
107 me = new MulExp(loc, me, ve); | |
108 e = new CommaExp(loc, ae, me); | |
109 e = e.semantic(sc); | |
110 return e; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
111 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
112 |
170 | 113 if (!global.importMathChecked) |
135 | 114 { |
170 | 115 global.importMathChecked = true; |
169 | 116 auto amodules = global.amodules; |
117 for (int i = 0; i < amodules.dim; i++) | |
135 | 118 { |
169 | 119 auto mi = cast(Module)amodules.data[i]; |
135 | 120 //printf("\t[%d] %s\n", i, mi->toChars()); |
121 if (mi.ident == Id.math && | |
122 mi.parent.ident == Id.std && | |
123 !mi.parent.parent) | |
124 goto L1; | |
125 } | |
126 error("must import std.math to use ^^ operator"); | |
127 | |
128 L1: ; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
129 } |
135 | 130 |
131 e = new IdentifierExp(loc, Id.empty); | |
132 e = new DotIdExp(loc, e, Id.std); | |
133 e = new DotIdExp(loc, e, Id.math); | |
134 if (e2.op == TOK.TOKfloat64 && e2.toReal() == 0.5) | |
135 { // Replace e1 ^^ 0.5 with .std.math.sqrt(x) | |
136 typeCombine(sc); | |
137 e = new CallExp(loc, new DotIdExp(loc, e, Id._sqrt), e1); | |
138 } | |
139 else | |
140 { | |
141 // Replace e1 ^^ e2 with .std.math.pow(e1, e2) | |
142 // We don't combine the types if raising to an integer power (because | |
143 // integer powers are treated specially by std.math.pow). | |
144 if (!e2.type.isintegral()) | |
145 typeCombine(sc); | |
146 e = new CallExp(loc, new DotIdExp(loc, e, Id._pow), e1, e2); | |
147 } | |
148 e = e.semantic(sc); | |
149 // Always constant fold integer powers of literals. This will run the interpreter | |
150 // on .std.math.pow | |
151 if ((e1.op == TOK.TOKfloat64 || e1.op == TOK.TOKint64) && (e2.op == TOK.TOKint64)) | |
152 e = e.optimize(WANT.WANTvalue | WANT.WANTinterpret); | |
153 | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
154 return e; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
155 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
156 error("%s ^^ %s is not supported", e1.type.toChars(), e2.type.toChars() ); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
157 return new ErrorExp(); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
158 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
159 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
160 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
161 // For operator overloading |
135 | 162 override Identifier opId() |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
163 { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
164 return Id.pow; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
165 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
166 |
135 | 167 override Identifier opId_r() |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
168 { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
169 return Id.pow_r; |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
170 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
171 } |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
172 |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
diff
changeset
|
173 } |