Mercurial > projects > ddmd
annotate dmd/CatExp.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 | e28b18c23469 |
children | e8a741997ccf |
rev | line source |
---|---|
72 | 1 module dmd.CatExp; |
2 | |
114 | 3 import dmd.common; |
72 | 4 import dmd.Expression; |
5 import dmd.Identifier; | |
6 import dmd.InterState; | |
7 import dmd.Loc; | |
8 import dmd.Scope; | |
9 import dmd.IRState; | |
10 import dmd.BinExp; | |
0 | 11 import dmd.TOK; |
12 import dmd.Type; | |
13 import dmd.TY; | |
14 import dmd.MATCH; | |
15 import dmd.ArrayLiteralExp; | |
16 import dmd.StringExp; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
17 import dmd.ErrorExp; |
0 | 18 import dmd.WANT; |
19 import dmd.Id; | |
72 | 20 import dmd.GlobalExpressions; |
21 | |
0 | 22 import dmd.backend.elem; |
23 import dmd.backend.Util; | |
24 import dmd.backend.TYM; | |
25 import dmd.backend.OPER; | |
26 import dmd.backend.RTLSYM; | |
27 import dmd.codegen.Util; | |
72 | 28 import dmd.expression.Cat; |
29 | |
0 | 30 class CatExp : BinExp |
31 { | |
32 this(Loc loc, Expression e1, Expression e2) | |
33 { | |
34 super(loc, TOK.TOKcat, CatExp.sizeof, e1, e2); | |
35 } | |
36 | |
72 | 37 override Expression semantic(Scope sc) |
0 | 38 { |
39 Expression e; | |
40 | |
41 //printf("CatExp.semantic() %s\n", toChars()); | |
42 if (!type) | |
43 { | |
44 BinExp.semanticp(sc); | |
45 e = op_overload(sc); | |
46 if (e) | |
47 return e; | |
48 | |
49 Type tb1 = e1.type.toBasetype(); | |
50 Type tb2 = e2.type.toBasetype(); | |
51 | |
52 | |
53 /* BUG: Should handle things like: | |
54 * char c; | |
55 * c ~ ' ' | |
56 * ' ' ~ c; | |
57 */ | |
58 | |
59 static if (false) { | |
60 e1.type.print(); | |
61 e2.type.print(); | |
62 } | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
63 Type tb1next = tb1.nextOf(); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
64 Type tb2next = tb2.nextOf(); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
65 |
0 | 66 if ((tb1.ty == Tsarray || tb1.ty == Tarray) && |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
67 e2.implicitConvTo(tb1next) >= MATCHconvert) |
0 | 68 { |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
69 e2 = e2.implicitCastTo(sc, tb1next); |
0 | 70 if (tb2.ty == Tarray) |
71 { | |
72 // Make e2 into [e2] | |
73 e2 = new ArrayLiteralExp(e2.loc, e2); | |
74 e2.type = type; | |
75 } | |
76 return this; | |
77 } | |
78 else if ((tb2.ty == Tsarray || tb2.ty == Tarray) && | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
79 e1.implicitConvTo(tb2next) >= MATCHconvert) |
0 | 80 { |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
81 e1 = e1.implicitCastTo(sc, tb2next); |
0 | 82 if (tb1.ty == Tarray) |
83 { | |
84 // Make e1 into [e1] | |
85 e1 = new ArrayLiteralExp(e1.loc, e1); | |
86 e1.type = type; | |
87 } | |
88 return this; | |
89 } | |
90 | |
91 if ((tb1.ty == Tsarray || tb1.ty == Tarray) && | |
92 (tb2.ty == Tsarray || tb2.ty == Tarray) && | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
93 (tb1next.mod || tb2next.mod) && |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
94 (tb1next.mod != tb2next.mod) |
0 | 95 ) |
96 { | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
97 Type t1 = tb1next.mutableOf().constOf().arrayOf(); |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
98 Type t2 = tb2next.mutableOf().constOf().arrayOf(); |
0 | 99 if (e1.op == TOKstring && !(cast(StringExp)e1).committed) |
100 e1.type = t1; | |
101 else | |
102 e1 = e1.castTo(sc, t1); | |
103 if (e2.op == TOKstring && !(cast(StringExp)e2).committed) | |
104 e2.type = t2; | |
105 else | |
106 e2 = e2.castTo(sc, t2); | |
107 } | |
108 | |
109 typeCombine(sc); | |
110 type = type.toHeadMutable(); | |
111 | |
112 Type tb = type.toBasetype(); | |
113 if (tb.ty == Tsarray) | |
114 type = tb.nextOf().arrayOf(); | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
115 if (type.ty == Tarray && tb1next && tb2next && |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
116 tb1next.mod != tb2next.mod) |
0 | 117 { |
118 type = type.nextOf().toHeadMutable().arrayOf(); | |
119 } | |
120 static if (false) { | |
121 e1.type.print(); | |
122 e2.type.print(); | |
123 type.print(); | |
124 print(); | |
125 } | |
126 Type t1 = e1.type.toBasetype(); | |
127 Type t2 = e2.type.toBasetype(); | |
128 if (e1.op == TOKstring && e2.op == TOKstring) | |
129 e = optimize(WANTvalue); | |
130 else if ((t1.ty == Tarray || t1.ty == Tsarray) && | |
131 (t2.ty == Tarray || t2.ty == Tsarray)) | |
132 { | |
133 e = this; | |
134 } | |
135 else | |
136 { | |
137 //printf("(%s) ~ (%s)\n", e1.toChars(), e2.toChars()); | |
138 error("Can only concatenate arrays, not (%s ~ %s)", | |
139 e1.type.toChars(), e2.type.toChars()); | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
140 return new ErrorExp(); |
0 | 141 } |
142 e.type = e.type.semantic(loc, sc); | |
143 return e; | |
144 } | |
145 return this; | |
146 } | |
147 | |
72 | 148 override Expression optimize(int result) |
0 | 149 { |
150 //printf("CatExp::optimize(%d) %s\n", result, toChars()); | |
151 e1 = e1.optimize(result); | |
152 e2 = e2.optimize(result); | |
153 Expression e = Cat(type, e1, e2); | |
154 if (e is EXP_CANT_INTERPRET) | |
155 e = this; | |
156 | |
157 return e; | |
158 } | |
159 | |
72 | 160 override Expression interpret(InterState istate) |
0 | 161 { |
72 | 162 Expression e; |
163 Expression e1; | |
164 Expression e2; | |
165 | |
166 version (LOG) { | |
167 printf("CatExp.interpret() %.*s\n", toChars()); | |
168 } | |
169 e1 = this.e1.interpret(istate); | |
170 if (e1 is EXP_CANT_INTERPRET) | |
171 { | |
172 goto Lcant; | |
173 } | |
174 e2 = this.e2.interpret(istate); | |
175 if (e2 is EXP_CANT_INTERPRET) | |
176 goto Lcant; | |
177 return Cat(type, e1, e2); | |
178 | |
179 Lcant: | |
180 version (LOG) { | |
181 printf("CatExp.interpret() %.*s CANT\n", toChars()); | |
182 } | |
63 | 183 return EXP_CANT_INTERPRET; |
0 | 184 } |
185 | |
72 | 186 override Identifier opId() |
0 | 187 { |
188 return Id.cat; | |
189 } | |
190 | |
72 | 191 override Identifier opId_r() |
0 | 192 { |
193 return Id.cat_r; | |
194 } | |
195 | |
72 | 196 override elem* toElem(IRState* irs) |
0 | 197 { |
198 elem *e; | |
199 | |
200 static if (false) { | |
201 printf("CatExp::toElem()\n"); | |
202 print(); | |
203 } | |
204 | |
205 Type tb1 = e1.type.toBasetype(); | |
206 Type tb2 = e2.type.toBasetype(); | |
207 Type tn; | |
208 | |
209 ///static if (false) { | |
210 /// if ((tb1.ty == Tarray || tb1.ty == Tsarray) && | |
211 /// (tb2.ty == Tarray || tb2.ty == Tsarray) | |
212 /// ) | |
213 ///} | |
214 | |
215 Type ta = tb1.nextOf() ? e1.type : e2.type; | |
216 tn = tb1.nextOf() ? tb1.nextOf() : tb2.nextOf(); | |
217 { | |
218 if (e1.op == TOKcat) | |
219 { | |
220 elem* ep; | |
221 CatExp ce = this; | |
222 int n = 2; | |
223 | |
224 ep = eval_Darray(irs, ce.e2); | |
225 do | |
226 { | |
227 n++; | |
228 ce = cast(CatExp)ce.e1; | |
229 ep = el_param(ep, eval_Darray(irs, ce.e2)); | |
230 } while (ce.e1.op == TOKcat); | |
231 | |
232 ep = el_param(ep, eval_Darray(irs, ce.e1)); | |
233 static if (true) { | |
234 ep = el_params( | |
235 ep, | |
236 el_long(TYint, n), | |
237 ta.getTypeInfo(null).toElem(irs), | |
238 null); | |
239 e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCATNT]), ep); | |
240 } else { | |
241 ep = el_params( | |
242 ep, | |
243 el_long(TYint, n), | |
244 el_long(TYint, tn.size()), | |
245 null); | |
246 e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCATN]), ep); | |
247 } | |
248 } | |
249 else | |
250 { | |
251 elem *e1; | |
252 elem *e2; | |
253 elem *ep; | |
254 | |
255 e1 = eval_Darray(irs, this.e1); | |
256 e2 = eval_Darray(irs, this.e2); | |
257 static if (true) { | |
258 ep = el_params(e2, e1, ta.getTypeInfo(null).toElem(irs), null); | |
259 e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCATT]), ep); | |
260 } else { | |
261 ep = el_params(el_long(TYint, tn.size()), e2, e1, null); | |
262 e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCAT]), ep); | |
263 } | |
264 } | |
265 el_setLoc(e,loc); | |
266 } | |
267 /// static if (false) { | |
268 /// else if ((tb1.ty == Tarray || tb1.ty == Tsarray) && | |
269 /// e2.type.equals(tb1.next)) | |
270 /// { | |
271 /// error("array cat with element not implemented"); | |
272 /// e = el_long(TYint, 0); | |
273 /// } | |
274 /// else | |
275 /// assert(0); | |
276 /// } | |
277 return e; | |
278 } | |
279 } | |
280 |