Mercurial > projects > ldc
annotate dmd/expression.c @ 1064:f0b6549055ab
Make LDC work with LLVM trunk (s/LinkOnceLinkage/LinkOnceOdrLinkage/)
Also moved the #defines for linkage types into a separate header instead of
mars.h so we can #include revisions.h without having to rebuild the entire
frontend every time we update.
(I'm using revisions.h to get the LLVM revision for use in preprocessor
conditionals. It should work with LLVM release 2.5, old trunk and new trunk)
author | Frits van Bommel <fvbommel wxs.nl> |
---|---|
date | Sun, 08 Mar 2009 16:13:10 +0100 |
parents | 39cf8fa483fd |
children | b30fe7e1dbb9 |
rev | line source |
---|---|
159 | 1 |
2 // Compiler implementation of the D programming language | |
3 // Copyright (c) 1999-2008 by Digital Mars | |
4 // All Rights Reserved | |
5 // written by Walter Bright | |
6 // http://www.digitalmars.com | |
7 // License for redistribution is by either the Artistic License | |
8 // in artistic.txt, or the GNU General Public License in gnu.txt. | |
9 // See the included readme.txt for details. | |
10 | |
11 #include <stdio.h> | |
12 #include <stdlib.h> | |
13 #include <ctype.h> | |
14 #include <assert.h> | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
15 #if _MSC_VER |
159 | 16 #include <complex> |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
17 #else |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
18 #endif |
159 | 19 #include <math.h> |
20 | |
21 #if _WIN32 && __DMC__ | |
22 extern "C" char * __cdecl __locale_decpoint; | |
23 #endif | |
24 | |
285
297690b5d4a5
[svn r306] Fixed: it's now possible to compile and link llvmdc with MinGW32 and msys on Win32 :D I tried it myself ;) Building the runtime still needs some work, but it's a step in the right direction.
lindquist
parents:
163
diff
changeset
|
25 #if __MINGW32__ |
297690b5d4a5
[svn r306] Fixed: it's now possible to compile and link llvmdc with MinGW32 and msys on Win32 :D I tried it myself ;) Building the runtime still needs some work, but it's a step in the right direction.
lindquist
parents:
163
diff
changeset
|
26 #ifndef isnan |
297690b5d4a5
[svn r306] Fixed: it's now possible to compile and link llvmdc with MinGW32 and msys on Win32 :D I tried it myself ;) Building the runtime still needs some work, but it's a step in the right direction.
lindquist
parents:
163
diff
changeset
|
27 #define isnan _isnan |
297690b5d4a5
[svn r306] Fixed: it's now possible to compile and link llvmdc with MinGW32 and msys on Win32 :D I tried it myself ;) Building the runtime still needs some work, but it's a step in the right direction.
lindquist
parents:
163
diff
changeset
|
28 #endif |
297690b5d4a5
[svn r306] Fixed: it's now possible to compile and link llvmdc with MinGW32 and msys on Win32 :D I tried it myself ;) Building the runtime still needs some work, but it's a step in the right direction.
lindquist
parents:
163
diff
changeset
|
29 #endif |
297690b5d4a5
[svn r306] Fixed: it's now possible to compile and link llvmdc with MinGW32 and msys on Win32 :D I tried it myself ;) Building the runtime still needs some work, but it's a step in the right direction.
lindquist
parents:
163
diff
changeset
|
30 |
536
0d2db7efa105
Add isnan for __APPLE__ and darwin version ident for OSX.
Christian Kamm <kamm incasoftware de>
parents:
535
diff
changeset
|
31 #ifdef __APPLE__ |
0d2db7efa105
Add isnan for __APPLE__ and darwin version ident for OSX.
Christian Kamm <kamm incasoftware de>
parents:
535
diff
changeset
|
32 #ifndef isnan |
0d2db7efa105
Add isnan for __APPLE__ and darwin version ident for OSX.
Christian Kamm <kamm incasoftware de>
parents:
535
diff
changeset
|
33 int isnan(double); |
0d2db7efa105
Add isnan for __APPLE__ and darwin version ident for OSX.
Christian Kamm <kamm incasoftware de>
parents:
535
diff
changeset
|
34 #endif |
0d2db7efa105
Add isnan for __APPLE__ and darwin version ident for OSX.
Christian Kamm <kamm incasoftware de>
parents:
535
diff
changeset
|
35 #endif |
0d2db7efa105
Add isnan for __APPLE__ and darwin version ident for OSX.
Christian Kamm <kamm incasoftware de>
parents:
535
diff
changeset
|
36 |
159 | 37 #if IN_GCC |
38 // Issues with using -include total.h (defines integer_t) and then complex.h fails... | |
39 #undef integer_t | |
40 #endif | |
41 | |
42 #ifdef __APPLE__ | |
43 #define integer_t dmd_integer_t | |
44 #endif | |
45 | |
46 #if IN_GCC || IN_LLVM | |
47 #include "mem.h" | |
48 #elif _WIN32 | |
49 #include "..\root\mem.h" | |
571
cbd6c8073a32
Changed all '#if linux || __APPLE__' to '#if POSIX' so we can support other platforms too, thanx for the suggestion anders.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
536
diff
changeset
|
50 #elif POSIX |
159 | 51 #include "../root/mem.h" |
52 #endif | |
53 | |
54 //#include "port.h" | |
55 #include "mtype.h" | |
56 #include "init.h" | |
57 #include "expression.h" | |
58 #include "template.h" | |
59 #include "utf.h" | |
60 #include "enum.h" | |
61 #include "scope.h" | |
62 #include "statement.h" | |
63 #include "declaration.h" | |
64 #include "aggregate.h" | |
65 #include "import.h" | |
66 #include "id.h" | |
67 #include "dsymbol.h" | |
68 #include "module.h" | |
69 #include "attrib.h" | |
70 #include "hdrgen.h" | |
71 #include "parse.h" | |
72 | |
73 Expression *createTypeInfoArray(Scope *sc, Expression *args[], int dim); | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
74 Expression *expandVar(int result, VarDeclaration *v); |
159 | 75 |
76 #define LOGSEMANTIC 0 | |
77 | |
78 /********************************** | |
79 * Set operator precedence for each operator. | |
80 */ | |
81 | |
82 // Operator precedence - greater values are higher precedence | |
83 | |
84 enum PREC | |
85 { | |
86 PREC_zero, | |
87 PREC_expr, | |
88 PREC_assign, | |
89 PREC_cond, | |
90 PREC_oror, | |
91 PREC_andand, | |
92 PREC_or, | |
93 PREC_xor, | |
94 PREC_and, | |
95 PREC_equal, | |
96 PREC_rel, | |
97 PREC_shift, | |
98 PREC_add, | |
99 PREC_mul, | |
100 PREC_unary, | |
101 PREC_primary, | |
102 }; | |
103 | |
104 enum PREC precedence[TOKMAX]; | |
105 | |
106 void initPrecedence() | |
107 { | |
108 precedence[TOKdotvar] = PREC_primary; | |
109 precedence[TOKimport] = PREC_primary; | |
110 precedence[TOKidentifier] = PREC_primary; | |
111 precedence[TOKthis] = PREC_primary; | |
112 precedence[TOKsuper] = PREC_primary; | |
113 precedence[TOKint64] = PREC_primary; | |
114 precedence[TOKfloat64] = PREC_primary; | |
115 precedence[TOKnull] = PREC_primary; | |
116 precedence[TOKstring] = PREC_primary; | |
117 precedence[TOKarrayliteral] = PREC_primary; | |
118 precedence[TOKtypedot] = PREC_primary; | |
119 precedence[TOKtypeid] = PREC_primary; | |
120 precedence[TOKis] = PREC_primary; | |
121 precedence[TOKassert] = PREC_primary; | |
122 precedence[TOKfunction] = PREC_primary; | |
123 precedence[TOKvar] = PREC_primary; | |
336 | 124 #if DMDV2 |
125 precedence[TOKdefault] = PREC_primary; | |
126 #endif | |
159 | 127 |
128 // post | |
129 precedence[TOKdotti] = PREC_primary; | |
130 precedence[TOKdot] = PREC_primary; | |
131 // precedence[TOKarrow] = PREC_primary; | |
132 precedence[TOKplusplus] = PREC_primary; | |
133 precedence[TOKminusminus] = PREC_primary; | |
134 precedence[TOKcall] = PREC_primary; | |
135 precedence[TOKslice] = PREC_primary; | |
136 precedence[TOKarray] = PREC_primary; | |
137 | |
138 precedence[TOKaddress] = PREC_unary; | |
139 precedence[TOKstar] = PREC_unary; | |
140 precedence[TOKneg] = PREC_unary; | |
141 precedence[TOKuadd] = PREC_unary; | |
142 precedence[TOKnot] = PREC_unary; | |
143 precedence[TOKtobool] = PREC_add; | |
144 precedence[TOKtilde] = PREC_unary; | |
145 precedence[TOKdelete] = PREC_unary; | |
146 precedence[TOKnew] = PREC_unary; | |
147 precedence[TOKcast] = PREC_unary; | |
148 | |
149 precedence[TOKmul] = PREC_mul; | |
150 precedence[TOKdiv] = PREC_mul; | |
151 precedence[TOKmod] = PREC_mul; | |
152 | |
153 precedence[TOKadd] = PREC_add; | |
154 precedence[TOKmin] = PREC_add; | |
155 precedence[TOKcat] = PREC_add; | |
156 | |
157 precedence[TOKshl] = PREC_shift; | |
158 precedence[TOKshr] = PREC_shift; | |
159 precedence[TOKushr] = PREC_shift; | |
160 | |
161 precedence[TOKlt] = PREC_rel; | |
162 precedence[TOKle] = PREC_rel; | |
163 precedence[TOKgt] = PREC_rel; | |
164 precedence[TOKge] = PREC_rel; | |
165 precedence[TOKunord] = PREC_rel; | |
166 precedence[TOKlg] = PREC_rel; | |
167 precedence[TOKleg] = PREC_rel; | |
168 precedence[TOKule] = PREC_rel; | |
169 precedence[TOKul] = PREC_rel; | |
170 precedence[TOKuge] = PREC_rel; | |
171 precedence[TOKug] = PREC_rel; | |
172 precedence[TOKue] = PREC_rel; | |
173 precedence[TOKin] = PREC_rel; | |
174 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
175 #if 0 |
159 | 176 precedence[TOKequal] = PREC_equal; |
177 precedence[TOKnotequal] = PREC_equal; | |
178 precedence[TOKidentity] = PREC_equal; | |
179 precedence[TOKnotidentity] = PREC_equal; | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
180 #else |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
181 /* Note that we changed precedence, so that < and != have the same |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
182 * precedence. This change is in the parser, too. |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
183 */ |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
184 precedence[TOKequal] = PREC_rel; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
185 precedence[TOKnotequal] = PREC_rel; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
186 precedence[TOKidentity] = PREC_rel; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
187 precedence[TOKnotidentity] = PREC_rel; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
188 #endif |
159 | 189 |
190 precedence[TOKand] = PREC_and; | |
191 | |
192 precedence[TOKxor] = PREC_xor; | |
193 | |
194 precedence[TOKor] = PREC_or; | |
195 | |
196 precedence[TOKandand] = PREC_andand; | |
197 | |
198 precedence[TOKoror] = PREC_oror; | |
199 | |
200 precedence[TOKquestion] = PREC_cond; | |
201 | |
202 precedence[TOKassign] = PREC_assign; | |
203 precedence[TOKconstruct] = PREC_assign; | |
204 precedence[TOKblit] = PREC_assign; | |
205 precedence[TOKaddass] = PREC_assign; | |
206 precedence[TOKminass] = PREC_assign; | |
207 precedence[TOKcatass] = PREC_assign; | |
208 precedence[TOKmulass] = PREC_assign; | |
209 precedence[TOKdivass] = PREC_assign; | |
210 precedence[TOKmodass] = PREC_assign; | |
211 precedence[TOKshlass] = PREC_assign; | |
212 precedence[TOKshrass] = PREC_assign; | |
213 precedence[TOKushrass] = PREC_assign; | |
214 precedence[TOKandass] = PREC_assign; | |
215 precedence[TOKorass] = PREC_assign; | |
216 precedence[TOKxorass] = PREC_assign; | |
217 | |
218 precedence[TOKcomma] = PREC_expr; | |
219 } | |
220 | |
336 | 221 /************************************************************* |
222 * Given var, we need to get the | |
223 * right 'this' pointer if var is in an outer class, but our | |
224 * existing 'this' pointer is in an inner class. | |
225 * Input: | |
226 * e1 existing 'this' | |
227 * ad struct or class we need the correct 'this' for | |
228 * var the specific member of ad we're accessing | |
229 */ | |
230 | |
231 Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad, | |
232 Expression *e1, Declaration *var) | |
233 { | |
234 //printf("\ngetRightThis(e1 = %s, ad = %s, var = %s)\n", e1->toChars(), ad->toChars(), var->toChars()); | |
235 L1: | |
236 Type *t = e1->type->toBasetype(); | |
237 //printf("e1->type = %s, var->type = %s\n", e1->type->toChars(), var->type->toChars()); | |
238 | |
239 /* If e1 is not the 'this' pointer for ad | |
240 */ | |
241 if (ad && | |
242 !(t->ty == Tpointer && t->nextOf()->ty == Tstruct && | |
243 ((TypeStruct *)t->nextOf())->sym == ad) | |
244 && | |
245 !(t->ty == Tstruct && | |
246 ((TypeStruct *)t)->sym == ad) | |
247 ) | |
248 { | |
249 ClassDeclaration *cd = ad->isClassDeclaration(); | |
250 ClassDeclaration *tcd = t->isClassHandle(); | |
251 | |
252 /* e1 is the right this if ad is a base class of e1 | |
253 */ | |
254 if (!cd || !tcd || | |
255 !(tcd == cd || cd->isBaseOf(tcd, NULL)) | |
256 ) | |
257 { | |
258 /* Only classes can be inner classes with an 'outer' | |
259 * member pointing to the enclosing class instance | |
260 */ | |
261 if (tcd && tcd->isNested()) | |
262 { /* e1 is the 'this' pointer for an inner class: tcd. | |
263 * Rewrite it as the 'this' pointer for the outer class. | |
264 */ | |
265 | |
266 e1 = new DotVarExp(loc, e1, tcd->vthis); | |
267 e1->type = tcd->vthis->type; | |
268 // Do not call checkNestedRef() | |
269 //e1 = e1->semantic(sc); | |
270 | |
271 // Skip up over nested functions, and get the enclosing | |
272 // class type. | |
273 int n = 0; | |
274 Dsymbol *s; | |
275 for (s = tcd->toParent(); | |
276 s && s->isFuncDeclaration(); | |
277 s = s->toParent()) | |
278 { FuncDeclaration *f = s->isFuncDeclaration(); | |
279 if (f->vthis) | |
280 { | |
281 //printf("rewriting e1 to %s's this\n", f->toChars()); | |
282 n++; | |
486
a34078905d01
Added pragma(llvmdc, "string") for misc per-module compiler configuration, currently "string" can only be "verbose" which forces -vv for module it appears in.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
471
diff
changeset
|
283 |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
639
diff
changeset
|
284 // LDC seems dmd misses it sometimes here :/ |
486
a34078905d01
Added pragma(llvmdc, "string") for misc per-module compiler configuration, currently "string" can only be "verbose" which forces -vv for module it appears in.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
471
diff
changeset
|
285 f->vthis->nestedref = 1; |
a34078905d01
Added pragma(llvmdc, "string") for misc per-module compiler configuration, currently "string" can only be "verbose" which forces -vv for module it appears in.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
471
diff
changeset
|
286 |
336 | 287 e1 = new VarExp(loc, f->vthis); |
288 } | |
289 } | |
290 if (s && s->isClassDeclaration()) | |
291 { e1->type = s->isClassDeclaration()->type; | |
292 if (n > 1) | |
293 e1 = e1->semantic(sc); | |
294 } | |
295 else | |
296 e1 = e1->semantic(sc); | |
297 goto L1; | |
298 } | |
299 /* Can't find a path from e1 to ad | |
300 */ | |
301 e1->error("this for %s needs to be type %s not type %s", | |
302 var->toChars(), ad->toChars(), t->toChars()); | |
303 } | |
304 } | |
305 return e1; | |
306 } | |
307 | |
159 | 308 /***************************************** |
309 * Determine if 'this' is available. | |
310 * If it is, return the FuncDeclaration that has it. | |
311 */ | |
312 | |
313 FuncDeclaration *hasThis(Scope *sc) | |
314 { FuncDeclaration *fd; | |
315 FuncDeclaration *fdthis; | |
316 | |
317 //printf("hasThis()\n"); | |
318 fdthis = sc->parent->isFuncDeclaration(); | |
319 //printf("fdthis = %p, '%s'\n", fdthis, fdthis ? fdthis->toChars() : ""); | |
320 | |
321 // Go upwards until we find the enclosing member function | |
322 fd = fdthis; | |
323 while (1) | |
324 { | |
325 if (!fd) | |
326 { | |
327 goto Lno; | |
328 } | |
329 if (!fd->isNested()) | |
330 break; | |
331 | |
332 Dsymbol *parent = fd->parent; | |
333 while (parent) | |
334 { | |
335 TemplateInstance *ti = parent->isTemplateInstance(); | |
336 if (ti) | |
337 parent = ti->parent; | |
338 else | |
339 break; | |
340 } | |
341 | |
342 fd = fd->parent->isFuncDeclaration(); | |
343 } | |
344 | |
345 if (!fd->isThis()) | |
346 { //printf("test '%s'\n", fd->toChars()); | |
347 goto Lno; | |
348 } | |
349 | |
350 assert(fd->vthis); | |
351 return fd; | |
352 | |
353 Lno: | |
354 return NULL; // don't have 'this' available | |
355 } | |
356 | |
357 | |
358 /*************************************** | |
359 * Pull out any properties. | |
360 */ | |
361 | |
362 Expression *resolveProperties(Scope *sc, Expression *e) | |
363 { | |
364 //printf("resolveProperties(%s)\n", e->toChars()); | |
365 if (e->type) | |
366 { | |
367 Type *t = e->type->toBasetype(); | |
368 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
369 if (t->ty == Tfunction /*|| e->op == TOKoverloadset*/) |
159 | 370 { |
371 e = new CallExp(e->loc, e); | |
372 e = e->semantic(sc); | |
373 } | |
374 | |
375 /* Look for e being a lazy parameter; rewrite as delegate call | |
376 */ | |
377 else if (e->op == TOKvar) | |
378 { VarExp *ve = (VarExp *)e; | |
379 | |
380 if (ve->var->storage_class & STClazy) | |
381 { | |
382 e = new CallExp(e->loc, e); | |
383 e = e->semantic(sc); | |
384 } | |
385 } | |
386 | |
387 else if (e->op == TOKdotexp) | |
388 { | |
389 e->error("expression has no value"); | |
390 } | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
391 |
159 | 392 } |
393 return e; | |
394 } | |
395 | |
396 /****************************** | |
397 * Perform semantic() on an array of Expressions. | |
398 */ | |
399 | |
400 void arrayExpressionSemantic(Expressions *exps, Scope *sc) | |
401 { | |
402 if (exps) | |
403 { | |
404 for (size_t i = 0; i < exps->dim; i++) | |
405 { Expression *e = (Expression *)exps->data[i]; | |
406 | |
407 e = e->semantic(sc); | |
408 exps->data[i] = (void *)e; | |
409 } | |
410 } | |
411 } | |
412 | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
413 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
414 /****************************** |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
415 * Perform canThrow() on an array of Expressions. |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
416 */ |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
417 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
418 #if DMDV2 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
419 int arrayExpressionCanThrow(Expressions *exps) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
420 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
421 if (exps) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
422 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
423 for (size_t i = 0; i < exps->dim; i++) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
424 { Expression *e = (Expression *)exps->data[i]; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
425 if (e && e->canThrow()) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
426 return 1; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
427 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
428 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
429 return 0; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
430 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
431 #endif |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
432 |
159 | 433 /**************************************** |
434 * Expand tuples. | |
435 */ | |
436 | |
437 void expandTuples(Expressions *exps) | |
438 { | |
439 //printf("expandTuples()\n"); | |
440 if (exps) | |
441 { | |
442 for (size_t i = 0; i < exps->dim; i++) | |
443 { Expression *arg = (Expression *)exps->data[i]; | |
444 if (!arg) | |
445 continue; | |
446 | |
447 // Look for tuple with 0 members | |
448 if (arg->op == TOKtype) | |
449 { TypeExp *e = (TypeExp *)arg; | |
450 if (e->type->toBasetype()->ty == Ttuple) | |
451 { TypeTuple *tt = (TypeTuple *)e->type->toBasetype(); | |
452 | |
453 if (!tt->arguments || tt->arguments->dim == 0) | |
454 { | |
455 exps->remove(i); | |
456 if (i == exps->dim) | |
457 return; | |
458 i--; | |
459 continue; | |
460 } | |
461 } | |
462 } | |
463 | |
464 // Inline expand all the tuples | |
465 while (arg->op == TOKtuple) | |
466 { TupleExp *te = (TupleExp *)arg; | |
467 | |
468 exps->remove(i); // remove arg | |
469 exps->insert(i, te->exps); // replace with tuple contents | |
470 if (i == exps->dim) | |
471 return; // empty tuple, no more arguments | |
472 arg = (Expression *)exps->data[i]; | |
473 } | |
474 } | |
475 } | |
476 } | |
477 | |
478 /**************************************** | |
479 * Preprocess arguments to function. | |
480 */ | |
481 | |
482 void preFunctionArguments(Loc loc, Scope *sc, Expressions *exps) | |
483 { | |
484 if (exps) | |
485 { | |
486 expandTuples(exps); | |
487 | |
488 for (size_t i = 0; i < exps->dim; i++) | |
489 { Expression *arg = (Expression *)exps->data[i]; | |
490 | |
491 if (!arg->type) | |
492 { | |
493 #ifdef DEBUG | |
494 if (!global.gag) | |
495 printf("1: \n"); | |
496 #endif | |
497 arg->error("%s is not an expression", arg->toChars()); | |
498 arg = new IntegerExp(arg->loc, 0, Type::tint32); | |
499 } | |
500 | |
501 arg = resolveProperties(sc, arg); | |
502 exps->data[i] = (void *) arg; | |
503 | |
504 //arg->rvalue(); | |
505 #if 0 | |
506 if (arg->type->ty == Tfunction) | |
507 { | |
508 arg = new AddrExp(arg->loc, arg); | |
509 arg = arg->semantic(sc); | |
510 exps->data[i] = (void *) arg; | |
511 } | |
512 #endif | |
513 } | |
514 } | |
515 } | |
516 | |
336 | 517 /********************************************* |
518 * Call copy constructor for struct value argument. | |
519 */ | |
520 #if DMDV2 | |
521 Expression *callCpCtor(Loc loc, Scope *sc, Expression *e) | |
522 { | |
523 Type *tb = e->type->toBasetype(); | |
524 assert(tb->ty == Tstruct); | |
525 StructDeclaration *sd = ((TypeStruct *)tb)->sym; | |
526 if (sd->cpctor) | |
527 { | |
528 /* Create a variable tmp, and replace the argument e with: | |
529 * (tmp = e),tmp | |
530 * and let AssignExp() handle the construction. | |
531 * This is not the most efficent, ideally tmp would be constructed | |
532 * directly onto the stack. | |
533 */ | |
534 Identifier *idtmp = Lexer::uniqueId("__tmp"); | |
535 VarDeclaration *tmp = new VarDeclaration(loc, tb, idtmp, new ExpInitializer(0, e)); | |
536 Expression *ae = new DeclarationExp(loc, tmp); | |
537 e = new CommaExp(loc, ae, new VarExp(loc, tmp)); | |
538 e = e->semantic(sc); | |
539 } | |
540 return e; | |
541 } | |
542 #endif | |
159 | 543 |
544 /**************************************** | |
545 * Now that we know the exact type of the function we're calling, | |
546 * the arguments[] need to be adjusted: | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
547 * 1. implicitly convert argument to the corresponding parameter type |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
548 * 2. add default arguments for any missing arguments |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
549 * 3. do default promotions on arguments corresponding to ... |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
550 * 4. add hidden _arguments[] argument |
159 | 551 */ |
552 | |
553 void functionArguments(Loc loc, Scope *sc, TypeFunction *tf, Expressions *arguments) | |
554 { | |
555 unsigned n; | |
556 | |
557 //printf("functionArguments()\n"); | |
558 assert(arguments); | |
559 size_t nargs = arguments ? arguments->dim : 0; | |
560 size_t nparams = Argument::dim(tf->parameters); | |
561 | |
562 if (nargs > nparams && tf->varargs == 0) | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
563 error(loc, "expected %"PRIuSIZE" arguments, not %"PRIuSIZE, nparams, nargs); |
159 | 564 |
565 n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams) | |
566 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
567 int done = 0; |
159 | 568 for (size_t i = 0; i < n; i++) |
569 { | |
570 Expression *arg; | |
571 | |
572 if (i < nargs) | |
573 arg = (Expression *)arguments->data[i]; | |
574 else | |
575 arg = NULL; | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
576 Type *tb; |
159 | 577 |
578 if (i < nparams) | |
579 { | |
580 Argument *p = Argument::getNth(tf->parameters, i); | |
581 | |
582 if (!arg) | |
583 { | |
584 if (!p->defaultArg) | |
585 { | |
586 if (tf->varargs == 2 && i + 1 == nparams) | |
587 goto L2; | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
588 error(loc, "expected %"PRIuSIZE" arguments, not %"PRIuSIZE, nparams, nargs); |
159 | 589 break; |
590 } | |
336 | 591 arg = p->defaultArg; |
592 #if DMDV2 | |
593 if (arg->op == TOKdefault) | |
594 { DefaultInitExp *de = (DefaultInitExp *)arg; | |
595 arg = de->resolve(loc, sc); | |
596 } | |
597 else | |
598 #endif | |
599 arg = arg->copy(); | |
159 | 600 arguments->push(arg); |
601 nargs++; | |
602 } | |
603 | |
604 if (tf->varargs == 2 && i + 1 == nparams) | |
605 { | |
606 //printf("\t\tvarargs == 2, p->type = '%s'\n", p->type->toChars()); | |
607 if (arg->implicitConvTo(p->type)) | |
608 { | |
609 if (nargs != nparams) | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
610 error(loc, "expected %"PRIuSIZE" arguments, not %"PRIuSIZE, nparams, nargs); |
159 | 611 goto L1; |
612 } | |
613 L2: | |
614 Type *tb = p->type->toBasetype(); | |
615 Type *tret = p->isLazyArray(); | |
616 switch (tb->ty) | |
617 { | |
618 case Tsarray: | |
619 case Tarray: | |
620 { // Create a static array variable v of type arg->type | |
621 #ifdef IN_GCC | |
622 /* GCC 4.0 does not like zero length arrays used like | |
623 this; pass a null array value instead. Could also | |
624 just make a one-element array. */ | |
625 if (nargs - i == 0) | |
626 { | |
627 arg = new NullExp(loc); | |
628 break; | |
629 } | |
630 #endif | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
631 Identifier *id = Lexer::uniqueId("__arrayArg"); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
632 Type *t = new TypeSArray(((TypeArray *)tb)->next, new IntegerExp(nargs - i)); |
159 | 633 t = t->semantic(loc, sc); |
634 VarDeclaration *v = new VarDeclaration(loc, t, id, new VoidInitializer(loc)); | |
635 v->semantic(sc); | |
636 v->parent = sc->parent; | |
637 //sc->insert(v); | |
638 | |
639 Expression *c = new DeclarationExp(0, v); | |
640 c->type = v->type; | |
641 | |
642 for (size_t u = i; u < nargs; u++) | |
643 { Expression *a = (Expression *)arguments->data[u]; | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
644 if (tret && !((TypeArray *)tb)->next->equals(a->type)) |
159 | 645 a = a->toDelegate(sc, tret); |
646 | |
647 Expression *e = new VarExp(loc, v); | |
648 e = new IndexExp(loc, e, new IntegerExp(u + 1 - nparams)); | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
649 AssignExp *ae = new AssignExp(loc, e, a); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
650 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
651 ae->op = TOKconstruct; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
652 #endif |
159 | 653 if (c) |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
654 c = new CommaExp(loc, c, ae); |
159 | 655 else |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
656 c = ae; |
159 | 657 } |
658 arg = new VarExp(loc, v); | |
659 if (c) | |
660 arg = new CommaExp(loc, c, arg); | |
661 break; | |
662 } | |
663 case Tclass: | |
664 { /* Set arg to be: | |
665 * new Tclass(arg0, arg1, ..., argn) | |
666 */ | |
667 Expressions *args = new Expressions(); | |
668 args->setDim(nargs - i); | |
669 for (size_t u = i; u < nargs; u++) | |
670 args->data[u - i] = arguments->data[u]; | |
671 arg = new NewExp(loc, NULL, NULL, p->type, args); | |
672 break; | |
673 } | |
674 default: | |
675 if (!arg) | |
676 { error(loc, "not enough arguments"); | |
677 return; | |
678 } | |
679 break; | |
680 } | |
681 arg = arg->semantic(sc); | |
682 //printf("\targ = '%s'\n", arg->toChars()); | |
683 arguments->setDim(i + 1); | |
684 done = 1; | |
685 } | |
686 | |
687 L1: | |
688 if (!(p->storageClass & STClazy && p->type->ty == Tvoid)) | |
689 arg = arg->implicitCastTo(sc, p->type); | |
690 if (p->storageClass & (STCout | STCref)) | |
691 { | |
692 // BUG: should check that argument to ref is type 'invariant' | |
693 // BUG: assignments to ref should also be type 'invariant' | |
694 arg = arg->modifiableLvalue(sc, arg); | |
695 | |
696 //if (arg->op == TOKslice) | |
697 //arg->error("cannot modify slice %s", arg->toChars()); | |
698 } | |
699 | |
723
55f6c2e454d7
Implemented correct parameter order according to x86-32 ABI documentation.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
717
diff
changeset
|
700 // LDC we don't want this! |
55f6c2e454d7
Implemented correct parameter order according to x86-32 ABI documentation.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
717
diff
changeset
|
701 #if !IN_LLVM |
159 | 702 // Convert static arrays to pointers |
703 tb = arg->type->toBasetype(); | |
704 if (tb->ty == Tsarray) | |
705 { | |
706 arg = arg->checkToPointer(); | |
707 } | |
723
55f6c2e454d7
Implemented correct parameter order according to x86-32 ABI documentation.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
717
diff
changeset
|
708 #endif |
55f6c2e454d7
Implemented correct parameter order according to x86-32 ABI documentation.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
717
diff
changeset
|
709 |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
710 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
711 if (tb->ty == Tstruct && !(p->storageClass & (STCref | STCout))) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
712 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
713 arg = callCpCtor(loc, sc, arg); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
714 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
715 #endif |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
716 |
159 | 717 |
718 // Convert lazy argument to a delegate | |
719 if (p->storageClass & STClazy) | |
720 { | |
721 arg = arg->toDelegate(sc, p->type); | |
722 } | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
723 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
724 /* Look for arguments that cannot 'escape' from the called |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
725 * function. |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
726 */ |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
727 if (!tf->parameterEscapes(p)) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
728 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
729 /* Function literals can only appear once, so if this |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
730 * appearance was scoped, there cannot be any others. |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
731 */ |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
732 if (arg->op == TOKfunction) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
733 { FuncExp *fe = (FuncExp *)arg; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
734 fe->fd->tookAddressOf = 0; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
735 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
736 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
737 /* For passing a delegate to a scoped parameter, |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
738 * this doesn't count as taking the address of it. |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
739 * We only worry about 'escaping' references to the function. |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
740 */ |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
741 else if (arg->op == TOKdelegate) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
742 { DelegateExp *de = (DelegateExp *)arg; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
743 if (de->e1->op == TOKvar) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
744 { VarExp *ve = (VarExp *)de->e1; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
745 FuncDeclaration *f = ve->var->isFuncDeclaration(); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
746 if (f) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
747 { f->tookAddressOf--; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
748 //printf("tookAddressOf = %d\n", f->tookAddressOf); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
749 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
750 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
751 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
752 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
753 #endif |
159 | 754 } |
755 else | |
756 { | |
757 | |
758 // If not D linkage, do promotions | |
723
55f6c2e454d7
Implemented correct parameter order according to x86-32 ABI documentation.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
717
diff
changeset
|
759 // LDC: don't do promotions on intrinsics |
55f6c2e454d7
Implemented correct parameter order according to x86-32 ABI documentation.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
717
diff
changeset
|
760 if (tf->linkage != LINKd && tf->linkage != LINKintrinsic) |
159 | 761 { |
762 // Promote bytes, words, etc., to ints | |
763 arg = arg->integralPromotions(sc); | |
764 | |
765 // Promote floats to doubles | |
766 switch (arg->type->ty) | |
767 { | |
768 case Tfloat32: | |
769 arg = arg->castTo(sc, Type::tfloat64); | |
770 break; | |
771 | |
772 case Timaginary32: | |
773 arg = arg->castTo(sc, Type::timaginary64); | |
774 break; | |
775 } | |
776 } | |
777 | |
778 // Convert static arrays to dynamic arrays | |
779 tb = arg->type->toBasetype(); | |
780 if (tb->ty == Tsarray) | |
781 { TypeSArray *ts = (TypeSArray *)tb; | |
336 | 782 Type *ta = ts->next->arrayOf(); |
159 | 783 if (ts->size(arg->loc) == 0) |
784 { arg = new NullExp(arg->loc); | |
785 arg->type = ta; | |
786 } | |
787 else | |
788 arg = arg->castTo(sc, ta); | |
789 } | |
336 | 790 #if DMDV2 |
791 if (tb->ty == Tstruct) | |
792 { | |
793 arg = callCpCtor(loc, sc, arg); | |
794 } | |
795 | |
796 // Give error for overloaded function addresses | |
797 if (arg->op == TOKsymoff) | |
798 { SymOffExp *se = (SymOffExp *)arg; | |
799 if (se->hasOverloads && !se->var->isFuncDeclaration()->isUnique()) | |
800 arg->error("function %s is overloaded", arg->toChars()); | |
801 } | |
802 #endif | |
159 | 803 arg->rvalue(); |
804 } | |
805 arg = arg->optimize(WANTvalue); | |
806 arguments->data[i] = (void *) arg; | |
807 if (done) | |
808 break; | |
809 } | |
810 | |
811 #if !IN_LLVM | |
812 // If D linkage and variadic, add _arguments[] as first argument | |
813 if (tf->linkage == LINKd && tf->varargs == 1) | |
814 { | |
815 Expression *e; | |
816 | |
817 e = createTypeInfoArray(sc, (Expression **)&arguments->data[nparams], | |
818 arguments->dim - nparams); | |
819 arguments->insert(0, e); | |
820 } | |
821 #endif | |
822 } | |
823 | |
824 /************************************************** | |
825 * Write expression out to buf, but wrap it | |
826 * in ( ) if its precedence is less than pr. | |
827 */ | |
828 | |
829 void expToCBuffer(OutBuffer *buf, HdrGenState *hgs, Expression *e, enum PREC pr) | |
830 { | |
336 | 831 //if (precedence[e->op] == 0) e->dump(0); |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
832 if (precedence[e->op] < pr || |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
833 /* Despite precedence, we don't allow a<b<c expressions. |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
834 * They must be parenthesized. |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
835 */ |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
836 (pr == PREC_rel && precedence[e->op] == pr)) |
159 | 837 { |
838 buf->writeByte('('); | |
839 e->toCBuffer(buf, hgs); | |
840 buf->writeByte(')'); | |
841 } | |
842 else | |
843 e->toCBuffer(buf, hgs); | |
844 } | |
845 | |
846 /************************************************** | |
847 * Write out argument list to buf. | |
848 */ | |
849 | |
850 void argsToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs) | |
851 { | |
852 if (arguments) | |
853 { | |
854 for (size_t i = 0; i < arguments->dim; i++) | |
855 { Expression *arg = (Expression *)arguments->data[i]; | |
856 | |
857 if (arg) | |
858 { if (i) | |
859 buf->writeByte(','); | |
860 expToCBuffer(buf, hgs, arg, PREC_assign); | |
861 } | |
862 } | |
863 } | |
864 } | |
865 | |
866 /************************************************** | |
867 * Write out argument types to buf. | |
868 */ | |
869 | |
870 void argExpTypesToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs) | |
871 { | |
872 if (arguments) | |
873 { OutBuffer argbuf; | |
874 | |
875 for (size_t i = 0; i < arguments->dim; i++) | |
876 { Expression *arg = (Expression *)arguments->data[i]; | |
877 | |
878 if (i) | |
879 buf->writeByte(','); | |
880 argbuf.reset(); | |
881 arg->type->toCBuffer2(&argbuf, hgs, 0); | |
882 buf->write(&argbuf); | |
883 } | |
884 } | |
885 } | |
886 | |
887 /******************************** Expression **************************/ | |
888 | |
889 Expression::Expression(Loc loc, enum TOK op, int size) | |
890 : loc(loc) | |
891 { | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
892 //printf("Expression::Expression(op = %d) this = %p\n", op, this); |
159 | 893 this->loc = loc; |
894 this->op = op; | |
895 this->size = size; | |
896 type = NULL; | |
897 } | |
898 | |
899 Expression *Expression::syntaxCopy() | |
900 { | |
901 //printf("Expression::syntaxCopy()\n"); | |
902 //dump(0); | |
903 return copy(); | |
904 } | |
905 | |
906 /********************************* | |
907 * Does *not* do a deep copy. | |
908 */ | |
909 | |
910 Expression *Expression::copy() | |
911 { | |
912 Expression *e; | |
913 if (!size) | |
914 { | |
915 #ifdef DEBUG | |
916 fprintf(stdmsg, "No expression copy for: %s\n", toChars()); | |
917 printf("op = %d\n", op); | |
918 dump(0); | |
919 #endif | |
920 assert(0); | |
921 } | |
922 e = (Expression *)mem.malloc(size); | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
923 //printf("Expression::copy(op = %d) e = %p\n", op, e); |
159 | 924 return (Expression *)memcpy(e, this, size); |
925 } | |
926 | |
927 /************************** | |
928 * Semantically analyze Expression. | |
929 * Determine types, fold constants, etc. | |
930 */ | |
931 | |
932 Expression *Expression::semantic(Scope *sc) | |
933 { | |
934 #if LOGSEMANTIC | |
336 | 935 printf("Expression::semantic() %s\n", toChars()); |
159 | 936 #endif |
937 if (type) | |
938 type = type->semantic(loc, sc); | |
939 else | |
940 type = Type::tvoid; | |
941 return this; | |
942 } | |
943 | |
944 void Expression::print() | |
945 { | |
946 fprintf(stdmsg, "%s\n", toChars()); | |
947 fflush(stdmsg); | |
948 } | |
949 | |
950 char *Expression::toChars() | |
951 { OutBuffer *buf; | |
952 HdrGenState hgs; | |
953 | |
954 memset(&hgs, 0, sizeof(hgs)); | |
955 buf = new OutBuffer(); | |
956 toCBuffer(buf, &hgs); | |
957 return buf->toChars(); | |
958 } | |
959 | |
960 void Expression::error(const char *format, ...) | |
961 { | |
962 va_list ap; | |
963 va_start(ap, format); | |
964 ::verror(loc, format, ap); | |
965 va_end( ap ); | |
966 } | |
967 | |
968 void Expression::rvalue() | |
969 { | |
970 if (type && type->toBasetype()->ty == Tvoid) | |
971 { error("expression %s is void and has no value", toChars()); | |
972 #if 0 | |
973 dump(0); | |
974 halt(); | |
975 #endif | |
336 | 976 type = Type::tint32; |
159 | 977 } |
978 } | |
979 | |
980 Expression *Expression::combine(Expression *e1, Expression *e2) | |
981 { | |
982 if (e1) | |
983 { | |
984 if (e2) | |
985 { | |
986 e1 = new CommaExp(e1->loc, e1, e2); | |
987 e1->type = e2->type; | |
988 } | |
989 } | |
990 else | |
991 e1 = e2; | |
992 return e1; | |
993 } | |
994 | |
995 integer_t Expression::toInteger() | |
996 { | |
997 //printf("Expression %s\n", Token::toChars(op)); | |
998 error("Integer constant expression expected instead of %s", toChars()); | |
999 return 0; | |
1000 } | |
1001 | |
1002 uinteger_t Expression::toUInteger() | |
1003 { | |
1004 //printf("Expression %s\n", Token::toChars(op)); | |
1005 return (uinteger_t)toInteger(); | |
1006 } | |
1007 | |
1008 real_t Expression::toReal() | |
1009 { | |
1010 error("Floating point constant expression expected instead of %s", toChars()); | |
1011 return 0; | |
1012 } | |
1013 | |
1014 real_t Expression::toImaginary() | |
1015 { | |
1016 error("Floating point constant expression expected instead of %s", toChars()); | |
1017 return 0; | |
1018 } | |
1019 | |
1020 complex_t Expression::toComplex() | |
1021 { | |
1022 error("Floating point constant expression expected instead of %s", toChars()); | |
1023 #ifdef IN_GCC | |
1024 return complex_t(real_t(0)); // %% nicer | |
1025 #else | |
1026 return 0; | |
1027 #endif | |
1028 } | |
1029 | |
1030 void Expression::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
1031 { | |
1032 buf->writestring(Token::toChars(op)); | |
1033 } | |
1034 | |
1035 void Expression::toMangleBuffer(OutBuffer *buf) | |
1036 { | |
1037 error("expression %s is not a valid template value argument", toChars()); | |
1038 } | |
1039 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
1040 /*************************************** |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
1041 * Return !=0 if expression is an lvalue. |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
1042 */ |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
1043 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
1044 int Expression::isLvalue() |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
1045 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
1046 return 0; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
1047 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
1048 #endif |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
1049 |
159 | 1050 /******************************* |
1051 * Give error if we're not an lvalue. | |
1052 * If we can, convert expression to be an lvalue. | |
1053 */ | |
1054 | |
1055 Expression *Expression::toLvalue(Scope *sc, Expression *e) | |
1056 { | |
1057 if (!e) | |
1058 e = this; | |
1059 else if (!loc.filename) | |
1060 loc = e->loc; | |
1061 error("%s is not an lvalue", e->toChars()); | |
1062 return this; | |
1063 } | |
1064 | |
1065 Expression *Expression::modifiableLvalue(Scope *sc, Expression *e) | |
1066 { | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
1067 //printf("Expression::modifiableLvalue() %s, type = %s\n", toChars(), type->toChars()); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
1068 |
159 | 1069 // See if this expression is a modifiable lvalue (i.e. not const) |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
1070 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
1071 if (type && (!type->isMutable() || !type->isAssignable())) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
1072 error("%s is not mutable", e->toChars()); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
1073 #endif |
159 | 1074 return toLvalue(sc, e); |
1075 } | |
1076 | |
1077 /************************************ | |
1078 * Detect cases where pointers to the stack can 'escape' the | |
1079 * lifetime of the stack frame. | |
1080 */ | |
1081 | |
1082 void Expression::checkEscape() | |
1083 { | |
1084 } | |
1085 | |
1086 void Expression::checkScalar() | |
1087 { | |
1088 if (!type->isscalar()) | |
1089 error("'%s' is not a scalar, it is a %s", toChars(), type->toChars()); | |
1090 } | |
1091 | |
1092 void Expression::checkNoBool() | |
1093 { | |
1094 if (type->toBasetype()->ty == Tbool) | |
1095 error("operation not allowed on bool '%s'", toChars()); | |
1096 } | |
1097 | |
1098 Expression *Expression::checkIntegral() | |
1099 { | |
1100 if (!type->isintegral()) | |
1101 { error("'%s' is not of integral type, it is a %s", toChars(), type->toChars()); | |
1102 return new IntegerExp(0); | |
1103 } | |
1104 return this; | |
1105 } | |
1106 | |
1107 Expression *Expression::checkArithmetic() | |
1108 { | |
1109 if (!type->isintegral() && !type->isfloating()) | |
1110 { error("'%s' is not of arithmetic type, it is a %s", toChars(), type->toChars()); | |
1111 return new IntegerExp(0); | |
1112 } | |
1113 return this; | |
1114 } | |
1115 | |
1116 void Expression::checkDeprecated(Scope *sc, Dsymbol *s) | |
1117 { | |
1118 s->checkDeprecated(loc, sc); | |
1119 } | |
1120 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
1121 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
1122 void Expression::checkPurity(Scope *sc, FuncDeclaration *f) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
1123 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
1124 if (sc->func && sc->func->isPure() && !sc->intypeof && !f->isPure()) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
1125 error("pure function '%s' cannot call impure function '%s'\n", |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
1126 sc->func->toChars(), f->toChars()); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
1127 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
1128 #endif |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
1129 |
159 | 1130 /******************************** |
1131 * Check for expressions that have no use. | |
1132 * Input: | |
1133 * flag 0 not going to use the result, so issue error message if no | |
1134 * side effects | |
1135 * 1 the result of the expression is used, but still check | |
1136 * for useless subexpressions | |
1137 * 2 do not issue error messages, just return !=0 if expression | |
1138 * has side effects | |
1139 */ | |
1140 | |
1141 int Expression::checkSideEffect(int flag) | |
1142 { | |
1143 if (flag == 0) | |
1144 { if (op == TOKimport) | |
1145 { | |
1146 error("%s has no effect", toChars()); | |
1147 } | |
1148 else | |
1149 error("%s has no effect in expression (%s)", | |
1150 Token::toChars(op), toChars()); | |
1151 } | |
1152 return 0; | |
1153 } | |
1154 | |
1155 /***************************** | |
1156 * Check that expression can be tested for true or false. | |
1157 */ | |
1158 | |
1159 Expression *Expression::checkToBoolean() | |
1160 { | |
1161 // Default is 'yes' - do nothing | |
1162 | |
1163 #ifdef DEBUG | |
1164 if (!type) | |
1165 dump(0); | |
1166 #endif | |
1167 | |
1168 if (!type->checkBoolean()) | |
1169 { | |
1170 error("expression %s of type %s does not have a boolean value", toChars(), type->toChars()); | |
1171 } | |
1172 return this; | |
1173 } | |
1174 | |
1175 /**************************** | |
1176 */ | |
1177 | |
1178 Expression *Expression::checkToPointer() | |
1179 { | |
1180 Expression *e; | |
1181 Type *tb; | |
1182 | |
1183 //printf("Expression::checkToPointer()\n"); | |
1184 e = this; | |
1185 | |
1186 // If C static array, convert to pointer | |
1187 tb = type->toBasetype(); | |
1188 if (tb->ty == Tsarray) | |
1189 { TypeSArray *ts = (TypeSArray *)tb; | |
1190 if (ts->size(loc) == 0) | |
1191 e = new NullExp(loc); | |
1192 else | |
1193 e = new AddrExp(loc, this); | |
336 | 1194 e->type = ts->next->pointerTo(); |
159 | 1195 } |
1196 return e; | |
1197 } | |
1198 | |
1199 /****************************** | |
1200 * Take address of expression. | |
1201 */ | |
1202 | |
1203 Expression *Expression::addressOf(Scope *sc) | |
1204 { | |
1205 Expression *e; | |
1206 | |
1207 //printf("Expression::addressOf()\n"); | |
1208 e = toLvalue(sc, NULL); | |
1209 e = new AddrExp(loc, e); | |
1210 e->type = type->pointerTo(); | |
1211 return e; | |
1212 } | |
1213 | |
1214 /****************************** | |
1215 * If this is a reference, dereference it. | |
1216 */ | |
1217 | |
1218 Expression *Expression::deref() | |
1219 { | |
1220 //printf("Expression::deref()\n"); | |
1221 if (type->ty == Treference) | |
1222 { Expression *e; | |
1223 | |
1224 e = new PtrExp(loc, this); | |
336 | 1225 e->type = ((TypeReference *)type)->next; |
159 | 1226 return e; |
1227 } | |
1228 return this; | |
1229 } | |
1230 | |
1231 /******************************** | |
1232 * Does this expression statically evaluate to a boolean TRUE or FALSE? | |
1233 */ | |
1234 | |
1235 int Expression::isBool(int result) | |
1236 { | |
1237 return FALSE; | |
1238 } | |
1239 | |
1240 /******************************** | |
1241 * Does this expression result in either a 1 or a 0? | |
1242 */ | |
1243 | |
1244 int Expression::isBit() | |
1245 { | |
1246 return FALSE; | |
1247 } | |
1248 | |
336 | 1249 /******************************** |
1250 * Can this expression throw an exception? | |
1251 * Valid only after semantic() pass. | |
1252 */ | |
1253 | |
1254 int Expression::canThrow() | |
1255 { | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
1256 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
1257 return FALSE; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
1258 #else |
336 | 1259 return TRUE; |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
1260 #endif |
336 | 1261 } |
1262 | |
1263 | |
1264 | |
159 | 1265 Expressions *Expression::arraySyntaxCopy(Expressions *exps) |
1266 { Expressions *a = NULL; | |
1267 | |
1268 if (exps) | |
1269 { | |
1270 a = new Expressions(); | |
1271 a->setDim(exps->dim); | |
1272 for (int i = 0; i < a->dim; i++) | |
1273 { Expression *e = (Expression *)exps->data[i]; | |
1274 | |
1275 e = e->syntaxCopy(); | |
1276 a->data[i] = e; | |
1277 } | |
1278 } | |
1279 return a; | |
1280 } | |
1281 | |
1282 /******************************** IntegerExp **************************/ | |
1283 | |
1284 IntegerExp::IntegerExp(Loc loc, integer_t value, Type *type) | |
1285 : Expression(loc, TOKint64, sizeof(IntegerExp)) | |
1286 { | |
1287 //printf("IntegerExp(value = %lld, type = '%s')\n", value, type ? type->toChars() : ""); | |
1288 if (type && !type->isscalar()) | |
1289 { | |
336 | 1290 //printf("%s, loc = %d\n", toChars(), loc.linnum); |
159 | 1291 error("integral constant must be scalar type, not %s", type->toChars()); |
1292 type = Type::terror; | |
1293 } | |
1294 this->type = type; | |
1295 this->value = value; | |
1296 } | |
1297 | |
1298 IntegerExp::IntegerExp(integer_t value) | |
1299 : Expression(0, TOKint64, sizeof(IntegerExp)) | |
1300 { | |
1301 this->type = Type::tint32; | |
1302 this->value = value; | |
1303 } | |
1304 | |
1305 int IntegerExp::equals(Object *o) | |
1306 { IntegerExp *ne; | |
1307 | |
1308 if (this == o || | |
1309 (((Expression *)o)->op == TOKint64 && | |
1310 ((ne = (IntegerExp *)o), type->equals(ne->type)) && | |
1311 value == ne->value)) | |
1312 return 1; | |
1313 return 0; | |
1314 } | |
1315 | |
1316 char *IntegerExp::toChars() | |
1317 { | |
1318 #if 1 | |
1319 return Expression::toChars(); | |
1320 #else | |
1321 static char buffer[sizeof(value) * 3 + 1]; | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
1322 sprintf(buffer, "%lld", value); |
159 | 1323 return buffer; |
1324 #endif | |
1325 } | |
1326 | |
1327 integer_t IntegerExp::toInteger() | |
1328 { Type *t; | |
1329 | |
1330 t = type; | |
1331 while (t) | |
1332 { | |
1333 switch (t->ty) | |
1334 { | |
1335 case Tbit: | |
1336 case Tbool: value = (value != 0); break; | |
1337 case Tint8: value = (d_int8) value; break; | |
1338 case Tchar: | |
1339 case Tuns8: value = (d_uns8) value; break; | |
1340 case Tint16: value = (d_int16) value; break; | |
1341 case Twchar: | |
1342 case Tuns16: value = (d_uns16) value; break; | |
1343 case Tint32: value = (d_int32) value; break; | |
1344 case Tpointer: | |
1345 case Tdchar: | |
1346 case Tuns32: value = (d_uns32) value; break; | |
1347 case Tint64: value = (d_int64) value; break; | |
1348 case Tuns64: value = (d_uns64) value; break; | |
1349 | |
1350 case Tenum: | |
1351 { | |
1352 TypeEnum *te = (TypeEnum *)t; | |
1353 t = te->sym->memtype; | |
1354 continue; | |
1355 } | |
1356 | |
1357 case Ttypedef: | |
1358 { | |
1359 TypeTypedef *tt = (TypeTypedef *)t; | |
1360 t = tt->sym->basetype; | |
1361 continue; | |
1362 } | |
1363 | |
1364 default: | |
336 | 1365 /* This can happen if errors, such as |
1366 * the type is painted on like in fromConstInitializer(). | |
1367 */ | |
1368 if (!global.errors) | |
1369 { type->print(); | |
1370 assert(0); | |
1371 } | |
159 | 1372 break; |
1373 } | |
1374 break; | |
1375 } | |
1376 return value; | |
1377 } | |
1378 | |
1379 real_t IntegerExp::toReal() | |
1380 { | |
1381 Type *t; | |
1382 | |
1383 toInteger(); | |
1384 t = type->toBasetype(); | |
1385 if (t->ty == Tuns64) | |
1386 return (real_t)(d_uns64)value; | |
1387 else | |
1388 return (real_t)(d_int64)value; | |
1389 } | |
1390 | |
1391 real_t IntegerExp::toImaginary() | |
1392 { | |
1393 return (real_t) 0; | |
1394 } | |
1395 | |
1396 complex_t IntegerExp::toComplex() | |
1397 { | |
1398 return toReal(); | |
1399 } | |
1400 | |
1401 int IntegerExp::isBool(int result) | |
1402 { | |
1403 return result ? value != 0 : value == 0; | |
1404 } | |
1405 | |
1406 Expression *IntegerExp::semantic(Scope *sc) | |
1407 { | |
1408 if (!type) | |
1409 { | |
1410 // Determine what the type of this number is | |
1411 integer_t number = value; | |
1412 | |
1413 if (number & 0x8000000000000000LL) | |
1414 type = Type::tuns64; | |
1415 else if (number & 0xFFFFFFFF80000000LL) | |
1416 type = Type::tint64; | |
1417 else | |
1418 type = Type::tint32; | |
1419 } | |
1420 else | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
1421 { if (!type->deco) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
1422 type = type->semantic(loc, sc); |
159 | 1423 } |
1424 return this; | |
1425 } | |
1426 | |
1427 Expression *IntegerExp::toLvalue(Scope *sc, Expression *e) | |
1428 { | |
1429 if (!e) | |
1430 e = this; | |
1431 else if (!loc.filename) | |
1432 loc = e->loc; | |
1433 e->error("constant %s is not an lvalue", e->toChars()); | |
1434 return this; | |
1435 } | |
1436 | |
1437 void IntegerExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
1438 { | |
1439 integer_t v = toInteger(); | |
1440 | |
1441 if (type) | |
1442 { Type *t = type; | |
1443 | |
1444 L1: | |
1445 switch (t->ty) | |
1446 { | |
1447 case Tenum: | |
1448 { TypeEnum *te = (TypeEnum *)t; | |
1449 buf->printf("cast(%s)", te->sym->toChars()); | |
1450 t = te->sym->memtype; | |
1451 goto L1; | |
1452 } | |
1453 | |
1454 case Ttypedef: | |
1455 { TypeTypedef *tt = (TypeTypedef *)t; | |
1456 buf->printf("cast(%s)", tt->sym->toChars()); | |
1457 t = tt->sym->basetype; | |
1458 goto L1; | |
1459 } | |
1460 | |
1461 case Twchar: // BUG: need to cast(wchar) | |
1462 case Tdchar: // BUG: need to cast(dchar) | |
1463 if ((uinteger_t)v > 0xFF) | |
1464 { | |
1465 buf->printf("'\\U%08x'", v); | |
1466 break; | |
1467 } | |
1468 case Tchar: | |
1469 if (v == '\'') | |
1470 buf->writestring("'\\''"); | |
1471 else if (isprint(v) && v != '\\') | |
1472 buf->printf("'%c'", (int)v); | |
1473 else | |
1474 buf->printf("'\\x%02x'", (int)v); | |
1475 break; | |
1476 | |
1477 case Tint8: | |
1478 buf->writestring("cast(byte)"); | |
1479 goto L2; | |
1480 | |
1481 case Tint16: | |
1482 buf->writestring("cast(short)"); | |
1483 goto L2; | |
1484 | |
1485 case Tint32: | |
1486 L2: | |
1487 buf->printf("%d", (int)v); | |
1488 break; | |
1489 | |
1490 case Tuns8: | |
1491 buf->writestring("cast(ubyte)"); | |
1492 goto L3; | |
1493 | |
1494 case Tuns16: | |
1495 buf->writestring("cast(ushort)"); | |
1496 goto L3; | |
1497 | |
1498 case Tuns32: | |
1499 L3: | |
1500 buf->printf("%du", (unsigned)v); | |
1501 break; | |
1502 | |
1503 case Tint64: | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
1504 buf->printf("%lldL", v); |
159 | 1505 break; |
1506 | |
1507 case Tuns64: | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
1508 buf->printf("%lluLU", v); |
159 | 1509 break; |
1510 | |
1511 case Tbit: | |
1512 case Tbool: | |
1513 buf->writestring((char *)(v ? "true" : "false")); | |
1514 break; | |
1515 | |
1516 case Tpointer: | |
1517 buf->writestring("cast("); | |
1518 buf->writestring(t->toChars()); | |
1519 buf->writeByte(')'); | |
1520 goto L3; | |
1521 | |
1522 default: | |
336 | 1523 /* This can happen if errors, such as |
1524 * the type is painted on like in fromConstInitializer(). | |
1525 */ | |
1526 if (!global.errors) | |
1527 { | |
159 | 1528 #ifdef DEBUG |
336 | 1529 t->print(); |
159 | 1530 #endif |
336 | 1531 assert(0); |
1532 } | |
1533 break; | |
159 | 1534 } |
1535 } | |
1536 else if (v & 0x8000000000000000LL) | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
1537 buf->printf("0x%llx", v); |
159 | 1538 else |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
1539 buf->printf("%lld", v); |
159 | 1540 } |
1541 | |
1542 void IntegerExp::toMangleBuffer(OutBuffer *buf) | |
1543 { | |
1544 if ((sinteger_t)value < 0) | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
1545 buf->printf("N%lld", -value); |
159 | 1546 else |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
1547 buf->printf("%lld", value); |
159 | 1548 } |
1549 | |
1550 /******************************** RealExp **************************/ | |
1551 | |
1552 RealExp::RealExp(Loc loc, real_t value, Type *type) | |
1553 : Expression(loc, TOKfloat64, sizeof(RealExp)) | |
1554 { | |
1555 //printf("RealExp::RealExp(%Lg)\n", value); | |
1556 this->value = value; | |
1557 this->type = type; | |
1558 } | |
1559 | |
1560 char *RealExp::toChars() | |
1561 { | |
1562 char buffer[sizeof(value) * 3 + 8 + 1 + 1]; | |
1563 | |
1564 #ifdef IN_GCC | |
1565 value.format(buffer, sizeof(buffer)); | |
1566 if (type->isimaginary()) | |
1567 strcat(buffer, "i"); | |
1568 #else | |
1569 sprintf(buffer, type->isimaginary() ? "%Lgi" : "%Lg", value); | |
1570 #endif | |
1571 assert(strlen(buffer) < sizeof(buffer)); | |
1572 return mem.strdup(buffer); | |
1573 } | |
1574 | |
1575 integer_t RealExp::toInteger() | |
1576 { | |
1577 #ifdef IN_GCC | |
1578 return toReal().toInt(); | |
1579 #else | |
1580 return (sinteger_t) toReal(); | |
1581 #endif | |
1582 } | |
1583 | |
1584 uinteger_t RealExp::toUInteger() | |
1585 { | |
1586 #ifdef IN_GCC | |
1587 return (uinteger_t) toReal().toInt(); | |
1588 #else | |
1589 return (uinteger_t) toReal(); | |
1590 #endif | |
1591 } | |
1592 | |
1593 real_t RealExp::toReal() | |
1594 { | |
1595 return type->isreal() ? value : 0; | |
1596 } | |
1597 | |
1598 real_t RealExp::toImaginary() | |
1599 { | |
1600 return type->isreal() ? 0 : value; | |
1601 } | |
1602 | |
1603 complex_t RealExp::toComplex() | |
1604 { | |
1605 #ifdef __DMC__ | |
1606 return toReal() + toImaginary() * I; | |
1607 #else | |
1608 return complex_t(toReal(), toImaginary()); | |
1609 #endif | |
1610 } | |
1611 | |
1612 /******************************** | |
1613 * Test to see if two reals are the same. | |
1614 * Regard NaN's as equivalent. | |
1615 * Regard +0 and -0 as different. | |
1616 */ | |
1617 | |
1618 int RealEquals(real_t x1, real_t x2) | |
1619 { | |
421
1c65b5477eaa
Fix real comparison for real: allow +0 to be distinguished from -0.
Christian Kamm <kamm incasoftware de>
parents:
420
diff
changeset
|
1620 return // special case nans |
1c65b5477eaa
Fix real comparison for real: allow +0 to be distinguished from -0.
Christian Kamm <kamm incasoftware de>
parents:
420
diff
changeset
|
1621 (isnan(x1) && isnan(x2)) || |
1c65b5477eaa
Fix real comparison for real: allow +0 to be distinguished from -0.
Christian Kamm <kamm incasoftware de>
parents:
420
diff
changeset
|
1622 // and zero, in order to distinguish +0 from -0 |
1c65b5477eaa
Fix real comparison for real: allow +0 to be distinguished from -0.
Christian Kamm <kamm incasoftware de>
parents:
420
diff
changeset
|
1623 (x1 == 0 && x2 == 0 && 1./x1 == 1./x2) || |
1c65b5477eaa
Fix real comparison for real: allow +0 to be distinguished from -0.
Christian Kamm <kamm incasoftware de>
parents:
420
diff
changeset
|
1624 // otherwise just compare |
1c65b5477eaa
Fix real comparison for real: allow +0 to be distinguished from -0.
Christian Kamm <kamm incasoftware de>
parents:
420
diff
changeset
|
1625 (x1 != 0. && x1 == x2); |
159 | 1626 } |
1627 | |
1628 int RealExp::equals(Object *o) | |
1629 { RealExp *ne; | |
1630 | |
1631 if (this == o || | |
1632 (((Expression *)o)->op == TOKfloat64 && | |
1633 ((ne = (RealExp *)o), type->equals(ne->type)) && | |
1634 RealEquals(value, ne->value) | |
1635 ) | |
1636 ) | |
1637 return 1; | |
1638 return 0; | |
1639 } | |
1640 | |
1641 Expression *RealExp::semantic(Scope *sc) | |
1642 { | |
1643 if (!type) | |
1644 type = Type::tfloat64; | |
1645 else | |
1646 type = type->semantic(loc, sc); | |
1647 return this; | |
1648 } | |
1649 | |
1650 int RealExp::isBool(int result) | |
1651 { | |
1652 #ifdef IN_GCC | |
1653 return result ? (! value.isZero()) : (value.isZero()); | |
1654 #else | |
1655 return result ? (value != 0) | |
1656 : (value == 0); | |
1657 #endif | |
1658 } | |
1659 | |
1660 void floatToBuffer(OutBuffer *buf, Type *type, real_t value) | |
1661 { | |
1662 /* In order to get an exact representation, try converting it | |
1663 * to decimal then back again. If it matches, use it. | |
1664 * If it doesn't, fall back to hex, which is | |
1665 * always exact. | |
1666 */ | |
1667 char buffer[25]; | |
1668 sprintf(buffer, "%Lg", value); | |
1669 assert(strlen(buffer) < sizeof(buffer)); | |
1670 #if _WIN32 && __DMC__ | |
1671 char *save = __locale_decpoint; | |
1672 __locale_decpoint = "."; | |
1673 real_t r = strtold(buffer, NULL); | |
1674 __locale_decpoint = save; | |
1675 #else | |
1676 real_t r = strtold(buffer, NULL); | |
1677 #endif | |
1678 if (r == value) // if exact duplication | |
1679 buf->writestring(buffer); | |
1680 else | |
1681 buf->printf("%La", value); // ensure exact duplication | |
1682 | |
1683 if (type) | |
1684 { | |
1685 Type *t = type->toBasetype(); | |
1686 switch (t->ty) | |
1687 { | |
1688 case Tfloat32: | |
1689 case Timaginary32: | |
1690 case Tcomplex32: | |
1691 buf->writeByte('F'); | |
1692 break; | |
1693 | |
1694 case Tfloat80: | |
1695 case Timaginary80: | |
1696 case Tcomplex80: | |
1697 buf->writeByte('L'); | |
1698 break; | |
1699 | |
1700 default: | |
1701 break; | |
1702 } | |
1703 if (t->isimaginary()) | |
1704 buf->writeByte('i'); | |
1705 } | |
1706 } | |
1707 | |
1708 void RealExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
1709 { | |
1710 floatToBuffer(buf, type, value); | |
1711 } | |
1712 | |
1713 void realToMangleBuffer(OutBuffer *buf, real_t value) | |
1714 { | |
1715 /* Rely on %A to get portable mangling. | |
1716 * Must munge result to get only identifier characters. | |
1717 * | |
1718 * Possible values from %A => mangled result | |
1719 * NAN => NAN | |
1720 * -INF => NINF | |
1721 * INF => INF | |
1722 * -0X1.1BC18BA997B95P+79 => N11BC18BA997B95P79 | |
1723 * 0X1.9P+2 => 19P2 | |
1724 */ | |
1725 | |
1726 if (isnan(value)) | |
1727 buf->writestring("NAN"); // no -NAN bugs | |
1728 else | |
1729 { | |
1730 char buffer[32]; | |
1731 int n = sprintf(buffer, "%LA", value); | |
1732 assert(n > 0 && n < sizeof(buffer)); | |
1733 for (int i = 0; i < n; i++) | |
1734 { char c = buffer[i]; | |
1735 | |
1736 switch (c) | |
1737 { | |
1738 case '-': | |
1739 buf->writeByte('N'); | |
1740 break; | |
1741 | |
1742 case '+': | |
1743 case 'X': | |
1744 case '.': | |
1745 break; | |
1746 | |
1747 case '0': | |
1748 if (i < 2) | |
1749 break; // skip leading 0X | |
1750 default: | |
1751 buf->writeByte(c); | |
1752 break; | |
1753 } | |
1754 } | |
1755 } | |
1756 } | |
1757 | |
1758 void RealExp::toMangleBuffer(OutBuffer *buf) | |
1759 { | |
1760 buf->writeByte('e'); | |
1761 realToMangleBuffer(buf, value); | |
1762 } | |
1763 | |
1764 | |
1765 /******************************** ComplexExp **************************/ | |
1766 | |
1767 ComplexExp::ComplexExp(Loc loc, complex_t value, Type *type) | |
1768 : Expression(loc, TOKcomplex80, sizeof(ComplexExp)) | |
1769 { | |
1770 this->value = value; | |
1771 this->type = type; | |
1772 //printf("ComplexExp::ComplexExp(%s)\n", toChars()); | |
1773 } | |
1774 | |
1775 char *ComplexExp::toChars() | |
1776 { | |
1777 char buffer[sizeof(value) * 3 + 8 + 1]; | |
1778 | |
1779 #ifdef IN_GCC | |
1780 char buf1[sizeof(value) * 3 + 8 + 1]; | |
1781 char buf2[sizeof(value) * 3 + 8 + 1]; | |
1782 creall(value).format(buf1, sizeof(buf1)); | |
1783 cimagl(value).format(buf2, sizeof(buf2)); | |
1784 sprintf(buffer, "(%s+%si)", buf1, buf2); | |
1785 #else | |
1786 sprintf(buffer, "(%Lg+%Lgi)", creall(value), cimagl(value)); | |
1787 assert(strlen(buffer) < sizeof(buffer)); | |
1788 #endif | |
1789 return mem.strdup(buffer); | |
1790 } | |
1791 | |
1792 integer_t ComplexExp::toInteger() | |
1793 { | |
1794 #ifdef IN_GCC | |
1795 return (sinteger_t) toReal().toInt(); | |
1796 #else | |
1797 return (sinteger_t) toReal(); | |
1798 #endif | |
1799 } | |
1800 | |
1801 uinteger_t ComplexExp::toUInteger() | |
1802 { | |
1803 #ifdef IN_GCC | |
1804 return (uinteger_t) toReal().toInt(); | |
1805 #else | |
1806 return (uinteger_t) toReal(); | |
1807 #endif | |
1808 } | |
1809 | |
1810 real_t ComplexExp::toReal() | |
1811 { | |
1812 return creall(value); | |
1813 } | |
1814 | |
1815 real_t ComplexExp::toImaginary() | |
1816 { | |
1817 return cimagl(value); | |
1818 } | |
1819 | |
1820 complex_t ComplexExp::toComplex() | |
1821 { | |
1822 return value; | |
1823 } | |
1824 | |
1825 int ComplexExp::equals(Object *o) | |
1826 { ComplexExp *ne; | |
1827 | |
1828 if (this == o || | |
1829 (((Expression *)o)->op == TOKcomplex80 && | |
1830 ((ne = (ComplexExp *)o), type->equals(ne->type)) && | |
1831 RealEquals(creall(value), creall(ne->value)) && | |
1832 RealEquals(cimagl(value), cimagl(ne->value)) | |
1833 ) | |
1834 ) | |
1835 return 1; | |
1836 return 0; | |
1837 } | |
1838 | |
1839 Expression *ComplexExp::semantic(Scope *sc) | |
1840 { | |
1841 if (!type) | |
1842 type = Type::tcomplex80; | |
1843 else | |
1844 type = type->semantic(loc, sc); | |
1845 return this; | |
1846 } | |
1847 | |
1848 int ComplexExp::isBool(int result) | |
1849 { | |
1850 if (result) | |
1851 return (bool)(value); | |
1852 else | |
1853 return !value; | |
1854 } | |
1855 | |
1856 void ComplexExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
1857 { | |
1858 /* Print as: | |
1859 * (re+imi) | |
1860 */ | |
1861 #ifdef IN_GCC | |
1862 char buf1[sizeof(value) * 3 + 8 + 1]; | |
1863 char buf2[sizeof(value) * 3 + 8 + 1]; | |
1864 creall(value).format(buf1, sizeof(buf1)); | |
1865 cimagl(value).format(buf2, sizeof(buf2)); | |
1866 buf->printf("(%s+%si)", buf1, buf2); | |
1867 #else | |
1868 buf->writeByte('('); | |
1869 floatToBuffer(buf, type, creall(value)); | |
1870 buf->writeByte('+'); | |
1871 floatToBuffer(buf, type, cimagl(value)); | |
1872 buf->writestring("i)"); | |
1873 #endif | |
1874 } | |
1875 | |
1876 void ComplexExp::toMangleBuffer(OutBuffer *buf) | |
1877 { | |
1878 buf->writeByte('c'); | |
1879 real_t r = toReal(); | |
1880 realToMangleBuffer(buf, r); | |
1881 buf->writeByte('c'); // separate the two | |
1882 r = toImaginary(); | |
1883 realToMangleBuffer(buf, r); | |
1884 } | |
1885 | |
1886 /******************************** IdentifierExp **************************/ | |
1887 | |
1888 IdentifierExp::IdentifierExp(Loc loc, Identifier *ident) | |
1889 : Expression(loc, TOKidentifier, sizeof(IdentifierExp)) | |
1890 { | |
1891 this->ident = ident; | |
1892 } | |
1893 | |
1894 Expression *IdentifierExp::semantic(Scope *sc) | |
1895 { | |
1896 Dsymbol *s; | |
1897 Dsymbol *scopesym; | |
1898 | |
1899 #if LOGSEMANTIC | |
1900 printf("IdentifierExp::semantic('%s')\n", ident->toChars()); | |
1901 #endif | |
1902 s = sc->search(loc, ident, &scopesym); | |
1903 if (s) | |
1904 { Expression *e; | |
1905 WithScopeSymbol *withsym; | |
1906 | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
1907 /* See if the symbol was a member of an enclosing 'with' |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
1908 */ |
159 | 1909 withsym = scopesym->isWithScopeSymbol(); |
1910 if (withsym) | |
1911 { | |
1912 s = s->toAlias(); | |
1913 | |
1914 // Same as wthis.ident | |
1915 if (s->needThis() || s->isTemplateDeclaration()) | |
1916 { | |
1917 e = new VarExp(loc, withsym->withstate->wthis); | |
1918 e = new DotIdExp(loc, e, ident); | |
1919 } | |
1920 else | |
1921 { Type *t = withsym->withstate->wthis->type; | |
1922 if (t->ty == Tpointer) | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
1923 t = ((TypePointer *)t)->next; |
159 | 1924 e = new TypeDotIdExp(loc, t, ident); |
1925 } | |
1926 } | |
1927 else | |
1928 { | |
1929 if (!s->parent && scopesym->isArrayScopeSymbol()) | |
1930 { // Kludge to run semantic() here because | |
1931 // ArrayScopeSymbol::search() doesn't have access to sc. | |
1932 s->semantic(sc); | |
1933 } | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
1934 /* If f is really a function template, |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
1935 * then replace f with the function template declaration. |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
1936 */ |
159 | 1937 FuncDeclaration *f = s->isFuncDeclaration(); |
1938 if (f && f->parent) | |
1939 { TemplateInstance *ti = f->parent->isTemplateInstance(); | |
1940 | |
1941 if (ti && | |
1942 !ti->isTemplateMixin() && | |
1943 (ti->name == f->ident || | |
1944 ti->toAlias()->ident == f->ident) | |
1945 && | |
1946 ti->tempdecl && ti->tempdecl->onemember) | |
1947 { | |
1948 TemplateDeclaration *tempdecl = ti->tempdecl; | |
1949 if (tempdecl->overroot) // if not start of overloaded list of TemplateDeclaration's | |
1950 tempdecl = tempdecl->overroot; // then get the start | |
1951 e = new TemplateExp(loc, tempdecl); | |
1952 e = e->semantic(sc); | |
1953 return e; | |
1954 } | |
1955 } | |
1956 e = new DsymbolExp(loc, s); | |
1957 } | |
1958 return e->semantic(sc); | |
1959 } | |
1960 error("undefined identifier %s", ident->toChars()); | |
1961 type = Type::terror; | |
1962 return this; | |
1963 } | |
1964 | |
1965 char *IdentifierExp::toChars() | |
1966 { | |
1967 return ident->toChars(); | |
1968 } | |
1969 | |
1970 void IdentifierExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
1971 { | |
1972 if (hgs->hdrgen) | |
1973 buf->writestring(ident->toHChars2()); | |
1974 else | |
1975 buf->writestring(ident->toChars()); | |
1976 } | |
1977 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
1978 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
1979 int IdentifierExp::isLvalue() |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
1980 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
1981 return 1; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
1982 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
1983 #endif |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
1984 |
159 | 1985 Expression *IdentifierExp::toLvalue(Scope *sc, Expression *e) |
1986 { | |
1987 #if 0 | |
1988 tym = tybasic(e1->ET->Tty); | |
1989 if (!(tyscalar(tym) || | |
1990 tym == TYstruct || | |
1991 tym == TYarray && e->Eoper == TOKaddr)) | |
1992 synerr(EM_lvalue); // lvalue expected | |
1993 #endif | |
1994 return this; | |
1995 } | |
1996 | |
1997 /******************************** DollarExp **************************/ | |
1998 | |
1999 DollarExp::DollarExp(Loc loc) | |
2000 : IdentifierExp(loc, Id::dollar) | |
2001 { | |
2002 } | |
2003 | |
2004 /******************************** DsymbolExp **************************/ | |
2005 | |
2006 DsymbolExp::DsymbolExp(Loc loc, Dsymbol *s) | |
2007 : Expression(loc, TOKdsymbol, sizeof(DsymbolExp)) | |
2008 { | |
2009 this->s = s; | |
2010 } | |
2011 | |
2012 Expression *DsymbolExp::semantic(Scope *sc) | |
2013 { | |
2014 #if LOGSEMANTIC | |
2015 printf("DsymbolExp::semantic('%s')\n", s->toChars()); | |
2016 #endif | |
2017 | |
2018 Lagain: | |
2019 EnumMember *em; | |
2020 Expression *e; | |
2021 VarDeclaration *v; | |
2022 FuncDeclaration *f; | |
2023 FuncLiteralDeclaration *fld; | |
2024 Declaration *d; | |
2025 ClassDeclaration *cd; | |
2026 ClassDeclaration *thiscd = NULL; | |
2027 Import *imp; | |
2028 Package *pkg; | |
2029 Type *t; | |
2030 | |
2031 //printf("DsymbolExp:: %p '%s' is a symbol\n", this, toChars()); | |
2032 //printf("s = '%s', s->kind = '%s'\n", s->toChars(), s->kind()); | |
2033 if (type) | |
2034 return this; | |
2035 if (!s->isFuncDeclaration()) // functions are checked after overloading | |
2036 checkDeprecated(sc, s); | |
2037 s = s->toAlias(); | |
2038 //printf("s = '%s', s->kind = '%s', s->needThis() = %p\n", s->toChars(), s->kind(), s->needThis()); | |
2039 if (!s->isFuncDeclaration()) | |
2040 checkDeprecated(sc, s); | |
2041 | |
2042 if (sc->func) | |
2043 thiscd = sc->func->parent->isClassDeclaration(); | |
2044 | |
2045 // BUG: This should happen after overload resolution for functions, not before | |
2046 if (s->needThis()) | |
2047 { | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
2048 if (hasThis(sc) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
2049 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
2050 && !s->isFuncDeclaration() |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
2051 #endif |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
2052 ) |
159 | 2053 { |
2054 // Supply an implicit 'this', as in | |
2055 // this.ident | |
2056 | |
2057 DotVarExp *de; | |
2058 | |
2059 de = new DotVarExp(loc, new ThisExp(loc), s->isDeclaration()); | |
2060 return de->semantic(sc); | |
2061 } | |
2062 } | |
2063 | |
2064 em = s->isEnumMember(); | |
2065 if (em) | |
2066 { | |
2067 e = em->value->copy(); | |
2068 e = e->semantic(sc); | |
2069 return e; | |
2070 } | |
2071 v = s->isVarDeclaration(); | |
2072 if (v) | |
2073 { | |
2074 //printf("Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars()); | |
2075 if (!type) | |
2076 { type = v->type; | |
2077 if (!v->type) | |
2078 { error("forward reference of %s", v->toChars()); | |
2079 type = Type::terror; | |
2080 } | |
2081 } | |
2082 if (v->isConst() && type->toBasetype()->ty != Tsarray) | |
2083 { | |
2084 if (v->init) | |
2085 { | |
2086 if (v->inuse) | |
2087 { | |
2088 error("circular reference to '%s'", v->toChars()); | |
2089 type = Type::tint32; | |
2090 return this; | |
2091 } | |
2092 ExpInitializer *ei = v->init->isExpInitializer(); | |
2093 if (ei) | |
2094 { | |
2095 e = ei->exp->copy(); // make copy so we can change loc | |
2096 if (e->op == TOKstring || !e->type) | |
2097 e = e->semantic(sc); | |
2098 e = e->implicitCastTo(sc, type); | |
2099 e->loc = loc; | |
2100 return e; | |
2101 } | |
2102 } | |
2103 else | |
2104 { | |
2105 e = type->defaultInit(); | |
2106 e->loc = loc; | |
2107 return e; | |
2108 } | |
2109 } | |
2110 e = new VarExp(loc, v); | |
2111 e->type = type; | |
2112 e = e->semantic(sc); | |
2113 return e->deref(); | |
2114 } | |
2115 fld = s->isFuncLiteralDeclaration(); | |
2116 if (fld) | |
2117 { //printf("'%s' is a function literal\n", fld->toChars()); | |
2118 e = new FuncExp(loc, fld); | |
2119 return e->semantic(sc); | |
2120 } | |
2121 f = s->isFuncDeclaration(); | |
2122 if (f) | |
2123 { //printf("'%s' is a function\n", f->toChars()); | |
2124 return new VarExp(loc, f); | |
2125 } | |
2126 cd = s->isClassDeclaration(); | |
2127 if (cd && thiscd && cd->isBaseOf(thiscd, NULL) && sc->func->needThis()) | |
2128 { | |
2129 // We need to add an implicit 'this' if cd is this class or a base class. | |
2130 DotTypeExp *dte; | |
2131 | |
2132 dte = new DotTypeExp(loc, new ThisExp(loc), s); | |
2133 return dte->semantic(sc); | |
2134 } | |
2135 imp = s->isImport(); | |
2136 if (imp) | |
2137 { | |
2138 ScopeExp *ie; | |
2139 | |
2140 ie = new ScopeExp(loc, imp->pkg); | |
2141 return ie->semantic(sc); | |
2142 } | |
2143 pkg = s->isPackage(); | |
2144 if (pkg) | |
2145 { | |
2146 ScopeExp *ie; | |
2147 | |
2148 ie = new ScopeExp(loc, pkg); | |
2149 return ie->semantic(sc); | |
2150 } | |
2151 Module *mod = s->isModule(); | |
2152 if (mod) | |
2153 { | |
2154 ScopeExp *ie; | |
2155 | |
2156 ie = new ScopeExp(loc, mod); | |
2157 return ie->semantic(sc); | |
2158 } | |
2159 | |
2160 t = s->getType(); | |
2161 if (t) | |
2162 { | |
2163 return new TypeExp(loc, t); | |
2164 } | |
2165 | |
2166 TupleDeclaration *tup = s->isTupleDeclaration(); | |
2167 if (tup) | |
2168 { | |
2169 e = new TupleExp(loc, tup); | |
2170 e = e->semantic(sc); | |
2171 return e; | |
2172 } | |
2173 | |
2174 TemplateInstance *ti = s->isTemplateInstance(); | |
2175 if (ti && !global.errors) | |
2176 { if (!ti->semanticdone) | |
2177 ti->semantic(sc); | |
2178 s = ti->inst->toAlias(); | |
2179 if (!s->isTemplateInstance()) | |
2180 goto Lagain; | |
2181 e = new ScopeExp(loc, ti); | |
2182 e = e->semantic(sc); | |
2183 return e; | |
2184 } | |
2185 | |
2186 TemplateDeclaration *td = s->isTemplateDeclaration(); | |
2187 if (td) | |
2188 { | |
2189 e = new TemplateExp(loc, td); | |
2190 e = e->semantic(sc); | |
2191 return e; | |
2192 } | |
2193 | |
2194 Lerr: | |
2195 error("%s '%s' is not a variable", s->kind(), s->toChars()); | |
2196 type = Type::terror; | |
2197 return this; | |
2198 } | |
2199 | |
2200 char *DsymbolExp::toChars() | |
2201 { | |
2202 return s->toChars(); | |
2203 } | |
2204 | |
2205 void DsymbolExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
2206 { | |
2207 buf->writestring(s->toChars()); | |
2208 } | |
2209 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
2210 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
2211 int DsymbolExp::isLvalue() |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
2212 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
2213 return 1; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
2214 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
2215 #endif |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
2216 |
159 | 2217 Expression *DsymbolExp::toLvalue(Scope *sc, Expression *e) |
2218 { | |
2219 #if 0 | |
2220 tym = tybasic(e1->ET->Tty); | |
2221 if (!(tyscalar(tym) || | |
2222 tym == TYstruct || | |
2223 tym == TYarray && e->Eoper == TOKaddr)) | |
2224 synerr(EM_lvalue); // lvalue expected | |
2225 #endif | |
2226 return this; | |
2227 } | |
2228 | |
2229 /******************************** ThisExp **************************/ | |
2230 | |
2231 ThisExp::ThisExp(Loc loc) | |
2232 : Expression(loc, TOKthis, sizeof(ThisExp)) | |
2233 { | |
2234 var = NULL; | |
2235 } | |
2236 | |
2237 Expression *ThisExp::semantic(Scope *sc) | |
2238 { FuncDeclaration *fd; | |
2239 FuncDeclaration *fdthis; | |
2240 int nested = 0; | |
2241 | |
2242 #if LOGSEMANTIC | |
2243 printf("ThisExp::semantic()\n"); | |
2244 #endif | |
2245 if (type) | |
2246 { //assert(global.errors || var); | |
2247 return this; | |
2248 } | |
2249 | |
2250 /* Special case for typeof(this) and typeof(super) since both | |
2251 * should work even if they are not inside a non-static member function | |
2252 */ | |
2253 if (sc->intypeof) | |
2254 { | |
2255 // Find enclosing struct or class | |
2256 for (Dsymbol *s = sc->parent; 1; s = s->parent) | |
2257 { | |
2258 ClassDeclaration *cd; | |
2259 StructDeclaration *sd; | |
2260 | |
2261 if (!s) | |
2262 { | |
2263 error("%s is not in a struct or class scope", toChars()); | |
2264 goto Lerr; | |
2265 } | |
2266 cd = s->isClassDeclaration(); | |
2267 if (cd) | |
2268 { | |
2269 type = cd->type; | |
2270 return this; | |
2271 } | |
2272 sd = s->isStructDeclaration(); | |
2273 if (sd) | |
2274 { | |
2275 type = sd->type->pointerTo(); | |
2276 return this; | |
2277 } | |
2278 } | |
2279 } | |
2280 | |
2281 fdthis = sc->parent->isFuncDeclaration(); | |
2282 fd = hasThis(sc); // fd is the uplevel function with the 'this' variable | |
2283 if (!fd) | |
2284 goto Lerr; | |
2285 | |
2286 assert(fd->vthis); | |
2287 var = fd->vthis; | |
2288 assert(var->parent); | |
2289 type = var->type; | |
2290 var->isVarDeclaration()->checkNestedReference(sc, loc); | |
2291 #if 0 | |
2292 if (fd != fdthis) // if nested | |
2293 { | |
2294 fdthis->getLevel(loc, fd); | |
2295 fd->vthis->nestedref = 1; | |
2296 fd->nestedFrameRef = 1; | |
2297 } | |
2298 #endif | |
336 | 2299 if (!sc->intypeof) |
2300 sc->callSuper |= CSXthis; | |
159 | 2301 return this; |
2302 | |
2303 Lerr: | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
2304 error("'this' is only defined in non-static member functions, not %s", sc->parent->toChars()); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
2305 type = Type::terror; |
159 | 2306 return this; |
2307 } | |
2308 | |
2309 int ThisExp::isBool(int result) | |
2310 { | |
2311 return result ? TRUE : FALSE; | |
2312 } | |
2313 | |
2314 void ThisExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
2315 { | |
2316 buf->writestring("this"); | |
2317 } | |
2318 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
2319 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
2320 int ThisExp::isLvalue() |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
2321 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
2322 return 1; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
2323 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
2324 #endif |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
2325 |
159 | 2326 Expression *ThisExp::toLvalue(Scope *sc, Expression *e) |
2327 { | |
2328 return this; | |
2329 } | |
2330 | |
2331 /******************************** SuperExp **************************/ | |
2332 | |
2333 SuperExp::SuperExp(Loc loc) | |
2334 : ThisExp(loc) | |
2335 { | |
2336 op = TOKsuper; | |
2337 } | |
2338 | |
2339 Expression *SuperExp::semantic(Scope *sc) | |
2340 { FuncDeclaration *fd; | |
2341 FuncDeclaration *fdthis; | |
2342 ClassDeclaration *cd; | |
2343 Dsymbol *s; | |
2344 | |
2345 #if LOGSEMANTIC | |
2346 printf("SuperExp::semantic('%s')\n", toChars()); | |
2347 #endif | |
2348 if (type) | |
2349 return this; | |
2350 | |
2351 /* Special case for typeof(this) and typeof(super) since both | |
2352 * should work even if they are not inside a non-static member function | |
2353 */ | |
2354 if (sc->intypeof) | |
2355 { | |
2356 // Find enclosing class | |
2357 for (Dsymbol *s = sc->parent; 1; s = s->parent) | |
2358 { | |
2359 ClassDeclaration *cd; | |
2360 | |
2361 if (!s) | |
2362 { | |
2363 error("%s is not in a class scope", toChars()); | |
2364 goto Lerr; | |
2365 } | |
2366 cd = s->isClassDeclaration(); | |
2367 if (cd) | |
2368 { | |
2369 cd = cd->baseClass; | |
2370 if (!cd) | |
2371 { error("class %s has no 'super'", s->toChars()); | |
2372 goto Lerr; | |
2373 } | |
2374 type = cd->type; | |
2375 return this; | |
2376 } | |
2377 } | |
2378 } | |
2379 | |
2380 fdthis = sc->parent->isFuncDeclaration(); | |
2381 fd = hasThis(sc); | |
2382 if (!fd) | |
2383 goto Lerr; | |
2384 assert(fd->vthis); | |
2385 var = fd->vthis; | |
2386 assert(var->parent); | |
2387 | |
2388 s = fd->toParent(); | |
2389 while (s && s->isTemplateInstance()) | |
2390 s = s->toParent(); | |
2391 assert(s); | |
2392 cd = s->isClassDeclaration(); | |
2393 //printf("parent is %s %s\n", fd->toParent()->kind(), fd->toParent()->toChars()); | |
2394 if (!cd) | |
2395 goto Lerr; | |
2396 if (!cd->baseClass) | |
2397 { | |
2398 error("no base class for %s", cd->toChars()); | |
2399 type = fd->vthis->type; | |
2400 } | |
2401 else | |
2402 { | |
2403 type = cd->baseClass->type; | |
2404 } | |
2405 | |
2406 var->isVarDeclaration()->checkNestedReference(sc, loc); | |
2407 #if 0 | |
2408 if (fd != fdthis) | |
2409 { | |
2410 fdthis->getLevel(loc, fd); | |
2411 fd->vthis->nestedref = 1; | |
2412 fd->nestedFrameRef = 1; | |
2413 } | |
2414 #endif | |
2415 | |
336 | 2416 if (!sc->intypeof) |
2417 sc->callSuper |= CSXsuper; | |
159 | 2418 return this; |
2419 | |
2420 | |
2421 Lerr: | |
2422 error("'super' is only allowed in non-static class member functions"); | |
2423 type = Type::tint32; | |
2424 return this; | |
2425 } | |
2426 | |
2427 void SuperExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
2428 { | |
2429 buf->writestring("super"); | |
2430 } | |
2431 | |
2432 | |
2433 /******************************** NullExp **************************/ | |
2434 | |
2435 NullExp::NullExp(Loc loc) | |
2436 : Expression(loc, TOKnull, sizeof(NullExp)) | |
2437 { | |
2438 committed = 0; | |
2439 } | |
2440 | |
2441 Expression *NullExp::semantic(Scope *sc) | |
2442 { | |
2443 #if LOGSEMANTIC | |
2444 printf("NullExp::semantic('%s')\n", toChars()); | |
2445 #endif | |
2446 // NULL is the same as (void *)0 | |
2447 if (!type) | |
2448 type = Type::tvoid->pointerTo(); | |
2449 return this; | |
2450 } | |
2451 | |
2452 int NullExp::isBool(int result) | |
2453 { | |
2454 return result ? FALSE : TRUE; | |
2455 } | |
2456 | |
2457 void NullExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
2458 { | |
2459 buf->writestring("null"); | |
2460 } | |
2461 | |
2462 void NullExp::toMangleBuffer(OutBuffer *buf) | |
2463 { | |
2464 buf->writeByte('n'); | |
2465 } | |
2466 | |
2467 /******************************** StringExp **************************/ | |
2468 | |
2469 StringExp::StringExp(Loc loc, char *string) | |
2470 : Expression(loc, TOKstring, sizeof(StringExp)) | |
2471 { | |
2472 this->string = string; | |
2473 this->len = strlen(string); | |
2474 this->sz = 1; | |
2475 this->committed = 0; | |
2476 this->postfix = 0; | |
2477 } | |
2478 | |
2479 StringExp::StringExp(Loc loc, void *string, size_t len) | |
2480 : Expression(loc, TOKstring, sizeof(StringExp)) | |
2481 { | |
2482 this->string = string; | |
2483 this->len = len; | |
2484 this->sz = 1; | |
2485 this->committed = 0; | |
2486 this->postfix = 0; | |
2487 } | |
2488 | |
2489 StringExp::StringExp(Loc loc, void *string, size_t len, unsigned char postfix) | |
2490 : Expression(loc, TOKstring, sizeof(StringExp)) | |
2491 { | |
2492 this->string = string; | |
2493 this->len = len; | |
2494 this->sz = 1; | |
2495 this->committed = 0; | |
2496 this->postfix = postfix; | |
2497 } | |
2498 | |
2499 #if 0 | |
2500 Expression *StringExp::syntaxCopy() | |
2501 { | |
2502 printf("StringExp::syntaxCopy() %s\n", toChars()); | |
2503 return copy(); | |
2504 } | |
2505 #endif | |
2506 | |
2507 int StringExp::equals(Object *o) | |
2508 { | |
2509 //printf("StringExp::equals('%s')\n", o->toChars()); | |
2510 if (o && o->dyncast() == DYNCAST_EXPRESSION) | |
2511 { Expression *e = (Expression *)o; | |
2512 | |
2513 if (e->op == TOKstring) | |
2514 { | |
2515 return compare(o) == 0; | |
2516 } | |
2517 } | |
2518 return FALSE; | |
2519 } | |
2520 | |
2521 char *StringExp::toChars() | |
2522 { | |
2523 OutBuffer buf; | |
2524 HdrGenState hgs; | |
2525 char *p; | |
2526 | |
2527 memset(&hgs, 0, sizeof(hgs)); | |
2528 toCBuffer(&buf, &hgs); | |
2529 buf.writeByte(0); | |
2530 p = (char *)buf.data; | |
2531 buf.data = NULL; | |
2532 return p; | |
2533 } | |
2534 | |
2535 Expression *StringExp::semantic(Scope *sc) | |
2536 { | |
2537 #if LOGSEMANTIC | |
2538 printf("StringExp::semantic() %s\n", toChars()); | |
2539 #endif | |
2540 if (!type) | |
2541 { OutBuffer buffer; | |
2542 size_t newlen = 0; | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
2543 const char *p; |
159 | 2544 size_t u; |
2545 unsigned c; | |
2546 | |
2547 switch (postfix) | |
2548 { | |
2549 case 'd': | |
2550 for (u = 0; u < len;) | |
2551 { | |
2552 p = utf_decodeChar((unsigned char *)string, len, &u, &c); | |
2553 if (p) | |
2554 { error("%s", p); | |
2555 break; | |
2556 } | |
2557 else | |
2558 { buffer.write4(c); | |
2559 newlen++; | |
2560 } | |
2561 } | |
2562 buffer.write4(0); | |
2563 string = buffer.extractData(); | |
2564 len = newlen; | |
2565 sz = 4; | |
2566 type = new TypeSArray(Type::tdchar, new IntegerExp(loc, len, Type::tindex)); | |
2567 committed = 1; | |
2568 break; | |
2569 | |
2570 case 'w': | |
2571 for (u = 0; u < len;) | |
2572 { | |
2573 p = utf_decodeChar((unsigned char *)string, len, &u, &c); | |
2574 if (p) | |
2575 { error("%s", p); | |
2576 break; | |
2577 } | |
2578 else | |
2579 { buffer.writeUTF16(c); | |
2580 newlen++; | |
2581 if (c >= 0x10000) | |
2582 newlen++; | |
2583 } | |
2584 } | |
2585 buffer.writeUTF16(0); | |
2586 string = buffer.extractData(); | |
2587 len = newlen; | |
2588 sz = 2; | |
2589 type = new TypeSArray(Type::twchar, new IntegerExp(loc, len, Type::tindex)); | |
2590 committed = 1; | |
2591 break; | |
2592 | |
2593 case 'c': | |
2594 committed = 1; | |
2595 default: | |
2596 type = new TypeSArray(Type::tchar, new IntegerExp(loc, len, Type::tindex)); | |
2597 break; | |
2598 } | |
2599 type = type->semantic(loc, sc); | |
2600 } | |
2601 return this; | |
2602 } | |
2603 | |
2604 /**************************************** | |
2605 * Convert string to char[]. | |
2606 */ | |
2607 | |
2608 StringExp *StringExp::toUTF8(Scope *sc) | |
2609 { | |
2610 if (sz != 1) | |
2611 { // Convert to UTF-8 string | |
2612 committed = 0; | |
2613 Expression *e = castTo(sc, Type::tchar->arrayOf()); | |
2614 e = e->optimize(WANTvalue); | |
2615 assert(e->op == TOKstring); | |
2616 StringExp *se = (StringExp *)e; | |
2617 assert(se->sz == 1); | |
2618 return se; | |
2619 } | |
2620 return this; | |
2621 } | |
2622 | |
2623 int StringExp::compare(Object *obj) | |
2624 { | |
2625 // Used to sort case statement expressions so we can do an efficient lookup | |
2626 StringExp *se2 = (StringExp *)(obj); | |
2627 | |
2628 // This is a kludge so isExpression() in template.c will return 5 | |
2629 // for StringExp's. | |
2630 if (!se2) | |
2631 return 5; | |
2632 | |
2633 assert(se2->op == TOKstring); | |
2634 | |
2635 int len1 = len; | |
2636 int len2 = se2->len; | |
2637 | |
2638 if (len1 == len2) | |
2639 { | |
2640 switch (sz) | |
2641 { | |
2642 case 1: | |
2643 return strcmp((char *)string, (char *)se2->string); | |
2644 | |
2645 case 2: | |
2646 { unsigned u; | |
2647 d_wchar *s1 = (d_wchar *)string; | |
2648 d_wchar *s2 = (d_wchar *)se2->string; | |
2649 | |
2650 for (u = 0; u < len; u++) | |
2651 { | |
2652 if (s1[u] != s2[u]) | |
2653 return s1[u] - s2[u]; | |
2654 } | |
2655 } | |
2656 | |
2657 case 4: | |
2658 { unsigned u; | |
2659 d_dchar *s1 = (d_dchar *)string; | |
2660 d_dchar *s2 = (d_dchar *)se2->string; | |
2661 | |
2662 for (u = 0; u < len; u++) | |
2663 { | |
2664 if (s1[u] != s2[u]) | |
2665 return s1[u] - s2[u]; | |
2666 } | |
2667 } | |
2668 break; | |
2669 | |
2670 default: | |
2671 assert(0); | |
2672 } | |
2673 } | |
2674 return len1 - len2; | |
2675 } | |
2676 | |
2677 int StringExp::isBool(int result) | |
2678 { | |
2679 return result ? TRUE : FALSE; | |
2680 } | |
2681 | |
2682 unsigned StringExp::charAt(size_t i) | |
2683 { unsigned value; | |
2684 | |
2685 switch (sz) | |
2686 { | |
2687 case 1: | |
2688 value = ((unsigned char *)string)[i]; | |
2689 break; | |
2690 | |
2691 case 2: | |
2692 value = ((unsigned short *)string)[i]; | |
2693 break; | |
2694 | |
2695 case 4: | |
2696 value = ((unsigned int *)string)[i]; | |
2697 break; | |
2698 | |
2699 default: | |
2700 assert(0); | |
2701 break; | |
2702 } | |
2703 return value; | |
2704 } | |
2705 | |
2706 void StringExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
2707 { | |
2708 buf->writeByte('"'); | |
2709 for (size_t i = 0; i < len; i++) | |
2710 { unsigned c = charAt(i); | |
2711 | |
2712 switch (c) | |
2713 { | |
2714 case '"': | |
2715 case '\\': | |
2716 if (!hgs->console) | |
2717 buf->writeByte('\\'); | |
2718 default: | |
2719 if (c <= 0xFF) | |
2720 { if (c <= 0x7F && (isprint(c) || hgs->console)) | |
2721 buf->writeByte(c); | |
2722 else | |
2723 buf->printf("\\x%02x", c); | |
2724 } | |
2725 else if (c <= 0xFFFF) | |
2726 buf->printf("\\x%02x\\x%02x", c & 0xFF, c >> 8); | |
2727 else | |
2728 buf->printf("\\x%02x\\x%02x\\x%02x\\x%02x", | |
2729 c & 0xFF, (c >> 8) & 0xFF, (c >> 16) & 0xFF, c >> 24); | |
2730 break; | |
2731 } | |
2732 } | |
2733 buf->writeByte('"'); | |
2734 if (postfix) | |
2735 buf->writeByte(postfix); | |
2736 } | |
2737 | |
2738 void StringExp::toMangleBuffer(OutBuffer *buf) | |
2739 { char m; | |
2740 OutBuffer tmp; | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
2741 const char *p; |
159 | 2742 unsigned c; |
2743 size_t u; | |
2744 unsigned char *q; | |
2745 unsigned qlen; | |
2746 | |
2747 /* Write string in UTF-8 format | |
2748 */ | |
2749 switch (sz) | |
2750 { case 1: | |
2751 m = 'a'; | |
2752 q = (unsigned char *)string; | |
2753 qlen = len; | |
2754 break; | |
2755 case 2: | |
2756 m = 'w'; | |
2757 for (u = 0; u < len; ) | |
2758 { | |
2759 p = utf_decodeWchar((unsigned short *)string, len, &u, &c); | |
2760 if (p) | |
2761 error("%s", p); | |
2762 else | |
2763 tmp.writeUTF8(c); | |
2764 } | |
2765 q = tmp.data; | |
2766 qlen = tmp.offset; | |
2767 break; | |
2768 case 4: | |
2769 m = 'd'; | |
2770 for (u = 0; u < len; u++) | |
2771 { | |
2772 c = ((unsigned *)string)[u]; | |
2773 if (!utf_isValidDchar(c)) | |
2774 error("invalid UCS-32 char \\U%08x", c); | |
2775 else | |
2776 tmp.writeUTF8(c); | |
2777 } | |
2778 q = tmp.data; | |
2779 qlen = tmp.offset; | |
2780 break; | |
2781 default: | |
2782 assert(0); | |
2783 } | |
2784 buf->writeByte(m); | |
2785 buf->printf("%d_", qlen); | |
2786 for (size_t i = 0; i < qlen; i++) | |
2787 buf->printf("%02x", q[i]); | |
2788 } | |
2789 | |
2790 /************************ ArrayLiteralExp ************************************/ | |
2791 | |
2792 // [ e1, e2, e3, ... ] | |
2793 | |
2794 ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expressions *elements) | |
2795 : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp)) | |
2796 { | |
2797 this->elements = elements; | |
2798 } | |
2799 | |
2800 ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expression *e) | |
2801 : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp)) | |
2802 { | |
2803 elements = new Expressions; | |
2804 elements->push(e); | |
2805 } | |
2806 | |
2807 Expression *ArrayLiteralExp::syntaxCopy() | |
2808 { | |
2809 return new ArrayLiteralExp(loc, arraySyntaxCopy(elements)); | |
2810 } | |
2811 | |
2812 Expression *ArrayLiteralExp::semantic(Scope *sc) | |
2813 { Expression *e; | |
2814 Type *t0 = NULL; | |
2815 | |
2816 #if LOGSEMANTIC | |
2817 printf("ArrayLiteralExp::semantic('%s')\n", toChars()); | |
2818 #endif | |
2819 if (type) | |
2820 return this; | |
2821 | |
2822 // Run semantic() on each element | |
2823 for (int i = 0; i < elements->dim; i++) | |
2824 { e = (Expression *)elements->data[i]; | |
2825 e = e->semantic(sc); | |
2826 elements->data[i] = (void *)e; | |
2827 } | |
2828 expandTuples(elements); | |
2829 for (int i = 0; i < elements->dim; i++) | |
2830 { e = (Expression *)elements->data[i]; | |
2831 | |
2832 if (!e->type) | |
2833 error("%s has no value", e->toChars()); | |
2834 e = resolveProperties(sc, e); | |
2835 | |
2836 unsigned char committed = 1; | |
2837 if (e->op == TOKstring) | |
2838 committed = ((StringExp *)e)->committed; | |
2839 | |
2840 if (!t0) | |
2841 { t0 = e->type; | |
2842 // Convert any static arrays to dynamic arrays | |
2843 if (t0->ty == Tsarray) | |
2844 { | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
2845 t0 = ((TypeSArray *)t0)->next->arrayOf(); |
159 | 2846 e = e->implicitCastTo(sc, t0); |
2847 } | |
2848 } | |
2849 else | |
2850 e = e->implicitCastTo(sc, t0); | |
2851 if (!committed && e->op == TOKstring) | |
2852 { StringExp *se = (StringExp *)e; | |
2853 se->committed = 0; | |
2854 } | |
2855 elements->data[i] = (void *)e; | |
2856 } | |
2857 | |
2858 if (!t0) | |
2859 t0 = Type::tvoid; | |
2860 type = new TypeSArray(t0, new IntegerExp(elements->dim)); | |
2861 type = type->semantic(loc, sc); | |
2862 return this; | |
2863 } | |
2864 | |
2865 int ArrayLiteralExp::checkSideEffect(int flag) | |
2866 { int f = 0; | |
2867 | |
2868 for (size_t i = 0; i < elements->dim; i++) | |
2869 { Expression *e = (Expression *)elements->data[i]; | |
2870 | |
2871 f |= e->checkSideEffect(2); | |
2872 } | |
2873 if (flag == 0 && f == 0) | |
2874 Expression::checkSideEffect(0); | |
2875 return f; | |
2876 } | |
2877 | |
2878 int ArrayLiteralExp::isBool(int result) | |
2879 { | |
2880 size_t dim = elements ? elements->dim : 0; | |
2881 return result ? (dim != 0) : (dim == 0); | |
2882 } | |
2883 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
2884 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
2885 int ArrayLiteralExp::canThrow() |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
2886 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
2887 return 1; // because it can fail allocating memory |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
2888 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
2889 #endif |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
2890 |
159 | 2891 void ArrayLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
2892 { | |
2893 buf->writeByte('['); | |
2894 argsToCBuffer(buf, elements, hgs); | |
2895 buf->writeByte(']'); | |
2896 } | |
2897 | |
2898 void ArrayLiteralExp::toMangleBuffer(OutBuffer *buf) | |
2899 { | |
2900 size_t dim = elements ? elements->dim : 0; | |
2901 buf->printf("A%u", dim); | |
2902 for (size_t i = 0; i < dim; i++) | |
2903 { Expression *e = (Expression *)elements->data[i]; | |
2904 e->toMangleBuffer(buf); | |
2905 } | |
2906 } | |
2907 | |
2908 /************************ AssocArrayLiteralExp ************************************/ | |
2909 | |
2910 // [ key0 : value0, key1 : value1, ... ] | |
2911 | |
2912 AssocArrayLiteralExp::AssocArrayLiteralExp(Loc loc, | |
2913 Expressions *keys, Expressions *values) | |
2914 : Expression(loc, TOKassocarrayliteral, sizeof(AssocArrayLiteralExp)) | |
2915 { | |
2916 assert(keys->dim == values->dim); | |
2917 this->keys = keys; | |
2918 this->values = values; | |
2919 } | |
2920 | |
2921 Expression *AssocArrayLiteralExp::syntaxCopy() | |
2922 { | |
2923 return new AssocArrayLiteralExp(loc, | |
2924 arraySyntaxCopy(keys), arraySyntaxCopy(values)); | |
2925 } | |
2926 | |
2927 Expression *AssocArrayLiteralExp::semantic(Scope *sc) | |
2928 { Expression *e; | |
2929 Type *tkey = NULL; | |
2930 Type *tvalue = NULL; | |
2931 | |
2932 #if LOGSEMANTIC | |
2933 printf("AssocArrayLiteralExp::semantic('%s')\n", toChars()); | |
2934 #endif | |
2935 | |
2936 // Run semantic() on each element | |
2937 for (size_t i = 0; i < keys->dim; i++) | |
2938 { Expression *key = (Expression *)keys->data[i]; | |
2939 Expression *value = (Expression *)values->data[i]; | |
2940 | |
2941 key = key->semantic(sc); | |
2942 value = value->semantic(sc); | |
2943 | |
2944 keys->data[i] = (void *)key; | |
2945 values->data[i] = (void *)value; | |
2946 } | |
2947 expandTuples(keys); | |
2948 expandTuples(values); | |
2949 if (keys->dim != values->dim) | |
2950 { | |
2951 error("number of keys is %u, must match number of values %u", keys->dim, values->dim); | |
2952 keys->setDim(0); | |
2953 values->setDim(0); | |
2954 } | |
2955 for (size_t i = 0; i < keys->dim; i++) | |
2956 { Expression *key = (Expression *)keys->data[i]; | |
2957 Expression *value = (Expression *)values->data[i]; | |
2958 | |
2959 if (!key->type) | |
2960 error("%s has no value", key->toChars()); | |
2961 if (!value->type) | |
2962 error("%s has no value", value->toChars()); | |
2963 key = resolveProperties(sc, key); | |
2964 value = resolveProperties(sc, value); | |
2965 | |
2966 if (!tkey) | |
2967 tkey = key->type; | |
2968 else | |
2969 key = key->implicitCastTo(sc, tkey); | |
2970 keys->data[i] = (void *)key; | |
2971 | |
2972 if (!tvalue) | |
2973 tvalue = value->type; | |
2974 else | |
2975 value = value->implicitCastTo(sc, tvalue); | |
2976 values->data[i] = (void *)value; | |
2977 } | |
2978 | |
2979 if (!tkey) | |
2980 tkey = Type::tvoid; | |
2981 if (!tvalue) | |
2982 tvalue = Type::tvoid; | |
2983 type = new TypeAArray(tvalue, tkey); | |
2984 type = type->semantic(loc, sc); | |
2985 return this; | |
2986 } | |
2987 | |
2988 int AssocArrayLiteralExp::checkSideEffect(int flag) | |
2989 { int f = 0; | |
2990 | |
2991 for (size_t i = 0; i < keys->dim; i++) | |
2992 { Expression *key = (Expression *)keys->data[i]; | |
2993 Expression *value = (Expression *)values->data[i]; | |
2994 | |
2995 f |= key->checkSideEffect(2); | |
2996 f |= value->checkSideEffect(2); | |
2997 } | |
2998 if (flag == 0 && f == 0) | |
2999 Expression::checkSideEffect(0); | |
3000 return f; | |
3001 } | |
3002 | |
3003 int AssocArrayLiteralExp::isBool(int result) | |
3004 { | |
3005 size_t dim = keys->dim; | |
3006 return result ? (dim != 0) : (dim == 0); | |
3007 } | |
3008 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3009 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3010 int AssocArrayLiteralExp::canThrow() |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3011 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3012 return 1; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3013 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3014 #endif |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3015 |
159 | 3016 void AssocArrayLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
3017 { | |
3018 buf->writeByte('['); | |
3019 for (size_t i = 0; i < keys->dim; i++) | |
3020 { Expression *key = (Expression *)keys->data[i]; | |
3021 Expression *value = (Expression *)values->data[i]; | |
3022 | |
3023 if (i) | |
3024 buf->writeByte(','); | |
3025 expToCBuffer(buf, hgs, key, PREC_assign); | |
3026 buf->writeByte(':'); | |
3027 expToCBuffer(buf, hgs, value, PREC_assign); | |
3028 } | |
3029 buf->writeByte(']'); | |
3030 } | |
3031 | |
3032 void AssocArrayLiteralExp::toMangleBuffer(OutBuffer *buf) | |
3033 { | |
3034 size_t dim = keys->dim; | |
3035 buf->printf("A%u", dim); | |
3036 for (size_t i = 0; i < dim; i++) | |
3037 { Expression *key = (Expression *)keys->data[i]; | |
3038 Expression *value = (Expression *)values->data[i]; | |
3039 | |
3040 key->toMangleBuffer(buf); | |
3041 value->toMangleBuffer(buf); | |
3042 } | |
3043 } | |
3044 | |
3045 /************************ StructLiteralExp ************************************/ | |
3046 | |
3047 // sd( e1, e2, e3, ... ) | |
3048 | |
3049 StructLiteralExp::StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *elements) | |
3050 : Expression(loc, TOKstructliteral, sizeof(StructLiteralExp)) | |
3051 { | |
3052 this->sd = sd; | |
3053 this->elements = elements; | |
3054 this->sym = NULL; | |
3055 this->soffset = 0; | |
3056 this->fillHoles = 1; | |
3057 } | |
3058 | |
3059 Expression *StructLiteralExp::syntaxCopy() | |
3060 { | |
3061 return new StructLiteralExp(loc, sd, arraySyntaxCopy(elements)); | |
3062 } | |
3063 | |
3064 Expression *StructLiteralExp::semantic(Scope *sc) | |
3065 { Expression *e; | |
3066 | |
3067 #if LOGSEMANTIC | |
3068 printf("StructLiteralExp::semantic('%s')\n", toChars()); | |
3069 #endif | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
3070 if (type) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
3071 return this; |
159 | 3072 |
3073 // Run semantic() on each element | |
3074 for (size_t i = 0; i < elements->dim; i++) | |
3075 { e = (Expression *)elements->data[i]; | |
3076 if (!e) | |
3077 continue; | |
3078 e = e->semantic(sc); | |
3079 elements->data[i] = (void *)e; | |
3080 } | |
3081 expandTuples(elements); | |
3082 size_t offset = 0; | |
3083 for (size_t i = 0; i < elements->dim; i++) | |
3084 { e = (Expression *)elements->data[i]; | |
3085 if (!e) | |
3086 continue; | |
3087 | |
3088 if (!e->type) | |
3089 error("%s has no value", e->toChars()); | |
3090 e = resolveProperties(sc, e); | |
3091 if (i >= sd->fields.dim) | |
3092 { error("more initializers than fields of %s", sd->toChars()); | |
3093 break; | |
3094 } | |
3095 Dsymbol *s = (Dsymbol *)sd->fields.data[i]; | |
3096 VarDeclaration *v = s->isVarDeclaration(); | |
3097 assert(v); | |
3098 if (v->offset < offset) | |
3099 error("overlapping initialization for %s", v->toChars()); | |
3100 offset = v->offset + v->type->size(); | |
3101 | |
3102 Type *telem = v->type; | |
3103 while (!e->implicitConvTo(telem) && telem->toBasetype()->ty == Tsarray) | |
3104 { /* Static array initialization, as in: | |
3105 * T[3][5] = e; | |
3106 */ | |
3107 telem = telem->toBasetype()->nextOf(); | |
3108 } | |
3109 | |
3110 e = e->implicitCastTo(sc, telem); | |
3111 | |
3112 elements->data[i] = (void *)e; | |
3113 } | |
3114 | |
3115 /* Fill out remainder of elements[] with default initializers for fields[] | |
3116 */ | |
3117 for (size_t i = elements->dim; i < sd->fields.dim; i++) | |
3118 { Dsymbol *s = (Dsymbol *)sd->fields.data[i]; | |
3119 VarDeclaration *v = s->isVarDeclaration(); | |
3120 assert(v); | |
3121 | |
3122 if (v->offset < offset) | |
3123 { e = NULL; | |
3124 sd->hasUnions = 1; | |
3125 } | |
3126 else | |
3127 { | |
3128 if (v->init) | |
3129 { e = v->init->toExpression(); | |
3130 if (!e) | |
3131 error("cannot make expression out of initializer for %s", v->toChars()); | |
3132 } | |
3133 else | |
3134 { e = v->type->defaultInit(); | |
3135 e->loc = loc; | |
3136 } | |
3137 offset = v->offset + v->type->size(); | |
3138 } | |
3139 elements->push(e); | |
3140 } | |
3141 | |
3142 type = sd->type; | |
3143 return this; | |
3144 } | |
3145 | |
3146 /************************************** | |
3147 * Gets expression at offset of type. | |
3148 * Returns NULL if not found. | |
3149 */ | |
3150 | |
3151 Expression *StructLiteralExp::getField(Type *type, unsigned offset) | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
3152 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
3153 //printf("StructLiteralExp::getField(this = %s, type = %s, offset = %u)\n", |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
3154 // /*toChars()*/"", type->toChars(), offset); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
3155 Expression *e = NULL; |
159 | 3156 int i = getFieldIndex(type, offset); |
3157 | |
3158 if (i != -1) | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
3159 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
3160 //printf("\ti = %d\n", i); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
3161 assert(i < elements->dim); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
3162 e = (Expression *)elements->data[i]; |
159 | 3163 if (e) |
3164 { | |
3165 e = e->copy(); | |
3166 e->type = type; | |
3167 } | |
3168 } | |
3169 return e; | |
3170 } | |
3171 | |
3172 /************************************ | |
3173 * Get index of field. | |
3174 * Returns -1 if not found. | |
3175 */ | |
3176 | |
3177 int StructLiteralExp::getFieldIndex(Type *type, unsigned offset) | |
3178 { | |
3179 /* Find which field offset is by looking at the field offsets | |
3180 */ | |
3181 for (size_t i = 0; i < sd->fields.dim; i++) | |
3182 { | |
3183 Dsymbol *s = (Dsymbol *)sd->fields.data[i]; | |
3184 VarDeclaration *v = s->isVarDeclaration(); | |
3185 assert(v); | |
3186 | |
3187 if (offset == v->offset && | |
3188 type->size() == v->type->size()) | |
3189 { Expression *e = (Expression *)elements->data[i]; | |
3190 if (e) | |
3191 { | |
3192 return i; | |
3193 } | |
3194 break; | |
3195 } | |
3196 } | |
3197 return -1; | |
3198 } | |
3199 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3200 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3201 int StructLiteralExp::isLvalue() |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3202 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3203 return 1; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3204 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3205 #endif |
159 | 3206 |
3207 Expression *StructLiteralExp::toLvalue(Scope *sc, Expression *e) | |
3208 { | |
3209 return this; | |
3210 } | |
3211 | |
3212 | |
3213 int StructLiteralExp::checkSideEffect(int flag) | |
3214 { int f = 0; | |
3215 | |
3216 for (size_t i = 0; i < elements->dim; i++) | |
3217 { Expression *e = (Expression *)elements->data[i]; | |
3218 if (!e) | |
3219 continue; | |
3220 | |
3221 f |= e->checkSideEffect(2); | |
3222 } | |
3223 if (flag == 0 && f == 0) | |
3224 Expression::checkSideEffect(0); | |
3225 return f; | |
3226 } | |
3227 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3228 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3229 int StructLiteralExp::canThrow() |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3230 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3231 return arrayExpressionCanThrow(elements); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3232 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3233 #endif |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3234 |
159 | 3235 void StructLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
3236 { | |
3237 buf->writestring(sd->toChars()); | |
3238 buf->writeByte('('); | |
3239 argsToCBuffer(buf, elements, hgs); | |
3240 buf->writeByte(')'); | |
3241 } | |
3242 | |
3243 void StructLiteralExp::toMangleBuffer(OutBuffer *buf) | |
3244 { | |
3245 size_t dim = elements ? elements->dim : 0; | |
3246 buf->printf("S%u", dim); | |
3247 for (size_t i = 0; i < dim; i++) | |
3248 { Expression *e = (Expression *)elements->data[i]; | |
3249 if (e) | |
3250 e->toMangleBuffer(buf); | |
3251 else | |
3252 buf->writeByte('v'); // 'v' for void | |
3253 } | |
3254 } | |
3255 | |
3256 /************************ TypeDotIdExp ************************************/ | |
3257 | |
3258 /* Things like: | |
3259 * int.size | |
3260 * foo.size | |
3261 * (foo).size | |
3262 * cast(foo).size | |
3263 */ | |
3264 | |
3265 TypeDotIdExp::TypeDotIdExp(Loc loc, Type *type, Identifier *ident) | |
3266 : Expression(loc, TOKtypedot, sizeof(TypeDotIdExp)) | |
3267 { | |
3268 this->type = type; | |
3269 this->ident = ident; | |
3270 } | |
3271 | |
3272 Expression *TypeDotIdExp::syntaxCopy() | |
3273 { | |
3274 TypeDotIdExp *te = new TypeDotIdExp(loc, type->syntaxCopy(), ident); | |
3275 return te; | |
3276 } | |
3277 | |
3278 Expression *TypeDotIdExp::semantic(Scope *sc) | |
3279 { Expression *e; | |
3280 | |
3281 #if LOGSEMANTIC | |
3282 printf("TypeDotIdExp::semantic()\n"); | |
3283 #endif | |
3284 e = new DotIdExp(loc, new TypeExp(loc, type), ident); | |
3285 e = e->semantic(sc); | |
3286 return e; | |
3287 } | |
3288 | |
3289 void TypeDotIdExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3290 { | |
3291 buf->writeByte('('); | |
3292 type->toCBuffer(buf, NULL, hgs); | |
3293 buf->writeByte(')'); | |
3294 buf->writeByte('.'); | |
3295 buf->writestring(ident->toChars()); | |
3296 } | |
3297 | |
3298 /************************************************************/ | |
3299 | |
3300 // Mainly just a placeholder | |
3301 | |
3302 TypeExp::TypeExp(Loc loc, Type *type) | |
3303 : Expression(loc, TOKtype, sizeof(TypeExp)) | |
3304 { | |
3305 //printf("TypeExp::TypeExp(%s)\n", type->toChars()); | |
3306 this->type = type; | |
3307 } | |
3308 | |
876
27a379f288bf
Merged DMD 1.039
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
875
diff
changeset
|
3309 Expression *TypeExp::syntaxCopy() |
27a379f288bf
Merged DMD 1.039
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
875
diff
changeset
|
3310 { |
27a379f288bf
Merged DMD 1.039
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
875
diff
changeset
|
3311 //printf("TypeExp::syntaxCopy()\n"); |
27a379f288bf
Merged DMD 1.039
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
875
diff
changeset
|
3312 return new TypeExp(loc, type->syntaxCopy()); |
27a379f288bf
Merged DMD 1.039
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
875
diff
changeset
|
3313 } |
27a379f288bf
Merged DMD 1.039
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
875
diff
changeset
|
3314 |
159 | 3315 Expression *TypeExp::semantic(Scope *sc) |
3316 { | |
3317 //printf("TypeExp::semantic(%s)\n", type->toChars()); | |
3318 type = type->semantic(loc, sc); | |
3319 return this; | |
3320 } | |
3321 | |
3322 void TypeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3323 { | |
3324 type->toCBuffer(buf, NULL, hgs); | |
3325 } | |
3326 | |
3327 /************************************************************/ | |
3328 | |
3329 // Mainly just a placeholder | |
3330 | |
3331 ScopeExp::ScopeExp(Loc loc, ScopeDsymbol *pkg) | |
3332 : Expression(loc, TOKimport, sizeof(ScopeExp)) | |
3333 { | |
3334 //printf("ScopeExp::ScopeExp(pkg = '%s')\n", pkg->toChars()); | |
3335 //static int count; if (++count == 38) *(char*)0=0; | |
3336 this->sds = pkg; | |
3337 } | |
3338 | |
3339 Expression *ScopeExp::syntaxCopy() | |
3340 { | |
3341 ScopeExp *se = new ScopeExp(loc, (ScopeDsymbol *)sds->syntaxCopy(NULL)); | |
3342 return se; | |
3343 } | |
3344 | |
3345 Expression *ScopeExp::semantic(Scope *sc) | |
3346 { | |
3347 TemplateInstance *ti; | |
3348 ScopeDsymbol *sds2; | |
3349 | |
3350 #if LOGSEMANTIC | |
3351 printf("+ScopeExp::semantic('%s')\n", toChars()); | |
3352 #endif | |
3353 Lagain: | |
3354 ti = sds->isTemplateInstance(); | |
3355 if (ti && !global.errors) | |
3356 { Dsymbol *s; | |
3357 if (!ti->semanticdone) | |
3358 ti->semantic(sc); | |
3359 s = ti->inst->toAlias(); | |
3360 sds2 = s->isScopeDsymbol(); | |
3361 if (!sds2) | |
3362 { Expression *e; | |
3363 | |
3364 //printf("s = %s, '%s'\n", s->kind(), s->toChars()); | |
3365 if (ti->withsym) | |
3366 { | |
3367 // Same as wthis.s | |
3368 e = new VarExp(loc, ti->withsym->withstate->wthis); | |
3369 e = new DotVarExp(loc, e, s->isDeclaration()); | |
3370 } | |
3371 else | |
3372 e = new DsymbolExp(loc, s); | |
3373 e = e->semantic(sc); | |
3374 //printf("-1ScopeExp::semantic()\n"); | |
3375 return e; | |
3376 } | |
3377 if (sds2 != sds) | |
3378 { | |
3379 sds = sds2; | |
3380 goto Lagain; | |
3381 } | |
3382 //printf("sds = %s, '%s'\n", sds->kind(), sds->toChars()); | |
3383 } | |
3384 else | |
3385 { | |
3386 //printf("sds = %s, '%s'\n", sds->kind(), sds->toChars()); | |
3387 //printf("\tparent = '%s'\n", sds->parent->toChars()); | |
3388 sds->semantic(sc); | |
3389 } | |
3390 type = Type::tvoid; | |
3391 //printf("-2ScopeExp::semantic() %s\n", toChars()); | |
3392 return this; | |
3393 } | |
3394 | |
3395 void ScopeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3396 { | |
3397 if (sds->isTemplateInstance()) | |
3398 { | |
3399 sds->toCBuffer(buf, hgs); | |
3400 } | |
3401 else | |
3402 { | |
3403 buf->writestring(sds->kind()); | |
3404 buf->writestring(" "); | |
3405 buf->writestring(sds->toChars()); | |
3406 } | |
3407 } | |
3408 | |
3409 /********************** TemplateExp **************************************/ | |
3410 | |
3411 // Mainly just a placeholder | |
3412 | |
3413 TemplateExp::TemplateExp(Loc loc, TemplateDeclaration *td) | |
3414 : Expression(loc, TOKtemplate, sizeof(TemplateExp)) | |
3415 { | |
3416 //printf("TemplateExp(): %s\n", td->toChars()); | |
3417 this->td = td; | |
3418 } | |
3419 | |
3420 void TemplateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3421 { | |
3422 buf->writestring(td->toChars()); | |
3423 } | |
3424 | |
3425 void TemplateExp::rvalue() | |
3426 { | |
3427 error("template %s has no value", toChars()); | |
3428 } | |
3429 | |
3430 /********************** NewExp **************************************/ | |
3431 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3432 /* thisexp.new(newargs) newtype(arguments) */ |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3433 |
159 | 3434 NewExp::NewExp(Loc loc, Expression *thisexp, Expressions *newargs, |
3435 Type *newtype, Expressions *arguments) | |
3436 : Expression(loc, TOKnew, sizeof(NewExp)) | |
3437 { | |
3438 this->thisexp = thisexp; | |
3439 this->newargs = newargs; | |
3440 this->newtype = newtype; | |
3441 this->arguments = arguments; | |
3442 member = NULL; | |
3443 allocator = NULL; | |
3444 onstack = 0; | |
3445 } | |
3446 | |
3447 Expression *NewExp::syntaxCopy() | |
3448 { | |
3449 return new NewExp(loc, | |
3450 thisexp ? thisexp->syntaxCopy() : NULL, | |
3451 arraySyntaxCopy(newargs), | |
3452 newtype->syntaxCopy(), arraySyntaxCopy(arguments)); | |
3453 } | |
3454 | |
3455 | |
3456 Expression *NewExp::semantic(Scope *sc) | |
3457 { int i; | |
3458 Type *tb; | |
3459 ClassDeclaration *cdthis = NULL; | |
3460 | |
3461 #if LOGSEMANTIC | |
3462 printf("NewExp::semantic() %s\n", toChars()); | |
3463 if (thisexp) | |
3464 printf("\tthisexp = %s\n", thisexp->toChars()); | |
3465 printf("\tnewtype: %s\n", newtype->toChars()); | |
3466 #endif | |
3467 if (type) // if semantic() already run | |
3468 return this; | |
3469 | |
3470 Lagain: | |
3471 if (thisexp) | |
3472 { thisexp = thisexp->semantic(sc); | |
3473 cdthis = thisexp->type->isClassHandle(); | |
3474 if (cdthis) | |
3475 { | |
3476 sc = sc->push(cdthis); | |
3477 type = newtype->semantic(loc, sc); | |
3478 sc = sc->pop(); | |
3479 } | |
3480 else | |
3481 { | |
3482 error("'this' for nested class must be a class type, not %s", thisexp->type->toChars()); | |
3483 type = newtype->semantic(loc, sc); | |
3484 } | |
3485 } | |
3486 else | |
3487 type = newtype->semantic(loc, sc); | |
3488 newtype = type; // in case type gets cast to something else | |
3489 tb = type->toBasetype(); | |
3490 //printf("tb: %s, deco = %s\n", tb->toChars(), tb->deco); | |
3491 | |
3492 arrayExpressionSemantic(newargs, sc); | |
3493 preFunctionArguments(loc, sc, newargs); | |
3494 arrayExpressionSemantic(arguments, sc); | |
3495 preFunctionArguments(loc, sc, arguments); | |
3496 | |
3497 if (thisexp && tb->ty != Tclass) | |
3498 error("e.new is only for allocating nested classes, not %s", tb->toChars()); | |
3499 | |
3500 if (tb->ty == Tclass) | |
3501 { TypeFunction *tf; | |
3502 | |
3503 TypeClass *tc = (TypeClass *)(tb); | |
3504 ClassDeclaration *cd = tc->sym->isClassDeclaration(); | |
3505 if (cd->isInterfaceDeclaration()) | |
3506 error("cannot create instance of interface %s", cd->toChars()); | |
3507 else if (cd->isAbstract()) | |
3508 { error("cannot create instance of abstract class %s", cd->toChars()); | |
3509 for (int i = 0; i < cd->vtbl.dim; i++) | |
3510 { FuncDeclaration *fd = ((Dsymbol *)cd->vtbl.data[i])->isFuncDeclaration(); | |
3511 if (fd && fd->isAbstract()) | |
3512 error("function %s is abstract", fd->toChars()); | |
3513 } | |
3514 } | |
3515 checkDeprecated(sc, cd); | |
3516 if (cd->isNested()) | |
3517 { /* We need a 'this' pointer for the nested class. | |
3518 * Ensure we have the right one. | |
3519 */ | |
3520 Dsymbol *s = cd->toParent2(); | |
3521 ClassDeclaration *cdn = s->isClassDeclaration(); | |
639
8aebdf56c455
Move check for access of context for nested class from backend into frontend.
Christian Kamm <kamm incasoftware de>
parents:
599
diff
changeset
|
3522 FuncDeclaration *fdn = s->isFuncDeclaration(); |
159 | 3523 |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
3524 //printf("cd isNested, cdn = %s\n", cdn ? cdn->toChars() : "null"); |
159 | 3525 if (cdn) |
3526 { | |
3527 if (!cdthis) | |
3528 { | |
3529 // Supply an implicit 'this' and try again | |
3530 thisexp = new ThisExp(loc); | |
3531 for (Dsymbol *sp = sc->parent; 1; sp = sp->parent) | |
3532 { if (!sp) | |
3533 { | |
3534 error("outer class %s 'this' needed to 'new' nested class %s", cdn->toChars(), cd->toChars()); | |
3535 break; | |
3536 } | |
3537 ClassDeclaration *cdp = sp->isClassDeclaration(); | |
3538 if (!cdp) | |
3539 continue; | |
3540 if (cdp == cdn || cdn->isBaseOf(cdp, NULL)) | |
3541 break; | |
3542 // Add a '.outer' and try again | |
3543 thisexp = new DotIdExp(loc, thisexp, Id::outer); | |
3544 } | |
3545 if (!global.errors) | |
3546 goto Lagain; | |
3547 } | |
3548 if (cdthis) | |
3549 { | |
3550 //printf("cdthis = %s\n", cdthis->toChars()); | |
3551 if (cdthis != cdn && !cdn->isBaseOf(cdthis, NULL)) | |
3552 error("'this' for nested class must be of type %s, not %s", cdn->toChars(), thisexp->type->toChars()); | |
3553 } | |
3554 #if 0 | |
3555 else | |
3556 { | |
3557 for (Dsymbol *sf = sc->func; 1; sf= sf->toParent2()->isFuncDeclaration()) | |
3558 { | |
3559 if (!sf) | |
3560 { | |
3561 error("outer class %s 'this' needed to 'new' nested class %s", cdn->toChars(), cd->toChars()); | |
3562 break; | |
3563 } | |
3564 printf("sf = %s\n", sf->toChars()); | |
3565 AggregateDeclaration *ad = sf->isThis(); | |
3566 if (ad && (ad == cdn || cdn->isBaseOf(ad->isClassDeclaration(), NULL))) | |
3567 break; | |
3568 } | |
3569 } | |
3570 #endif | |
3571 } | |
3572 else if (thisexp) | |
3573 error("e.new is only for allocating nested classes"); | |
639
8aebdf56c455
Move check for access of context for nested class from backend into frontend.
Christian Kamm <kamm incasoftware de>
parents:
599
diff
changeset
|
3574 else if (fdn) |
8aebdf56c455
Move check for access of context for nested class from backend into frontend.
Christian Kamm <kamm incasoftware de>
parents:
599
diff
changeset
|
3575 { |
8aebdf56c455
Move check for access of context for nested class from backend into frontend.
Christian Kamm <kamm incasoftware de>
parents:
599
diff
changeset
|
3576 // make sure the parent context fdn of cd is reachable from sc |
8aebdf56c455
Move check for access of context for nested class from backend into frontend.
Christian Kamm <kamm incasoftware de>
parents:
599
diff
changeset
|
3577 for (Dsymbol *sp = sc->parent; 1; sp = sp->parent) |
8aebdf56c455
Move check for access of context for nested class from backend into frontend.
Christian Kamm <kamm incasoftware de>
parents:
599
diff
changeset
|
3578 { |
8aebdf56c455
Move check for access of context for nested class from backend into frontend.
Christian Kamm <kamm incasoftware de>
parents:
599
diff
changeset
|
3579 if (fdn == sp) |
8aebdf56c455
Move check for access of context for nested class from backend into frontend.
Christian Kamm <kamm incasoftware de>
parents:
599
diff
changeset
|
3580 break; |
8aebdf56c455
Move check for access of context for nested class from backend into frontend.
Christian Kamm <kamm incasoftware de>
parents:
599
diff
changeset
|
3581 FuncDeclaration *fsp = sp ? sp->isFuncDeclaration() : NULL; |
8aebdf56c455
Move check for access of context for nested class from backend into frontend.
Christian Kamm <kamm incasoftware de>
parents:
599
diff
changeset
|
3582 if (!sp || (fsp && fsp->isStatic())) |
8aebdf56c455
Move check for access of context for nested class from backend into frontend.
Christian Kamm <kamm incasoftware de>
parents:
599
diff
changeset
|
3583 { |
8aebdf56c455
Move check for access of context for nested class from backend into frontend.
Christian Kamm <kamm incasoftware de>
parents:
599
diff
changeset
|
3584 error("outer function context of %s is needed to 'new' nested class %s", fdn->toPrettyChars(), cd->toPrettyChars()); |
8aebdf56c455
Move check for access of context for nested class from backend into frontend.
Christian Kamm <kamm incasoftware de>
parents:
599
diff
changeset
|
3585 break; |
8aebdf56c455
Move check for access of context for nested class from backend into frontend.
Christian Kamm <kamm incasoftware de>
parents:
599
diff
changeset
|
3586 } |
8aebdf56c455
Move check for access of context for nested class from backend into frontend.
Christian Kamm <kamm incasoftware de>
parents:
599
diff
changeset
|
3587 } |
8aebdf56c455
Move check for access of context for nested class from backend into frontend.
Christian Kamm <kamm incasoftware de>
parents:
599
diff
changeset
|
3588 |
8aebdf56c455
Move check for access of context for nested class from backend into frontend.
Christian Kamm <kamm incasoftware de>
parents:
599
diff
changeset
|
3589 } |
159 | 3590 } |
3591 else if (thisexp) | |
3592 error("e.new is only for allocating nested classes"); | |
3593 | |
3594 FuncDeclaration *f = cd->ctor; | |
3595 if (f) | |
3596 { | |
3597 assert(f); | |
3598 f = f->overloadResolve(loc, arguments); | |
3599 checkDeprecated(sc, f); | |
3600 member = f->isCtorDeclaration(); | |
3601 assert(member); | |
3602 | |
3603 cd->accessCheck(loc, sc, member); | |
3604 | |
3605 tf = (TypeFunction *)f->type; | |
3606 type = tf->next; | |
3607 | |
3608 if (!arguments) | |
3609 arguments = new Expressions(); | |
3610 functionArguments(loc, sc, tf, arguments); | |
3611 } | |
3612 else | |
3613 { | |
3614 if (arguments && arguments->dim) | |
3615 error("no constructor for %s", cd->toChars()); | |
3616 } | |
3617 | |
3618 if (cd->aggNew) | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3619 { |
891
ea82e2077f9d
Change custom allocator new size argument to size_t instead of uint. See #175.
Christian Kamm <kamm incasoftware de>
parents:
876
diff
changeset
|
3620 // Prepend the size_t size argument to newargs[] |
ea82e2077f9d
Change custom allocator new size argument to size_t instead of uint. See #175.
Christian Kamm <kamm incasoftware de>
parents:
876
diff
changeset
|
3621 Expression *e = new IntegerExp(loc, cd->size(loc), Type::tsize_t); |
159 | 3622 if (!newargs) |
3623 newargs = new Expressions(); | |
3624 newargs->shift(e); | |
3625 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3626 f = cd->aggNew->overloadResolve(loc, newargs); |
159 | 3627 allocator = f->isNewDeclaration(); |
3628 assert(allocator); | |
3629 | |
3630 tf = (TypeFunction *)f->type; | |
3631 functionArguments(loc, sc, tf, newargs); | |
3632 } | |
3633 else | |
3634 { | |
3635 if (newargs && newargs->dim) | |
3636 error("no allocator for %s", cd->toChars()); | |
3637 } | |
3638 } | |
3639 else if (tb->ty == Tstruct) | |
3640 { | |
3641 TypeStruct *ts = (TypeStruct *)tb; | |
3642 StructDeclaration *sd = ts->sym; | |
3643 FuncDeclaration *f = sd->aggNew; | |
3644 TypeFunction *tf; | |
3645 | |
3646 if (arguments && arguments->dim) | |
3647 error("no constructor for %s", type->toChars()); | |
3648 | |
3649 if (f) | |
3650 { | |
3651 Expression *e; | |
3652 | |
3653 // Prepend the uint size argument to newargs[] | |
3654 e = new IntegerExp(loc, sd->size(loc), Type::tuns32); | |
3655 if (!newargs) | |
3656 newargs = new Expressions(); | |
3657 newargs->shift(e); | |
3658 | |
3659 f = f->overloadResolve(loc, newargs); | |
3660 allocator = f->isNewDeclaration(); | |
3661 assert(allocator); | |
3662 | |
3663 tf = (TypeFunction *)f->type; | |
3664 functionArguments(loc, sc, tf, newargs); | |
3665 | |
3666 e = new VarExp(loc, f); | |
3667 e = new CallExp(loc, e, newargs); | |
3668 e = e->semantic(sc); | |
3669 e->type = type->pointerTo(); | |
3670 return e; | |
3671 } | |
3672 | |
3673 type = type->pointerTo(); | |
3674 } | |
3675 else if (tb->ty == Tarray && (arguments && arguments->dim)) | |
3676 { | |
3677 for (size_t i = 0; i < arguments->dim; i++) | |
3678 { | |
3679 if (tb->ty != Tarray) | |
3680 { error("too many arguments for array"); | |
3681 arguments->dim = i; | |
3682 break; | |
3683 } | |
3684 | |
3685 Expression *arg = (Expression *)arguments->data[i]; | |
3686 arg = resolveProperties(sc, arg); | |
3687 arg = arg->implicitCastTo(sc, Type::tsize_t); | |
3688 if (arg->op == TOKint64 && (long long)arg->toInteger() < 0) | |
3689 error("negative array index %s", arg->toChars()); | |
3690 arguments->data[i] = (void *) arg; | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
3691 tb = ((TypeDArray *)tb)->next->toBasetype(); |
159 | 3692 } |
3693 } | |
3694 else if (tb->isscalar()) | |
3695 { | |
3696 if (arguments && arguments->dim) | |
3697 error("no constructor for %s", type->toChars()); | |
3698 | |
3699 type = type->pointerTo(); | |
3700 } | |
3701 else | |
3702 { | |
3703 error("new can only create structs, dynamic arrays or class objects, not %s's", type->toChars()); | |
3704 type = type->pointerTo(); | |
3705 } | |
3706 | |
3707 //printf("NewExp: '%s'\n", toChars()); | |
3708 //printf("NewExp:type '%s'\n", type->toChars()); | |
3709 | |
3710 return this; | |
3711 } | |
3712 | |
3713 int NewExp::checkSideEffect(int flag) | |
3714 { | |
3715 return 1; | |
3716 } | |
3717 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3718 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3719 int NewExp::canThrow() |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3720 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3721 return 1; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3722 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3723 #endif |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3724 |
159 | 3725 void NewExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
3726 { int i; | |
3727 | |
3728 if (thisexp) | |
3729 { expToCBuffer(buf, hgs, thisexp, PREC_primary); | |
3730 buf->writeByte('.'); | |
3731 } | |
3732 buf->writestring("new "); | |
3733 if (newargs && newargs->dim) | |
3734 { | |
3735 buf->writeByte('('); | |
3736 argsToCBuffer(buf, newargs, hgs); | |
3737 buf->writeByte(')'); | |
3738 } | |
3739 newtype->toCBuffer(buf, NULL, hgs); | |
3740 if (arguments && arguments->dim) | |
3741 { | |
3742 buf->writeByte('('); | |
3743 argsToCBuffer(buf, arguments, hgs); | |
3744 buf->writeByte(')'); | |
3745 } | |
3746 } | |
3747 | |
3748 /********************** NewAnonClassExp **************************************/ | |
3749 | |
3750 NewAnonClassExp::NewAnonClassExp(Loc loc, Expression *thisexp, | |
3751 Expressions *newargs, ClassDeclaration *cd, Expressions *arguments) | |
3752 : Expression(loc, TOKnewanonclass, sizeof(NewAnonClassExp)) | |
3753 { | |
3754 this->thisexp = thisexp; | |
3755 this->newargs = newargs; | |
3756 this->cd = cd; | |
3757 this->arguments = arguments; | |
3758 } | |
3759 | |
3760 Expression *NewAnonClassExp::syntaxCopy() | |
3761 { | |
3762 return new NewAnonClassExp(loc, | |
3763 thisexp ? thisexp->syntaxCopy() : NULL, | |
3764 arraySyntaxCopy(newargs), | |
3765 (ClassDeclaration *)cd->syntaxCopy(NULL), | |
3766 arraySyntaxCopy(arguments)); | |
3767 } | |
3768 | |
3769 | |
3770 Expression *NewAnonClassExp::semantic(Scope *sc) | |
3771 { | |
3772 #if LOGSEMANTIC | |
3773 printf("NewAnonClassExp::semantic() %s\n", toChars()); | |
336 | 3774 //printf("thisexp = %p\n", thisexp); |
159 | 3775 //printf("type: %s\n", type->toChars()); |
3776 #endif | |
3777 | |
3778 Expression *d = new DeclarationExp(loc, cd); | |
3779 d = d->semantic(sc); | |
3780 | |
3781 Expression *n = new NewExp(loc, thisexp, newargs, cd->type, arguments); | |
3782 | |
3783 Expression *c = new CommaExp(loc, d, n); | |
3784 return c->semantic(sc); | |
3785 } | |
3786 | |
3787 int NewAnonClassExp::checkSideEffect(int flag) | |
3788 { | |
3789 return 1; | |
3790 } | |
3791 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3792 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3793 int NewAnonClassExp::canThrow() |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3794 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3795 return 1; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3796 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3797 #endif |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3798 |
159 | 3799 void NewAnonClassExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
3800 { int i; | |
3801 | |
3802 if (thisexp) | |
3803 { expToCBuffer(buf, hgs, thisexp, PREC_primary); | |
3804 buf->writeByte('.'); | |
3805 } | |
3806 buf->writestring("new"); | |
3807 if (newargs && newargs->dim) | |
3808 { | |
3809 buf->writeByte('('); | |
3810 argsToCBuffer(buf, newargs, hgs); | |
3811 buf->writeByte(')'); | |
3812 } | |
3813 buf->writestring(" class "); | |
3814 if (arguments && arguments->dim) | |
3815 { | |
3816 buf->writeByte('('); | |
3817 argsToCBuffer(buf, arguments, hgs); | |
3818 buf->writeByte(')'); | |
3819 } | |
3820 //buf->writestring(" { }"); | |
3821 if (cd) | |
3822 { | |
3823 cd->toCBuffer(buf, hgs); | |
3824 } | |
3825 } | |
3826 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3827 /********************** SymbolExp **************************************/ |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3828 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3829 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3830 SymbolExp::SymbolExp(Loc loc, enum TOK op, int size, Declaration *var, int hasOverloads) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3831 : Expression(loc, op, size) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3832 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3833 assert(var); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3834 this->var = var; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3835 this->hasOverloads = hasOverloads; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3836 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3837 #endif |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3838 |
159 | 3839 /********************** SymOffExp **************************************/ |
3840 | |
3841 SymOffExp::SymOffExp(Loc loc, Declaration *var, unsigned offset) | |
3842 : Expression(loc, TOKsymoff, sizeof(SymOffExp)) | |
3843 { | |
3844 assert(var); | |
3845 this->var = var; | |
3846 this->offset = offset; | |
3847 VarDeclaration *v = var->isVarDeclaration(); | |
3848 if (v && v->needThis()) | |
3849 error("need 'this' for address of %s", v->toChars()); | |
3850 } | |
3851 | |
3852 Expression *SymOffExp::semantic(Scope *sc) | |
3853 { | |
3854 #if LOGSEMANTIC | |
3855 printf("SymOffExp::semantic('%s')\n", toChars()); | |
3856 #endif | |
3857 //var->semantic(sc); | |
3858 if (!type) | |
3859 type = var->type->pointerTo(); | |
3860 VarDeclaration *v = var->isVarDeclaration(); | |
3861 if (v) | |
3862 { | |
3863 v->checkNestedReference(sc, loc); | |
3864 } | |
3865 return this; | |
3866 } | |
3867 | |
3868 int SymOffExp::isBool(int result) | |
3869 { | |
3870 return result ? TRUE : FALSE; | |
3871 } | |
3872 | |
3873 void SymOffExp::checkEscape() | |
3874 { | |
3875 VarDeclaration *v = var->isVarDeclaration(); | |
3876 if (v) | |
3877 { | |
3878 if (!v->isDataseg()) | |
3879 error("escaping reference to local variable %s", v->toChars()); | |
3880 } | |
3881 } | |
3882 | |
3883 void SymOffExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3884 { | |
3885 if (offset) | |
3886 buf->printf("(& %s+%u)", var->toChars(), offset); | |
3887 else | |
3888 buf->printf("& %s", var->toChars()); | |
3889 } | |
3890 | |
3891 /******************************** VarExp **************************/ | |
3892 | |
3893 VarExp::VarExp(Loc loc, Declaration *var) | |
3894 : Expression(loc, TOKvar, sizeof(VarExp)) | |
3895 { | |
3896 //printf("VarExp(this = %p, '%s')\n", this, var->toChars()); | |
3897 this->var = var; | |
3898 this->type = var->type; | |
3899 } | |
3900 | |
3901 int VarExp::equals(Object *o) | |
3902 { VarExp *ne; | |
3903 | |
3904 if (this == o || | |
3905 (((Expression *)o)->op == TOKvar && | |
3906 ((ne = (VarExp *)o), type->equals(ne->type)) && | |
3907 var == ne->var)) | |
3908 return 1; | |
3909 return 0; | |
3910 } | |
3911 | |
3912 Expression *VarExp::semantic(Scope *sc) | |
3913 { FuncLiteralDeclaration *fd; | |
3914 | |
3915 #if LOGSEMANTIC | |
3916 printf("VarExp::semantic(%s)\n", toChars()); | |
3917 #endif | |
3918 if (!type) | |
3919 { type = var->type; | |
3920 #if 0 | |
3921 if (var->storage_class & STClazy) | |
3922 { | |
3923 TypeFunction *tf = new TypeFunction(NULL, type, 0, LINKd); | |
3924 type = new TypeDelegate(tf); | |
3925 type = type->semantic(loc, sc); | |
3926 } | |
3927 #endif | |
3928 } | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3929 /* Fix for 1161 doesn't work because it causes protection |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3930 * problems when instantiating imported templates passing private |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3931 * variables as alias template parameters. |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3932 */ |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3933 //accessCheck(loc, sc, NULL, var); |
159 | 3934 |
3935 VarDeclaration *v = var->isVarDeclaration(); | |
3936 if (v) | |
3937 { | |
3938 if (v->isConst() && type->toBasetype()->ty != Tsarray && v->init) | |
3939 { | |
3940 ExpInitializer *ei = v->init->isExpInitializer(); | |
3941 if (ei) | |
3942 { | |
3943 //ei->exp->implicitCastTo(sc, type)->print(); | |
3944 return ei->exp->implicitCastTo(sc, type); | |
3945 } | |
3946 } | |
3947 v->checkNestedReference(sc, loc); | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3948 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3949 if (sc->func && sc->func->isPure() && !sc->intypeof) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3950 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3951 if (v->isDataseg() && !v->isInvariant()) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3952 error("pure function '%s' cannot access mutable static data '%s'", sc->func->toChars(), v->toChars()); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3953 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3954 #endif |
159 | 3955 } |
3956 #if 0 | |
3957 else if ((fd = var->isFuncLiteralDeclaration()) != NULL) | |
3958 { Expression *e; | |
3959 e = new FuncExp(loc, fd); | |
3960 e->type = type; | |
3961 return e; | |
3962 } | |
3963 #endif | |
3964 return this; | |
3965 } | |
3966 | |
3967 char *VarExp::toChars() | |
3968 { | |
3969 return var->toChars(); | |
3970 } | |
3971 | |
3972 void VarExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3973 { | |
3974 buf->writestring(var->toChars()); | |
3975 } | |
3976 | |
3977 void VarExp::checkEscape() | |
3978 { | |
3979 VarDeclaration *v = var->isVarDeclaration(); | |
3980 if (v) | |
3981 { Type *tb = v->type->toBasetype(); | |
3982 // if reference type | |
3983 if (tb->ty == Tarray || tb->ty == Tsarray || tb->ty == Tclass) | |
3984 { | |
3985 if ((v->isAuto() || v->isScope()) && !v->noauto) | |
3986 error("escaping reference to auto local %s", v->toChars()); | |
3987 else if (v->storage_class & STCvariadic) | |
3988 error("escaping reference to variadic parameter %s", v->toChars()); | |
3989 } | |
3990 } | |
3991 } | |
3992 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3993 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3994 int VarExp::isLvalue() |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3995 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3996 if (var->storage_class & STClazy) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3997 return 0; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3998 return 1; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
3999 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
4000 #endif |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
4001 |
159 | 4002 Expression *VarExp::toLvalue(Scope *sc, Expression *e) |
4003 { | |
4004 #if 0 | |
4005 tym = tybasic(e1->ET->Tty); | |
4006 if (!(tyscalar(tym) || | |
4007 tym == TYstruct || | |
4008 tym == TYarray && e->Eoper == TOKaddr)) | |
4009 synerr(EM_lvalue); // lvalue expected | |
4010 #endif | |
4011 if (var->storage_class & STClazy) | |
4012 error("lazy variables cannot be lvalues"); | |
4013 return this; | |
4014 } | |
4015 | |
4016 Expression *VarExp::modifiableLvalue(Scope *sc, Expression *e) | |
4017 { | |
4018 //printf("VarExp::modifiableLvalue('%s')\n", var->toChars()); | |
4019 if (sc->incontract && var->isParameter()) | |
4020 error("cannot modify parameter '%s' in contract", var->toChars()); | |
4021 | |
4022 if (type && type->toBasetype()->ty == Tsarray) | |
4023 error("cannot change reference to static array '%s'", var->toChars()); | |
4024 | |
4025 VarDeclaration *v = var->isVarDeclaration(); | |
4026 if (v && v->canassign == 0 && | |
4027 (var->isConst() || (global.params.Dversion > 1 && var->isFinal()))) | |
4028 error("cannot modify final variable '%s'", var->toChars()); | |
4029 | |
4030 if (var->isCtorinit()) | |
4031 { // It's only modifiable if inside the right constructor | |
4032 Dsymbol *s = sc->func; | |
4033 while (1) | |
4034 { | |
4035 FuncDeclaration *fd = NULL; | |
4036 if (s) | |
4037 fd = s->isFuncDeclaration(); | |
4038 if (fd && | |
4039 ((fd->isCtorDeclaration() && var->storage_class & STCfield) || | |
4040 (fd->isStaticCtorDeclaration() && !(var->storage_class & STCfield))) && | |
4041 fd->toParent() == var->toParent() | |
4042 ) | |
4043 { | |
4044 VarDeclaration *v = var->isVarDeclaration(); | |
4045 assert(v); | |
4046 v->ctorinit = 1; | |
4047 //printf("setting ctorinit\n"); | |
4048 } | |
4049 else | |
4050 { | |
4051 if (s) | |
4052 { s = s->toParent2(); | |
4053 continue; | |
4054 } | |
4055 else | |
4056 { | |
4057 const char *p = var->isStatic() ? "static " : ""; | |
4058 error("can only initialize %sconst %s inside %sconstructor", | |
4059 p, var->toChars(), p); | |
4060 } | |
4061 } | |
4062 break; | |
4063 } | |
4064 } | |
4065 | |
4066 // See if this expression is a modifiable lvalue (i.e. not const) | |
4067 return toLvalue(sc, e); | |
4068 } | |
4069 | |
4070 | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4071 /******************************** OverExp **************************/ |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4072 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4073 #if DMDV2 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4074 OverExp::OverExp(OverloadSet *s) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4075 : Expression(loc, TOKoverloadset, sizeof(OverExp)) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4076 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4077 //printf("OverExp(this = %p, '%s')\n", this, var->toChars()); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4078 vars = s; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4079 type = Type::tvoid; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4080 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4081 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4082 int OverExp::isLvalue() |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4083 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4084 return 1; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4085 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4086 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4087 Expression *OverExp::toLvalue(Scope *sc, Expression *e) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4088 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4089 return this; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4090 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4091 #endif |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4092 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4093 |
159 | 4094 /******************************** TupleExp **************************/ |
4095 | |
4096 TupleExp::TupleExp(Loc loc, Expressions *exps) | |
4097 : Expression(loc, TOKtuple, sizeof(TupleExp)) | |
4098 { | |
4099 //printf("TupleExp(this = %p)\n", this); | |
4100 this->exps = exps; | |
4101 this->type = NULL; | |
4102 } | |
4103 | |
4104 | |
4105 TupleExp::TupleExp(Loc loc, TupleDeclaration *tup) | |
4106 : Expression(loc, TOKtuple, sizeof(TupleExp)) | |
4107 { | |
4108 exps = new Expressions(); | |
4109 type = NULL; | |
4110 | |
4111 exps->reserve(tup->objects->dim); | |
4112 for (size_t i = 0; i < tup->objects->dim; i++) | |
4113 { Object *o = (Object *)tup->objects->data[i]; | |
4114 if (o->dyncast() == DYNCAST_EXPRESSION) | |
4115 { | |
4116 Expression *e = (Expression *)o; | |
4117 e = e->syntaxCopy(); | |
4118 exps->push(e); | |
4119 } | |
4120 else if (o->dyncast() == DYNCAST_DSYMBOL) | |
4121 { | |
4122 Dsymbol *s = (Dsymbol *)o; | |
4123 Expression *e = new DsymbolExp(loc, s); | |
4124 exps->push(e); | |
4125 } | |
4126 else if (o->dyncast() == DYNCAST_TYPE) | |
4127 { | |
4128 Type *t = (Type *)o; | |
4129 Expression *e = new TypeExp(loc, t); | |
4130 exps->push(e); | |
4131 } | |
4132 else | |
4133 { | |
4134 error("%s is not an expression", o->toChars()); | |
4135 } | |
4136 } | |
4137 } | |
4138 | |
4139 int TupleExp::equals(Object *o) | |
4140 { TupleExp *ne; | |
4141 | |
4142 if (this == o) | |
4143 return 1; | |
4144 if (((Expression *)o)->op == TOKtuple) | |
4145 { | |
4146 TupleExp *te = (TupleExp *)o; | |
4147 if (exps->dim != te->exps->dim) | |
4148 return 0; | |
4149 for (size_t i = 0; i < exps->dim; i++) | |
4150 { Expression *e1 = (Expression *)exps->data[i]; | |
4151 Expression *e2 = (Expression *)te->exps->data[i]; | |
4152 | |
4153 if (!e1->equals(e2)) | |
4154 return 0; | |
4155 } | |
4156 return 1; | |
4157 } | |
4158 return 0; | |
4159 } | |
4160 | |
4161 Expression *TupleExp::syntaxCopy() | |
4162 { | |
4163 return new TupleExp(loc, arraySyntaxCopy(exps)); | |
4164 } | |
4165 | |
4166 Expression *TupleExp::semantic(Scope *sc) | |
4167 { | |
4168 #if LOGSEMANTIC | |
4169 printf("+TupleExp::semantic(%s)\n", toChars()); | |
4170 #endif | |
4171 if (type) | |
4172 return this; | |
4173 | |
4174 // Run semantic() on each argument | |
4175 for (size_t i = 0; i < exps->dim; i++) | |
4176 { Expression *e = (Expression *)exps->data[i]; | |
4177 | |
4178 e = e->semantic(sc); | |
4179 if (!e->type) | |
4180 { error("%s has no value", e->toChars()); | |
4181 e->type = Type::terror; | |
4182 } | |
4183 exps->data[i] = (void *)e; | |
4184 } | |
4185 | |
4186 expandTuples(exps); | |
4187 if (0 && exps->dim == 1) | |
4188 { | |
4189 return (Expression *)exps->data[0]; | |
4190 } | |
4191 type = new TypeTuple(exps); | |
4192 //printf("-TupleExp::semantic(%s)\n", toChars()); | |
4193 return this; | |
4194 } | |
4195 | |
4196 void TupleExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
4197 { | |
4198 buf->writestring("tuple("); | |
4199 argsToCBuffer(buf, exps, hgs); | |
4200 buf->writeByte(')'); | |
4201 } | |
4202 | |
4203 int TupleExp::checkSideEffect(int flag) | |
4204 { int f = 0; | |
4205 | |
4206 for (int i = 0; i < exps->dim; i++) | |
4207 { Expression *e = (Expression *)exps->data[i]; | |
4208 | |
4209 f |= e->checkSideEffect(2); | |
4210 } | |
4211 if (flag == 0 && f == 0) | |
4212 Expression::checkSideEffect(0); | |
4213 return f; | |
4214 } | |
4215 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
4216 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
4217 int TupleExp::canThrow() |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
4218 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
4219 return arrayExpressionCanThrow(exps); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
4220 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
4221 #endif |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
4222 |
159 | 4223 void TupleExp::checkEscape() |
4224 { | |
4225 for (size_t i = 0; i < exps->dim; i++) | |
4226 { Expression *e = (Expression *)exps->data[i]; | |
4227 e->checkEscape(); | |
4228 } | |
4229 } | |
4230 | |
4231 /******************************** FuncExp *********************************/ | |
4232 | |
4233 FuncExp::FuncExp(Loc loc, FuncLiteralDeclaration *fd) | |
4234 : Expression(loc, TOKfunction, sizeof(FuncExp)) | |
4235 { | |
4236 this->fd = fd; | |
4237 } | |
4238 | |
4239 Expression *FuncExp::syntaxCopy() | |
4240 { | |
4241 return new FuncExp(loc, (FuncLiteralDeclaration *)fd->syntaxCopy(NULL)); | |
4242 } | |
4243 | |
4244 Expression *FuncExp::semantic(Scope *sc) | |
4245 { | |
4246 #if LOGSEMANTIC | |
4247 printf("FuncExp::semantic(%s)\n", toChars()); | |
4248 #endif | |
4249 if (!type) | |
4250 { | |
4251 fd->semantic(sc); | |
4252 fd->parent = sc->parent; | |
4253 if (global.errors) | |
4254 { | |
4255 if (!fd->type->next) | |
4256 fd->type->next = Type::terror; | |
4257 } | |
4258 else | |
4259 { | |
4260 fd->semantic2(sc); | |
4261 if (!global.errors) | |
4262 { | |
4263 fd->semantic3(sc); | |
4264 | |
4265 if (!global.errors && global.params.useInline) | |
4266 fd->inlineScan(); | |
4267 } | |
4268 } | |
4269 | |
4270 // Type is a "delegate to" or "pointer to" the function literal | |
4271 if (fd->isNested()) | |
4272 { | |
4273 type = new TypeDelegate(fd->type); | |
4274 type = type->semantic(loc, sc); | |
4275 } | |
4276 else | |
4277 { | |
4278 type = fd->type->pointerTo(); | |
4279 } | |
4280 } | |
4281 return this; | |
4282 } | |
4283 | |
4284 char *FuncExp::toChars() | |
4285 { | |
4286 return fd->toChars(); | |
4287 } | |
4288 | |
4289 void FuncExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
4290 { | |
4291 buf->writestring(fd->toChars()); | |
4292 } | |
4293 | |
4294 | |
4295 /******************************** DeclarationExp **************************/ | |
4296 | |
4297 DeclarationExp::DeclarationExp(Loc loc, Dsymbol *declaration) | |
4298 : Expression(loc, TOKdeclaration, sizeof(DeclarationExp)) | |
4299 { | |
4300 this->declaration = declaration; | |
4301 } | |
4302 | |
4303 Expression *DeclarationExp::syntaxCopy() | |
4304 { | |
4305 return new DeclarationExp(loc, declaration->syntaxCopy(NULL)); | |
4306 } | |
4307 | |
4308 Expression *DeclarationExp::semantic(Scope *sc) | |
4309 { | |
4310 if (type) | |
4311 return this; | |
4312 | |
4313 #if LOGSEMANTIC | |
4314 printf("DeclarationExp::semantic() %s\n", toChars()); | |
4315 #endif | |
4316 | |
4317 /* This is here to support extern(linkage) declaration, | |
4318 * where the extern(linkage) winds up being an AttribDeclaration | |
4319 * wrapper. | |
4320 */ | |
4321 Dsymbol *s = declaration; | |
4322 | |
4323 AttribDeclaration *ad = declaration->isAttribDeclaration(); | |
4324 if (ad) | |
4325 { | |
4326 if (ad->decl && ad->decl->dim == 1) | |
4327 s = (Dsymbol *)ad->decl->data[0]; | |
4328 } | |
4329 | |
4330 if (s->isVarDeclaration()) | |
4331 { // Do semantic() on initializer first, so: | |
4332 // int a = a; | |
4333 // will be illegal. | |
4334 declaration->semantic(sc); | |
4335 s->parent = sc->parent; | |
4336 } | |
4337 | |
4338 //printf("inserting '%s' %p into sc = %p\n", s->toChars(), s, sc); | |
4339 // Insert into both local scope and function scope. | |
4340 // Must be unique in both. | |
4341 if (s->ident) | |
4342 { | |
4343 if (!sc->insert(s)) | |
4344 error("declaration %s is already defined", s->toPrettyChars()); | |
4345 else if (sc->func) | |
4346 { VarDeclaration *v = s->isVarDeclaration(); | |
4347 if ((s->isFuncDeclaration() /*|| v && v->storage_class & STCstatic*/) && | |
4348 !sc->func->localsymtab->insert(s)) | |
4349 error("declaration %s is already defined in another scope in %s", s->toPrettyChars(), sc->func->toChars()); | |
4350 else if (!global.params.useDeprecated) | |
4351 { // Disallow shadowing | |
4352 | |
4353 for (Scope *scx = sc->enclosing; scx && scx->func == sc->func; scx = scx->enclosing) | |
4354 { Dsymbol *s2; | |
4355 | |
4356 if (scx->scopesym && scx->scopesym->symtab && | |
4357 (s2 = scx->scopesym->symtab->lookup(s->ident)) != NULL && | |
4358 s != s2) | |
4359 { | |
4360 error("shadowing declaration %s is deprecated", s->toPrettyChars()); | |
4361 } | |
4362 } | |
4363 } | |
4364 } | |
4365 } | |
4366 if (!s->isVarDeclaration()) | |
4367 { | |
4368 declaration->semantic(sc); | |
4369 s->parent = sc->parent; | |
4370 } | |
4371 if (!global.errors) | |
4372 { | |
4373 declaration->semantic2(sc); | |
4374 if (!global.errors) | |
4375 { | |
4376 declaration->semantic3(sc); | |
4377 | |
4378 if (!global.errors && global.params.useInline) | |
4379 declaration->inlineScan(); | |
4380 } | |
4381 } | |
4382 | |
4383 type = Type::tvoid; | |
4384 return this; | |
4385 } | |
4386 | |
4387 int DeclarationExp::checkSideEffect(int flag) | |
4388 { | |
4389 return 1; | |
4390 } | |
4391 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
4392 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
4393 int DeclarationExp::canThrow() |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
4394 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
4395 VarDeclaration *v = declaration->isVarDeclaration(); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
4396 if (v && v->init) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
4397 { ExpInitializer *ie = v->init->isExpInitializer(); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
4398 return ie && ie->exp->canThrow(); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
4399 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
4400 return 0; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
4401 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
4402 #endif |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
4403 |
159 | 4404 void DeclarationExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
4405 { | |
4406 declaration->toCBuffer(buf, hgs); | |
4407 } | |
4408 | |
4409 | |
4410 /************************ TypeidExp ************************************/ | |
4411 | |
4412 /* | |
4413 * typeid(int) | |
4414 */ | |
4415 | |
4416 TypeidExp::TypeidExp(Loc loc, Type *typeidType) | |
4417 : Expression(loc, TOKtypeid, sizeof(TypeidExp)) | |
4418 { | |
4419 this->typeidType = typeidType; | |
4420 } | |
4421 | |
4422 | |
4423 Expression *TypeidExp::syntaxCopy() | |
4424 { | |
4425 return new TypeidExp(loc, typeidType->syntaxCopy()); | |
4426 } | |
4427 | |
4428 | |
4429 Expression *TypeidExp::semantic(Scope *sc) | |
4430 { Expression *e; | |
4431 | |
4432 #if LOGSEMANTIC | |
4433 printf("TypeidExp::semantic()\n"); | |
4434 #endif | |
4435 typeidType = typeidType->semantic(loc, sc); | |
4436 e = typeidType->getTypeInfo(sc); | |
336 | 4437 if (e->loc.linnum == 0) |
4438 e->loc = loc; // so there's at least some line number info | |
159 | 4439 return e; |
4440 } | |
4441 | |
4442 void TypeidExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
4443 { | |
4444 buf->writestring("typeid("); | |
4445 typeidType->toCBuffer(buf, NULL, hgs); | |
4446 buf->writeByte(')'); | |
4447 } | |
4448 | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4449 /************************ TraitsExp ************************************/ |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4450 #if DMDV2 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4451 /* |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4452 * __traits(identifier, args...) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4453 */ |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4454 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4455 TraitsExp::TraitsExp(Loc loc, Identifier *ident, Objects *args) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4456 : Expression(loc, TOKtraits, sizeof(TraitsExp)) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4457 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4458 this->ident = ident; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4459 this->args = args; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4460 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4461 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4462 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4463 Expression *TraitsExp::syntaxCopy() |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4464 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4465 return new TraitsExp(loc, ident, TemplateInstance::arraySyntaxCopy(args)); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4466 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4467 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4468 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4469 void TraitsExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4470 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4471 buf->writestring("__traits("); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4472 buf->writestring(ident->toChars()); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4473 if (args) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4474 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4475 for (int i = 0; i < args->dim; i++) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4476 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4477 buf->writeByte(','); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4478 Object *oarg = (Object *)args->data[i]; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4479 ObjectToCBuffer(buf, hgs, oarg); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4480 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4481 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4482 buf->writeByte(')'); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4483 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4484 #endif |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4485 |
159 | 4486 /************************************************************/ |
4487 | |
4488 HaltExp::HaltExp(Loc loc) | |
4489 : Expression(loc, TOKhalt, sizeof(HaltExp)) | |
4490 { | |
4491 } | |
4492 | |
4493 Expression *HaltExp::semantic(Scope *sc) | |
4494 { | |
4495 #if LOGSEMANTIC | |
4496 printf("HaltExp::semantic()\n"); | |
4497 #endif | |
4498 type = Type::tvoid; | |
4499 return this; | |
4500 } | |
4501 | |
4502 int HaltExp::checkSideEffect(int flag) | |
4503 { | |
4504 return 1; | |
4505 } | |
4506 | |
4507 void HaltExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
4508 { | |
4509 buf->writestring("halt"); | |
4510 } | |
4511 | |
4512 /************************************************************/ | |
4513 | |
4514 IsExp::IsExp(Loc loc, Type *targ, Identifier *id, enum TOK tok, | |
4515 Type *tspec, enum TOK tok2) | |
4516 : Expression(loc, TOKis, sizeof(IsExp)) | |
4517 { | |
4518 this->targ = targ; | |
4519 this->id = id; | |
4520 this->tok = tok; | |
4521 this->tspec = tspec; | |
4522 this->tok2 = tok2; | |
4523 } | |
4524 | |
4525 Expression *IsExp::syntaxCopy() | |
4526 { | |
4527 return new IsExp(loc, | |
4528 targ->syntaxCopy(), | |
4529 id, | |
4530 tok, | |
4531 tspec ? tspec->syntaxCopy() : NULL, | |
4532 tok2); | |
4533 } | |
4534 | |
4535 Expression *IsExp::semantic(Scope *sc) | |
4536 { Type *tded; | |
4537 | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4538 /* is(targ id tok tspec) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4539 * is(targ id == tok2) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4540 */ |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4541 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4542 //printf("IsExp::semantic(%s)\n", toChars()); |
159 | 4543 if (id && !(sc->flags & SCOPEstaticif)) |
4544 error("can only declare type aliases within static if conditionals"); | |
4545 | |
4546 unsigned errors_save = global.errors; | |
4547 global.errors = 0; | |
4548 global.gag++; // suppress printing of error messages | |
4549 targ = targ->semantic(loc, sc); | |
4550 global.gag--; | |
4551 unsigned gerrors = global.errors; | |
4552 global.errors = errors_save; | |
4553 | |
4554 if (gerrors) // if any errors happened | |
4555 { // then condition is false | |
4556 goto Lno; | |
4557 } | |
4558 else if (tok2 != TOKreserved) | |
4559 { | |
4560 switch (tok2) | |
4561 { | |
4562 case TOKtypedef: | |
4563 if (targ->ty != Ttypedef) | |
4564 goto Lno; | |
4565 tded = ((TypeTypedef *)targ)->sym->basetype; | |
4566 break; | |
4567 | |
4568 case TOKstruct: | |
4569 if (targ->ty != Tstruct) | |
4570 goto Lno; | |
4571 if (((TypeStruct *)targ)->sym->isUnionDeclaration()) | |
4572 goto Lno; | |
4573 tded = targ; | |
4574 break; | |
4575 | |
4576 case TOKunion: | |
4577 if (targ->ty != Tstruct) | |
4578 goto Lno; | |
4579 if (!((TypeStruct *)targ)->sym->isUnionDeclaration()) | |
4580 goto Lno; | |
4581 tded = targ; | |
4582 break; | |
4583 | |
4584 case TOKclass: | |
4585 if (targ->ty != Tclass) | |
4586 goto Lno; | |
4587 if (((TypeClass *)targ)->sym->isInterfaceDeclaration()) | |
4588 goto Lno; | |
4589 tded = targ; | |
4590 break; | |
4591 | |
4592 case TOKinterface: | |
4593 if (targ->ty != Tclass) | |
4594 goto Lno; | |
4595 if (!((TypeClass *)targ)->sym->isInterfaceDeclaration()) | |
4596 goto Lno; | |
4597 tded = targ; | |
4598 break; | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4599 #if DMDV2 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4600 case TOKconst: |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4601 if (!targ->isConst()) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4602 goto Lno; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4603 tded = targ; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4604 break; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4605 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4606 case TOKinvariant: |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
4607 case TOKimmutable: |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4608 if (!targ->isInvariant()) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4609 goto Lno; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4610 tded = targ; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4611 break; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4612 #endif |
159 | 4613 |
4614 case TOKsuper: | |
4615 // If class or interface, get the base class and interfaces | |
4616 if (targ->ty != Tclass) | |
4617 goto Lno; | |
4618 else | |
4619 { ClassDeclaration *cd = ((TypeClass *)targ)->sym; | |
4620 Arguments *args = new Arguments; | |
4621 args->reserve(cd->baseclasses.dim); | |
4622 for (size_t i = 0; i < cd->baseclasses.dim; i++) | |
4623 { BaseClass *b = (BaseClass *)cd->baseclasses.data[i]; | |
4624 args->push(new Argument(STCin, b->type, NULL, NULL)); | |
4625 } | |
4626 tded = new TypeTuple(args); | |
4627 } | |
4628 break; | |
4629 | |
4630 case TOKenum: | |
4631 if (targ->ty != Tenum) | |
4632 goto Lno; | |
4633 tded = ((TypeEnum *)targ)->sym->memtype; | |
4634 break; | |
4635 | |
4636 case TOKdelegate: | |
4637 if (targ->ty != Tdelegate) | |
4638 goto Lno; | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4639 tded = ((TypeDelegate *)targ)->next; // the underlying function type |
159 | 4640 break; |
4641 | |
4642 case TOKfunction: | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4643 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4644 if (targ->ty != Tfunction) |
159 | 4645 goto Lno; |
4646 tded = targ; | |
4647 | |
4648 /* Generate tuple from function parameter types. | |
4649 */ | |
4650 assert(tded->ty == Tfunction); | |
4651 Arguments *params = ((TypeFunction *)tded)->parameters; | |
4652 size_t dim = Argument::dim(params); | |
4653 Arguments *args = new Arguments; | |
4654 args->reserve(dim); | |
4655 for (size_t i = 0; i < dim; i++) | |
4656 { Argument *arg = Argument::getNth(params, i); | |
4657 assert(arg && arg->type); | |
4658 args->push(new Argument(arg->storageClass, arg->type, NULL, NULL)); | |
4659 } | |
4660 tded = new TypeTuple(args); | |
4661 break; | |
4662 } | |
4663 case TOKreturn: | |
4664 /* Get the 'return type' for the function, | |
4665 * delegate, or pointer to function. | |
4666 */ | |
4667 if (targ->ty == Tfunction) | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4668 tded = ((TypeFunction *)targ)->next; |
159 | 4669 else if (targ->ty == Tdelegate) |
4670 tded = targ->next->next; | |
4671 else if (targ->ty == Tpointer && targ->next->ty == Tfunction) | |
4672 tded = targ->next->next; | |
4673 else | |
4674 goto Lno; | |
4675 break; | |
4676 | |
4677 default: | |
4678 assert(0); | |
4679 } | |
4680 goto Lyes; | |
4681 } | |
4682 else if (id && tspec) | |
4683 { | |
4684 /* Evaluate to TRUE if targ matches tspec. | |
4685 * If TRUE, declare id as an alias for the specialized type. | |
4686 */ | |
4687 | |
4688 MATCH m; | |
4689 TemplateTypeParameter tp(loc, id, NULL, NULL); | |
4690 | |
4691 TemplateParameters parameters; | |
4692 parameters.setDim(1); | |
4693 parameters.data[0] = (void *)&tp; | |
4694 | |
4695 Objects dedtypes; | |
4696 dedtypes.setDim(1); | |
4697 dedtypes.data[0] = NULL; | |
4698 | |
4699 m = targ->deduceType(NULL, tspec, ¶meters, &dedtypes); | |
4700 if (m == MATCHnomatch || | |
4701 (m != MATCHexact && tok == TOKequal)) | |
4702 goto Lno; | |
4703 else | |
4704 { | |
4705 assert(dedtypes.dim == 1); | |
4706 tded = (Type *)dedtypes.data[0]; | |
4707 if (!tded) | |
4708 tded = targ; | |
4709 goto Lyes; | |
4710 } | |
4711 } | |
4712 else if (id) | |
4713 { | |
4714 /* Declare id as an alias for type targ. Evaluate to TRUE | |
4715 */ | |
4716 tded = targ; | |
4717 goto Lyes; | |
4718 } | |
4719 else if (tspec) | |
4720 { | |
4721 /* Evaluate to TRUE if targ matches tspec | |
4722 */ | |
4723 tspec = tspec->semantic(loc, sc); | |
4724 //printf("targ = %s\n", targ->toChars()); | |
4725 //printf("tspec = %s\n", tspec->toChars()); | |
4726 if (tok == TOKcolon) | |
4727 { if (targ->implicitConvTo(tspec)) | |
4728 goto Lyes; | |
4729 else | |
4730 goto Lno; | |
4731 } | |
4732 else /* == */ | |
4733 { if (targ->equals(tspec)) | |
4734 goto Lyes; | |
4735 else | |
4736 goto Lno; | |
4737 } | |
4738 } | |
4739 | |
4740 Lyes: | |
4741 if (id) | |
4742 { | |
4743 Dsymbol *s = new AliasDeclaration(loc, id, tded); | |
4744 s->semantic(sc); | |
4745 sc->insert(s); | |
4746 if (sc->sd) | |
4747 s->addMember(sc, sc->sd, 1); | |
4748 } | |
4749 return new IntegerExp(1); | |
4750 | |
4751 Lno: | |
4752 return new IntegerExp(0); | |
4753 } | |
4754 | |
4755 void IsExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
4756 { | |
4757 buf->writestring("is("); | |
4758 targ->toCBuffer(buf, id, hgs); | |
4759 if (tok2 != TOKreserved) | |
4760 { | |
4761 buf->printf(" %s %s", Token::toChars(tok), Token::toChars(tok2)); | |
4762 } | |
4763 else if (tspec) | |
4764 { | |
4765 if (tok == TOKcolon) | |
4766 buf->writestring(" : "); | |
4767 else | |
4768 buf->writestring(" == "); | |
4769 tspec->toCBuffer(buf, NULL, hgs); | |
4770 } | |
336 | 4771 #if DMDV2 |
159 | 4772 if (parameters) |
4773 { // First parameter is already output, so start with second | |
4774 for (int i = 1; i < parameters->dim; i++) | |
4775 { | |
4776 buf->writeByte(','); | |
4777 TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; | |
4778 tp->toCBuffer(buf, hgs); | |
4779 } | |
4780 } | |
4781 #endif | |
4782 buf->writeByte(')'); | |
4783 } | |
4784 | |
4785 | |
4786 /************************************************************/ | |
4787 | |
4788 UnaExp::UnaExp(Loc loc, enum TOK op, int size, Expression *e1) | |
4789 : Expression(loc, op, size) | |
4790 { | |
4791 this->e1 = e1; | |
4792 } | |
4793 | |
4794 Expression *UnaExp::syntaxCopy() | |
4795 { UnaExp *e; | |
4796 | |
4797 e = (UnaExp *)copy(); | |
4798 e->type = NULL; | |
4799 e->e1 = e->e1->syntaxCopy(); | |
4800 return e; | |
4801 } | |
4802 | |
4803 Expression *UnaExp::semantic(Scope *sc) | |
4804 { | |
4805 #if LOGSEMANTIC | |
4806 printf("UnaExp::semantic('%s')\n", toChars()); | |
4807 #endif | |
4808 e1 = e1->semantic(sc); | |
4809 // if (!e1->type) | |
4810 // error("%s has no value", e1->toChars()); | |
4811 return this; | |
4812 } | |
4813 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
4814 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
4815 int UnaExp::canThrow() |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
4816 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
4817 return e1->canThrow(); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
4818 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
4819 #endif |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
4820 |
159 | 4821 void UnaExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
4822 { | |
4823 buf->writestring(Token::toChars(op)); | |
4824 expToCBuffer(buf, hgs, e1, precedence[op]); | |
4825 } | |
4826 | |
4827 /************************************************************/ | |
4828 | |
4829 BinExp::BinExp(Loc loc, enum TOK op, int size, Expression *e1, Expression *e2) | |
4830 : Expression(loc, op, size) | |
4831 { | |
4832 this->e1 = e1; | |
4833 this->e2 = e2; | |
4834 } | |
4835 | |
4836 Expression *BinExp::syntaxCopy() | |
4837 { BinExp *e; | |
4838 | |
4839 e = (BinExp *)copy(); | |
4840 e->type = NULL; | |
4841 e->e1 = e->e1->syntaxCopy(); | |
4842 e->e2 = e->e2->syntaxCopy(); | |
4843 return e; | |
4844 } | |
4845 | |
4846 Expression *BinExp::semantic(Scope *sc) | |
4847 { | |
4848 #if LOGSEMANTIC | |
4849 printf("BinExp::semantic('%s')\n", toChars()); | |
4850 #endif | |
4851 e1 = e1->semantic(sc); | |
717
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
4852 if (!e1->type && |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
4853 !(op == TOKassign && e1->op == TOKdottd)) // a.template = e2 |
159 | 4854 { |
4855 error("%s has no value", e1->toChars()); | |
4856 e1->type = Type::terror; | |
4857 } | |
4858 e2 = e2->semantic(sc); | |
4859 if (!e2->type) | |
4860 { | |
4861 error("%s has no value", e2->toChars()); | |
4862 e2->type = Type::terror; | |
4863 } | |
4864 return this; | |
4865 } | |
4866 | |
4867 Expression *BinExp::semanticp(Scope *sc) | |
4868 { | |
4869 BinExp::semantic(sc); | |
4870 e1 = resolveProperties(sc, e1); | |
4871 e2 = resolveProperties(sc, e2); | |
4872 return this; | |
4873 } | |
4874 | |
4875 /*************************** | |
4876 * Common semantic routine for some xxxAssignExp's. | |
4877 */ | |
4878 | |
4879 Expression *BinExp::commonSemanticAssign(Scope *sc) | |
4880 { Expression *e; | |
4881 | |
4882 if (!type) | |
4883 { | |
4884 BinExp::semantic(sc); | |
4885 e2 = resolveProperties(sc, e2); | |
4886 | |
4887 e = op_overload(sc); | |
4888 if (e) | |
4889 return e; | |
4890 | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4891 if (e1->op == TOKslice) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4892 { // T[] op= ... |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4893 typeCombine(sc); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4894 type = e1->type; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4895 return arrayOp(sc); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4896 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4897 |
159 | 4898 e1 = e1->modifiableLvalue(sc, e1); |
4899 e1->checkScalar(); | |
4900 type = e1->type; | |
4901 if (type->toBasetype()->ty == Tbool) | |
4902 { | |
4903 error("operator not allowed on bool expression %s", toChars()); | |
4904 } | |
4905 typeCombine(sc); | |
4906 e1->checkArithmetic(); | |
4907 e2->checkArithmetic(); | |
4908 | |
4909 if (op == TOKmodass && e2->type->iscomplex()) | |
4910 { error("cannot perform modulo complex arithmetic"); | |
4911 return new IntegerExp(0); | |
4912 } | |
4913 } | |
4914 return this; | |
4915 } | |
4916 | |
4917 Expression *BinExp::commonSemanticAssignIntegral(Scope *sc) | |
4918 { Expression *e; | |
4919 | |
4920 if (!type) | |
4921 { | |
4922 BinExp::semantic(sc); | |
4923 e2 = resolveProperties(sc, e2); | |
4924 | |
4925 e = op_overload(sc); | |
4926 if (e) | |
4927 return e; | |
4928 | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4929 if (e1->op == TOKslice) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4930 { // T[] op= ... |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4931 typeCombine(sc); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4932 type = e1->type; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4933 return arrayOp(sc); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4934 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4935 |
159 | 4936 e1 = e1->modifiableLvalue(sc, e1); |
4937 e1->checkScalar(); | |
4938 type = e1->type; | |
4939 if (type->toBasetype()->ty == Tbool) | |
4940 { | |
4941 e2 = e2->implicitCastTo(sc, type); | |
4942 } | |
4943 | |
4944 typeCombine(sc); | |
4945 e1->checkIntegral(); | |
4946 e2->checkIntegral(); | |
4947 } | |
4948 return this; | |
4949 } | |
4950 | |
4951 int BinExp::checkSideEffect(int flag) | |
4952 { | |
4953 if (op == TOKplusplus || | |
4954 op == TOKminusminus || | |
4955 op == TOKassign || | |
4956 op == TOKconstruct || | |
4957 op == TOKblit || | |
4958 op == TOKaddass || | |
4959 op == TOKminass || | |
4960 op == TOKcatass || | |
4961 op == TOKmulass || | |
4962 op == TOKdivass || | |
4963 op == TOKmodass || | |
4964 op == TOKshlass || | |
4965 op == TOKshrass || | |
4966 op == TOKushrass || | |
4967 op == TOKandass || | |
4968 op == TOKorass || | |
4969 op == TOKxorass || | |
4970 op == TOKin || | |
4971 op == TOKremove) | |
4972 return 1; | |
4973 return Expression::checkSideEffect(flag); | |
4974 } | |
4975 | |
4976 void BinExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
4977 { | |
4978 expToCBuffer(buf, hgs, e1, precedence[op]); | |
4979 buf->writeByte(' '); | |
4980 buf->writestring(Token::toChars(op)); | |
4981 buf->writeByte(' '); | |
4982 expToCBuffer(buf, hgs, e2, (enum PREC)(precedence[op] + 1)); | |
4983 } | |
4984 | |
4985 int BinExp::isunsigned() | |
4986 { | |
4987 return e1->type->isunsigned() || e2->type->isunsigned(); | |
4988 } | |
4989 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
4990 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
4991 int BinExp::canThrow() |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
4992 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
4993 return e1->canThrow() || e2->canThrow(); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
4994 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
4995 #endif |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
4996 |
159 | 4997 void BinExp::incompatibleTypes() |
4998 { | |
4999 error("incompatible types for ((%s) %s (%s)): '%s' and '%s'", | |
5000 e1->toChars(), Token::toChars(op), e2->toChars(), | |
5001 e1->type->toChars(), e2->type->toChars()); | |
5002 } | |
5003 | |
5004 /************************************************************/ | |
5005 | |
5006 CompileExp::CompileExp(Loc loc, Expression *e) | |
5007 : UnaExp(loc, TOKmixin, sizeof(CompileExp), e) | |
5008 { | |
5009 } | |
5010 | |
5011 Expression *CompileExp::semantic(Scope *sc) | |
5012 { | |
5013 #if LOGSEMANTIC | |
5014 printf("CompileExp::semantic('%s')\n", toChars()); | |
5015 #endif | |
5016 UnaExp::semantic(sc); | |
5017 e1 = resolveProperties(sc, e1); | |
5018 e1 = e1->optimize(WANTvalue | WANTinterpret); | |
5019 if (e1->op != TOKstring) | |
5020 { error("argument to mixin must be a string, not (%s)", e1->toChars()); | |
5021 type = Type::terror; | |
5022 return this; | |
5023 } | |
5024 StringExp *se = (StringExp *)e1; | |
5025 se = se->toUTF8(sc); | |
5026 Parser p(sc->module, (unsigned char *)se->string, se->len, 0); | |
5027 p.loc = loc; | |
5028 p.nextToken(); | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5029 //printf("p.loc.linnum = %d\n", p.loc.linnum); |
159 | 5030 Expression *e = p.parseExpression(); |
5031 if (p.token.value != TOKeof) | |
5032 error("incomplete mixin expression (%s)", se->toChars()); | |
5033 return e->semantic(sc); | |
5034 } | |
5035 | |
5036 void CompileExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
5037 { | |
5038 buf->writestring("mixin("); | |
5039 expToCBuffer(buf, hgs, e1, PREC_assign); | |
5040 buf->writeByte(')'); | |
5041 } | |
5042 | |
5043 /************************************************************/ | |
5044 | |
5045 FileExp::FileExp(Loc loc, Expression *e) | |
5046 : UnaExp(loc, TOKmixin, sizeof(FileExp), e) | |
5047 { | |
5048 } | |
5049 | |
5050 Expression *FileExp::semantic(Scope *sc) | |
5051 { char *name; | |
5052 StringExp *se; | |
5053 | |
5054 #if LOGSEMANTIC | |
5055 printf("FileExp::semantic('%s')\n", toChars()); | |
5056 #endif | |
5057 UnaExp::semantic(sc); | |
5058 e1 = resolveProperties(sc, e1); | |
5059 e1 = e1->optimize(WANTvalue); | |
5060 if (e1->op != TOKstring) | |
5061 { error("file name argument must be a string, not (%s)", e1->toChars()); | |
5062 goto Lerror; | |
5063 } | |
5064 se = (StringExp *)e1; | |
5065 se = se->toUTF8(sc); | |
5066 name = (char *)se->string; | |
5067 | |
5068 if (!global.params.fileImppath) | |
5069 { error("need -Jpath switch to import text file %s", name); | |
5070 goto Lerror; | |
5071 } | |
5072 | |
5073 if (name != FileName::name(name)) | |
5074 { error("use -Jpath switch to provide path for filename %s", name); | |
5075 goto Lerror; | |
5076 } | |
5077 | |
5078 name = FileName::searchPath(global.filePath, name, 0); | |
5079 if (!name) | |
5080 { error("file %s cannot be found, check -Jpath", se->toChars()); | |
5081 goto Lerror; | |
5082 } | |
5083 | |
5084 if (global.params.verbose) | |
794
661384d6a936
Fix warnings on x86-64. By fvbommel.
Christian Kamm <kamm incasoftware de>
parents:
779
diff
changeset
|
5085 printf("file %s\t(%s)\n", (char*)se->string, name); |
159 | 5086 |
5087 { File f(name); | |
5088 if (f.read()) | |
5089 { error("cannot read file %s", f.toChars()); | |
5090 goto Lerror; | |
5091 } | |
5092 else | |
5093 { | |
5094 f.ref = 1; | |
5095 se = new StringExp(loc, f.buffer, f.len); | |
5096 } | |
5097 } | |
5098 Lret: | |
5099 return se->semantic(sc); | |
5100 | |
5101 Lerror: | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5102 se = new StringExp(loc, (char *)""); |
159 | 5103 goto Lret; |
5104 } | |
5105 | |
5106 void FileExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
5107 { | |
5108 buf->writestring("import("); | |
5109 expToCBuffer(buf, hgs, e1, PREC_assign); | |
5110 buf->writeByte(')'); | |
5111 } | |
5112 | |
5113 /************************************************************/ | |
5114 | |
5115 AssertExp::AssertExp(Loc loc, Expression *e, Expression *msg) | |
5116 : UnaExp(loc, TOKassert, sizeof(AssertExp), e) | |
5117 { | |
5118 this->msg = msg; | |
5119 } | |
5120 | |
5121 Expression *AssertExp::syntaxCopy() | |
5122 { | |
5123 AssertExp *ae = new AssertExp(loc, e1->syntaxCopy(), | |
5124 msg ? msg->syntaxCopy() : NULL); | |
5125 return ae; | |
5126 } | |
5127 | |
5128 Expression *AssertExp::semantic(Scope *sc) | |
5129 { | |
5130 #if LOGSEMANTIC | |
5131 printf("AssertExp::semantic('%s')\n", toChars()); | |
5132 #endif | |
5133 UnaExp::semantic(sc); | |
5134 e1 = resolveProperties(sc, e1); | |
5135 // BUG: see if we can do compile time elimination of the Assert | |
5136 e1 = e1->optimize(WANTvalue); | |
5137 e1 = e1->checkToBoolean(); | |
5138 if (msg) | |
5139 { | |
5140 msg = msg->semantic(sc); | |
5141 msg = resolveProperties(sc, msg); | |
5142 msg = msg->implicitCastTo(sc, Type::tchar->arrayOf()); | |
5143 msg = msg->optimize(WANTvalue); | |
5144 } | |
5145 if (e1->isBool(FALSE)) | |
5146 { | |
5147 FuncDeclaration *fd = sc->parent->isFuncDeclaration(); | |
5148 fd->hasReturnExp |= 4; | |
5149 | |
5150 if (!global.params.useAssert) | |
5151 { Expression *e = new HaltExp(loc); | |
5152 e = e->semantic(sc); | |
5153 return e; | |
5154 } | |
5155 } | |
5156 type = Type::tvoid; | |
5157 return this; | |
5158 } | |
5159 | |
5160 int AssertExp::checkSideEffect(int flag) | |
5161 { | |
5162 return 1; | |
5163 } | |
5164 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5165 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5166 int AssertExp::canThrow() |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5167 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5168 return (global.params.useAssert != 0); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5169 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5170 #endif |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5171 |
159 | 5172 void AssertExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
5173 { | |
5174 buf->writestring("assert("); | |
5175 expToCBuffer(buf, hgs, e1, PREC_assign); | |
5176 if (msg) | |
5177 { | |
5178 buf->writeByte(','); | |
5179 expToCBuffer(buf, hgs, msg, PREC_assign); | |
5180 } | |
5181 buf->writeByte(')'); | |
5182 } | |
5183 | |
5184 /************************************************************/ | |
5185 | |
5186 DotIdExp::DotIdExp(Loc loc, Expression *e, Identifier *ident) | |
5187 : UnaExp(loc, TOKdot, sizeof(DotIdExp), e) | |
5188 { | |
5189 this->ident = ident; | |
5190 } | |
5191 | |
5192 Expression *DotIdExp::semantic(Scope *sc) | |
5193 { Expression *e; | |
5194 Expression *eleft; | |
5195 Expression *eright; | |
5196 | |
5197 #if LOGSEMANTIC | |
5198 printf("DotIdExp::semantic(this = %p, '%s')\n", this, toChars()); | |
5199 //printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op)); | |
5200 #endif | |
5201 | |
5202 //{ static int z; fflush(stdout); if (++z == 10) *(char*)0=0; } | |
5203 | |
5204 #if 0 | |
5205 /* Don't do semantic analysis if we'll be converting | |
5206 * it to a string. | |
5207 */ | |
5208 if (ident == Id::stringof) | |
5209 { char *s = e1->toChars(); | |
5210 e = new StringExp(loc, s, strlen(s), 'c'); | |
5211 e = e->semantic(sc); | |
5212 return e; | |
5213 } | |
5214 #endif | |
5215 | |
5216 /* Special case: rewrite this.id and super.id | |
5217 * to be classtype.id and baseclasstype.id | |
5218 * if we have no this pointer. | |
5219 */ | |
5220 if ((e1->op == TOKthis || e1->op == TOKsuper) && !hasThis(sc)) | |
5221 { ClassDeclaration *cd; | |
5222 StructDeclaration *sd; | |
5223 AggregateDeclaration *ad; | |
5224 | |
5225 ad = sc->getStructClassScope(); | |
5226 if (ad) | |
5227 { | |
5228 cd = ad->isClassDeclaration(); | |
5229 if (cd) | |
5230 { | |
5231 if (e1->op == TOKthis) | |
5232 { | |
5233 e = new TypeDotIdExp(loc, cd->type, ident); | |
5234 return e->semantic(sc); | |
5235 } | |
5236 else if (cd->baseClass && e1->op == TOKsuper) | |
5237 { | |
5238 e = new TypeDotIdExp(loc, cd->baseClass->type, ident); | |
5239 return e->semantic(sc); | |
5240 } | |
5241 } | |
5242 else | |
5243 { | |
5244 sd = ad->isStructDeclaration(); | |
5245 if (sd) | |
5246 { | |
5247 if (e1->op == TOKthis) | |
5248 { | |
5249 e = new TypeDotIdExp(loc, sd->type, ident); | |
5250 return e->semantic(sc); | |
5251 } | |
5252 } | |
5253 } | |
5254 } | |
5255 } | |
5256 | |
5257 UnaExp::semantic(sc); | |
5258 | |
5259 if (e1->op == TOKdotexp) | |
5260 { | |
5261 DotExp *de = (DotExp *)e1; | |
5262 eleft = de->e1; | |
5263 eright = de->e2; | |
5264 } | |
5265 else | |
5266 { | |
5267 e1 = resolveProperties(sc, e1); | |
5268 eleft = NULL; | |
5269 eright = e1; | |
5270 } | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5271 #if DMDV2 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5272 if (e1->op == TOKtuple && ident == Id::offsetof) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5273 { /* 'distribute' the .offsetof to each of the tuple elements. |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5274 */ |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5275 TupleExp *te = (TupleExp *)e1; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5276 Expressions *exps = new Expressions(); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5277 exps->setDim(te->exps->dim); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5278 for (int i = 0; i < exps->dim; i++) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5279 { Expression *e = (Expression *)te->exps->data[i]; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5280 e = e->semantic(sc); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5281 e = new DotIdExp(e->loc, e, Id::offsetof); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5282 exps->data[i] = (void *)e; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5283 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5284 e = new TupleExp(loc, exps); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5285 e = e->semantic(sc); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5286 return e; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5287 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5288 #endif |
159 | 5289 |
5290 if (e1->op == TOKtuple && ident == Id::length) | |
5291 { | |
5292 TupleExp *te = (TupleExp *)e1; | |
5293 e = new IntegerExp(loc, te->exps->dim, Type::tsize_t); | |
5294 return e; | |
5295 } | |
5296 | |
5297 if (eright->op == TOKimport) // also used for template alias's | |
5298 { | |
5299 ScopeExp *ie = (ScopeExp *)eright; | |
5300 | |
846
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
841
diff
changeset
|
5301 /* Disable access to another module's private imports. |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
841
diff
changeset
|
5302 * The check for 'is sds our current module' is because |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
841
diff
changeset
|
5303 * the current module should have access to its own imports. |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
841
diff
changeset
|
5304 */ |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
841
diff
changeset
|
5305 Dsymbol *s = ie->sds->search(loc, ident, |
bc982f1ad106
Merged DMD 1.037 frontend
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
841
diff
changeset
|
5306 (ie->sds->isModule() && ie->sds != sc->module) ? 1 : 0); |
159 | 5307 if (s) |
5308 { | |
5309 s = s->toAlias(); | |
5310 checkDeprecated(sc, s); | |
5311 | |
5312 EnumMember *em = s->isEnumMember(); | |
5313 if (em) | |
5314 { | |
5315 e = em->value; | |
5316 e = e->semantic(sc); | |
5317 return e; | |
5318 } | |
5319 | |
5320 VarDeclaration *v = s->isVarDeclaration(); | |
5321 if (v) | |
5322 { | |
5323 //printf("DotIdExp:: Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars()); | |
5324 if (v->inuse) | |
5325 { | |
5326 error("circular reference to '%s'", v->toChars()); | |
5327 type = Type::tint32; | |
5328 return this; | |
5329 } | |
5330 type = v->type; | |
5331 if (v->isConst()) | |
5332 { | |
5333 if (v->init) | |
5334 { | |
5335 ExpInitializer *ei = v->init->isExpInitializer(); | |
5336 if (ei) | |
5337 { | |
5338 //printf("\tei: %p (%s)\n", ei->exp, ei->exp->toChars()); | |
5339 //ei->exp = ei->exp->semantic(sc); | |
5340 if (ei->exp->type == type) | |
5341 { | |
5342 e = ei->exp->copy(); // make copy so we can change loc | |
5343 e->loc = loc; | |
5344 return e; | |
5345 } | |
5346 } | |
5347 } | |
5348 else if (type->isscalar()) | |
5349 { | |
5350 e = type->defaultInit(); | |
5351 e->loc = loc; | |
5352 return e; | |
5353 } | |
5354 } | |
5355 if (v->needThis()) | |
5356 { | |
5357 if (!eleft) | |
5358 eleft = new ThisExp(loc); | |
5359 e = new DotVarExp(loc, eleft, v); | |
5360 e = e->semantic(sc); | |
5361 } | |
5362 else | |
5363 { | |
5364 e = new VarExp(loc, v); | |
5365 if (eleft) | |
5366 { e = new CommaExp(loc, eleft, e); | |
5367 e->type = v->type; | |
5368 } | |
5369 } | |
5370 return e->deref(); | |
5371 } | |
5372 | |
5373 FuncDeclaration *f = s->isFuncDeclaration(); | |
5374 if (f) | |
5375 { | |
5376 //printf("it's a function\n"); | |
5377 if (f->needThis()) | |
5378 { | |
5379 if (!eleft) | |
5380 eleft = new ThisExp(loc); | |
5381 e = new DotVarExp(loc, eleft, f); | |
5382 e = e->semantic(sc); | |
5383 } | |
5384 else | |
5385 { | |
5386 e = new VarExp(loc, f); | |
5387 if (eleft) | |
5388 { e = new CommaExp(loc, eleft, e); | |
5389 e->type = f->type; | |
5390 } | |
5391 } | |
5392 return e; | |
5393 } | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5394 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5395 OverloadSet *o = s->isOverloadSet(); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5396 if (o) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5397 { //printf("'%s' is an overload set\n", o->toChars()); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5398 return new OverExp(o); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5399 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5400 #endif |
159 | 5401 |
5402 Type *t = s->getType(); | |
5403 if (t) | |
5404 { | |
5405 return new TypeExp(loc, t); | |
5406 } | |
5407 | |
336 | 5408 TupleDeclaration *tup = s->isTupleDeclaration(); |
5409 if (tup) | |
5410 { | |
5411 if (eleft) | |
5412 error("cannot have e.tuple"); | |
5413 e = new TupleExp(loc, tup); | |
5414 e = e->semantic(sc); | |
5415 return e; | |
5416 } | |
5417 | |
159 | 5418 ScopeDsymbol *sds = s->isScopeDsymbol(); |
5419 if (sds) | |
5420 { | |
5421 //printf("it's a ScopeDsymbol\n"); | |
5422 e = new ScopeExp(loc, sds); | |
5423 e = e->semantic(sc); | |
5424 if (eleft) | |
5425 e = new DotExp(loc, eleft, e); | |
5426 return e; | |
5427 } | |
5428 | |
5429 Import *imp = s->isImport(); | |
5430 if (imp) | |
5431 { | |
5432 ScopeExp *ie; | |
5433 | |
5434 ie = new ScopeExp(loc, imp->pkg); | |
5435 return ie->semantic(sc); | |
5436 } | |
5437 | |
5438 // BUG: handle other cases like in IdentifierExp::semantic() | |
5439 #ifdef DEBUG | |
5440 printf("s = '%s', kind = '%s'\n", s->toChars(), s->kind()); | |
5441 #endif | |
5442 assert(0); | |
5443 } | |
5444 else if (ident == Id::stringof) | |
5445 { char *s = ie->toChars(); | |
5446 e = new StringExp(loc, s, strlen(s), 'c'); | |
5447 e = e->semantic(sc); | |
5448 return e; | |
5449 } | |
5450 error("undefined identifier %s", toChars()); | |
5451 type = Type::tvoid; | |
5452 return this; | |
5453 } | |
5454 else if (e1->type->ty == Tpointer && | |
5455 ident != Id::init && ident != Id::__sizeof && | |
5456 ident != Id::alignof && ident != Id::offsetof && | |
5457 ident != Id::mangleof && ident != Id::stringof) | |
5458 { | |
5459 e = new PtrExp(loc, e1); | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5460 e->type = ((TypePointer *)e1->type)->next; |
159 | 5461 return e->type->dotExp(sc, e, ident); |
5462 } | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5463 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5464 else if (t1b->ty == Tarray || |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5465 t1b->ty == Tsarray || |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5466 t1b->ty == Taarray) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5467 { /* If ident is not a valid property, rewrite: |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5468 * e1.ident |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5469 * as: |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5470 * .ident(e1) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5471 */ |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5472 unsigned errors = global.errors; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5473 global.gag++; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5474 e = e1->type->dotExp(sc, e1, ident); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5475 global.gag--; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5476 if (errors != global.errors) // if failed to find the property |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5477 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5478 global.errors = errors; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5479 e = new DotIdExp(loc, new IdentifierExp(loc, Id::empty), ident); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5480 e = new CallExp(loc, e, e1); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5481 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5482 e = e->semantic(sc); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5483 return e; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5484 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5485 #endif |
159 | 5486 else |
5487 { | |
5488 e = e1->type->dotExp(sc, e1, ident); | |
5489 e = e->semantic(sc); | |
5490 return e; | |
5491 } | |
5492 } | |
5493 | |
5494 void DotIdExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
5495 { | |
5496 //printf("DotIdExp::toCBuffer()\n"); | |
5497 expToCBuffer(buf, hgs, e1, PREC_primary); | |
5498 buf->writeByte('.'); | |
5499 buf->writestring(ident->toChars()); | |
5500 } | |
5501 | |
5502 /********************** DotTemplateExp ***********************************/ | |
5503 | |
5504 // Mainly just a placeholder | |
5505 | |
5506 DotTemplateExp::DotTemplateExp(Loc loc, Expression *e, TemplateDeclaration *td) | |
5507 : UnaExp(loc, TOKdottd, sizeof(DotTemplateExp), e) | |
5508 | |
5509 { | |
5510 this->td = td; | |
5511 } | |
5512 | |
5513 void DotTemplateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
5514 { | |
5515 expToCBuffer(buf, hgs, e1, PREC_primary); | |
5516 buf->writeByte('.'); | |
5517 buf->writestring(td->toChars()); | |
5518 } | |
5519 | |
5520 | |
5521 /************************************************************/ | |
5522 | |
5523 DotVarExp::DotVarExp(Loc loc, Expression *e, Declaration *v) | |
5524 : UnaExp(loc, TOKdotvar, sizeof(DotVarExp), e) | |
5525 { | |
5526 //printf("DotVarExp()\n"); | |
5527 this->var = v; | |
5528 } | |
5529 | |
5530 Expression *DotVarExp::semantic(Scope *sc) | |
5531 { | |
5532 #if LOGSEMANTIC | |
5533 printf("DotVarExp::semantic('%s')\n", toChars()); | |
5534 #endif | |
5535 if (!type) | |
5536 { | |
5537 var = var->toAlias()->isDeclaration(); | |
5538 | |
5539 TupleDeclaration *tup = var->isTupleDeclaration(); | |
5540 if (tup) | |
5541 { /* Replace: | |
5542 * e1.tuple(a, b, c) | |
5543 * with: | |
5544 * tuple(e1.a, e1.b, e1.c) | |
5545 */ | |
5546 Expressions *exps = new Expressions; | |
5547 | |
5548 exps->reserve(tup->objects->dim); | |
5549 for (size_t i = 0; i < tup->objects->dim; i++) | |
5550 { Object *o = (Object *)tup->objects->data[i]; | |
5551 if (o->dyncast() != DYNCAST_EXPRESSION) | |
5552 { | |
5553 error("%s is not an expression", o->toChars()); | |
5554 } | |
5555 else | |
5556 { | |
5557 Expression *e = (Expression *)o; | |
5558 if (e->op != TOKdsymbol) | |
5559 error("%s is not a member", e->toChars()); | |
5560 else | |
5561 { DsymbolExp *ve = (DsymbolExp *)e; | |
5562 | |
5563 e = new DotVarExp(loc, e1, ve->s->isDeclaration()); | |
5564 exps->push(e); | |
5565 } | |
5566 } | |
5567 } | |
5568 Expression *e = new TupleExp(loc, exps); | |
5569 e = e->semantic(sc); | |
5570 return e; | |
5571 } | |
5572 | |
5573 e1 = e1->semantic(sc); | |
5574 type = var->type; | |
5575 if (!type && global.errors) | |
5576 { // var is goofed up, just return 0 | |
5577 return new IntegerExp(0); | |
5578 } | |
5579 assert(type); | |
5580 | |
5581 if (!var->isFuncDeclaration()) // for functions, do checks after overload resolution | |
5582 { | |
5583 AggregateDeclaration *ad = var->toParent()->isAggregateDeclaration(); | |
336 | 5584 e1 = getRightThis(loc, sc, ad, e1, var); |
5585 if (!sc->noaccesscheck) | |
5586 accessCheck(loc, sc, e1, var); | |
5587 | |
5588 VarDeclaration *v = var->isVarDeclaration(); | |
5589 if (v && v->isConst()) | |
5590 { ExpInitializer *ei = v->getExpInitializer(); | |
5591 if (ei) | |
5592 { Expression *e = ei->exp->copy(); | |
5593 e = e->semantic(sc); | |
5594 return e; | |
159 | 5595 } |
5596 } | |
5597 } | |
5598 } | |
5599 //printf("-DotVarExp::semantic('%s')\n", toChars()); | |
5600 return this; | |
5601 } | |
5602 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5603 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5604 int DotVarExp::isLvalue() |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5605 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5606 return 1; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5607 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5608 #endif |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5609 |
159 | 5610 Expression *DotVarExp::toLvalue(Scope *sc, Expression *e) |
5611 { | |
5612 //printf("DotVarExp::toLvalue(%s)\n", toChars()); | |
5613 return this; | |
5614 } | |
5615 | |
5616 Expression *DotVarExp::modifiableLvalue(Scope *sc, Expression *e) | |
5617 { | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5618 #if 0 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5619 printf("DotVarExp::modifiableLvalue(%s)\n", toChars()); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5620 printf("e1->type = %s\n", e1->type->toChars()); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5621 printf("var->type = %s\n", var->type->toChars()); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5622 #endif |
159 | 5623 |
5624 if (var->isCtorinit()) | |
5625 { // It's only modifiable if inside the right constructor | |
5626 Dsymbol *s = sc->func; | |
5627 while (1) | |
5628 { | |
5629 FuncDeclaration *fd = NULL; | |
5630 if (s) | |
5631 fd = s->isFuncDeclaration(); | |
5632 if (fd && | |
5633 ((fd->isCtorDeclaration() && var->storage_class & STCfield) || | |
5634 (fd->isStaticCtorDeclaration() && !(var->storage_class & STCfield))) && | |
5635 fd->toParent() == var->toParent() && | |
5636 e1->op == TOKthis | |
5637 ) | |
5638 { | |
5639 VarDeclaration *v = var->isVarDeclaration(); | |
5640 assert(v); | |
5641 v->ctorinit = 1; | |
5642 //printf("setting ctorinit\n"); | |
5643 } | |
5644 else | |
5645 { | |
5646 if (s) | |
5647 { s = s->toParent2(); | |
5648 continue; | |
5649 } | |
5650 else | |
5651 { | |
5652 const char *p = var->isStatic() ? "static " : ""; | |
5653 error("can only initialize %sconst member %s inside %sconstructor", | |
5654 p, var->toChars(), p); | |
5655 } | |
5656 } | |
5657 break; | |
5658 } | |
5659 } | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5660 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5661 else |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5662 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5663 Type *t1 = e1->type->toBasetype(); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5664 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5665 if (!t1->isMutable() || |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5666 (t1->ty == Tpointer && !t1->nextOf()->isMutable()) || |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5667 !var->type->isMutable() || |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5668 !var->type->isAssignable() || |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5669 var->storage_class & STCmanifest |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5670 ) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5671 error("cannot modify const/invariant %s", toChars()); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5672 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5673 #endif |
159 | 5674 return this; |
5675 } | |
5676 | |
5677 void DotVarExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
5678 { | |
5679 expToCBuffer(buf, hgs, e1, PREC_primary); | |
5680 buf->writeByte('.'); | |
5681 buf->writestring(var->toChars()); | |
5682 } | |
5683 | |
5684 /************************************************************/ | |
5685 | |
5686 /* Things like: | |
5687 * foo.bar!(args) | |
5688 */ | |
5689 | |
5690 DotTemplateInstanceExp::DotTemplateInstanceExp(Loc loc, Expression *e, TemplateInstance *ti) | |
5691 : UnaExp(loc, TOKdotti, sizeof(DotTemplateInstanceExp), e) | |
5692 { | |
5693 //printf("DotTemplateInstanceExp()\n"); | |
5694 this->ti = ti; | |
5695 } | |
5696 | |
5697 Expression *DotTemplateInstanceExp::syntaxCopy() | |
5698 { | |
5699 DotTemplateInstanceExp *de = new DotTemplateInstanceExp(loc, | |
5700 e1->syntaxCopy(), | |
5701 (TemplateInstance *)ti->syntaxCopy(NULL)); | |
5702 return de; | |
5703 } | |
5704 | |
5705 Expression *DotTemplateInstanceExp::semantic(Scope *sc) | |
5706 { Dsymbol *s; | |
5707 Dsymbol *s2; | |
5708 TemplateDeclaration *td; | |
5709 Expression *e; | |
5710 Identifier *id; | |
5711 Type *t1; | |
5712 Expression *eleft = NULL; | |
5713 Expression *eright; | |
5714 | |
5715 #if LOGSEMANTIC | |
5716 printf("DotTemplateInstanceExp::semantic('%s')\n", toChars()); | |
5717 #endif | |
5718 //e1->print(); | |
5719 //print(); | |
5720 e1 = e1->semantic(sc); | |
5721 t1 = e1->type; | |
5722 if (t1) | |
5723 t1 = t1->toBasetype(); | |
5724 //t1->print(); | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5725 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5726 /* Extract the following from e1: |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5727 * s: the symbol which ti should be a member of |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5728 * eleft: if not NULL, it is the 'this' pointer for ti |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5729 */ |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5730 |
159 | 5731 if (e1->op == TOKdotexp) |
5732 { DotExp *de = (DotExp *)e1; | |
5733 eleft = de->e1; | |
5734 eright = de->e2; | |
5735 } | |
5736 else | |
5737 { eleft = NULL; | |
5738 eright = e1; | |
5739 } | |
5740 if (eright->op == TOKimport) | |
5741 { | |
5742 s = ((ScopeExp *)eright)->sds; | |
5743 } | |
5744 else if (e1->op == TOKtype) | |
5745 { | |
5746 s = t1->isClassHandle(); | |
5747 if (!s) | |
5748 { if (t1->ty == Tstruct) | |
5749 s = ((TypeStruct *)t1)->sym; | |
5750 else | |
5751 goto L1; | |
5752 } | |
5753 } | |
5754 else if (t1 && (t1->ty == Tstruct || t1->ty == Tclass)) | |
5755 { | |
5756 s = t1->toDsymbol(sc); | |
5757 eleft = e1; | |
5758 } | |
5759 else if (t1 && t1->ty == Tpointer) | |
5760 { | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5761 t1 = ((TypePointer *)t1)->next->toBasetype(); |
159 | 5762 if (t1->ty != Tstruct) |
5763 goto L1; | |
5764 s = t1->toDsymbol(sc); | |
5765 eleft = e1; | |
5766 } | |
5767 else | |
5768 { | |
5769 L1: | |
5770 error("template %s is not a member of %s", ti->toChars(), e1->toChars()); | |
5771 goto Lerr; | |
5772 } | |
5773 | |
5774 assert(s); | |
5775 id = ti->name; | |
5776 s2 = s->search(loc, id, 0); | |
5777 if (!s2) | |
5778 { error("template identifier %s is not a member of %s %s", id->toChars(), s->kind(), s->ident->toChars()); | |
5779 goto Lerr; | |
5780 } | |
5781 s = s2; | |
5782 s->semantic(sc); | |
5783 s = s->toAlias(); | |
5784 td = s->isTemplateDeclaration(); | |
5785 if (!td) | |
5786 { | |
5787 error("%s is not a template", id->toChars()); | |
5788 goto Lerr; | |
5789 } | |
5790 if (global.errors) | |
5791 goto Lerr; | |
5792 | |
5793 ti->tempdecl = td; | |
5794 | |
5795 if (eleft) | |
5796 { Declaration *v; | |
5797 | |
5798 ti->semantic(sc); | |
5799 s = ti->inst->toAlias(); | |
5800 v = s->isDeclaration(); | |
5801 if (v) | |
5802 { e = new DotVarExp(loc, eleft, v); | |
5803 e = e->semantic(sc); | |
5804 return e; | |
5805 } | |
5806 } | |
5807 | |
5808 e = new ScopeExp(loc, ti); | |
5809 if (eleft) | |
5810 { | |
5811 e = new DotExp(loc, eleft, e); | |
5812 } | |
5813 e = e->semantic(sc); | |
5814 return e; | |
5815 | |
5816 Lerr: | |
336 | 5817 return new IntegerExp(loc, 0, Type::tint32); |
159 | 5818 } |
5819 | |
5820 void DotTemplateInstanceExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
5821 { | |
5822 expToCBuffer(buf, hgs, e1, PREC_primary); | |
5823 buf->writeByte('.'); | |
5824 ti->toCBuffer(buf, hgs); | |
5825 } | |
5826 | |
5827 /************************************************************/ | |
5828 | |
5829 DelegateExp::DelegateExp(Loc loc, Expression *e, FuncDeclaration *f) | |
5830 : UnaExp(loc, TOKdelegate, sizeof(DelegateExp), e) | |
5831 { | |
5832 this->func = f; | |
5833 } | |
5834 | |
5835 Expression *DelegateExp::semantic(Scope *sc) | |
5836 { | |
5837 #if LOGSEMANTIC | |
5838 printf("DelegateExp::semantic('%s')\n", toChars()); | |
5839 #endif | |
5840 if (!type) | |
5841 { | |
5842 e1 = e1->semantic(sc); | |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
639
diff
changeset
|
5843 // LDC we need a copy as we store the LLVM tpye in TypeFunction, and delegate/members have different types for 'this' |
471
e19e20103119
Changed DMD to make a copy of the TypeFunction in DelegateExp.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
468
diff
changeset
|
5844 type = new TypeDelegate(func->type->syntaxCopy()); |
159 | 5845 type = type->semantic(loc, sc); |
5846 AggregateDeclaration *ad = func->toParent()->isAggregateDeclaration(); | |
336 | 5847 if (func->needThis()) |
5848 e1 = getRightThis(loc, sc, ad, e1, func); | |
159 | 5849 } |
5850 return this; | |
5851 } | |
5852 | |
5853 void DelegateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
5854 { | |
5855 buf->writeByte('&'); | |
5856 if (!func->isNested()) | |
5857 { | |
5858 expToCBuffer(buf, hgs, e1, PREC_primary); | |
5859 buf->writeByte('.'); | |
5860 } | |
5861 buf->writestring(func->toChars()); | |
5862 } | |
5863 | |
5864 /************************************************************/ | |
5865 | |
5866 DotTypeExp::DotTypeExp(Loc loc, Expression *e, Dsymbol *s) | |
5867 : UnaExp(loc, TOKdottype, sizeof(DotTypeExp), e) | |
5868 { | |
5869 this->sym = s; | |
5870 this->type = s->getType(); | |
5871 } | |
5872 | |
5873 Expression *DotTypeExp::semantic(Scope *sc) | |
5874 { | |
5875 #if LOGSEMANTIC | |
5876 printf("DotTypeExp::semantic('%s')\n", toChars()); | |
5877 #endif | |
5878 UnaExp::semantic(sc); | |
5879 return this; | |
5880 } | |
5881 | |
5882 void DotTypeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
5883 { | |
5884 expToCBuffer(buf, hgs, e1, PREC_primary); | |
5885 buf->writeByte('.'); | |
5886 buf->writestring(sym->toChars()); | |
5887 } | |
5888 | |
5889 /************************************************************/ | |
5890 | |
5891 CallExp::CallExp(Loc loc, Expression *e, Expressions *exps) | |
5892 : UnaExp(loc, TOKcall, sizeof(CallExp), e) | |
5893 { | |
5894 this->arguments = exps; | |
5895 } | |
5896 | |
5897 CallExp::CallExp(Loc loc, Expression *e) | |
5898 : UnaExp(loc, TOKcall, sizeof(CallExp), e) | |
5899 { | |
5900 this->arguments = NULL; | |
5901 } | |
5902 | |
5903 CallExp::CallExp(Loc loc, Expression *e, Expression *earg1) | |
5904 : UnaExp(loc, TOKcall, sizeof(CallExp), e) | |
5905 { | |
5906 Expressions *arguments = new Expressions(); | |
5907 arguments->setDim(1); | |
5908 arguments->data[0] = (void *)earg1; | |
5909 | |
5910 this->arguments = arguments; | |
5911 } | |
5912 | |
5913 CallExp::CallExp(Loc loc, Expression *e, Expression *earg1, Expression *earg2) | |
5914 : UnaExp(loc, TOKcall, sizeof(CallExp), e) | |
5915 { | |
5916 Expressions *arguments = new Expressions(); | |
5917 arguments->setDim(2); | |
5918 arguments->data[0] = (void *)earg1; | |
5919 arguments->data[1] = (void *)earg2; | |
5920 | |
5921 this->arguments = arguments; | |
5922 } | |
5923 | |
5924 Expression *CallExp::syntaxCopy() | |
5925 { | |
5926 return new CallExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments)); | |
5927 } | |
5928 | |
5929 | |
5930 Expression *CallExp::semantic(Scope *sc) | |
5931 { | |
5932 TypeFunction *tf; | |
5933 FuncDeclaration *f; | |
5934 int i; | |
5935 Type *t1; | |
5936 int istemp; | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5937 Objects *targsi = NULL; // initial list of template arguments |
159 | 5938 |
5939 #if LOGSEMANTIC | |
5940 printf("CallExp::semantic() %s\n", toChars()); | |
5941 #endif | |
5942 if (type) | |
5943 return this; // semantic() already run | |
5944 #if 0 | |
5945 if (arguments && arguments->dim) | |
5946 { | |
5947 Expression *earg = (Expression *)arguments->data[0]; | |
5948 earg->print(); | |
5949 if (earg->type) earg->type->print(); | |
5950 } | |
5951 #endif | |
5952 | |
5953 if (e1->op == TOKdelegate) | |
5954 { DelegateExp *de = (DelegateExp *)e1; | |
5955 | |
5956 e1 = new DotVarExp(de->loc, de->e1, de->func); | |
5957 return semantic(sc); | |
5958 } | |
5959 | |
5960 /* Transform: | |
5961 * array.id(args) into id(array,args) | |
5962 * aa.remove(arg) into delete aa[arg] | |
5963 */ | |
5964 if (e1->op == TOKdot) | |
5965 { | |
5966 // BUG: we should handle array.a.b.c.e(args) too | |
5967 | |
5968 DotIdExp *dotid = (DotIdExp *)(e1); | |
5969 dotid->e1 = dotid->e1->semantic(sc); | |
5970 assert(dotid->e1); | |
5971 if (dotid->e1->type) | |
5972 { | |
5973 TY e1ty = dotid->e1->type->toBasetype()->ty; | |
5974 if (e1ty == Taarray && dotid->ident == Id::remove) | |
5975 { | |
5976 if (!arguments || arguments->dim != 1) | |
5977 { error("expected key as argument to aa.remove()"); | |
5978 goto Lagain; | |
5979 } | |
5980 Expression *key = (Expression *)arguments->data[0]; | |
5981 key = key->semantic(sc); | |
5982 key = resolveProperties(sc, key); | |
5983 key->rvalue(); | |
5984 | |
5985 TypeAArray *taa = (TypeAArray *)dotid->e1->type->toBasetype(); | |
5986 key = key->implicitCastTo(sc, taa->index); | |
5987 key = key->implicitCastTo(sc, taa->key); | |
5988 | |
5989 return new RemoveExp(loc, dotid->e1, key); | |
5990 } | |
5991 else if (e1ty == Tarray || e1ty == Tsarray || e1ty == Taarray) | |
5992 { | |
5993 if (!arguments) | |
5994 arguments = new Expressions(); | |
5995 arguments->shift(dotid->e1); | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5996 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5997 e1 = new DotIdExp(dotid->loc, new IdentifierExp(dotid->loc, Id::empty), dotid->ident); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
5998 #else |
159 | 5999 e1 = new IdentifierExp(dotid->loc, dotid->ident); |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6000 #endif |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6001 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6002 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6003 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6004 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6005 #if 1 |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6006 /* This recognizes: |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6007 * foo!(tiargs)(funcargs) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6008 */ |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6009 if (e1->op == TOKimport && !e1->type) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6010 { ScopeExp *se = (ScopeExp *)e1; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6011 TemplateInstance *ti = se->sds->isTemplateInstance(); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6012 if (ti && !ti->semanticdone) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6013 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6014 /* Attempt to instantiate ti. If that works, go with it. |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6015 * If not, go with partial explicit specialization. |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6016 */ |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6017 ti->semanticTiargs(sc); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6018 unsigned errors = global.errors; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6019 global.gag++; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6020 ti->semantic(sc); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6021 global.gag--; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6022 if (errors != global.errors) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6023 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6024 /* Didn't work, go with partial explicit specialization |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6025 */ |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6026 global.errors = errors; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6027 targsi = ti->tiargs; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6028 e1 = new IdentifierExp(loc, ti->name); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6029 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6030 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6031 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6032 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6033 /* This recognizes: |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6034 * expr.foo!(tiargs)(funcargs) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6035 */ |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6036 if (e1->op == TOKdotti && !e1->type) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6037 { DotTemplateInstanceExp *se = (DotTemplateInstanceExp *)e1; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6038 TemplateInstance *ti = se->ti; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6039 if (!ti->semanticdone) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6040 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6041 /* Attempt to instantiate ti. If that works, go with it. |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6042 * If not, go with partial explicit specialization. |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6043 */ |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6044 ti->semanticTiargs(sc); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6045 Expression *etmp; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6046 unsigned errors = global.errors; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6047 global.gag++; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6048 etmp = e1->semantic(sc); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6049 global.gag--; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6050 if (errors != global.errors) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6051 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6052 global.errors = errors; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6053 targsi = ti->tiargs; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6054 e1 = new DotIdExp(loc, se->e1, ti->name); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6055 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6056 else |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6057 e1 = etmp; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6058 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6059 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6060 #endif |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6061 |
159 | 6062 istemp = 0; |
6063 Lagain: | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6064 //printf("Lagain: %s\n", toChars()); |
159 | 6065 f = NULL; |
6066 if (e1->op == TOKthis || e1->op == TOKsuper) | |
6067 { | |
6068 // semantic() run later for these | |
6069 } | |
6070 else | |
6071 { | |
6072 UnaExp::semantic(sc); | |
6073 | |
6074 /* Look for e1 being a lazy parameter | |
6075 */ | |
6076 if (e1->op == TOKvar) | |
6077 { VarExp *ve = (VarExp *)e1; | |
6078 | |
6079 if (ve->var->storage_class & STClazy) | |
6080 { | |
6081 TypeFunction *tf = new TypeFunction(NULL, ve->var->type, 0, LINKd); | |
6082 TypeDelegate *t = new TypeDelegate(tf); | |
6083 ve->type = t->semantic(loc, sc); | |
6084 } | |
6085 } | |
6086 | |
6087 if (e1->op == TOKimport) | |
6088 { // Perhaps this should be moved to ScopeExp::semantic() | |
6089 ScopeExp *se = (ScopeExp *)e1; | |
6090 e1 = new DsymbolExp(loc, se->sds); | |
6091 e1 = e1->semantic(sc); | |
6092 } | |
6093 #if 1 // patch for #540 by Oskar Linde | |
6094 else if (e1->op == TOKdotexp) | |
6095 { | |
6096 DotExp *de = (DotExp *) e1; | |
6097 | |
6098 if (de->e2->op == TOKimport) | |
6099 { // This should *really* be moved to ScopeExp::semantic() | |
6100 ScopeExp *se = (ScopeExp *)de->e2; | |
6101 de->e2 = new DsymbolExp(loc, se->sds); | |
6102 de->e2 = de->e2->semantic(sc); | |
6103 } | |
6104 | |
6105 if (de->e2->op == TOKtemplate) | |
6106 { TemplateExp *te = (TemplateExp *) de->e2; | |
6107 e1 = new DotTemplateExp(loc,de->e1,te->td); | |
6108 } | |
6109 } | |
6110 #endif | |
6111 } | |
6112 | |
6113 if (e1->op == TOKcomma) | |
6114 { | |
6115 CommaExp *ce = (CommaExp *)e1; | |
6116 | |
6117 e1 = ce->e2; | |
6118 e1->type = ce->type; | |
6119 ce->e2 = this; | |
6120 ce->type = NULL; | |
6121 return ce->semantic(sc); | |
6122 } | |
6123 | |
6124 t1 = NULL; | |
6125 if (e1->type) | |
6126 t1 = e1->type->toBasetype(); | |
6127 | |
6128 // Check for call operator overload | |
6129 if (t1) | |
6130 { AggregateDeclaration *ad; | |
6131 | |
6132 if (t1->ty == Tstruct) | |
6133 { | |
6134 ad = ((TypeStruct *)t1)->sym; | |
6135 if (search_function(ad, Id::call)) | |
6136 goto L1; // overload of opCall, therefore it's a call | |
6137 | |
6138 if (e1->op != TOKtype) | |
6139 error("%s %s does not overload ()", ad->kind(), ad->toChars()); | |
6140 /* It's a struct literal | |
6141 */ | |
6142 Expression *e = new StructLiteralExp(loc, (StructDeclaration *)ad, arguments); | |
6143 e = e->semantic(sc); | |
6144 e->type = e1->type; // in case e1->type was a typedef | |
6145 return e; | |
6146 } | |
6147 else if (t1->ty == Tclass) | |
6148 { | |
6149 ad = ((TypeClass *)t1)->sym; | |
6150 goto L1; | |
6151 L1: | |
6152 // Rewrite as e1.call(arguments) | |
6153 Expression *e = new DotIdExp(loc, e1, Id::call); | |
6154 e = new CallExp(loc, e, arguments); | |
6155 e = e->semantic(sc); | |
6156 return e; | |
6157 } | |
6158 } | |
6159 | |
6160 arrayExpressionSemantic(arguments, sc); | |
6161 preFunctionArguments(loc, sc, arguments); | |
6162 | |
6163 if (e1->op == TOKdotvar && t1->ty == Tfunction || | |
6164 e1->op == TOKdottd) | |
6165 { | |
6166 DotVarExp *dve; | |
6167 DotTemplateExp *dte; | |
6168 AggregateDeclaration *ad; | |
6169 UnaExp *ue = (UnaExp *)(e1); | |
336 | 6170 |
159 | 6171 if (e1->op == TOKdotvar) |
6172 { // Do overload resolution | |
6173 dve = (DotVarExp *)(e1); | |
6174 | |
6175 f = dve->var->isFuncDeclaration(); | |
6176 assert(f); | |
6177 f = f->overloadResolve(loc, arguments); | |
6178 | |
6179 ad = f->toParent()->isAggregateDeclaration(); | |
6180 } | |
6181 else | |
6182 { dte = (DotTemplateExp *)(e1); | |
6183 TemplateDeclaration *td = dte->td; | |
6184 assert(td); | |
6185 if (!arguments) | |
6186 // Should fix deduceFunctionTemplate() so it works on NULL argument | |
6187 arguments = new Expressions(); | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6188 f = td->deduceFunctionTemplate(sc, loc, targsi, NULL, arguments); |
159 | 6189 if (!f) |
6190 { type = Type::terror; | |
6191 return this; | |
6192 } | |
6193 ad = td->toParent()->isAggregateDeclaration(); | |
6194 } | |
336 | 6195 if (f->needThis()) |
6196 { | |
6197 ue->e1 = getRightThis(loc, sc, ad, ue->e1, f); | |
6198 } | |
6199 | |
6200 /* Cannot call public functions from inside invariant | |
6201 * (because then the invariant would have infinite recursion) | |
159 | 6202 */ |
336 | 6203 if (sc->func && sc->func->isInvariantDeclaration() && |
6204 ue->e1->op == TOKthis && | |
6205 f->addPostInvariant() | |
159 | 6206 ) |
6207 { | |
336 | 6208 error("cannot call public/export function %s from invariant", f->toChars()); |
159 | 6209 } |
6210 | |
6211 checkDeprecated(sc, f); | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6212 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6213 checkPurity(sc, f); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6214 #endif |
159 | 6215 accessCheck(loc, sc, ue->e1, f); |
6216 if (!f->needThis()) | |
6217 { | |
6218 VarExp *ve = new VarExp(loc, f); | |
6219 e1 = new CommaExp(loc, ue->e1, ve); | |
6220 e1->type = f->type; | |
6221 } | |
6222 else | |
6223 { | |
6224 if (e1->op == TOKdotvar) | |
6225 dve->var = f; | |
6226 else | |
6227 e1 = new DotVarExp(loc, dte->e1, f); | |
6228 e1->type = f->type; | |
6229 | |
6230 // See if we need to adjust the 'this' pointer | |
6231 AggregateDeclaration *ad = f->isThis(); | |
6232 ClassDeclaration *cd = ue->e1->type->isClassHandle(); | |
6233 if (ad && cd && ad->isClassDeclaration() && ad != cd && | |
6234 ue->e1->op != TOKsuper) | |
6235 { | |
6236 ue->e1 = ue->e1->castTo(sc, ad->type); //new CastExp(loc, ue->e1, ad->type); | |
6237 ue->e1 = ue->e1->semantic(sc); | |
6238 } | |
6239 } | |
6240 t1 = e1->type; | |
6241 } | |
6242 else if (e1->op == TOKsuper) | |
6243 { | |
6244 // Base class constructor call | |
6245 ClassDeclaration *cd = NULL; | |
6246 | |
6247 if (sc->func) | |
6248 cd = sc->func->toParent()->isClassDeclaration(); | |
6249 if (!cd || !cd->baseClass || !sc->func->isCtorDeclaration()) | |
6250 { | |
6251 error("super class constructor call must be in a constructor"); | |
6252 type = Type::terror; | |
6253 return this; | |
6254 } | |
6255 else | |
6256 { | |
6257 f = cd->baseClass->ctor; | |
6258 if (!f) | |
6259 { error("no super class constructor for %s", cd->baseClass->toChars()); | |
6260 type = Type::terror; | |
6261 return this; | |
6262 } | |
6263 else | |
6264 { | |
336 | 6265 if (!sc->intypeof) |
6266 { | |
159 | 6267 #if 0 |
336 | 6268 if (sc->callSuper & (CSXthis | CSXsuper)) |
6269 error("reference to this before super()"); | |
159 | 6270 #endif |
336 | 6271 if (sc->noctor || sc->callSuper & CSXlabel) |
6272 error("constructor calls not allowed in loops or after labels"); | |
6273 if (sc->callSuper & (CSXsuper_ctor | CSXthis_ctor)) | |
6274 error("multiple constructor calls"); | |
6275 sc->callSuper |= CSXany_ctor | CSXsuper_ctor; | |
6276 } | |
159 | 6277 |
6278 f = f->overloadResolve(loc, arguments); | |
6279 checkDeprecated(sc, f); | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6280 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6281 checkPurity(sc, f); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6282 #endif |
159 | 6283 e1 = new DotVarExp(e1->loc, e1, f); |
6284 e1 = e1->semantic(sc); | |
6285 t1 = e1->type; | |
6286 } | |
6287 } | |
6288 } | |
6289 else if (e1->op == TOKthis) | |
6290 { | |
6291 // same class constructor call | |
6292 ClassDeclaration *cd = NULL; | |
6293 | |
6294 if (sc->func) | |
6295 cd = sc->func->toParent()->isClassDeclaration(); | |
6296 if (!cd || !sc->func->isCtorDeclaration()) | |
6297 { | |
6298 error("class constructor call must be in a constructor"); | |
6299 type = Type::terror; | |
6300 return this; | |
6301 } | |
6302 else | |
6303 { | |
336 | 6304 if (!sc->intypeof) |
6305 { | |
159 | 6306 #if 0 |
336 | 6307 if (sc->callSuper & (CSXthis | CSXsuper)) |
6308 error("reference to this before super()"); | |
159 | 6309 #endif |
336 | 6310 if (sc->noctor || sc->callSuper & CSXlabel) |
6311 error("constructor calls not allowed in loops or after labels"); | |
6312 if (sc->callSuper & (CSXsuper_ctor | CSXthis_ctor)) | |
6313 error("multiple constructor calls"); | |
6314 sc->callSuper |= CSXany_ctor | CSXthis_ctor; | |
6315 } | |
159 | 6316 |
6317 f = cd->ctor; | |
6318 f = f->overloadResolve(loc, arguments); | |
6319 checkDeprecated(sc, f); | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6320 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6321 checkPurity(sc, f); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6322 #endif |
159 | 6323 e1 = new DotVarExp(e1->loc, e1, f); |
6324 e1 = e1->semantic(sc); | |
6325 t1 = e1->type; | |
6326 | |
6327 // BUG: this should really be done by checking the static | |
6328 // call graph | |
6329 if (f == sc->func) | |
6330 error("cyclic constructor call"); | |
6331 } | |
6332 } | |
6333 else if (!t1) | |
6334 { | |
6335 error("function expected before (), not '%s'", e1->toChars()); | |
6336 type = Type::terror; | |
6337 return this; | |
6338 } | |
6339 else if (t1->ty != Tfunction) | |
6340 { | |
6341 if (t1->ty == Tdelegate) | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6342 { TypeDelegate *td = (TypeDelegate *)t1; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6343 assert(td->next->ty == Tfunction); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6344 tf = (TypeFunction *)(td->next); |
159 | 6345 goto Lcheckargs; |
6346 } | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6347 else if (t1->ty == Tpointer && ((TypePointer *)t1)->next->ty == Tfunction) |
159 | 6348 { Expression *e; |
6349 | |
6350 e = new PtrExp(loc, e1); | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6351 t1 = ((TypePointer *)t1)->next; |
159 | 6352 e->type = t1; |
6353 e1 = e; | |
6354 } | |
6355 else if (e1->op == TOKtemplate) | |
6356 { | |
6357 TemplateExp *te = (TemplateExp *)e1; | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6358 f = te->td->deduceFunctionTemplate(sc, loc, targsi, NULL, arguments); |
159 | 6359 if (!f) |
6360 { type = Type::terror; | |
6361 return this; | |
6362 } | |
6363 if (f->needThis() && hasThis(sc)) | |
6364 { | |
6365 // Supply an implicit 'this', as in | |
6366 // this.ident | |
6367 | |
6368 e1 = new DotTemplateExp(loc, (new ThisExp(loc))->semantic(sc), te->td); | |
6369 goto Lagain; | |
6370 } | |
6371 | |
6372 e1 = new VarExp(loc, f); | |
6373 goto Lagain; | |
6374 } | |
6375 else | |
6376 { error("function expected before (), not %s of type %s", e1->toChars(), e1->type->toChars()); | |
6377 type = Type::terror; | |
6378 return this; | |
6379 } | |
6380 } | |
6381 else if (e1->op == TOKvar) | |
6382 { | |
6383 // Do overload resolution | |
6384 VarExp *ve = (VarExp *)e1; | |
6385 | |
6386 f = ve->var->isFuncDeclaration(); | |
6387 assert(f); | |
6388 | |
6389 // Look to see if f is really a function template | |
6390 if (0 && !istemp && f->parent) | |
6391 { TemplateInstance *ti = f->parent->isTemplateInstance(); | |
6392 | |
6393 if (ti && | |
6394 (ti->name == f->ident || | |
6395 ti->toAlias()->ident == f->ident) | |
6396 && | |
6397 ti->tempdecl) | |
6398 { | |
6399 /* This is so that one can refer to the enclosing | |
6400 * template, even if it has the same name as a member | |
6401 * of the template, if it has a !(arguments) | |
6402 */ | |
6403 TemplateDeclaration *tempdecl = ti->tempdecl; | |
6404 if (tempdecl->overroot) // if not start of overloaded list of TemplateDeclaration's | |
6405 tempdecl = tempdecl->overroot; // then get the start | |
6406 e1 = new TemplateExp(loc, tempdecl); | |
6407 istemp = 1; | |
6408 goto Lagain; | |
6409 } | |
6410 } | |
6411 | |
6412 f = f->overloadResolve(loc, arguments); | |
6413 checkDeprecated(sc, f); | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6414 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6415 checkPurity(sc, f); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6416 #endif |
159 | 6417 |
6418 if (f->needThis() && hasThis(sc)) | |
6419 { | |
6420 // Supply an implicit 'this', as in | |
6421 // this.ident | |
6422 | |
6423 e1 = new DotVarExp(loc, new ThisExp(loc), f); | |
6424 goto Lagain; | |
6425 } | |
6426 | |
6427 accessCheck(loc, sc, NULL, f); | |
6428 | |
6429 ve->var = f; | |
6430 ve->type = f->type; | |
6431 t1 = f->type; | |
6432 } | |
6433 assert(t1->ty == Tfunction); | |
6434 tf = (TypeFunction *)(t1); | |
6435 | |
6436 Lcheckargs: | |
6437 assert(tf->ty == Tfunction); | |
6438 type = tf->next; | |
6439 | |
6440 if (!arguments) | |
6441 arguments = new Expressions(); | |
6442 functionArguments(loc, sc, tf, arguments); | |
6443 | |
6444 assert(type); | |
6445 | |
6446 if (f && f->tintro) | |
6447 { | |
6448 Type *t = type; | |
6449 int offset = 0; | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6450 TypeFunction *tf = (TypeFunction *)f->tintro; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6451 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6452 if (tf->next->isBaseOf(t, &offset) && offset) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6453 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6454 type = tf->next; |
159 | 6455 return castTo(sc, t); |
6456 } | |
6457 } | |
6458 | |
6459 return this; | |
6460 } | |
6461 | |
6462 int CallExp::checkSideEffect(int flag) | |
6463 { | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6464 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6465 if (flag != 2) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6466 return 1; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6467 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6468 if (e1->checkSideEffect(2)) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6469 return 1; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6470 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6471 /* If any of the arguments have side effects, this expression does |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6472 */ |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6473 for (size_t i = 0; i < arguments->dim; i++) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6474 { Expression *e = (Expression *)arguments->data[i]; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6475 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6476 if (e->checkSideEffect(2)) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6477 return 1; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6478 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6479 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6480 /* If calling a function or delegate that is typed as pure, |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6481 * then this expression has no side effects. |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6482 */ |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6483 Type *t = e1->type->toBasetype(); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6484 if (t->ty == Tfunction && ((TypeFunction *)t)->ispure) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6485 return 0; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6486 if (t->ty == Tdelegate && ((TypeFunction *)((TypeDelegate *)t)->next)->ispure) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6487 return 0; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6488 #endif |
159 | 6489 return 1; |
6490 } | |
6491 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6492 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6493 int CallExp::canThrow() |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6494 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6495 if (e1->canThrow()) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6496 return 1; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6497 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6498 /* If any of the arguments can throw, then this expression can throw |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6499 */ |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6500 for (size_t i = 0; i < arguments->dim; i++) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6501 { Expression *e = (Expression *)arguments->data[i]; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6502 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6503 if (e->canThrow()) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6504 return 1; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6505 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6506 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6507 /* If calling a function or delegate that is typed as nothrow, |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6508 * then this expression cannot throw. |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6509 * Note that pure functions can throw. |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6510 */ |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6511 Type *t = e1->type->toBasetype(); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6512 if (t->ty == Tfunction && ((TypeFunction *)t)->isnothrow) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6513 return 0; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6514 if (t->ty == Tdelegate && ((TypeFunction *)((TypeDelegate *)t)->next)->isnothrow) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6515 return 0; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6516 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6517 return 1; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6518 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6519 #endif |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6520 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6521 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6522 int CallExp::isLvalue() |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6523 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6524 if (type->toBasetype()->ty == Tstruct) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6525 return 1; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6526 Type *tb = e1->type->toBasetype(); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6527 if (tb->ty == Tfunction && ((TypeFunction *)tb)->isref) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6528 return 1; // function returns a reference |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6529 return 0; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6530 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6531 #endif |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6532 |
159 | 6533 Expression *CallExp::toLvalue(Scope *sc, Expression *e) |
6534 { | |
6535 if (type->toBasetype()->ty == Tstruct) | |
6536 return this; | |
6537 else | |
6538 return Expression::toLvalue(sc, e); | |
6539 } | |
6540 | |
6541 void CallExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
6542 { int i; | |
6543 | |
6544 expToCBuffer(buf, hgs, e1, precedence[op]); | |
6545 buf->writeByte('('); | |
6546 argsToCBuffer(buf, arguments, hgs); | |
6547 buf->writeByte(')'); | |
6548 } | |
6549 | |
6550 | |
6551 /************************************************************/ | |
6552 | |
6553 AddrExp::AddrExp(Loc loc, Expression *e) | |
6554 : UnaExp(loc, TOKaddress, sizeof(AddrExp), e) | |
6555 { | |
6556 } | |
6557 | |
6558 Expression *AddrExp::semantic(Scope *sc) | |
6559 { | |
6560 #if LOGSEMANTIC | |
6561 printf("AddrExp::semantic('%s')\n", toChars()); | |
6562 #endif | |
6563 if (!type) | |
6564 { | |
6565 UnaExp::semantic(sc); | |
6566 e1 = e1->toLvalue(sc, NULL); | |
6567 if (!e1->type) | |
6568 { | |
6569 error("cannot take address of %s", e1->toChars()); | |
6570 type = Type::tint32; | |
6571 return this; | |
6572 } | |
6573 type = e1->type->pointerTo(); | |
6574 | |
6575 // See if this should really be a delegate | |
6576 if (e1->op == TOKdotvar) | |
6577 { | |
6578 DotVarExp *dve = (DotVarExp *)e1; | |
6579 FuncDeclaration *f = dve->var->isFuncDeclaration(); | |
6580 | |
6581 if (f) | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6582 { Expression *e = new DelegateExp(loc, dve->e1, f); |
159 | 6583 e = e->semantic(sc); |
6584 return e; | |
6585 } | |
6586 } | |
6587 else if (e1->op == TOKvar) | |
6588 { | |
6589 VarExp *dve = (VarExp *)e1; | |
6590 FuncDeclaration *f = dve->var->isFuncDeclaration(); | |
6591 VarDeclaration *v = dve->var->isVarDeclaration(); | |
6592 | |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
639
diff
changeset
|
6593 // LDC |
486
a34078905d01
Added pragma(llvmdc, "string") for misc per-module compiler configuration, currently "string" can only be "verbose" which forces -vv for module it appears in.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
471
diff
changeset
|
6594 if (f && f->isIntrinsic()) |
a34078905d01
Added pragma(llvmdc, "string") for misc per-module compiler configuration, currently "string" can only be "verbose" which forces -vv for module it appears in.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
471
diff
changeset
|
6595 { |
a34078905d01
Added pragma(llvmdc, "string") for misc per-module compiler configuration, currently "string" can only be "verbose" which forces -vv for module it appears in.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
471
diff
changeset
|
6596 error("cannot take the address of intrinsic function %s", e1->toChars()); |
a34078905d01
Added pragma(llvmdc, "string") for misc per-module compiler configuration, currently "string" can only be "verbose" which forces -vv for module it appears in.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
471
diff
changeset
|
6597 return this; |
a34078905d01
Added pragma(llvmdc, "string") for misc per-module compiler configuration, currently "string" can only be "verbose" which forces -vv for module it appears in.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
471
diff
changeset
|
6598 } |
a34078905d01
Added pragma(llvmdc, "string") for misc per-module compiler configuration, currently "string" can only be "verbose" which forces -vv for module it appears in.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
471
diff
changeset
|
6599 |
159 | 6600 if (f && f->isNested()) |
6601 { Expression *e; | |
6602 | |
6603 e = new DelegateExp(loc, e1, f); | |
6604 e = e->semantic(sc); | |
6605 return e; | |
6606 } | |
6607 } | |
6608 else if (e1->op == TOKarray) | |
6609 { | |
6610 if (e1->type->toBasetype()->ty == Tbit) | |
6611 error("cannot take address of bit in array"); | |
6612 } | |
6613 return optimize(WANTvalue); | |
6614 } | |
6615 return this; | |
6616 } | |
6617 | |
6618 /************************************************************/ | |
6619 | |
6620 PtrExp::PtrExp(Loc loc, Expression *e) | |
6621 : UnaExp(loc, TOKstar, sizeof(PtrExp), e) | |
6622 { | |
6623 if (e->type) | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6624 type = ((TypePointer *)e->type)->next; |
159 | 6625 } |
6626 | |
6627 PtrExp::PtrExp(Loc loc, Expression *e, Type *t) | |
6628 : UnaExp(loc, TOKstar, sizeof(PtrExp), e) | |
6629 { | |
6630 type = t; | |
6631 } | |
6632 | |
6633 Expression *PtrExp::semantic(Scope *sc) | |
6634 { Type *tb; | |
6635 | |
6636 #if LOGSEMANTIC | |
6637 printf("PtrExp::semantic('%s')\n", toChars()); | |
6638 #endif | |
6639 UnaExp::semantic(sc); | |
6640 e1 = resolveProperties(sc, e1); | |
6641 if (type) | |
6642 return this; | |
6643 if (!e1->type) | |
6644 printf("PtrExp::semantic('%s')\n", toChars()); | |
6645 tb = e1->type->toBasetype(); | |
6646 switch (tb->ty) | |
6647 { | |
6648 case Tpointer: | |
6649 type = tb->next; | |
6650 if (type->isbit()) | |
6651 { Expression *e; | |
6652 | |
6653 // Rewrite *p as p[0] | |
6654 e = new IndexExp(loc, e1, new IntegerExp(0)); | |
6655 return e->semantic(sc); | |
6656 } | |
6657 break; | |
6658 | |
6659 case Tsarray: | |
6660 case Tarray: | |
6661 type = tb->next; | |
6662 e1 = e1->castTo(sc, type->pointerTo()); | |
6663 break; | |
6664 | |
6665 default: | |
6666 error("can only * a pointer, not a '%s'", e1->type->toChars()); | |
6667 type = Type::tint32; | |
6668 break; | |
6669 } | |
6670 rvalue(); | |
6671 return this; | |
6672 } | |
6673 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6674 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6675 int PtrExp::isLvalue() |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6676 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6677 return 1; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6678 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6679 #endif |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6680 |
159 | 6681 Expression *PtrExp::toLvalue(Scope *sc, Expression *e) |
6682 { | |
6683 #if 0 | |
6684 tym = tybasic(e1->ET->Tty); | |
6685 if (!(tyscalar(tym) || | |
6686 tym == TYstruct || | |
6687 tym == TYarray && e->Eoper == TOKaddr)) | |
6688 synerr(EM_lvalue); // lvalue expected | |
6689 #endif | |
6690 return this; | |
6691 } | |
6692 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6693 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6694 Expression *PtrExp::modifiableLvalue(Scope *sc, Expression *e) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6695 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6696 //printf("PtrExp::modifiableLvalue() %s, type %s\n", toChars(), type->toChars()); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6697 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6698 if (e1->op == TOKsymoff) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6699 { SymOffExp *se = (SymOffExp *)e1; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6700 se->var->checkModify(loc, sc, type); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6701 //return toLvalue(sc, e); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6702 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6703 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6704 return Expression::modifiableLvalue(sc, e); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6705 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6706 #endif |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6707 |
159 | 6708 void PtrExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
6709 { | |
6710 buf->writeByte('*'); | |
6711 expToCBuffer(buf, hgs, e1, precedence[op]); | |
6712 } | |
6713 | |
6714 /************************************************************/ | |
6715 | |
6716 NegExp::NegExp(Loc loc, Expression *e) | |
6717 : UnaExp(loc, TOKneg, sizeof(NegExp), e) | |
6718 { | |
6719 } | |
6720 | |
6721 Expression *NegExp::semantic(Scope *sc) | |
6722 { Expression *e; | |
6723 | |
6724 #if LOGSEMANTIC | |
6725 printf("NegExp::semantic('%s')\n", toChars()); | |
6726 #endif | |
6727 if (!type) | |
6728 { | |
6729 UnaExp::semantic(sc); | |
6730 e1 = resolveProperties(sc, e1); | |
6731 e = op_overload(sc); | |
6732 if (e) | |
6733 return e; | |
6734 | |
6735 e1->checkNoBool(); | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6736 if (e1->op != TOKslice) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6737 e1->checkArithmetic(); |
159 | 6738 type = e1->type; |
6739 } | |
6740 return this; | |
6741 } | |
6742 | |
6743 /************************************************************/ | |
6744 | |
6745 UAddExp::UAddExp(Loc loc, Expression *e) | |
6746 : UnaExp(loc, TOKuadd, sizeof(UAddExp), e) | |
6747 { | |
6748 } | |
6749 | |
6750 Expression *UAddExp::semantic(Scope *sc) | |
6751 { Expression *e; | |
6752 | |
6753 #if LOGSEMANTIC | |
6754 printf("UAddExp::semantic('%s')\n", toChars()); | |
6755 #endif | |
6756 assert(!type); | |
6757 UnaExp::semantic(sc); | |
6758 e1 = resolveProperties(sc, e1); | |
6759 e = op_overload(sc); | |
6760 if (e) | |
6761 return e; | |
6762 e1->checkNoBool(); | |
6763 e1->checkArithmetic(); | |
6764 return e1; | |
6765 } | |
6766 | |
6767 /************************************************************/ | |
6768 | |
6769 ComExp::ComExp(Loc loc, Expression *e) | |
6770 : UnaExp(loc, TOKtilde, sizeof(ComExp), e) | |
6771 { | |
6772 } | |
6773 | |
6774 Expression *ComExp::semantic(Scope *sc) | |
6775 { Expression *e; | |
6776 | |
6777 if (!type) | |
6778 { | |
6779 UnaExp::semantic(sc); | |
6780 e1 = resolveProperties(sc, e1); | |
6781 e = op_overload(sc); | |
6782 if (e) | |
6783 return e; | |
6784 | |
6785 e1->checkNoBool(); | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6786 if (e1->op != TOKslice) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6787 e1 = e1->checkIntegral(); |
159 | 6788 type = e1->type; |
6789 } | |
6790 return this; | |
6791 } | |
6792 | |
6793 /************************************************************/ | |
6794 | |
6795 NotExp::NotExp(Loc loc, Expression *e) | |
6796 : UnaExp(loc, TOKnot, sizeof(NotExp), e) | |
6797 { | |
6798 } | |
6799 | |
6800 Expression *NotExp::semantic(Scope *sc) | |
6801 { | |
6802 UnaExp::semantic(sc); | |
6803 e1 = resolveProperties(sc, e1); | |
6804 e1 = e1->checkToBoolean(); | |
6805 type = Type::tboolean; | |
6806 return this; | |
6807 } | |
6808 | |
6809 int NotExp::isBit() | |
6810 { | |
6811 return TRUE; | |
6812 } | |
6813 | |
6814 | |
6815 | |
6816 /************************************************************/ | |
6817 | |
6818 BoolExp::BoolExp(Loc loc, Expression *e, Type *t) | |
6819 : UnaExp(loc, TOKtobool, sizeof(BoolExp), e) | |
6820 { | |
6821 type = t; | |
6822 } | |
6823 | |
6824 Expression *BoolExp::semantic(Scope *sc) | |
6825 { | |
6826 UnaExp::semantic(sc); | |
6827 e1 = resolveProperties(sc, e1); | |
6828 e1 = e1->checkToBoolean(); | |
6829 type = Type::tboolean; | |
6830 return this; | |
6831 } | |
6832 | |
6833 int BoolExp::isBit() | |
6834 { | |
6835 return TRUE; | |
6836 } | |
6837 | |
6838 /************************************************************/ | |
6839 | |
6840 DeleteExp::DeleteExp(Loc loc, Expression *e) | |
6841 : UnaExp(loc, TOKdelete, sizeof(DeleteExp), e) | |
6842 { | |
6843 } | |
6844 | |
6845 Expression *DeleteExp::semantic(Scope *sc) | |
6846 { | |
6847 Type *tb; | |
6848 | |
6849 UnaExp::semantic(sc); | |
6850 e1 = resolveProperties(sc, e1); | |
6851 e1 = e1->toLvalue(sc, NULL); | |
6852 type = Type::tvoid; | |
6853 | |
6854 tb = e1->type->toBasetype(); | |
6855 switch (tb->ty) | |
6856 { case Tclass: | |
6857 { TypeClass *tc = (TypeClass *)tb; | |
6858 ClassDeclaration *cd = tc->sym; | |
6859 | |
6860 if (cd->isCOMinterface()) | |
6861 { /* Because COM classes are deleted by IUnknown.Release() | |
6862 */ | |
6863 error("cannot delete instance of COM interface %s", cd->toChars()); | |
6864 } | |
6865 break; | |
6866 } | |
6867 case Tpointer: | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6868 tb = ((TypePointer *)tb)->next->toBasetype(); |
159 | 6869 if (tb->ty == Tstruct) |
6870 { | |
6871 TypeStruct *ts = (TypeStruct *)tb; | |
6872 StructDeclaration *sd = ts->sym; | |
6873 FuncDeclaration *f = sd->aggDelete; | |
6874 | |
6875 if (f) | |
6876 { | |
6877 Type *tpv = Type::tvoid->pointerTo(); | |
6878 | |
6879 Expression *e = e1->castTo(sc, tpv); | |
6880 Expression *ec = new VarExp(loc, f); | |
6881 e = new CallExp(loc, ec, e); | |
6882 return e->semantic(sc); | |
6883 } | |
6884 } | |
6885 break; | |
6886 | |
6887 case Tarray: | |
6888 break; | |
6889 | |
6890 default: | |
6891 if (e1->op == TOKindex) | |
6892 { | |
6893 IndexExp *ae = (IndexExp *)(e1); | |
6894 Type *tb1 = ae->e1->type->toBasetype(); | |
6895 if (tb1->ty == Taarray) | |
6896 break; | |
6897 } | |
6898 error("cannot delete type %s", e1->type->toChars()); | |
6899 break; | |
6900 } | |
6901 | |
6902 if (e1->op == TOKindex) | |
6903 { | |
6904 IndexExp *ae = (IndexExp *)(e1); | |
6905 Type *tb1 = ae->e1->type->toBasetype(); | |
6906 if (tb1->ty == Taarray) | |
6907 { if (!global.params.useDeprecated) | |
6908 error("delete aa[key] deprecated, use aa.remove(key)"); | |
6909 } | |
6910 } | |
6911 | |
6912 return this; | |
6913 } | |
6914 | |
6915 int DeleteExp::checkSideEffect(int flag) | |
6916 { | |
6917 return 1; | |
6918 } | |
6919 | |
6920 Expression *DeleteExp::checkToBoolean() | |
6921 { | |
6922 error("delete does not give a boolean result"); | |
6923 return this; | |
6924 } | |
6925 | |
6926 void DeleteExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
6927 { | |
6928 buf->writestring("delete "); | |
6929 expToCBuffer(buf, hgs, e1, precedence[op]); | |
6930 } | |
6931 | |
6932 /************************************************************/ | |
6933 | |
6934 CastExp::CastExp(Loc loc, Expression *e, Type *t) | |
6935 : UnaExp(loc, TOKcast, sizeof(CastExp), e) | |
6936 { | |
6937 to = t; | |
6938 } | |
6939 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6940 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6941 /* For cast(const) and cast(immutable) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6942 */ |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6943 CastExp::CastExp(Loc loc, Expression *e, unsigned mod) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6944 : UnaExp(loc, TOKcast, sizeof(CastExp), e) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6945 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6946 to = NULL; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6947 this->mod = mod; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6948 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6949 #endif |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
6950 |
159 | 6951 Expression *CastExp::syntaxCopy() |
6952 { | |
6953 return new CastExp(loc, e1->syntaxCopy(), to->syntaxCopy()); | |
6954 } | |
6955 | |
6956 | |
6957 Expression *CastExp::semantic(Scope *sc) | |
6958 { Expression *e; | |
6959 BinExp *b; | |
6960 UnaExp *u; | |
6961 | |
6962 #if LOGSEMANTIC | |
6963 printf("CastExp::semantic('%s')\n", toChars()); | |
6964 #endif | |
6965 | |
6966 //static int x; assert(++x < 10); | |
6967 | |
6968 if (type) | |
6969 return this; | |
6970 UnaExp::semantic(sc); | |
6971 if (e1->type) // if not a tuple | |
6972 { | |
6973 e1 = resolveProperties(sc, e1); | |
6974 to = to->semantic(loc, sc); | |
6975 | |
6976 e = op_overload(sc); | |
6977 if (e) | |
6978 { | |
6979 return e->implicitCastTo(sc, to); | |
6980 } | |
6981 | |
6982 Type *tob = to->toBasetype(); | |
6983 if (tob->ty == Tstruct && | |
6984 !tob->equals(e1->type->toBasetype()) && | |
6985 ((TypeStruct *)to)->sym->search(0, Id::call, 0) | |
6986 ) | |
6987 { | |
6988 /* Look to replace: | |
6989 * cast(S)t | |
6990 * with: | |
6991 * S(t) | |
6992 */ | |
6993 | |
6994 // Rewrite as to.call(e1) | |
6995 e = new TypeExp(loc, to); | |
6996 e = new DotIdExp(loc, e, Id::call); | |
6997 e = new CallExp(loc, e, e1); | |
6998 e = e->semantic(sc); | |
6999 return e; | |
7000 } | |
7001 } | |
7002 e = e1->castTo(sc, to); | |
7003 return e; | |
7004 } | |
7005 | |
7006 int CastExp::checkSideEffect(int flag) | |
7007 { | |
7008 /* if not: | |
7009 * cast(void) | |
7010 * cast(classtype)func() | |
7011 */ | |
7012 if (!to->equals(Type::tvoid) && | |
7013 !(to->ty == Tclass && e1->op == TOKcall && e1->type->ty == Tclass)) | |
7014 return Expression::checkSideEffect(flag); | |
7015 return 1; | |
7016 } | |
7017 | |
7018 void CastExp::checkEscape() | |
7019 { Type *tb = type->toBasetype(); | |
7020 if (tb->ty == Tarray && e1->op == TOKvar && | |
7021 e1->type->toBasetype()->ty == Tsarray) | |
7022 { VarExp *ve = (VarExp *)e1; | |
7023 VarDeclaration *v = ve->var->isVarDeclaration(); | |
7024 if (v) | |
7025 { | |
7026 if (!v->isDataseg() && !v->isParameter()) | |
7027 error("escaping reference to local %s", v->toChars()); | |
7028 } | |
7029 } | |
7030 } | |
7031 | |
7032 void CastExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
7033 { | |
7034 buf->writestring("cast("); | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7035 #if DMDV1 |
159 | 7036 to->toCBuffer(buf, NULL, hgs); |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7037 #else |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7038 if (to) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7039 to->toCBuffer(buf, NULL, hgs); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7040 else |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7041 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7042 switch (mod) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7043 { case 0: |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7044 break; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7045 case MODconst: |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7046 buf->writestring(Token::tochars[TOKconst]); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7047 break; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7048 case MODinvariant: |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7049 buf->writestring(Token::tochars[TOKimmutable]); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7050 break; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7051 case MODshared: |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7052 buf->writestring(Token::tochars[TOKshared]); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7053 break; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7054 case MODshared | MODconst: |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7055 buf->writestring(Token::tochars[TOKshared]); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7056 buf->writeByte(' '); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7057 buf->writestring(Token::tochars[TOKconst]); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7058 break; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7059 default: |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7060 assert(0); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7061 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7062 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7063 #endif |
159 | 7064 buf->writeByte(')'); |
7065 expToCBuffer(buf, hgs, e1, precedence[op]); | |
7066 } | |
7067 | |
7068 | |
7069 /************************************************************/ | |
7070 | |
7071 SliceExp::SliceExp(Loc loc, Expression *e1, Expression *lwr, Expression *upr) | |
7072 : UnaExp(loc, TOKslice, sizeof(SliceExp), e1) | |
7073 { | |
7074 this->upr = upr; | |
7075 this->lwr = lwr; | |
7076 lengthVar = NULL; | |
7077 } | |
7078 | |
7079 Expression *SliceExp::syntaxCopy() | |
7080 { | |
7081 Expression *lwr = NULL; | |
7082 if (this->lwr) | |
7083 lwr = this->lwr->syntaxCopy(); | |
7084 | |
7085 Expression *upr = NULL; | |
7086 if (this->upr) | |
7087 upr = this->upr->syntaxCopy(); | |
7088 | |
7089 return new SliceExp(loc, e1->syntaxCopy(), lwr, upr); | |
7090 } | |
7091 | |
7092 Expression *SliceExp::semantic(Scope *sc) | |
7093 { Expression *e; | |
7094 AggregateDeclaration *ad; | |
7095 //FuncDeclaration *fd; | |
7096 ScopeDsymbol *sym; | |
7097 | |
7098 #if LOGSEMANTIC | |
7099 printf("SliceExp::semantic('%s')\n", toChars()); | |
7100 #endif | |
7101 if (type) | |
7102 return this; | |
7103 | |
7104 UnaExp::semantic(sc); | |
7105 e1 = resolveProperties(sc, e1); | |
7106 | |
7107 e = this; | |
7108 | |
7109 Type *t = e1->type->toBasetype(); | |
7110 if (t->ty == Tpointer) | |
7111 { | |
7112 if (!lwr || !upr) | |
7113 error("need upper and lower bound to slice pointer"); | |
7114 } | |
7115 else if (t->ty == Tarray) | |
7116 { | |
7117 } | |
7118 else if (t->ty == Tsarray) | |
7119 { | |
7120 } | |
7121 else if (t->ty == Tclass) | |
7122 { | |
7123 ad = ((TypeClass *)t)->sym; | |
7124 goto L1; | |
7125 } | |
7126 else if (t->ty == Tstruct) | |
7127 { | |
7128 ad = ((TypeStruct *)t)->sym; | |
7129 | |
7130 L1: | |
7131 if (search_function(ad, Id::slice)) | |
7132 { | |
7133 // Rewrite as e1.slice(lwr, upr) | |
7134 e = new DotIdExp(loc, e1, Id::slice); | |
7135 | |
7136 if (lwr) | |
7137 { | |
7138 assert(upr); | |
7139 e = new CallExp(loc, e, lwr, upr); | |
7140 } | |
7141 else | |
7142 { assert(!upr); | |
7143 e = new CallExp(loc, e); | |
7144 } | |
7145 e = e->semantic(sc); | |
7146 return e; | |
7147 } | |
7148 goto Lerror; | |
7149 } | |
7150 else if (t->ty == Ttuple) | |
7151 { | |
7152 if (!lwr && !upr) | |
7153 return e1; | |
7154 if (!lwr || !upr) | |
7155 { error("need upper and lower bound to slice tuple"); | |
7156 goto Lerror; | |
7157 } | |
7158 } | |
7159 else | |
7160 goto Lerror; | |
7161 | |
7162 if (t->ty == Tsarray || t->ty == Tarray || t->ty == Ttuple) | |
7163 { | |
7164 sym = new ArrayScopeSymbol(this); | |
7165 sym->loc = loc; | |
7166 sym->parent = sc->scopesym; | |
7167 sc = sc->push(sym); | |
7168 } | |
7169 | |
7170 if (lwr) | |
7171 { lwr = lwr->semantic(sc); | |
7172 lwr = resolveProperties(sc, lwr); | |
7173 lwr = lwr->implicitCastTo(sc, Type::tsize_t); | |
7174 } | |
7175 if (upr) | |
7176 { upr = upr->semantic(sc); | |
7177 upr = resolveProperties(sc, upr); | |
7178 upr = upr->implicitCastTo(sc, Type::tsize_t); | |
7179 } | |
7180 | |
7181 if (t->ty == Tsarray || t->ty == Tarray || t->ty == Ttuple) | |
7182 sc->pop(); | |
7183 | |
7184 if (t->ty == Ttuple) | |
7185 { | |
7186 lwr = lwr->optimize(WANTvalue); | |
7187 upr = upr->optimize(WANTvalue); | |
7188 uinteger_t i1 = lwr->toUInteger(); | |
7189 uinteger_t i2 = upr->toUInteger(); | |
7190 | |
7191 size_t length; | |
7192 TupleExp *te; | |
7193 TypeTuple *tup; | |
7194 | |
7195 if (e1->op == TOKtuple) // slicing an expression tuple | |
7196 { te = (TupleExp *)e1; | |
7197 length = te->exps->dim; | |
7198 } | |
7199 else if (e1->op == TOKtype) // slicing a type tuple | |
7200 { tup = (TypeTuple *)t; | |
7201 length = Argument::dim(tup->arguments); | |
7202 } | |
7203 else | |
7204 assert(0); | |
7205 | |
7206 if (i1 <= i2 && i2 <= length) | |
7207 { size_t j1 = (size_t) i1; | |
7208 size_t j2 = (size_t) i2; | |
7209 | |
7210 if (e1->op == TOKtuple) | |
7211 { Expressions *exps = new Expressions; | |
7212 exps->setDim(j2 - j1); | |
7213 for (size_t i = 0; i < j2 - j1; i++) | |
7214 { Expression *e = (Expression *)te->exps->data[j1 + i]; | |
7215 exps->data[i] = (void *)e; | |
7216 } | |
7217 e = new TupleExp(loc, exps); | |
7218 } | |
7219 else | |
7220 { Arguments *args = new Arguments; | |
7221 args->reserve(j2 - j1); | |
7222 for (size_t i = j1; i < j2; i++) | |
7223 { Argument *arg = Argument::getNth(tup->arguments, i); | |
7224 args->push(arg); | |
7225 } | |
7226 e = new TypeExp(e1->loc, new TypeTuple(args)); | |
7227 } | |
7228 e = e->semantic(sc); | |
7229 } | |
7230 else | |
7231 { | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
7232 error("string slice [%llu .. %llu] is out of bounds", i1, i2); |
159 | 7233 e = e1; |
7234 } | |
7235 return e; | |
7236 } | |
7237 | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7238 type = t->nextOf()->arrayOf(); |
159 | 7239 return e; |
7240 | |
7241 Lerror: | |
7242 char *s; | |
7243 if (t->ty == Tvoid) | |
7244 s = e1->toChars(); | |
7245 else | |
7246 s = t->toChars(); | |
7247 error("%s cannot be sliced with []", s); | |
876
27a379f288bf
Merged DMD 1.039
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
875
diff
changeset
|
7248 e = new IntegerExp(0); |
159 | 7249 return e; |
7250 } | |
7251 | |
7252 void SliceExp::checkEscape() | |
7253 { | |
7254 e1->checkEscape(); | |
7255 } | |
7256 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7257 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7258 int SliceExp::isLvalue() |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7259 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7260 return 1; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7261 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7262 #endif |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7263 |
159 | 7264 Expression *SliceExp::toLvalue(Scope *sc, Expression *e) |
7265 { | |
7266 return this; | |
7267 } | |
7268 | |
7269 Expression *SliceExp::modifiableLvalue(Scope *sc, Expression *e) | |
7270 { | |
7271 error("slice expression %s is not a modifiable lvalue", toChars()); | |
7272 return this; | |
7273 } | |
7274 | |
7275 void SliceExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
7276 { | |
7277 expToCBuffer(buf, hgs, e1, precedence[op]); | |
7278 buf->writeByte('['); | |
7279 if (upr || lwr) | |
7280 { | |
7281 if (lwr) | |
7282 expToCBuffer(buf, hgs, lwr, PREC_assign); | |
7283 else | |
7284 buf->writeByte('0'); | |
7285 buf->writestring(".."); | |
7286 if (upr) | |
7287 expToCBuffer(buf, hgs, upr, PREC_assign); | |
7288 else | |
7289 buf->writestring("length"); // BUG: should be array.length | |
7290 } | |
7291 buf->writeByte(']'); | |
7292 } | |
7293 | |
7294 /********************** ArrayLength **************************************/ | |
7295 | |
7296 ArrayLengthExp::ArrayLengthExp(Loc loc, Expression *e1) | |
7297 : UnaExp(loc, TOKarraylength, sizeof(ArrayLengthExp), e1) | |
7298 { | |
7299 } | |
7300 | |
7301 Expression *ArrayLengthExp::semantic(Scope *sc) | |
7302 { Expression *e; | |
7303 | |
7304 #if LOGSEMANTIC | |
7305 printf("ArrayLengthExp::semantic('%s')\n", toChars()); | |
7306 #endif | |
7307 if (!type) | |
7308 { | |
7309 UnaExp::semantic(sc); | |
7310 e1 = resolveProperties(sc, e1); | |
7311 | |
7312 type = Type::tsize_t; | |
7313 } | |
7314 return this; | |
7315 } | |
7316 | |
7317 void ArrayLengthExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
7318 { | |
7319 expToCBuffer(buf, hgs, e1, PREC_primary); | |
7320 buf->writestring(".length"); | |
7321 } | |
7322 | |
7323 /*********************** ArrayExp *************************************/ | |
7324 | |
7325 // e1 [ i1, i2, i3, ... ] | |
7326 | |
7327 ArrayExp::ArrayExp(Loc loc, Expression *e1, Expressions *args) | |
7328 : UnaExp(loc, TOKarray, sizeof(ArrayExp), e1) | |
7329 { | |
7330 arguments = args; | |
7331 } | |
7332 | |
7333 Expression *ArrayExp::syntaxCopy() | |
7334 { | |
7335 return new ArrayExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments)); | |
7336 } | |
7337 | |
7338 Expression *ArrayExp::semantic(Scope *sc) | |
7339 { Expression *e; | |
7340 Type *t1; | |
7341 | |
7342 #if LOGSEMANTIC | |
7343 printf("ArrayExp::semantic('%s')\n", toChars()); | |
7344 #endif | |
7345 UnaExp::semantic(sc); | |
7346 e1 = resolveProperties(sc, e1); | |
7347 | |
7348 t1 = e1->type->toBasetype(); | |
7349 if (t1->ty != Tclass && t1->ty != Tstruct) | |
7350 { // Convert to IndexExp | |
7351 if (arguments->dim != 1) | |
7352 error("only one index allowed to index %s", t1->toChars()); | |
7353 e = new IndexExp(loc, e1, (Expression *)arguments->data[0]); | |
7354 return e->semantic(sc); | |
7355 } | |
7356 | |
7357 // Run semantic() on each argument | |
7358 for (size_t i = 0; i < arguments->dim; i++) | |
7359 { e = (Expression *)arguments->data[i]; | |
7360 | |
7361 e = e->semantic(sc); | |
7362 if (!e->type) | |
7363 error("%s has no value", e->toChars()); | |
7364 arguments->data[i] = (void *)e; | |
7365 } | |
7366 | |
7367 expandTuples(arguments); | |
7368 assert(arguments && arguments->dim); | |
7369 | |
7370 e = op_overload(sc); | |
7371 if (!e) | |
7372 { error("no [] operator overload for type %s", e1->type->toChars()); | |
7373 e = e1; | |
7374 } | |
7375 return e; | |
7376 } | |
7377 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7378 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7379 int ArrayExp::isLvalue() |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7380 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7381 if (type && type->toBasetype()->ty == Tvoid) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7382 return 0; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7383 return 1; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7384 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7385 #endif |
159 | 7386 |
7387 Expression *ArrayExp::toLvalue(Scope *sc, Expression *e) | |
7388 { | |
7389 if (type && type->toBasetype()->ty == Tvoid) | |
7390 error("voids have no value"); | |
7391 return this; | |
7392 } | |
7393 | |
7394 | |
7395 void ArrayExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
7396 { int i; | |
7397 | |
7398 expToCBuffer(buf, hgs, e1, PREC_primary); | |
7399 buf->writeByte('['); | |
7400 argsToCBuffer(buf, arguments, hgs); | |
7401 buf->writeByte(']'); | |
7402 } | |
7403 | |
7404 /************************* DotExp ***********************************/ | |
7405 | |
7406 DotExp::DotExp(Loc loc, Expression *e1, Expression *e2) | |
7407 : BinExp(loc, TOKdotexp, sizeof(DotExp), e1, e2) | |
7408 { | |
7409 } | |
7410 | |
7411 Expression *DotExp::semantic(Scope *sc) | |
7412 { | |
7413 #if LOGSEMANTIC | |
7414 printf("DotExp::semantic('%s')\n", toChars()); | |
7415 if (type) printf("\ttype = %s\n", type->toChars()); | |
7416 #endif | |
7417 e1 = e1->semantic(sc); | |
7418 e2 = e2->semantic(sc); | |
7419 if (e2->op == TOKimport) | |
7420 { | |
7421 ScopeExp *se = (ScopeExp *)e2; | |
7422 TemplateDeclaration *td = se->sds->isTemplateDeclaration(); | |
7423 if (td) | |
7424 { Expression *e = new DotTemplateExp(loc, e1, td); | |
7425 e = e->semantic(sc); | |
7426 return e; | |
7427 } | |
7428 } | |
7429 if (!type) | |
7430 type = e2->type; | |
7431 return this; | |
7432 } | |
7433 | |
7434 | |
7435 /************************* CommaExp ***********************************/ | |
7436 | |
7437 CommaExp::CommaExp(Loc loc, Expression *e1, Expression *e2) | |
7438 : BinExp(loc, TOKcomma, sizeof(CommaExp), e1, e2) | |
7439 { | |
7440 } | |
7441 | |
7442 Expression *CommaExp::semantic(Scope *sc) | |
7443 { | |
7444 if (!type) | |
7445 { BinExp::semanticp(sc); | |
7446 type = e2->type; | |
7447 } | |
7448 return this; | |
7449 } | |
7450 | |
7451 void CommaExp::checkEscape() | |
7452 { | |
7453 e2->checkEscape(); | |
7454 } | |
7455 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7456 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7457 int CommaExp::isLvalue() |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7458 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7459 return e2->isLvalue(); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7460 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7461 #endif |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7462 |
159 | 7463 Expression *CommaExp::toLvalue(Scope *sc, Expression *e) |
7464 { | |
7465 e2 = e2->toLvalue(sc, NULL); | |
7466 return this; | |
7467 } | |
7468 | |
7469 Expression *CommaExp::modifiableLvalue(Scope *sc, Expression *e) | |
7470 { | |
7471 e2 = e2->modifiableLvalue(sc, e); | |
7472 return this; | |
7473 } | |
7474 | |
7475 int CommaExp::isBool(int result) | |
7476 { | |
7477 return e2->isBool(result); | |
7478 } | |
7479 | |
7480 int CommaExp::checkSideEffect(int flag) | |
7481 { | |
7482 if (flag == 2) | |
7483 return e1->checkSideEffect(2) || e2->checkSideEffect(2); | |
7484 else | |
7485 { | |
7486 // Don't check e1 until we cast(void) the a,b code generation | |
7487 return e2->checkSideEffect(flag); | |
7488 } | |
7489 } | |
7490 | |
7491 /************************** IndexExp **********************************/ | |
7492 | |
7493 // e1 [ e2 ] | |
7494 | |
7495 IndexExp::IndexExp(Loc loc, Expression *e1, Expression *e2) | |
7496 : BinExp(loc, TOKindex, sizeof(IndexExp), e1, e2) | |
7497 { | |
7498 //printf("IndexExp::IndexExp('%s')\n", toChars()); | |
7499 lengthVar = NULL; | |
7500 modifiable = 0; // assume it is an rvalue | |
7501 } | |
7502 | |
7503 Expression *IndexExp::semantic(Scope *sc) | |
7504 { Expression *e; | |
7505 BinExp *b; | |
7506 UnaExp *u; | |
7507 Type *t1; | |
7508 ScopeDsymbol *sym; | |
7509 | |
7510 #if LOGSEMANTIC | |
7511 printf("IndexExp::semantic('%s')\n", toChars()); | |
7512 #endif | |
7513 if (type) | |
7514 return this; | |
7515 if (!e1->type) | |
7516 e1 = e1->semantic(sc); | |
7517 assert(e1->type); // semantic() should already be run on it | |
7518 e = this; | |
7519 | |
7520 // Note that unlike C we do not implement the int[ptr] | |
7521 | |
7522 t1 = e1->type->toBasetype(); | |
7523 | |
7524 if (t1->ty == Tsarray || t1->ty == Tarray || t1->ty == Ttuple) | |
7525 { // Create scope for 'length' variable | |
7526 sym = new ArrayScopeSymbol(this); | |
7527 sym->loc = loc; | |
7528 sym->parent = sc->scopesym; | |
7529 sc = sc->push(sym); | |
7530 } | |
7531 | |
7532 e2 = e2->semantic(sc); | |
7533 if (!e2->type) | |
7534 { | |
7535 error("%s has no value", e2->toChars()); | |
7536 e2->type = Type::terror; | |
7537 } | |
7538 e2 = resolveProperties(sc, e2); | |
7539 | |
7540 if (t1->ty == Tsarray || t1->ty == Tarray || t1->ty == Ttuple) | |
7541 sc = sc->pop(); | |
7542 | |
7543 switch (t1->ty) | |
7544 { | |
7545 case Tpointer: | |
7546 case Tarray: | |
7547 e2 = e2->implicitCastTo(sc, Type::tsize_t); | |
7548 e->type = t1->next; | |
7549 break; | |
7550 | |
7551 case Tsarray: | |
7552 { | |
7553 e2 = e2->implicitCastTo(sc, Type::tsize_t); | |
7554 | |
7555 TypeSArray *tsa = (TypeSArray *)t1; | |
7556 | |
7557 #if 0 // Don't do now, because it might be short-circuit evaluated | |
7558 // Do compile time array bounds checking if possible | |
7559 e2 = e2->optimize(WANTvalue); | |
7560 if (e2->op == TOKint64) | |
7561 { | |
7562 integer_t index = e2->toInteger(); | |
7563 integer_t length = tsa->dim->toInteger(); | |
7564 if (index < 0 || index >= length) | |
7565 error("array index [%lld] is outside array bounds [0 .. %lld]", | |
7566 index, length); | |
7567 } | |
7568 #endif | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7569 e->type = t1->nextOf(); |
159 | 7570 break; |
7571 } | |
7572 | |
7573 case Taarray: | |
7574 { TypeAArray *taa = (TypeAArray *)t1; | |
7575 | |
7576 e2 = e2->implicitCastTo(sc, taa->index); // type checking | |
7577 e2 = e2->implicitCastTo(sc, taa->key); // actual argument type | |
7578 type = taa->next; | |
7579 break; | |
7580 } | |
7581 | |
7582 case Ttuple: | |
7583 { | |
7584 e2 = e2->implicitCastTo(sc, Type::tsize_t); | |
7585 e2 = e2->optimize(WANTvalue); | |
7586 uinteger_t index = e2->toUInteger(); | |
7587 size_t length; | |
7588 TupleExp *te; | |
7589 TypeTuple *tup; | |
7590 | |
7591 if (e1->op == TOKtuple) | |
7592 { te = (TupleExp *)e1; | |
7593 length = te->exps->dim; | |
7594 } | |
7595 else if (e1->op == TOKtype) | |
7596 { | |
7597 tup = (TypeTuple *)t1; | |
7598 length = Argument::dim(tup->arguments); | |
7599 } | |
7600 else | |
7601 assert(0); | |
7602 | |
7603 if (index < length) | |
7604 { | |
7605 | |
7606 if (e1->op == TOKtuple) | |
7607 e = (Expression *)te->exps->data[(size_t)index]; | |
7608 else | |
7609 e = new TypeExp(e1->loc, Argument::getNth(tup->arguments, (size_t)index)->type); | |
7610 } | |
7611 else | |
7612 { | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
7613 error("array index [%llu] is outside array bounds [0 .. %"PRIuSIZE"]", |
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
7614 index, length); |
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
7615 e = e1; |
159 | 7616 } |
7617 break; | |
7618 } | |
7619 | |
7620 default: | |
7621 error("%s must be an array or pointer type, not %s", | |
7622 e1->toChars(), e1->type->toChars()); | |
7623 type = Type::tint32; | |
7624 break; | |
7625 } | |
7626 return e; | |
7627 } | |
7628 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7629 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7630 int IndexExp::isLvalue() |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7631 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7632 return 1; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7633 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7634 #endif |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
7635 |
159 | 7636 Expression *IndexExp::toLvalue(Scope *sc, Expression *e) |
7637 { | |
7638 // if (type && type->toBasetype()->ty == Tvoid) | |
7639 // error("voids have no value"); | |
7640 return this; | |
7641 } | |
7642 | |
7643 Expression *IndexExp::modifiableLvalue(Scope *sc, Expression *e) | |
7644 { | |
7645 //printf("IndexExp::modifiableLvalue(%s)\n", toChars()); | |
7646 modifiable = 1; | |
7647 if (e1->op == TOKstring) | |
7648 error("string literals are immutable"); | |
7649 if (e1->type->toBasetype()->ty == Taarray) | |
7650 e1 = e1->modifiableLvalue(sc, e1); | |
7651 return toLvalue(sc, e); | |
7652 } | |
7653 | |
7654 void IndexExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
7655 { | |
7656 expToCBuffer(buf, hgs, e1, PREC_primary); | |
7657 buf->writeByte('['); | |
7658 expToCBuffer(buf, hgs, e2, PREC_assign); | |
7659 buf->writeByte(']'); | |
7660 } | |
7661 | |
7662 | |
7663 /************************* PostExp ***********************************/ | |
7664 | |
7665 PostExp::PostExp(enum TOK op, Loc loc, Expression *e) | |
7666 : BinExp(loc, op, sizeof(PostExp), e, | |
7667 new IntegerExp(loc, 1, Type::tint32)) | |
7668 { | |
7669 } | |
7670 | |
7671 Expression *PostExp::semantic(Scope *sc) | |
7672 { Expression *e = this; | |
7673 | |
7674 if (!type) | |
7675 { | |
7676 BinExp::semantic(sc); | |
7677 e2 = resolveProperties(sc, e2); | |
7678 | |
7679 e = op_overload(sc); | |
7680 if (e) | |
7681 return e; | |
7682 | |
7683 e = this; | |
7684 e1 = e1->modifiableLvalue(sc, e1); | |
7685 e1->checkScalar(); | |
7686 e1->checkNoBool(); | |
7687 if (e1->type->ty == Tpointer) | |
7688 e = scaleFactor(sc); | |
7689 else | |
7690 e2 = e2->castTo(sc, e1->type); | |
7691 e->type = e1->type; | |
7692 } | |
7693 return e; | |
7694 } | |
7695 | |
7696 void PostExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
7697 { | |
7698 expToCBuffer(buf, hgs, e1, precedence[op]); | |
7699 buf->writestring((op == TOKplusplus) ? (char *)"++" : (char *)"--"); | |
7700 } | |
7701 | |
7702 /************************************************************/ | |
7703 | |
7704 /* Can be TOKconstruct too */ | |
7705 | |
7706 AssignExp::AssignExp(Loc loc, Expression *e1, Expression *e2) | |
7707 : BinExp(loc, TOKassign, sizeof(AssignExp), e1, e2) | |
7708 { | |
7709 ismemset = 0; | |
7710 } | |
7711 | |
7712 Expression *AssignExp::semantic(Scope *sc) | |
7713 { Type *t1; | |
7714 Expression *e1old = e1; | |
7715 | |
7716 #if LOGSEMANTIC | |
7717 printf("AssignExp::semantic('%s')\n", toChars()); | |
7718 #endif | |
7719 //printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op)); | |
7720 | |
7721 /* Look for operator overloading of a[i]=value. | |
7722 * Do it before semantic() otherwise the a[i] will have been | |
7723 * converted to a.opIndex() already. | |
7724 */ | |
7725 if (e1->op == TOKarray) | |
7726 { Type *t1; | |
7727 ArrayExp *ae = (ArrayExp *)e1; | |
7728 AggregateDeclaration *ad; | |
7729 Identifier *id = Id::index; | |
7730 | |
7731 ae->e1 = ae->e1->semantic(sc); | |
7732 t1 = ae->e1->type->toBasetype(); | |
7733 if (t1->ty == Tstruct) | |
7734 { | |
7735 ad = ((TypeStruct *)t1)->sym; | |
7736 goto L1; | |
7737 } | |
7738 else if (t1->ty == Tclass) | |
7739 { | |
7740 ad = ((TypeClass *)t1)->sym; | |
7741 L1: | |
7742 // Rewrite (a[i] = value) to (a.opIndexAssign(value, i)) | |
7743 if (search_function(ad, Id::indexass)) | |
7744 { Expression *e = new DotIdExp(loc, ae->e1, Id::indexass); | |
7745 Expressions *a = (Expressions *)ae->arguments->copy(); | |
7746 | |
7747 a->insert(0, e2); | |
7748 e = new CallExp(loc, e, a); | |
7749 e = e->semantic(sc); | |
7750 return e; | |
7751 } | |
7752 else | |
7753 { | |
7754 // Rewrite (a[i] = value) to (a.opIndex(i, value)) | |
7755 if (search_function(ad, id)) | |
7756 { Expression *e = new DotIdExp(loc, ae->e1, id); | |
7757 | |
7758 if (1 || !global.params.useDeprecated) | |
7759 error("operator [] assignment overload with opIndex(i, value) illegal, use opIndexAssign(value, i)"); | |
7760 | |
7761 e = new CallExp(loc, e, (Expression *)ae->arguments->data[0], e2); | |
7762 e = e->semantic(sc); | |
7763 return e; | |
7764 } | |
7765 } | |
7766 } | |
7767 } | |
7768 /* Look for operator overloading of a[i..j]=value. | |
7769 * Do it before semantic() otherwise the a[i..j] will have been | |
7770 * converted to a.opSlice() already. | |
7771 */ | |
7772 if (e1->op == TOKslice) | |
7773 { Type *t1; | |
7774 SliceExp *ae = (SliceExp *)e1; | |
7775 AggregateDeclaration *ad; | |
7776 Identifier *id = Id::index; | |
7777 | |
7778 ae->e1 = ae->e1->semantic(sc); | |
7779 ae->e1 = resolveProperties(sc, ae->e1); | |
7780 t1 = ae->e1->type->toBasetype(); | |
7781 if (t1->ty == Tstruct) | |
7782 { | |
7783 ad = ((TypeStruct *)t1)->sym; | |
7784 goto L2; | |
7785 } | |
7786 else if (t1->ty == Tclass) | |
7787 { | |
7788 ad = ((TypeClass *)t1)->sym; | |
7789 L2: | |
7790 // Rewrite (a[i..j] = value) to (a.opIndexAssign(value, i, j)) | |
7791 if (search_function(ad, Id::sliceass)) | |
7792 { Expression *e = new DotIdExp(loc, ae->e1, Id::sliceass); | |
7793 Expressions *a = new Expressions(); | |
7794 | |
7795 a->push(e2); | |
7796 if (ae->lwr) | |
7797 { a->push(ae->lwr); | |
7798 assert(ae->upr); | |
7799 a->push(ae->upr); | |
7800 } | |
7801 else | |
7802 assert(!ae->upr); | |
7803 e = new CallExp(loc, e, a); | |
7804 e = e->semantic(sc); | |
7805 return e; | |
7806 } | |
7807 } | |
7808 } | |
7809 | |
7810 BinExp::semantic(sc); | |
717
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
7811 |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
7812 if (e1->op == TOKdottd) |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
7813 { // Rewrite a.b=e2, when b is a template, as a.b(e2) |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
7814 Expression *e = new CallExp(loc, e1, e2); |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
7815 e = e->semantic(sc); |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
7816 return e; |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
7817 } |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
7818 |
159 | 7819 e2 = resolveProperties(sc, e2); |
7820 assert(e1->type); | |
7821 | |
7822 /* Rewrite tuple assignment as a tuple of assignments. | |
7823 */ | |
7824 if (e1->op == TOKtuple && e2->op == TOKtuple) | |
7825 { TupleExp *tup1 = (TupleExp *)e1; | |
7826 TupleExp *tup2 = (TupleExp *)e2; | |
7827 size_t dim = tup1->exps->dim; | |
7828 if (dim != tup2->exps->dim) | |
7829 { | |
7830 error("mismatched tuple lengths, %d and %d", (int)dim, (int)tup2->exps->dim); | |
7831 } | |
7832 else | |
7833 { Expressions *exps = new Expressions; | |
7834 exps->setDim(dim); | |
7835 | |
7836 for (int i = 0; i < dim; i++) | |
7837 { Expression *ex1 = (Expression *)tup1->exps->data[i]; | |
7838 Expression *ex2 = (Expression *)tup2->exps->data[i]; | |
7839 exps->data[i] = (void *) new AssignExp(loc, ex1, ex2); | |
7840 } | |
7841 Expression *e = new TupleExp(loc, exps); | |
7842 e = e->semantic(sc); | |
7843 return e; | |
7844 } | |
7845 } | |
7846 | |
7847 t1 = e1->type->toBasetype(); | |
7848 | |
7849 if (t1->ty == Tfunction) | |
7850 { // Rewrite f=value to f(value) | |
7851 Expression *e; | |
7852 | |
7853 e = new CallExp(loc, e1, e2); | |
7854 e = e->semantic(sc); | |
7855 return e; | |
7856 } | |
7857 | |
7858 /* If it is an assignment from a 'foreign' type, | |
7859 * check for operator overloading. | |
7860 */ | |
7861 if (t1->ty == Tclass || t1->ty == Tstruct) | |
7862 { | |
7863 if (!e2->type->implicitConvTo(e1->type)) | |
7864 { | |
7865 Expression *e = op_overload(sc); | |
7866 if (e) | |
7867 return e; | |
7868 } | |
7869 } | |
7870 | |
7871 e2->rvalue(); | |
7872 | |
7873 if (e1->op == TOKarraylength) | |
7874 { | |
7875 // e1 is not an lvalue, but we let code generator handle it | |
7876 ArrayLengthExp *ale = (ArrayLengthExp *)e1; | |
7877 | |
7878 ale->e1 = ale->e1->modifiableLvalue(sc, e1); | |
7879 } | |
7880 else if (e1->op == TOKslice) | |
7881 ; | |
7882 else | |
7883 { // Try to do a decent error message with the expression | |
7884 // before it got constant folded | |
7885 e1 = e1->modifiableLvalue(sc, e1old); | |
7886 } | |
7887 | |
7888 if (e1->op == TOKslice && | |
7889 t1->nextOf() && | |
7890 e2->implicitConvTo(t1->nextOf()) | |
7891 // !(t1->nextOf()->equals(e2->type->nextOf())) | |
7892 ) | |
7893 { // memset | |
7894 ismemset = 1; // make it easy for back end to tell what this is | |
7895 e2 = e2->implicitCastTo(sc, t1->next); | |
7896 } | |
7897 else if (t1->ty == Tsarray) | |
7898 { | |
7899 error("cannot assign to static array %s", e1->toChars()); | |
7900 } | |
7901 else | |
7902 { | |
7903 e2 = e2->implicitCastTo(sc, e1->type); | |
7904 } | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7905 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7906 /* Look for array operations |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7907 */ |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7908 if (e1->op == TOKslice && !ismemset && |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7909 (e2->op == TOKadd || e2->op == TOKmin || |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7910 e2->op == TOKmul || e2->op == TOKdiv || |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7911 e2->op == TOKmod || e2->op == TOKxor || |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7912 e2->op == TOKand || e2->op == TOKor || |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7913 e2->op == TOKtilde || e2->op == TOKneg)) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7914 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7915 type = e1->type; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7916 return arrayOp(sc); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7917 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7918 |
159 | 7919 type = e1->type; |
7920 assert(type); | |
7921 return this; | |
7922 } | |
7923 | |
7924 Expression *AssignExp::checkToBoolean() | |
7925 { | |
7926 // Things like: | |
7927 // if (a = b) ... | |
7928 // are usually mistakes. | |
7929 | |
7930 error("'=' does not give a boolean result"); | |
7931 return this; | |
7932 } | |
7933 | |
7934 /************************************************************/ | |
7935 | |
7936 AddAssignExp::AddAssignExp(Loc loc, Expression *e1, Expression *e2) | |
7937 : BinExp(loc, TOKaddass, sizeof(AddAssignExp), e1, e2) | |
7938 { | |
7939 } | |
7940 | |
7941 Expression *AddAssignExp::semantic(Scope *sc) | |
7942 { Expression *e; | |
7943 | |
7944 if (type) | |
7945 return this; | |
7946 | |
7947 BinExp::semantic(sc); | |
7948 e2 = resolveProperties(sc, e2); | |
7949 | |
7950 e = op_overload(sc); | |
7951 if (e) | |
7952 return e; | |
7953 | |
7954 Type *tb1 = e1->type->toBasetype(); | |
7955 Type *tb2 = e2->type->toBasetype(); | |
7956 | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7957 if (e1->op == TOKslice) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7958 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7959 typeCombine(sc); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7960 type = e1->type; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7961 return arrayOp(sc); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7962 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7963 else |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7964 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7965 e1 = e1->modifiableLvalue(sc, e1); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7966 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7967 |
159 | 7968 if ((tb1->ty == Tarray || tb1->ty == Tsarray) && |
7969 (tb2->ty == Tarray || tb2->ty == Tsarray) && | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7970 tb1->nextOf()->equals(tb2->nextOf()) |
159 | 7971 ) |
7972 { | |
7973 type = e1->type; | |
7974 e = this; | |
7975 } | |
7976 else | |
7977 { | |
7978 e1->checkScalar(); | |
7979 e1->checkNoBool(); | |
7980 if (tb1->ty == Tpointer && tb2->isintegral()) | |
7981 e = scaleFactor(sc); | |
7982 else if (tb1->ty == Tbit || tb1->ty == Tbool) | |
7983 { | |
7984 #if 0 | |
7985 // Need to rethink this | |
7986 if (e1->op != TOKvar) | |
7987 { // Rewrite e1+=e2 to (v=&e1),*v=*v+e2 | |
7988 VarDeclaration *v; | |
7989 Expression *ea; | |
7990 Expression *ex; | |
7991 | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7992 Identifier *id = Lexer::uniqueId("__name"); |
159 | 7993 |
7994 v = new VarDeclaration(loc, tb1->pointerTo(), id, NULL); | |
7995 v->semantic(sc); | |
7996 if (!sc->insert(v)) | |
7997 assert(0); | |
7998 v->parent = sc->func; | |
7999 | |
8000 ea = new AddrExp(loc, e1); | |
8001 ea = new AssignExp(loc, new VarExp(loc, v), ea); | |
8002 | |
8003 ex = new VarExp(loc, v); | |
8004 ex = new PtrExp(loc, ex); | |
8005 e = new AddExp(loc, ex, e2); | |
8006 e = new CastExp(loc, e, e1->type); | |
8007 e = new AssignExp(loc, ex->syntaxCopy(), e); | |
8008 | |
8009 e = new CommaExp(loc, ea, e); | |
8010 } | |
8011 else | |
8012 #endif | |
8013 { // Rewrite e1+=e2 to e1=e1+e2 | |
8014 // BUG: doesn't account for side effects in e1 | |
8015 // BUG: other assignment operators for bits aren't handled at all | |
8016 e = new AddExp(loc, e1, e2); | |
8017 e = new CastExp(loc, e, e1->type); | |
8018 e = new AssignExp(loc, e1->syntaxCopy(), e); | |
8019 } | |
8020 e = e->semantic(sc); | |
8021 } | |
8022 else | |
8023 { | |
8024 type = e1->type; | |
8025 typeCombine(sc); | |
8026 e1->checkArithmetic(); | |
8027 e2->checkArithmetic(); | |
8028 if (type->isreal() || type->isimaginary()) | |
8029 { | |
8030 assert(global.errors || e2->type->isfloating()); | |
8031 e2 = e2->castTo(sc, e1->type); | |
8032 } | |
8033 e = this; | |
1012
39cf8fa483fd
Error gracefully for +=, -=, *=, /= if rhs is complex but lhs isn't.
Christian Kamm <kamm incasoftware de>
parents:
891
diff
changeset
|
8034 |
39cf8fa483fd
Error gracefully for +=, -=, *=, /= if rhs is complex but lhs isn't.
Christian Kamm <kamm incasoftware de>
parents:
891
diff
changeset
|
8035 if (e2->type->iscomplex() && !type->iscomplex()) |
39cf8fa483fd
Error gracefully for +=, -=, *=, /= if rhs is complex but lhs isn't.
Christian Kamm <kamm incasoftware de>
parents:
891
diff
changeset
|
8036 error("Cannot assign %s to %s", e2->type->toChars(), type->toChars()); |
159 | 8037 } |
8038 } | |
8039 return e; | |
8040 } | |
8041 | |
8042 /************************************************************/ | |
8043 | |
8044 MinAssignExp::MinAssignExp(Loc loc, Expression *e1, Expression *e2) | |
8045 : BinExp(loc, TOKminass, sizeof(MinAssignExp), e1, e2) | |
8046 { | |
8047 } | |
8048 | |
8049 Expression *MinAssignExp::semantic(Scope *sc) | |
8050 { Expression *e; | |
8051 | |
8052 if (type) | |
8053 return this; | |
8054 | |
8055 BinExp::semantic(sc); | |
8056 e2 = resolveProperties(sc, e2); | |
8057 | |
8058 e = op_overload(sc); | |
8059 if (e) | |
8060 return e; | |
8061 | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8062 if (e1->op == TOKslice) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8063 { // T[] -= ... |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8064 typeCombine(sc); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8065 type = e1->type; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8066 return arrayOp(sc); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8067 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8068 |
159 | 8069 e1 = e1->modifiableLvalue(sc, e1); |
8070 e1->checkScalar(); | |
8071 e1->checkNoBool(); | |
8072 if (e1->type->ty == Tpointer && e2->type->isintegral()) | |
8073 e = scaleFactor(sc); | |
8074 else | |
8075 { | |
8076 e1 = e1->checkArithmetic(); | |
8077 e2 = e2->checkArithmetic(); | |
8078 type = e1->type; | |
8079 typeCombine(sc); | |
8080 if (type->isreal() || type->isimaginary()) | |
8081 { | |
8082 assert(e2->type->isfloating()); | |
8083 e2 = e2->castTo(sc, e1->type); | |
8084 } | |
8085 e = this; | |
1012
39cf8fa483fd
Error gracefully for +=, -=, *=, /= if rhs is complex but lhs isn't.
Christian Kamm <kamm incasoftware de>
parents:
891
diff
changeset
|
8086 |
39cf8fa483fd
Error gracefully for +=, -=, *=, /= if rhs is complex but lhs isn't.
Christian Kamm <kamm incasoftware de>
parents:
891
diff
changeset
|
8087 if (e2->type->iscomplex() && !type->iscomplex()) |
39cf8fa483fd
Error gracefully for +=, -=, *=, /= if rhs is complex but lhs isn't.
Christian Kamm <kamm incasoftware de>
parents:
891
diff
changeset
|
8088 error("Cannot assign %s to %s", e2->type->toChars(), type->toChars()); |
159 | 8089 } |
8090 return e; | |
8091 } | |
8092 | |
8093 /************************************************************/ | |
8094 | |
8095 CatAssignExp::CatAssignExp(Loc loc, Expression *e1, Expression *e2) | |
8096 : BinExp(loc, TOKcatass, sizeof(CatAssignExp), e1, e2) | |
8097 { | |
8098 } | |
8099 | |
8100 Expression *CatAssignExp::semantic(Scope *sc) | |
8101 { Expression *e; | |
8102 | |
8103 BinExp::semantic(sc); | |
8104 e2 = resolveProperties(sc, e2); | |
8105 | |
8106 e = op_overload(sc); | |
8107 if (e) | |
8108 return e; | |
8109 | |
8110 if (e1->op == TOKslice) | |
8111 { SliceExp *se = (SliceExp *)e1; | |
8112 | |
8113 if (se->e1->type->toBasetype()->ty == Tsarray) | |
8114 error("cannot append to static array %s", se->e1->type->toChars()); | |
8115 } | |
8116 | |
8117 e1 = e1->modifiableLvalue(sc, e1); | |
8118 | |
8119 Type *tb1 = e1->type->toBasetype(); | |
8120 Type *tb2 = e2->type->toBasetype(); | |
8121 | |
8122 e2->rvalue(); | |
8123 | |
8124 if ((tb1->ty == Tarray) && | |
8125 (tb2->ty == Tarray || tb2->ty == Tsarray) && | |
8126 e2->implicitConvTo(e1->type) | |
8127 //e1->type->next->equals(e2->type->next) | |
8128 ) | |
8129 { // Append array | |
8130 e2 = e2->castTo(sc, e1->type); | |
8131 type = e1->type; | |
8132 e = this; | |
8133 } | |
8134 else if ((tb1->ty == Tarray) && | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8135 e2->implicitConvTo(tb1->nextOf()) |
159 | 8136 ) |
8137 { // Append element | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8138 e2 = e2->castTo(sc, tb1->nextOf()); |
159 | 8139 type = e1->type; |
8140 e = this; | |
8141 } | |
8142 else | |
8143 { | |
8144 error("cannot append type %s to type %s", tb2->toChars(), tb1->toChars()); | |
8145 type = Type::tint32; | |
8146 e = this; | |
8147 } | |
8148 return e; | |
8149 } | |
8150 | |
8151 /************************************************************/ | |
8152 | |
8153 MulAssignExp::MulAssignExp(Loc loc, Expression *e1, Expression *e2) | |
8154 : BinExp(loc, TOKmulass, sizeof(MulAssignExp), e1, e2) | |
8155 { | |
8156 } | |
8157 | |
8158 Expression *MulAssignExp::semantic(Scope *sc) | |
8159 { Expression *e; | |
8160 | |
8161 BinExp::semantic(sc); | |
8162 e2 = resolveProperties(sc, e2); | |
8163 | |
8164 e = op_overload(sc); | |
8165 if (e) | |
8166 return e; | |
8167 | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8168 if (e1->op == TOKslice) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8169 { // T[] -= ... |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8170 typeCombine(sc); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8171 type = e1->type; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8172 return arrayOp(sc); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8173 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8174 |
159 | 8175 e1 = e1->modifiableLvalue(sc, e1); |
8176 e1->checkScalar(); | |
8177 e1->checkNoBool(); | |
8178 type = e1->type; | |
8179 typeCombine(sc); | |
8180 e1->checkArithmetic(); | |
8181 e2->checkArithmetic(); | |
8182 if (e2->type->isfloating()) | |
8183 { Type *t1; | |
8184 Type *t2; | |
8185 | |
8186 t1 = e1->type; | |
8187 t2 = e2->type; | |
8188 if (t1->isreal()) | |
8189 { | |
8190 if (t2->isimaginary() || t2->iscomplex()) | |
8191 { | |
8192 e2 = e2->castTo(sc, t1); | |
8193 } | |
8194 } | |
8195 else if (t1->isimaginary()) | |
8196 { | |
8197 if (t2->isimaginary() || t2->iscomplex()) | |
8198 { | |
8199 switch (t1->ty) | |
8200 { | |
8201 case Timaginary32: t2 = Type::tfloat32; break; | |
8202 case Timaginary64: t2 = Type::tfloat64; break; | |
8203 case Timaginary80: t2 = Type::tfloat80; break; | |
8204 default: | |
8205 assert(0); | |
8206 } | |
8207 e2 = e2->castTo(sc, t2); | |
8208 } | |
8209 } | |
1012
39cf8fa483fd
Error gracefully for +=, -=, *=, /= if rhs is complex but lhs isn't.
Christian Kamm <kamm incasoftware de>
parents:
891
diff
changeset
|
8210 |
39cf8fa483fd
Error gracefully for +=, -=, *=, /= if rhs is complex but lhs isn't.
Christian Kamm <kamm incasoftware de>
parents:
891
diff
changeset
|
8211 if (e2->type->iscomplex() && !type->iscomplex()) |
39cf8fa483fd
Error gracefully for +=, -=, *=, /= if rhs is complex but lhs isn't.
Christian Kamm <kamm incasoftware de>
parents:
891
diff
changeset
|
8212 error("Cannot assign %s to %s", e2->type->toChars(), type->toChars()); |
159 | 8213 } |
8214 return this; | |
8215 } | |
8216 | |
8217 /************************************************************/ | |
8218 | |
8219 DivAssignExp::DivAssignExp(Loc loc, Expression *e1, Expression *e2) | |
8220 : BinExp(loc, TOKdivass, sizeof(DivAssignExp), e1, e2) | |
8221 { | |
8222 } | |
8223 | |
8224 Expression *DivAssignExp::semantic(Scope *sc) | |
8225 { Expression *e; | |
8226 | |
8227 BinExp::semantic(sc); | |
8228 e2 = resolveProperties(sc, e2); | |
8229 | |
8230 e = op_overload(sc); | |
8231 if (e) | |
8232 return e; | |
8233 | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8234 if (e1->op == TOKslice) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8235 { // T[] -= ... |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8236 typeCombine(sc); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8237 type = e1->type; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8238 return arrayOp(sc); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8239 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8240 |
159 | 8241 e1 = e1->modifiableLvalue(sc, e1); |
8242 e1->checkScalar(); | |
8243 e1->checkNoBool(); | |
8244 type = e1->type; | |
8245 typeCombine(sc); | |
8246 e1->checkArithmetic(); | |
8247 e2->checkArithmetic(); | |
8248 if (e2->type->isimaginary()) | |
8249 { Type *t1; | |
8250 Type *t2; | |
8251 | |
8252 t1 = e1->type; | |
8253 if (t1->isreal()) | |
8254 { // x/iv = i(-x/v) | |
8255 // Therefore, the result is 0 | |
8256 e2 = new CommaExp(loc, e2, new RealExp(loc, 0, t1)); | |
8257 e2->type = t1; | |
8258 e = new AssignExp(loc, e1, e2); | |
8259 e->type = t1; | |
8260 return e; | |
8261 } | |
8262 else if (t1->isimaginary()) | |
8263 { Expression *e; | |
8264 | |
8265 switch (t1->ty) | |
8266 { | |
8267 case Timaginary32: t2 = Type::tfloat32; break; | |
8268 case Timaginary64: t2 = Type::tfloat64; break; | |
8269 case Timaginary80: t2 = Type::tfloat80; break; | |
8270 default: | |
8271 assert(0); | |
8272 } | |
8273 e2 = e2->castTo(sc, t2); | |
8274 e = new AssignExp(loc, e1, e2); | |
8275 e->type = t1; | |
8276 return e; | |
8277 } | |
8278 } | |
1012
39cf8fa483fd
Error gracefully for +=, -=, *=, /= if rhs is complex but lhs isn't.
Christian Kamm <kamm incasoftware de>
parents:
891
diff
changeset
|
8279 |
39cf8fa483fd
Error gracefully for +=, -=, *=, /= if rhs is complex but lhs isn't.
Christian Kamm <kamm incasoftware de>
parents:
891
diff
changeset
|
8280 if (e2->type->iscomplex() && !type->iscomplex()) |
39cf8fa483fd
Error gracefully for +=, -=, *=, /= if rhs is complex but lhs isn't.
Christian Kamm <kamm incasoftware de>
parents:
891
diff
changeset
|
8281 error("Cannot assign %s to %s", e2->type->toChars(), type->toChars()); |
39cf8fa483fd
Error gracefully for +=, -=, *=, /= if rhs is complex but lhs isn't.
Christian Kamm <kamm incasoftware de>
parents:
891
diff
changeset
|
8282 |
159 | 8283 return this; |
8284 } | |
8285 | |
8286 /************************************************************/ | |
8287 | |
8288 ModAssignExp::ModAssignExp(Loc loc, Expression *e1, Expression *e2) | |
8289 : BinExp(loc, TOKmodass, sizeof(ModAssignExp), e1, e2) | |
8290 { | |
8291 } | |
8292 | |
8293 Expression *ModAssignExp::semantic(Scope *sc) | |
8294 { | |
8295 return commonSemanticAssign(sc); | |
8296 } | |
8297 | |
8298 /************************************************************/ | |
8299 | |
8300 ShlAssignExp::ShlAssignExp(Loc loc, Expression *e1, Expression *e2) | |
8301 : BinExp(loc, TOKshlass, sizeof(ShlAssignExp), e1, e2) | |
8302 { | |
8303 } | |
8304 | |
8305 Expression *ShlAssignExp::semantic(Scope *sc) | |
8306 { Expression *e; | |
8307 | |
8308 //printf("ShlAssignExp::semantic()\n"); | |
8309 BinExp::semantic(sc); | |
8310 e2 = resolveProperties(sc, e2); | |
8311 | |
8312 e = op_overload(sc); | |
8313 if (e) | |
8314 return e; | |
8315 | |
8316 e1 = e1->modifiableLvalue(sc, e1); | |
8317 e1->checkScalar(); | |
8318 e1->checkNoBool(); | |
8319 type = e1->type; | |
8320 typeCombine(sc); | |
8321 e1->checkIntegral(); | |
8322 e2 = e2->checkIntegral(); | |
8323 //e2 = e2->castTo(sc, Type::tshiftcnt); | |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
639
diff
changeset
|
8324 e2 = e2->castTo(sc, e1->type); // LDC |
159 | 8325 return this; |
8326 } | |
8327 | |
8328 /************************************************************/ | |
8329 | |
8330 ShrAssignExp::ShrAssignExp(Loc loc, Expression *e1, Expression *e2) | |
8331 : BinExp(loc, TOKshrass, sizeof(ShrAssignExp), e1, e2) | |
8332 { | |
8333 } | |
8334 | |
8335 Expression *ShrAssignExp::semantic(Scope *sc) | |
8336 { Expression *e; | |
8337 | |
8338 BinExp::semantic(sc); | |
8339 e2 = resolveProperties(sc, e2); | |
8340 | |
8341 e = op_overload(sc); | |
8342 if (e) | |
8343 return e; | |
8344 | |
8345 e1 = e1->modifiableLvalue(sc, e1); | |
8346 e1->checkScalar(); | |
8347 e1->checkNoBool(); | |
8348 type = e1->type; | |
8349 typeCombine(sc); | |
8350 e1->checkIntegral(); | |
8351 e2 = e2->checkIntegral(); | |
8352 //e2 = e2->castTo(sc, Type::tshiftcnt); | |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
639
diff
changeset
|
8353 e2 = e2->castTo(sc, e1->type); // LDC |
159 | 8354 return this; |
8355 } | |
8356 | |
8357 /************************************************************/ | |
8358 | |
8359 UshrAssignExp::UshrAssignExp(Loc loc, Expression *e1, Expression *e2) | |
8360 : BinExp(loc, TOKushrass, sizeof(UshrAssignExp), e1, e2) | |
8361 { | |
8362 } | |
8363 | |
8364 Expression *UshrAssignExp::semantic(Scope *sc) | |
8365 { Expression *e; | |
8366 | |
8367 BinExp::semantic(sc); | |
8368 e2 = resolveProperties(sc, e2); | |
8369 | |
8370 e = op_overload(sc); | |
8371 if (e) | |
8372 return e; | |
8373 | |
8374 e1 = e1->modifiableLvalue(sc, e1); | |
8375 e1->checkScalar(); | |
8376 e1->checkNoBool(); | |
8377 type = e1->type; | |
8378 typeCombine(sc); | |
8379 e1->checkIntegral(); | |
8380 e2 = e2->checkIntegral(); | |
8381 //e2 = e2->castTo(sc, Type::tshiftcnt); | |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
639
diff
changeset
|
8382 e2 = e2->castTo(sc, e1->type); // LDC |
159 | 8383 return this; |
8384 } | |
8385 | |
8386 /************************************************************/ | |
8387 | |
8388 AndAssignExp::AndAssignExp(Loc loc, Expression *e1, Expression *e2) | |
8389 : BinExp(loc, TOKandass, sizeof(AndAssignExp), e1, e2) | |
8390 { | |
8391 } | |
8392 | |
8393 Expression *AndAssignExp::semantic(Scope *sc) | |
8394 { | |
8395 return commonSemanticAssignIntegral(sc); | |
8396 } | |
8397 | |
8398 /************************************************************/ | |
8399 | |
8400 OrAssignExp::OrAssignExp(Loc loc, Expression *e1, Expression *e2) | |
8401 : BinExp(loc, TOKorass, sizeof(OrAssignExp), e1, e2) | |
8402 { | |
8403 } | |
8404 | |
8405 Expression *OrAssignExp::semantic(Scope *sc) | |
8406 { | |
8407 return commonSemanticAssignIntegral(sc); | |
8408 } | |
8409 | |
8410 /************************************************************/ | |
8411 | |
8412 XorAssignExp::XorAssignExp(Loc loc, Expression *e1, Expression *e2) | |
8413 : BinExp(loc, TOKxorass, sizeof(XorAssignExp), e1, e2) | |
8414 { | |
8415 } | |
8416 | |
8417 Expression *XorAssignExp::semantic(Scope *sc) | |
8418 { | |
8419 return commonSemanticAssignIntegral(sc); | |
8420 } | |
8421 | |
8422 /************************* AddExp *****************************/ | |
8423 | |
8424 AddExp::AddExp(Loc loc, Expression *e1, Expression *e2) | |
8425 : BinExp(loc, TOKadd, sizeof(AddExp), e1, e2) | |
8426 { | |
8427 } | |
8428 | |
8429 Expression *AddExp::semantic(Scope *sc) | |
8430 { Expression *e; | |
8431 | |
8432 #if LOGSEMANTIC | |
8433 printf("AddExp::semantic('%s')\n", toChars()); | |
8434 #endif | |
8435 if (!type) | |
8436 { | |
8437 BinExp::semanticp(sc); | |
8438 | |
8439 e = op_overload(sc); | |
8440 if (e) | |
8441 return e; | |
8442 | |
8443 Type *tb1 = e1->type->toBasetype(); | |
8444 Type *tb2 = e2->type->toBasetype(); | |
8445 | |
8446 if ((tb1->ty == Tarray || tb1->ty == Tsarray) && | |
8447 (tb2->ty == Tarray || tb2->ty == Tsarray) && | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8448 tb1->nextOf()->equals(tb2->nextOf()) |
159 | 8449 ) |
8450 { | |
8451 type = e1->type; | |
8452 e = this; | |
8453 } | |
8454 else if (tb1->ty == Tpointer && e2->type->isintegral() || | |
8455 tb2->ty == Tpointer && e1->type->isintegral()) | |
8456 e = scaleFactor(sc); | |
8457 else if (tb1->ty == Tpointer && tb2->ty == Tpointer) | |
8458 { | |
8459 incompatibleTypes(); | |
8460 type = e1->type; | |
8461 e = this; | |
8462 } | |
8463 else | |
8464 { | |
8465 typeCombine(sc); | |
8466 if ((e1->type->isreal() && e2->type->isimaginary()) || | |
8467 (e1->type->isimaginary() && e2->type->isreal())) | |
8468 { | |
8469 switch (type->toBasetype()->ty) | |
8470 { | |
8471 case Tfloat32: | |
8472 case Timaginary32: | |
8473 type = Type::tcomplex32; | |
8474 break; | |
8475 | |
8476 case Tfloat64: | |
8477 case Timaginary64: | |
8478 type = Type::tcomplex64; | |
8479 break; | |
8480 | |
8481 case Tfloat80: | |
8482 case Timaginary80: | |
8483 type = Type::tcomplex80; | |
8484 break; | |
8485 | |
8486 default: | |
8487 assert(0); | |
8488 } | |
8489 } | |
8490 e = this; | |
8491 } | |
8492 return e; | |
8493 } | |
8494 return this; | |
8495 } | |
8496 | |
8497 /************************************************************/ | |
8498 | |
8499 MinExp::MinExp(Loc loc, Expression *e1, Expression *e2) | |
8500 : BinExp(loc, TOKmin, sizeof(MinExp), e1, e2) | |
8501 { | |
8502 } | |
8503 | |
8504 Expression *MinExp::semantic(Scope *sc) | |
8505 { Expression *e; | |
8506 Type *t1; | |
8507 Type *t2; | |
8508 | |
8509 #if LOGSEMANTIC | |
8510 printf("MinExp::semantic('%s')\n", toChars()); | |
8511 #endif | |
8512 if (type) | |
8513 return this; | |
8514 | |
8515 BinExp::semanticp(sc); | |
8516 | |
8517 e = op_overload(sc); | |
8518 if (e) | |
8519 return e; | |
8520 | |
8521 e = this; | |
8522 t1 = e1->type->toBasetype(); | |
8523 t2 = e2->type->toBasetype(); | |
8524 if (t1->ty == Tpointer) | |
8525 { | |
8526 if (t2->ty == Tpointer) | |
8527 { // Need to divide the result by the stride | |
8528 // Replace (ptr - ptr) with (ptr - ptr) / stride | |
8529 d_int64 stride; | |
8530 Expression *e; | |
8531 | |
8532 typeCombine(sc); // make sure pointer types are compatible | |
8533 type = Type::tptrdiff_t; | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8534 stride = t2->nextOf()->size(); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8535 if (stride == 0) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8536 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8537 e = new IntegerExp(loc, 0, Type::tptrdiff_t); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8538 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8539 else |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8540 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8541 e = new DivExp(loc, this, new IntegerExp(0, stride, Type::tptrdiff_t)); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8542 e->type = Type::tptrdiff_t; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8543 } |
159 | 8544 return e; |
8545 } | |
8546 else if (t2->isintegral()) | |
8547 e = scaleFactor(sc); | |
8548 else | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8549 { error("incompatible types for minus"); |
159 | 8550 return new IntegerExp(0); |
8551 } | |
8552 } | |
8553 else if (t2->ty == Tpointer) | |
8554 { | |
8555 type = e2->type; | |
8556 error("can't subtract pointer from %s", e1->type->toChars()); | |
8557 return new IntegerExp(0); | |
8558 } | |
8559 else | |
8560 { | |
8561 typeCombine(sc); | |
8562 t1 = e1->type->toBasetype(); | |
8563 t2 = e2->type->toBasetype(); | |
8564 if ((t1->isreal() && t2->isimaginary()) || | |
8565 (t1->isimaginary() && t2->isreal())) | |
8566 { | |
8567 switch (type->ty) | |
8568 { | |
8569 case Tfloat32: | |
8570 case Timaginary32: | |
8571 type = Type::tcomplex32; | |
8572 break; | |
8573 | |
8574 case Tfloat64: | |
8575 case Timaginary64: | |
8576 type = Type::tcomplex64; | |
8577 break; | |
8578 | |
8579 case Tfloat80: | |
8580 case Timaginary80: | |
8581 type = Type::tcomplex80; | |
8582 break; | |
8583 | |
8584 default: | |
8585 assert(0); | |
8586 } | |
8587 } | |
8588 } | |
8589 return e; | |
8590 } | |
8591 | |
8592 /************************* CatExp *****************************/ | |
8593 | |
8594 CatExp::CatExp(Loc loc, Expression *e1, Expression *e2) | |
8595 : BinExp(loc, TOKcat, sizeof(CatExp), e1, e2) | |
8596 { | |
8597 } | |
8598 | |
8599 Expression *CatExp::semantic(Scope *sc) | |
8600 { Expression *e; | |
8601 | |
8602 //printf("CatExp::semantic() %s\n", toChars()); | |
8603 if (!type) | |
8604 { | |
8605 BinExp::semanticp(sc); | |
8606 e = op_overload(sc); | |
8607 if (e) | |
8608 return e; | |
8609 | |
8610 Type *tb1 = e1->type->toBasetype(); | |
8611 Type *tb2 = e2->type->toBasetype(); | |
8612 | |
8613 | |
8614 /* BUG: Should handle things like: | |
8615 * char c; | |
8616 * c ~ ' ' | |
8617 * ' ' ~ c; | |
8618 */ | |
8619 | |
8620 #if 0 | |
8621 e1->type->print(); | |
8622 e2->type->print(); | |
8623 #endif | |
8624 if ((tb1->ty == Tsarray || tb1->ty == Tarray) && | |
8625 e2->type->equals(tb1->next)) | |
8626 { | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8627 type = tb1->nextOf()->arrayOf(); |
159 | 8628 if (tb2->ty == Tarray) |
8629 { // Make e2 into [e2] | |
8630 e2 = new ArrayLiteralExp(e2->loc, e2); | |
8631 e2->type = type; | |
8632 } | |
8633 return this; | |
8634 } | |
8635 else if ((tb2->ty == Tsarray || tb2->ty == Tarray) && | |
8636 e1->type->equals(tb2->next)) | |
8637 { | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8638 type = tb2->nextOf()->arrayOf(); |
159 | 8639 if (tb1->ty == Tarray) |
8640 { // Make e1 into [e1] | |
8641 e1 = new ArrayLiteralExp(e1->loc, e1); | |
8642 e1->type = type; | |
8643 } | |
8644 return this; | |
8645 } | |
8646 | |
8647 typeCombine(sc); | |
8648 | |
8649 if (type->toBasetype()->ty == Tsarray) | |
8650 type = type->toBasetype()->next->arrayOf(); | |
8651 #if 0 | |
8652 e1->type->print(); | |
8653 e2->type->print(); | |
8654 type->print(); | |
8655 print(); | |
8656 #endif | |
8657 if (e1->op == TOKstring && e2->op == TOKstring) | |
8658 e = optimize(WANTvalue); | |
8659 else if (e1->type->equals(e2->type) && | |
8660 (e1->type->toBasetype()->ty == Tarray || | |
8661 e1->type->toBasetype()->ty == Tsarray)) | |
8662 { | |
8663 e = this; | |
8664 } | |
8665 else | |
8666 { | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8667 //printf("(%s) ~ (%s)\n", e1->toChars(), e2->toChars()); |
159 | 8668 error("Can only concatenate arrays, not (%s ~ %s)", |
8669 e1->type->toChars(), e2->type->toChars()); | |
8670 type = Type::tint32; | |
8671 e = this; | |
8672 } | |
8673 e->type = e->type->semantic(loc, sc); | |
8674 return e; | |
8675 } | |
8676 return this; | |
8677 } | |
8678 | |
8679 /************************************************************/ | |
8680 | |
8681 MulExp::MulExp(Loc loc, Expression *e1, Expression *e2) | |
8682 : BinExp(loc, TOKmul, sizeof(MulExp), e1, e2) | |
8683 { | |
8684 } | |
8685 | |
8686 Expression *MulExp::semantic(Scope *sc) | |
8687 { Expression *e; | |
8688 | |
8689 #if 0 | |
8690 printf("MulExp::semantic() %s\n", toChars()); | |
8691 #endif | |
8692 if (type) | |
8693 { | |
8694 return this; | |
8695 } | |
8696 | |
8697 BinExp::semanticp(sc); | |
8698 e = op_overload(sc); | |
8699 if (e) | |
8700 return e; | |
8701 | |
8702 typeCombine(sc); | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8703 if (e1->op != TOKslice && e2->op != TOKslice) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8704 { e1->checkArithmetic(); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8705 e2->checkArithmetic(); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8706 } |
159 | 8707 if (type->isfloating()) |
8708 { Type *t1 = e1->type; | |
8709 Type *t2 = e2->type; | |
8710 | |
8711 if (t1->isreal()) | |
8712 { | |
8713 type = t2; | |
8714 } | |
8715 else if (t2->isreal()) | |
8716 { | |
8717 type = t1; | |
8718 } | |
8719 else if (t1->isimaginary()) | |
8720 { | |
8721 if (t2->isimaginary()) | |
8722 { Expression *e; | |
8723 | |
8724 switch (t1->ty) | |
8725 { | |
8726 case Timaginary32: type = Type::tfloat32; break; | |
8727 case Timaginary64: type = Type::tfloat64; break; | |
8728 case Timaginary80: type = Type::tfloat80; break; | |
8729 default: assert(0); | |
8730 } | |
8731 | |
8732 // iy * iv = -yv | |
8733 e1->type = type; | |
8734 e2->type = type; | |
8735 e = new NegExp(loc, this); | |
8736 e = e->semantic(sc); | |
8737 return e; | |
8738 } | |
8739 else | |
8740 type = t2; // t2 is complex | |
8741 } | |
8742 else if (t2->isimaginary()) | |
8743 { | |
8744 type = t1; // t1 is complex | |
8745 } | |
8746 } | |
8747 return this; | |
8748 } | |
8749 | |
8750 /************************************************************/ | |
8751 | |
8752 DivExp::DivExp(Loc loc, Expression *e1, Expression *e2) | |
8753 : BinExp(loc, TOKdiv, sizeof(DivExp), e1, e2) | |
8754 { | |
8755 } | |
8756 | |
8757 Expression *DivExp::semantic(Scope *sc) | |
8758 { Expression *e; | |
8759 | |
8760 if (type) | |
8761 return this; | |
8762 | |
8763 BinExp::semanticp(sc); | |
8764 e = op_overload(sc); | |
8765 if (e) | |
8766 return e; | |
8767 | |
8768 typeCombine(sc); | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8769 if (e1->op != TOKslice && e2->op != TOKslice) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8770 { e1->checkArithmetic(); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8771 e2->checkArithmetic(); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8772 } |
159 | 8773 if (type->isfloating()) |
8774 { Type *t1 = e1->type; | |
8775 Type *t2 = e2->type; | |
8776 | |
8777 if (t1->isreal()) | |
8778 { | |
8779 type = t2; | |
8780 if (t2->isimaginary()) | |
8781 { Expression *e; | |
8782 | |
8783 // x/iv = i(-x/v) | |
8784 e2->type = t1; | |
8785 e = new NegExp(loc, this); | |
8786 e = e->semantic(sc); | |
8787 return e; | |
8788 } | |
8789 } | |
8790 else if (t2->isreal()) | |
8791 { | |
8792 type = t1; | |
8793 } | |
8794 else if (t1->isimaginary()) | |
8795 { | |
8796 if (t2->isimaginary()) | |
8797 { | |
8798 switch (t1->ty) | |
8799 { | |
8800 case Timaginary32: type = Type::tfloat32; break; | |
8801 case Timaginary64: type = Type::tfloat64; break; | |
8802 case Timaginary80: type = Type::tfloat80; break; | |
8803 default: assert(0); | |
8804 } | |
8805 } | |
8806 else | |
8807 type = t2; // t2 is complex | |
8808 } | |
8809 else if (t2->isimaginary()) | |
8810 { | |
8811 type = t1; // t1 is complex | |
8812 } | |
8813 } | |
8814 return this; | |
8815 } | |
8816 | |
8817 /************************************************************/ | |
8818 | |
8819 ModExp::ModExp(Loc loc, Expression *e1, Expression *e2) | |
8820 : BinExp(loc, TOKmod, sizeof(ModExp), e1, e2) | |
8821 { | |
8822 } | |
8823 | |
8824 Expression *ModExp::semantic(Scope *sc) | |
8825 { Expression *e; | |
8826 | |
8827 if (type) | |
8828 return this; | |
8829 | |
8830 BinExp::semanticp(sc); | |
8831 e = op_overload(sc); | |
8832 if (e) | |
8833 return e; | |
8834 | |
8835 typeCombine(sc); | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8836 if (e1->op != TOKslice && e2->op != TOKslice) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8837 { e1->checkArithmetic(); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8838 e2->checkArithmetic(); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8839 } |
159 | 8840 if (type->isfloating()) |
8841 { type = e1->type; | |
8842 if (e2->type->iscomplex()) | |
8843 { error("cannot perform modulo complex arithmetic"); | |
8844 return new IntegerExp(0); | |
8845 } | |
8846 } | |
8847 return this; | |
8848 } | |
8849 | |
8850 /************************************************************/ | |
8851 | |
8852 ShlExp::ShlExp(Loc loc, Expression *e1, Expression *e2) | |
8853 : BinExp(loc, TOKshl, sizeof(ShlExp), e1, e2) | |
8854 { | |
8855 } | |
8856 | |
8857 Expression *ShlExp::semantic(Scope *sc) | |
8858 { Expression *e; | |
8859 | |
8860 //printf("ShlExp::semantic(), type = %p\n", type); | |
8861 if (!type) | |
8862 { BinExp::semanticp(sc); | |
8863 e = op_overload(sc); | |
8864 if (e) | |
8865 return e; | |
8866 e1 = e1->checkIntegral(); | |
8867 e2 = e2->checkIntegral(); | |
8868 e1 = e1->integralPromotions(sc); | |
8869 //e2 = e2->castTo(sc, Type::tshiftcnt); | |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
639
diff
changeset
|
8870 e2 = e2->castTo(sc, e1->type); // LDC |
159 | 8871 type = e1->type; |
8872 } | |
8873 return this; | |
8874 } | |
8875 | |
8876 /************************************************************/ | |
8877 | |
8878 ShrExp::ShrExp(Loc loc, Expression *e1, Expression *e2) | |
8879 : BinExp(loc, TOKshr, sizeof(ShrExp), e1, e2) | |
8880 { | |
8881 } | |
8882 | |
8883 Expression *ShrExp::semantic(Scope *sc) | |
8884 { Expression *e; | |
8885 | |
8886 if (!type) | |
8887 { BinExp::semanticp(sc); | |
8888 e = op_overload(sc); | |
8889 if (e) | |
8890 return e; | |
8891 e1 = e1->checkIntegral(); | |
8892 e2 = e2->checkIntegral(); | |
8893 e1 = e1->integralPromotions(sc); | |
8894 //e2 = e2->castTo(sc, Type::tshiftcnt); | |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
639
diff
changeset
|
8895 e2 = e2->castTo(sc, e1->type); // LDC |
159 | 8896 type = e1->type; |
8897 } | |
8898 return this; | |
8899 } | |
8900 | |
8901 /************************************************************/ | |
8902 | |
8903 UshrExp::UshrExp(Loc loc, Expression *e1, Expression *e2) | |
8904 : BinExp(loc, TOKushr, sizeof(UshrExp), e1, e2) | |
8905 { | |
8906 } | |
8907 | |
8908 Expression *UshrExp::semantic(Scope *sc) | |
8909 { Expression *e; | |
8910 | |
8911 if (!type) | |
8912 { BinExp::semanticp(sc); | |
8913 e = op_overload(sc); | |
8914 if (e) | |
8915 return e; | |
8916 e1 = e1->checkIntegral(); | |
8917 e2 = e2->checkIntegral(); | |
8918 e1 = e1->integralPromotions(sc); | |
8919 //e2 = e2->castTo(sc, Type::tshiftcnt); | |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
639
diff
changeset
|
8920 e2 = e2->castTo(sc, e1->type); // LDC |
159 | 8921 type = e1->type; |
8922 } | |
8923 return this; | |
8924 } | |
8925 | |
8926 /************************************************************/ | |
8927 | |
8928 AndExp::AndExp(Loc loc, Expression *e1, Expression *e2) | |
8929 : BinExp(loc, TOKand, sizeof(AndExp), e1, e2) | |
8930 { | |
8931 } | |
8932 | |
8933 Expression *AndExp::semantic(Scope *sc) | |
8934 { Expression *e; | |
8935 | |
8936 if (!type) | |
8937 { BinExp::semanticp(sc); | |
8938 e = op_overload(sc); | |
8939 if (e) | |
8940 return e; | |
8941 if (e1->type->toBasetype()->ty == Tbool && | |
8942 e2->type->toBasetype()->ty == Tbool) | |
8943 { | |
8944 type = e1->type; | |
8945 e = this; | |
8946 } | |
8947 else | |
8948 { | |
8949 typeCombine(sc); | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8950 if (e1->op != TOKslice && e2->op != TOKslice) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8951 { e1->checkIntegral(); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8952 e2->checkIntegral(); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8953 } |
159 | 8954 } |
8955 } | |
8956 return this; | |
8957 } | |
8958 | |
8959 /************************************************************/ | |
8960 | |
8961 OrExp::OrExp(Loc loc, Expression *e1, Expression *e2) | |
8962 : BinExp(loc, TOKor, sizeof(OrExp), e1, e2) | |
8963 { | |
8964 } | |
8965 | |
8966 Expression *OrExp::semantic(Scope *sc) | |
8967 { Expression *e; | |
8968 | |
8969 if (!type) | |
8970 { BinExp::semanticp(sc); | |
8971 e = op_overload(sc); | |
8972 if (e) | |
8973 return e; | |
8974 if (e1->type->toBasetype()->ty == Tbool && | |
8975 e2->type->toBasetype()->ty == Tbool) | |
8976 { | |
8977 type = e1->type; | |
8978 e = this; | |
8979 } | |
8980 else | |
8981 { | |
8982 typeCombine(sc); | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8983 if (e1->op != TOKslice && e2->op != TOKslice) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8984 { e1->checkIntegral(); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8985 e2->checkIntegral(); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8986 } |
159 | 8987 } |
8988 } | |
8989 return this; | |
8990 } | |
8991 | |
8992 /************************************************************/ | |
8993 | |
8994 XorExp::XorExp(Loc loc, Expression *e1, Expression *e2) | |
8995 : BinExp(loc, TOKxor, sizeof(XorExp), e1, e2) | |
8996 { | |
8997 } | |
8998 | |
8999 Expression *XorExp::semantic(Scope *sc) | |
9000 { Expression *e; | |
9001 | |
9002 if (!type) | |
9003 { BinExp::semanticp(sc); | |
9004 e = op_overload(sc); | |
9005 if (e) | |
9006 return e; | |
9007 if (e1->type->toBasetype()->ty == Tbool && | |
9008 e2->type->toBasetype()->ty == Tbool) | |
9009 { | |
9010 type = e1->type; | |
9011 e = this; | |
9012 } | |
9013 else | |
9014 { | |
9015 typeCombine(sc); | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
9016 if (e1->op != TOKslice && e2->op != TOKslice) |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
9017 { e1->checkIntegral(); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
9018 e2->checkIntegral(); |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
9019 } |
159 | 9020 } |
9021 } | |
9022 return this; | |
9023 } | |
9024 | |
9025 | |
9026 /************************************************************/ | |
9027 | |
9028 OrOrExp::OrOrExp(Loc loc, Expression *e1, Expression *e2) | |
9029 : BinExp(loc, TOKoror, sizeof(OrOrExp), e1, e2) | |
9030 { | |
9031 } | |
9032 | |
9033 Expression *OrOrExp::semantic(Scope *sc) | |
9034 { | |
9035 unsigned cs1; | |
9036 | |
9037 // same as for AndAnd | |
9038 e1 = e1->semantic(sc); | |
9039 e1 = resolveProperties(sc, e1); | |
9040 e1 = e1->checkToPointer(); | |
9041 e1 = e1->checkToBoolean(); | |
9042 cs1 = sc->callSuper; | |
9043 | |
9044 if (sc->flags & SCOPEstaticif) | |
9045 { | |
9046 /* If in static if, don't evaluate e2 if we don't have to. | |
9047 */ | |
9048 e1 = e1->optimize(WANTflags); | |
9049 if (e1->isBool(TRUE)) | |
9050 { | |
9051 return new IntegerExp(loc, 1, Type::tboolean); | |
9052 } | |
9053 } | |
9054 | |
9055 e2 = e2->semantic(sc); | |
9056 sc->mergeCallSuper(loc, cs1); | |
9057 e2 = resolveProperties(sc, e2); | |
9058 e2 = e2->checkToPointer(); | |
9059 | |
9060 type = Type::tboolean; | |
779
ef7fe998f9b3
Fix return type of OrOr and AndAndExp being set incorrectly if rhs is void. Thanks wilsonk!
Christian Kamm <kamm incasoftware de>
parents:
723
diff
changeset
|
9061 if (e2->type->ty == Tvoid) |
159 | 9062 type = Type::tvoid; |
9063 if (e2->op == TOKtype || e2->op == TOKimport) | |
9064 error("%s is not an expression", e2->toChars()); | |
9065 return this; | |
9066 } | |
9067 | |
9068 Expression *OrOrExp::checkToBoolean() | |
9069 { | |
9070 e2 = e2->checkToBoolean(); | |
9071 return this; | |
9072 } | |
9073 | |
9074 int OrOrExp::isBit() | |
9075 { | |
9076 return TRUE; | |
9077 } | |
9078 | |
9079 int OrOrExp::checkSideEffect(int flag) | |
9080 { | |
9081 if (flag == 2) | |
9082 { | |
9083 return e1->checkSideEffect(2) || e2->checkSideEffect(2); | |
9084 } | |
9085 else | |
9086 { e1->checkSideEffect(1); | |
9087 return e2->checkSideEffect(flag); | |
9088 } | |
9089 } | |
9090 | |
9091 /************************************************************/ | |
9092 | |
9093 AndAndExp::AndAndExp(Loc loc, Expression *e1, Expression *e2) | |
9094 : BinExp(loc, TOKandand, sizeof(AndAndExp), e1, e2) | |
9095 { | |
9096 } | |
9097 | |
9098 Expression *AndAndExp::semantic(Scope *sc) | |
9099 { | |
9100 unsigned cs1; | |
9101 | |
9102 // same as for OrOr | |
9103 e1 = e1->semantic(sc); | |
9104 e1 = resolveProperties(sc, e1); | |
9105 e1 = e1->checkToPointer(); | |
9106 e1 = e1->checkToBoolean(); | |
9107 cs1 = sc->callSuper; | |
9108 | |
9109 if (sc->flags & SCOPEstaticif) | |
9110 { | |
9111 /* If in static if, don't evaluate e2 if we don't have to. | |
9112 */ | |
9113 e1 = e1->optimize(WANTflags); | |
9114 if (e1->isBool(FALSE)) | |
9115 { | |
9116 return new IntegerExp(loc, 0, Type::tboolean); | |
9117 } | |
9118 } | |
9119 | |
9120 e2 = e2->semantic(sc); | |
9121 sc->mergeCallSuper(loc, cs1); | |
9122 e2 = resolveProperties(sc, e2); | |
9123 e2 = e2->checkToPointer(); | |
9124 | |
9125 type = Type::tboolean; | |
779
ef7fe998f9b3
Fix return type of OrOr and AndAndExp being set incorrectly if rhs is void. Thanks wilsonk!
Christian Kamm <kamm incasoftware de>
parents:
723
diff
changeset
|
9126 if (e2->type->ty == Tvoid) |
159 | 9127 type = Type::tvoid; |
9128 if (e2->op == TOKtype || e2->op == TOKimport) | |
9129 error("%s is not an expression", e2->toChars()); | |
9130 return this; | |
9131 } | |
9132 | |
9133 Expression *AndAndExp::checkToBoolean() | |
9134 { | |
9135 e2 = e2->checkToBoolean(); | |
9136 return this; | |
9137 } | |
9138 | |
9139 int AndAndExp::isBit() | |
9140 { | |
9141 return TRUE; | |
9142 } | |
9143 | |
9144 int AndAndExp::checkSideEffect(int flag) | |
9145 { | |
9146 if (flag == 2) | |
9147 { | |
9148 return e1->checkSideEffect(2) || e2->checkSideEffect(2); | |
9149 } | |
9150 else | |
9151 { | |
9152 e1->checkSideEffect(1); | |
9153 return e2->checkSideEffect(flag); | |
9154 } | |
9155 } | |
9156 | |
9157 /************************************************************/ | |
9158 | |
9159 InExp::InExp(Loc loc, Expression *e1, Expression *e2) | |
9160 : BinExp(loc, TOKin, sizeof(InExp), e1, e2) | |
9161 { | |
9162 } | |
9163 | |
9164 Expression *InExp::semantic(Scope *sc) | |
9165 { Expression *e; | |
9166 | |
9167 if (type) | |
9168 return this; | |
9169 | |
9170 BinExp::semanticp(sc); | |
9171 e = op_overload(sc); | |
9172 if (e) | |
9173 return e; | |
9174 | |
9175 //type = Type::tboolean; | |
9176 Type *t2b = e2->type->toBasetype(); | |
9177 if (t2b->ty != Taarray) | |
9178 { | |
9179 error("rvalue of in expression must be an associative array, not %s", e2->type->toChars()); | |
9180 type = Type::terror; | |
9181 } | |
9182 else | |
9183 { | |
9184 TypeAArray *ta = (TypeAArray *)t2b; | |
9185 | |
9186 // Convert key to type of key | |
9187 e1 = e1->implicitCastTo(sc, ta->index); | |
9188 | |
9189 // Return type is pointer to value | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
9190 type = ta->nextOf()->pointerTo(); |
159 | 9191 } |
9192 return this; | |
9193 } | |
9194 | |
9195 int InExp::isBit() | |
9196 { | |
9197 return FALSE; | |
9198 } | |
9199 | |
9200 | |
9201 /************************************************************/ | |
9202 | |
9203 /* This deletes the key e1 from the associative array e2 | |
9204 */ | |
9205 | |
9206 RemoveExp::RemoveExp(Loc loc, Expression *e1, Expression *e2) | |
9207 : BinExp(loc, TOKremove, sizeof(RemoveExp), e1, e2) | |
9208 { | |
9209 type = Type::tvoid; | |
9210 } | |
9211 | |
9212 /************************************************************/ | |
9213 | |
9214 CmpExp::CmpExp(enum TOK op, Loc loc, Expression *e1, Expression *e2) | |
9215 : BinExp(loc, op, sizeof(CmpExp), e1, e2) | |
9216 { | |
9217 } | |
9218 | |
9219 Expression *CmpExp::semantic(Scope *sc) | |
9220 { Expression *e; | |
9221 Type *t1; | |
9222 Type *t2; | |
9223 | |
9224 #if LOGSEMANTIC | |
9225 printf("CmpExp::semantic('%s')\n", toChars()); | |
9226 #endif | |
9227 if (type) | |
9228 return this; | |
9229 | |
9230 BinExp::semanticp(sc); | |
9231 | |
9232 if (e1->type->toBasetype()->ty == Tclass && e2->op == TOKnull || | |
9233 e2->type->toBasetype()->ty == Tclass && e1->op == TOKnull) | |
9234 { | |
9235 error("do not use null when comparing class types"); | |
9236 } | |
9237 | |
9238 e = op_overload(sc); | |
9239 if (e) | |
9240 { | |
9241 e = new CmpExp(op, loc, e, new IntegerExp(loc, 0, Type::tint32)); | |
9242 e = e->semantic(sc); | |
9243 return e; | |
9244 } | |
9245 | |
9246 typeCombine(sc); | |
9247 type = Type::tboolean; | |
9248 | |
9249 // Special handling for array comparisons | |
9250 t1 = e1->type->toBasetype(); | |
9251 t2 = e2->type->toBasetype(); | |
9252 if ((t1->ty == Tarray || t1->ty == Tsarray) && | |
9253 (t2->ty == Tarray || t2->ty == Tsarray)) | |
9254 { | |
9255 if (!t1->next->equals(t2->next)) | |
9256 error("array comparison type mismatch, %s vs %s", t1->next->toChars(), t2->next->toChars()); | |
9257 e = this; | |
9258 } | |
9259 else if (t1->ty == Tstruct || t2->ty == Tstruct || | |
9260 (t1->ty == Tclass && t2->ty == Tclass)) | |
9261 { | |
9262 if (t2->ty == Tstruct) | |
9263 error("need member function opCmp() for %s %s to compare", t2->toDsymbol(sc)->kind(), t2->toChars()); | |
9264 else | |
9265 error("need member function opCmp() for %s %s to compare", t1->toDsymbol(sc)->kind(), t1->toChars()); | |
9266 e = this; | |
9267 } | |
9268 #if 1 | |
9269 else if (t1->iscomplex() || t2->iscomplex()) | |
9270 { | |
9271 error("compare not defined for complex operands"); | |
9272 e = new IntegerExp(0); | |
9273 } | |
9274 #endif | |
9275 else | |
9276 e = this; | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
9277 //printf("CmpExp: %s\n", e->toChars()); |
159 | 9278 return e; |
9279 } | |
9280 | |
9281 int CmpExp::isBit() | |
9282 { | |
9283 return TRUE; | |
9284 } | |
9285 | |
9286 | |
9287 /************************************************************/ | |
9288 | |
9289 EqualExp::EqualExp(enum TOK op, Loc loc, Expression *e1, Expression *e2) | |
9290 : BinExp(loc, op, sizeof(EqualExp), e1, e2) | |
9291 { | |
9292 assert(op == TOKequal || op == TOKnotequal); | |
9293 } | |
9294 | |
9295 Expression *EqualExp::semantic(Scope *sc) | |
9296 { Expression *e; | |
9297 Type *t1; | |
9298 Type *t2; | |
9299 | |
9300 //printf("EqualExp::semantic('%s')\n", toChars()); | |
9301 if (type) | |
9302 return this; | |
9303 | |
9304 BinExp::semanticp(sc); | |
9305 | |
9306 /* Before checking for operator overloading, check to see if we're | |
9307 * comparing the addresses of two statics. If so, we can just see | |
9308 * if they are the same symbol. | |
9309 */ | |
9310 if (e1->op == TOKaddress && e2->op == TOKaddress) | |
9311 { AddrExp *ae1 = (AddrExp *)e1; | |
9312 AddrExp *ae2 = (AddrExp *)e2; | |
9313 | |
9314 if (ae1->e1->op == TOKvar && ae2->e1->op == TOKvar) | |
9315 { VarExp *ve1 = (VarExp *)ae1->e1; | |
9316 VarExp *ve2 = (VarExp *)ae2->e1; | |
9317 | |
9318 if (ve1->var == ve2->var /*|| ve1->var->toSymbol() == ve2->var->toSymbol()*/) | |
9319 { | |
9320 // They are the same, result is 'true' for ==, 'false' for != | |
9321 e = new IntegerExp(loc, (op == TOKequal), Type::tboolean); | |
9322 return e; | |
9323 } | |
9324 } | |
9325 } | |
9326 | |
9327 if (e1->type->toBasetype()->ty == Tclass && e2->op == TOKnull || | |
9328 e2->type->toBasetype()->ty == Tclass && e1->op == TOKnull) | |
9329 { | |
9330 error("use '%s' instead of '%s' when comparing with null", | |
9331 Token::toChars(op == TOKequal ? TOKidentity : TOKnotidentity), | |
9332 Token::toChars(op)); | |
9333 } | |
9334 | |
9335 //if (e2->op != TOKnull) | |
9336 { | |
9337 e = op_overload(sc); | |
9338 if (e) | |
9339 { | |
9340 if (op == TOKnotequal) | |
9341 { | |
9342 e = new NotExp(e->loc, e); | |
9343 e = e->semantic(sc); | |
9344 } | |
9345 return e; | |
9346 } | |
9347 } | |
9348 | |
9349 e = typeCombine(sc); | |
9350 type = Type::tboolean; | |
9351 | |
9352 // Special handling for array comparisons | |
9353 t1 = e1->type->toBasetype(); | |
9354 t2 = e2->type->toBasetype(); | |
9355 if ((t1->ty == Tarray || t1->ty == Tsarray) && | |
9356 (t2->ty == Tarray || t2->ty == Tsarray)) | |
9357 { | |
9358 if (!t1->next->equals(t2->next)) | |
9359 error("array comparison type mismatch, %s vs %s", t1->next->toChars(), t2->next->toChars()); | |
9360 } | |
9361 else | |
9362 { | |
9363 if (e1->type != e2->type && e1->type->isfloating() && e2->type->isfloating()) | |
9364 { | |
9365 // Cast both to complex | |
9366 e1 = e1->castTo(sc, Type::tcomplex80); | |
9367 e2 = e2->castTo(sc, Type::tcomplex80); | |
9368 } | |
9369 } | |
9370 return e; | |
9371 } | |
9372 | |
9373 int EqualExp::isBit() | |
9374 { | |
9375 return TRUE; | |
9376 } | |
9377 | |
9378 | |
9379 | |
9380 /************************************************************/ | |
9381 | |
9382 IdentityExp::IdentityExp(enum TOK op, Loc loc, Expression *e1, Expression *e2) | |
9383 : BinExp(loc, op, sizeof(IdentityExp), e1, e2) | |
9384 { | |
9385 } | |
9386 | |
9387 Expression *IdentityExp::semantic(Scope *sc) | |
9388 { | |
9389 if (type) | |
9390 return this; | |
9391 | |
9392 BinExp::semanticp(sc); | |
9393 type = Type::tboolean; | |
9394 typeCombine(sc); | |
9395 if (e1->type != e2->type && e1->type->isfloating() && e2->type->isfloating()) | |
9396 { | |
9397 // Cast both to complex | |
9398 e1 = e1->castTo(sc, Type::tcomplex80); | |
9399 e2 = e2->castTo(sc, Type::tcomplex80); | |
9400 } | |
9401 return this; | |
9402 } | |
9403 | |
9404 int IdentityExp::isBit() | |
9405 { | |
9406 return TRUE; | |
9407 } | |
9408 | |
9409 | |
9410 /****************************************************************/ | |
9411 | |
9412 CondExp::CondExp(Loc loc, Expression *econd, Expression *e1, Expression *e2) | |
9413 : BinExp(loc, TOKquestion, sizeof(CondExp), e1, e2) | |
9414 { | |
9415 this->econd = econd; | |
9416 } | |
9417 | |
9418 Expression *CondExp::syntaxCopy() | |
9419 { | |
9420 return new CondExp(loc, econd->syntaxCopy(), e1->syntaxCopy(), e2->syntaxCopy()); | |
9421 } | |
9422 | |
9423 | |
9424 Expression *CondExp::semantic(Scope *sc) | |
9425 { Type *t1; | |
9426 Type *t2; | |
9427 unsigned cs0; | |
9428 unsigned cs1; | |
9429 | |
9430 #if LOGSEMANTIC | |
9431 printf("CondExp::semantic('%s')\n", toChars()); | |
9432 #endif | |
9433 if (type) | |
9434 return this; | |
9435 | |
9436 econd = econd->semantic(sc); | |
9437 econd = resolveProperties(sc, econd); | |
9438 econd = econd->checkToPointer(); | |
9439 econd = econd->checkToBoolean(); | |
9440 | |
9441 #if 0 /* this cannot work right because the types of e1 and e2 | |
9442 * both contribute to the type of the result. | |
9443 */ | |
9444 if (sc->flags & SCOPEstaticif) | |
9445 { | |
9446 /* If in static if, don't evaluate what we don't have to. | |
9447 */ | |
9448 econd = econd->optimize(WANTflags); | |
9449 if (econd->isBool(TRUE)) | |
9450 { | |
9451 e1 = e1->semantic(sc); | |
9452 e1 = resolveProperties(sc, e1); | |
9453 return e1; | |
9454 } | |
9455 else if (econd->isBool(FALSE)) | |
9456 { | |
9457 e2 = e2->semantic(sc); | |
9458 e2 = resolveProperties(sc, e2); | |
9459 return e2; | |
9460 } | |
9461 } | |
9462 #endif | |
9463 | |
9464 | |
9465 cs0 = sc->callSuper; | |
9466 e1 = e1->semantic(sc); | |
9467 e1 = resolveProperties(sc, e1); | |
9468 cs1 = sc->callSuper; | |
9469 sc->callSuper = cs0; | |
9470 e2 = e2->semantic(sc); | |
9471 e2 = resolveProperties(sc, e2); | |
9472 sc->mergeCallSuper(loc, cs1); | |
9473 | |
9474 | |
9475 // If either operand is void, the result is void | |
9476 t1 = e1->type; | |
9477 t2 = e2->type; | |
9478 if (t1->ty == Tvoid || t2->ty == Tvoid) | |
9479 type = Type::tvoid; | |
9480 else if (t1 == t2) | |
9481 type = t1; | |
9482 else | |
9483 { | |
9484 typeCombine(sc); | |
9485 switch (e1->type->toBasetype()->ty) | |
9486 { | |
9487 case Tcomplex32: | |
9488 case Tcomplex64: | |
9489 case Tcomplex80: | |
9490 e2 = e2->castTo(sc, e1->type); | |
9491 break; | |
9492 } | |
9493 switch (e2->type->toBasetype()->ty) | |
9494 { | |
9495 case Tcomplex32: | |
9496 case Tcomplex64: | |
9497 case Tcomplex80: | |
9498 e1 = e1->castTo(sc, e2->type); | |
9499 break; | |
9500 } | |
9501 } | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
9502 #if 0 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
9503 printf("res: %s\n", type->toChars()); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
9504 printf("e1 : %s\n", e1->type->toChars()); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
9505 printf("e2 : %s\n", e2->type->toChars()); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
9506 #endif |
159 | 9507 return this; |
9508 } | |
9509 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
9510 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
9511 int CondExp::isLvalue() |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
9512 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
9513 return e1->isLvalue() && e2->isLvalue(); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
9514 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
9515 #endif |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
9516 |
159 | 9517 Expression *CondExp::toLvalue(Scope *sc, Expression *ex) |
9518 { | |
9519 PtrExp *e; | |
9520 | |
9521 // convert (econd ? e1 : e2) to *(econd ? &e1 : &e2) | |
9522 e = new PtrExp(loc, this, type); | |
9523 | |
9524 e1 = e1->addressOf(sc); | |
9525 //e1 = e1->toLvalue(sc, NULL); | |
9526 | |
9527 e2 = e2->addressOf(sc); | |
9528 //e2 = e2->toLvalue(sc, NULL); | |
9529 | |
9530 typeCombine(sc); | |
9531 | |
9532 type = e2->type; | |
9533 return e; | |
9534 } | |
9535 | |
9536 Expression *CondExp::modifiableLvalue(Scope *sc, Expression *e) | |
9537 { | |
9538 error("conditional expression %s is not a modifiable lvalue", toChars()); | |
9539 return this; | |
9540 } | |
9541 | |
9542 void CondExp::checkEscape() | |
9543 { | |
9544 e1->checkEscape(); | |
9545 e2->checkEscape(); | |
9546 } | |
9547 | |
9548 | |
9549 Expression *CondExp::checkToBoolean() | |
9550 { | |
9551 e1 = e1->checkToBoolean(); | |
9552 e2 = e2->checkToBoolean(); | |
9553 return this; | |
9554 } | |
9555 | |
9556 int CondExp::checkSideEffect(int flag) | |
9557 { | |
9558 if (flag == 2) | |
9559 { | |
9560 return econd->checkSideEffect(2) || | |
9561 e1->checkSideEffect(2) || | |
9562 e2->checkSideEffect(2); | |
9563 } | |
9564 else | |
9565 { | |
9566 econd->checkSideEffect(1); | |
9567 e1->checkSideEffect(flag); | |
9568 return e2->checkSideEffect(flag); | |
9569 } | |
9570 } | |
9571 | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
9572 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
9573 int CondExp::canThrow() |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
9574 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
9575 return econd->canThrow() || e1->canThrow() || e2->canThrow(); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
9576 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
9577 #endif |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
846
diff
changeset
|
9578 |
159 | 9579 void CondExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
9580 { | |
9581 expToCBuffer(buf, hgs, econd, PREC_oror); | |
9582 buf->writestring(" ? "); | |
9583 expToCBuffer(buf, hgs, e1, PREC_expr); | |
9584 buf->writestring(" : "); | |
9585 expToCBuffer(buf, hgs, e2, PREC_cond); | |
9586 } | |
9587 | |
599
4435f57956e7
Fixed .funcptr property of delegates, no longer uses the infamous DMD rewrites to pointer arithmetic, instead a GEPExp has been introduced.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
585
diff
changeset
|
9588 /************************************************************/ |
4435f57956e7
Fixed .funcptr property of delegates, no longer uses the infamous DMD rewrites to pointer arithmetic, instead a GEPExp has been introduced.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
585
diff
changeset
|
9589 |
4435f57956e7
Fixed .funcptr property of delegates, no longer uses the infamous DMD rewrites to pointer arithmetic, instead a GEPExp has been introduced.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
585
diff
changeset
|
9590 #if IN_LLVM |
4435f57956e7
Fixed .funcptr property of delegates, no longer uses the infamous DMD rewrites to pointer arithmetic, instead a GEPExp has been introduced.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
585
diff
changeset
|
9591 |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
639
diff
changeset
|
9592 // Strictly LDC specific stuff |
599
4435f57956e7
Fixed .funcptr property of delegates, no longer uses the infamous DMD rewrites to pointer arithmetic, instead a GEPExp has been introduced.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
585
diff
changeset
|
9593 |
4435f57956e7
Fixed .funcptr property of delegates, no longer uses the infamous DMD rewrites to pointer arithmetic, instead a GEPExp has been introduced.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
585
diff
changeset
|
9594 GEPExp::GEPExp(Loc loc, Expression* e, Identifier* id, unsigned idx) |
4435f57956e7
Fixed .funcptr property of delegates, no longer uses the infamous DMD rewrites to pointer arithmetic, instead a GEPExp has been introduced.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
585
diff
changeset
|
9595 : UnaExp(loc, TOKgep, sizeof(GEPExp), e) |
4435f57956e7
Fixed .funcptr property of delegates, no longer uses the infamous DMD rewrites to pointer arithmetic, instead a GEPExp has been introduced.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
585
diff
changeset
|
9596 { |
4435f57956e7
Fixed .funcptr property of delegates, no longer uses the infamous DMD rewrites to pointer arithmetic, instead a GEPExp has been introduced.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
585
diff
changeset
|
9597 index = idx; |
4435f57956e7
Fixed .funcptr property of delegates, no longer uses the infamous DMD rewrites to pointer arithmetic, instead a GEPExp has been introduced.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
585
diff
changeset
|
9598 ident = id; |
4435f57956e7
Fixed .funcptr property of delegates, no longer uses the infamous DMD rewrites to pointer arithmetic, instead a GEPExp has been introduced.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
585
diff
changeset
|
9599 } |
4435f57956e7
Fixed .funcptr property of delegates, no longer uses the infamous DMD rewrites to pointer arithmetic, instead a GEPExp has been introduced.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
585
diff
changeset
|
9600 |
4435f57956e7
Fixed .funcptr property of delegates, no longer uses the infamous DMD rewrites to pointer arithmetic, instead a GEPExp has been introduced.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
585
diff
changeset
|
9601 void GEPExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) |
4435f57956e7
Fixed .funcptr property of delegates, no longer uses the infamous DMD rewrites to pointer arithmetic, instead a GEPExp has been introduced.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
585
diff
changeset
|
9602 { |
4435f57956e7
Fixed .funcptr property of delegates, no longer uses the infamous DMD rewrites to pointer arithmetic, instead a GEPExp has been introduced.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
585
diff
changeset
|
9603 expToCBuffer(buf, hgs, e1, PREC_primary); |
4435f57956e7
Fixed .funcptr property of delegates, no longer uses the infamous DMD rewrites to pointer arithmetic, instead a GEPExp has been introduced.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
585
diff
changeset
|
9604 buf->writeByte('.'); |
4435f57956e7
Fixed .funcptr property of delegates, no longer uses the infamous DMD rewrites to pointer arithmetic, instead a GEPExp has been introduced.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
585
diff
changeset
|
9605 buf->writestring(ident->toChars()); |
4435f57956e7
Fixed .funcptr property of delegates, no longer uses the infamous DMD rewrites to pointer arithmetic, instead a GEPExp has been introduced.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
585
diff
changeset
|
9606 } |
4435f57956e7
Fixed .funcptr property of delegates, no longer uses the infamous DMD rewrites to pointer arithmetic, instead a GEPExp has been introduced.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
585
diff
changeset
|
9607 |
4435f57956e7
Fixed .funcptr property of delegates, no longer uses the infamous DMD rewrites to pointer arithmetic, instead a GEPExp has been introduced.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
585
diff
changeset
|
9608 Expression* GEPExp::toLvalue(Scope* sc, Expression* e) |
4435f57956e7
Fixed .funcptr property of delegates, no longer uses the infamous DMD rewrites to pointer arithmetic, instead a GEPExp has been introduced.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
585
diff
changeset
|
9609 { |
4435f57956e7
Fixed .funcptr property of delegates, no longer uses the infamous DMD rewrites to pointer arithmetic, instead a GEPExp has been introduced.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
585
diff
changeset
|
9610 // GEP's are always lvalues, at least in the "LLVM sense" ... |
4435f57956e7
Fixed .funcptr property of delegates, no longer uses the infamous DMD rewrites to pointer arithmetic, instead a GEPExp has been introduced.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
585
diff
changeset
|
9611 return this; |
4435f57956e7
Fixed .funcptr property of delegates, no longer uses the infamous DMD rewrites to pointer arithmetic, instead a GEPExp has been introduced.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
585
diff
changeset
|
9612 } |
4435f57956e7
Fixed .funcptr property of delegates, no longer uses the infamous DMD rewrites to pointer arithmetic, instead a GEPExp has been introduced.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
585
diff
changeset
|
9613 |
4435f57956e7
Fixed .funcptr property of delegates, no longer uses the infamous DMD rewrites to pointer arithmetic, instead a GEPExp has been introduced.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
585
diff
changeset
|
9614 #endif |