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