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