Mercurial > projects > ddmd
annotate dmd/DeleteExp.d @ 187:b0d41ff5e0df
Added expandability scheme outlined in http://www.dsource.org/forums/viewtopic.php?t=5659&sid=6f2150ff5b0bffcd47512a6a7608d218
author | Abscissa |
---|---|
date | Tue, 07 Jun 2011 23:37:34 -0400 |
parents | e3afd1303184 |
children |
rev | line source |
---|---|
72 | 1 module dmd.DeleteExp; |
2 | |
114 | 3 import dmd.common; |
72 | 4 import dmd.Expression; |
5 import dmd.backend.elem; | |
6 import dmd.UnaExp; | |
7 import dmd.OutBuffer; | |
8 import dmd.Loc; | |
9 import dmd.Scope; | |
10 import dmd.IRState; | |
0 | 11 import dmd.HdrGenState; |
12 import dmd.Type; | |
13 import dmd.IndexExp; | |
174 | 14 import dmd.PREC; |
0 | 15 import dmd.Global; |
16 import dmd.VarExp; | |
17 import dmd.Identifier; | |
18 import dmd.StructDeclaration; | |
19 import dmd.Lexer; | |
20 import dmd.FuncDeclaration; | |
21 import dmd.TypeStruct; | |
22 import dmd.CallExp; | |
23 import dmd.DotVarExp; | |
24 import dmd.DeclarationExp; | |
25 import dmd.ExpInitializer; | |
26 import dmd.VarDeclaration; | |
27 import dmd.TypePointer; | |
28 import dmd.ClassDeclaration; | |
29 import dmd.TypeClass; | |
72 | 30 import dmd.TY; |
0 | 31 import dmd.TOK; |
32 import dmd.TypeAArray; | |
33 import dmd.TypeSArray; | |
34 | |
174 | 35 import dmd.expression.Util; |
0 | 36 import dmd.codegen.Util; |
37 import dmd.backend.Util; | |
38 import dmd.backend.OPER; | |
39 import dmd.backend.RTLSYM; | |
40 import dmd.backend.mTY; | |
41 import dmd.backend.Symbol; | |
72 | 42 import dmd.backend.TYM; |
43 | |
187
b0d41ff5e0df
Added expandability scheme outlined in http://www.dsource.org/forums/viewtopic.php?t=5659&sid=6f2150ff5b0bffcd47512a6a7608d218
Abscissa
parents:
178
diff
changeset
|
44 import dmd.DDMDExtensions; |
b0d41ff5e0df
Added expandability scheme outlined in http://www.dsource.org/forums/viewtopic.php?t=5659&sid=6f2150ff5b0bffcd47512a6a7608d218
Abscissa
parents:
178
diff
changeset
|
45 |
0 | 46 class DeleteExp : UnaExp |
47 { | |
187
b0d41ff5e0df
Added expandability scheme outlined in http://www.dsource.org/forums/viewtopic.php?t=5659&sid=6f2150ff5b0bffcd47512a6a7608d218
Abscissa
parents:
178
diff
changeset
|
48 mixin insertMemberExtension!(typeof(this)); |
b0d41ff5e0df
Added expandability scheme outlined in http://www.dsource.org/forums/viewtopic.php?t=5659&sid=6f2150ff5b0bffcd47512a6a7608d218
Abscissa
parents:
178
diff
changeset
|
49 |
0 | 50 this(Loc loc, Expression e) |
51 { | |
178 | 52 register(); |
0 | 53 super(loc, TOK.TOKdelete, DeleteExp.sizeof, e); |
54 } | |
55 | |
72 | 56 override Expression semantic(Scope sc) |
0 | 57 { |
58 Type tb; | |
59 | |
60 UnaExp.semantic(sc); | |
61 e1 = resolveProperties(sc, e1); | |
62 e1 = e1.toLvalue(sc, null); | |
63 type = Type.tvoid; | |
64 | |
65 tb = e1.type.toBasetype(); | |
66 switch (tb.ty) | |
174 | 67 { |
0 | 68 case Tclass: |
174 | 69 { |
0 | 70 TypeClass tc = cast(TypeClass)tb; |
71 ClassDeclaration cd = tc.sym; | |
72 | |
73 if (cd.isCOMinterface()) | |
74 { /* Because COM classes are deleted by IUnknown.Release() | |
75 */ | |
76 error("cannot delete instance of COM interface %s", cd.toChars()); | |
77 } | |
78 break; | |
79 } | |
80 case Tpointer: | |
81 tb = (cast(TypePointer)tb).next.toBasetype(); | |
82 if (tb.ty == Tstruct) | |
83 { | |
84 TypeStruct ts = cast(TypeStruct)tb; | |
85 StructDeclaration sd = ts.sym; | |
86 FuncDeclaration f = sd.aggDelete; | |
87 FuncDeclaration fd = sd.dtor; | |
88 | |
89 if (!f && !fd) | |
90 break; | |
91 | |
92 /* Construct: | |
93 * ea = copy e1 to a tmp to do side effects only once | |
94 * eb = call destructor | |
95 * ec = call deallocator | |
96 */ | |
97 Expression ea = null; | |
98 Expression eb = null; | |
99 Expression ec = null; | |
100 VarDeclaration v; | |
101 | |
102 if (fd && f) | |
174 | 103 { |
0 | 104 Identifier id = Lexer.idPool("__tmp"); |
105 v = new VarDeclaration(loc, e1.type, id, new ExpInitializer(loc, e1)); | |
106 v.semantic(sc); | |
107 v.parent = sc.parent; | |
108 ea = new DeclarationExp(loc, v); | |
109 ea.type = v.type; | |
110 } | |
111 | |
112 if (fd) | |
174 | 113 { |
0 | 114 Expression e = ea ? new VarExp(loc, v) : e1; |
115 e = new DotVarExp(Loc(0), e, fd, 0); | |
116 eb = new CallExp(loc, e); | |
117 eb = eb.semantic(sc); | |
118 } | |
119 | |
120 if (f) | |
121 { | |
122 Type tpv = Type.tvoid.pointerTo(); | |
123 Expression e = ea ? new VarExp(loc, v) : e1.castTo(sc, tpv); | |
124 e = new CallExp(loc, new VarExp(loc, f), e); | |
125 ec = e.semantic(sc); | |
126 } | |
127 ea = combine(ea, eb); | |
128 ea = combine(ea, ec); | |
129 assert(ea); | |
130 return ea; | |
131 } | |
132 break; | |
133 | |
134 case Tarray: | |
135 /* BUG: look for deleting arrays of structs with dtors. | |
136 */ | |
137 break; | |
138 | |
139 default: | |
140 if (e1.op == TOKindex) | |
141 { | |
142 IndexExp ae = cast(IndexExp)e1; | |
143 Type tb1 = ae.e1.type.toBasetype(); | |
144 if (tb1.ty == Taarray) | |
145 break; | |
146 } | |
147 error("cannot delete type %s", e1.type.toChars()); | |
148 break; | |
149 } | |
174 | 150 |
0 | 151 if (e1.op == TOKindex) |
152 { | |
153 IndexExp ae = cast(IndexExp)e1; | |
154 Type tb1 = ae.e1.type.toBasetype(); | |
155 if (tb1.ty == Taarray) | |
174 | 156 { |
0 | 157 if (!global.params.useDeprecated) |
158 error("delete aa[key] deprecated, use aa.remove(key)"); | |
159 } | |
160 } | |
161 | |
162 return this; | |
163 } | |
164 | |
72 | 165 override Expression checkToBoolean() |
0 | 166 { |
167 assert(false); | |
168 } | |
169 | |
72 | 170 override bool checkSideEffect(int flag) |
0 | 171 { |
172 return true; | |
173 } | |
174 | |
72 | 175 override void toCBuffer(OutBuffer buf, HdrGenState* hgs) |
0 | 176 { |
174 | 177 buf.writestring("delete "); |
178 expToCBuffer(buf, hgs, e1, precedence[op]); | |
0 | 179 } |
180 | |
72 | 181 override elem* toElem(IRState* irs) |
0 | 182 { |
183 elem* e; | |
184 int rtl; | |
185 Type tb; | |
186 | |
187 //printf("DeleteExp.toElem()\n"); | |
188 if (e1.op == TOKindex) | |
189 { | |
190 IndexExp ae = cast(IndexExp)e1; | |
191 tb = ae.e1.type.toBasetype(); | |
192 if (tb.ty == Taarray) | |
193 { | |
194 TypeAArray taa = cast(TypeAArray)tb; | |
195 elem* ea = ae.e1.toElem(irs); | |
196 elem* ekey = ae.e2.toElem(irs); | |
197 elem* ep; | |
198 elem* keyti; | |
199 | |
108
6da99741178e
e2ir.c changes, mainly accounts for static arrays being value types now
Trass3r
parents:
72
diff
changeset
|
200 if (tybasic(ekey.Ety) == TYstruct || tybasic(ekey.Ety) == TYarray) |
0 | 201 { |
202 ekey = el_una(OPstrpar, TYstruct, ekey); | |
203 ekey.Enumbytes = ekey.E1.Enumbytes; | |
204 assert(ekey.Enumbytes); | |
205 } | |
206 | |
207 Symbol *s = taa.aaGetSymbol("Del", 0); | |
208 keyti = taa.index.getInternalTypeInfo(null).toElem(irs); | |
209 ep = el_params(ekey, keyti, ea, null); | |
210 e = el_bin(OPcall, TYnptr, el_var(s), ep); | |
211 goto Lret; | |
212 } | |
213 } | |
214 //e1.type.print(); | |
215 e = e1.toElem(irs); | |
216 tb = e1.type.toBasetype(); | |
217 switch (tb.ty) | |
218 { | |
219 case Tarray: | |
174 | 220 { |
0 | 221 e = addressElem(e, e1.type); |
222 rtl = RTLSYM_DELARRAYT; | |
223 | |
224 /* See if we need to run destructors on the array contents | |
225 */ | |
226 elem *et = null; | |
227 Type tv = tb.nextOf().toBasetype(); | |
228 while (tv.ty == Tsarray) | |
174 | 229 { |
0 | 230 TypeSArray ta = cast(TypeSArray)tv; |
231 tv = tv.nextOf().toBasetype(); | |
232 } | |
233 if (tv.ty == Tstruct) | |
174 | 234 { |
0 | 235 TypeStruct ts = cast(TypeStruct)tv; |
236 StructDeclaration sd = ts.sym; | |
237 if (sd.dtor) | |
238 et = tb.nextOf().getTypeInfo(null).toElem(irs); | |
239 } | |
240 if (!et) // if no destructors needed | |
241 et = el_long(TYnptr, 0); // pass null for TypeInfo | |
242 e = el_params(et, e, null); | |
243 // call _d_delarray_t(e, et); | |
244 e = el_bin(OPcall, TYvoid, el_var(rtlsym[rtl]), e); | |
245 goto Lret; | |
246 } | |
247 case Tclass: | |
248 if (e1.op == TOKvar) | |
174 | 249 { |
0 | 250 VarExp ve = cast(VarExp)e1; |
251 if (ve.var.isVarDeclaration() && | |
252 ve.var.isVarDeclaration().onstack) | |
253 { | |
254 rtl = RTLSYM_CALLFINALIZER; | |
255 if (tb.isClassHandle().isInterfaceDeclaration()) | |
256 rtl = RTLSYM_CALLINTERFACEFINALIZER; | |
257 break; | |
258 } | |
259 } | |
260 e = addressElem(e, e1.type); | |
261 rtl = RTLSYM_DELCLASS; | |
262 if (tb.isClassHandle().isInterfaceDeclaration()) | |
263 rtl = RTLSYM_DELINTERFACE; | |
264 break; | |
265 | |
266 case Tpointer: | |
267 e = addressElem(e, e1.type); | |
268 rtl = RTLSYM_DELMEMORY; | |
269 break; | |
270 | |
271 default: | |
272 assert(0); | |
273 break; | |
274 } | |
275 e = el_bin(OPcall, TYvoid, el_var(rtlsym[rtl]), e); | |
276 | |
277 Lret: | |
278 el_setLoc(e,loc); | |
279 return e; | |
280 } | |
281 } | |
282 |