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