Mercurial > projects > ldc
annotate dmd/expression.c @ 837:331a176c1f4f
Removed error on naked, not fully complete, but I'll be doing more work on it during this Christmas, and some things do work.
Fixed taking delegate of final class method. see mini/delegate3.d.
author | Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> |
---|---|
date | Tue, 09 Dec 2008 14:07:30 +0100 |
parents | 661384d6a936 |
children | 783f67fbdf4a |
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> | |
15 #include <complex> | |
16 #include <math.h> | |
17 | |
18 #if _WIN32 && __DMC__ | |
19 extern "C" char * __cdecl __locale_decpoint; | |
20 #endif | |
21 | |
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
|
22 #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
|
23 #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
|
24 #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
|
25 #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
|
26 #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
|
27 |
536
0d2db7efa105
Add isnan for __APPLE__ and darwin version ident for OSX.
Christian Kamm <kamm incasoftware de>
parents:
535
diff
changeset
|
28 #ifdef __APPLE__ |
0d2db7efa105
Add isnan for __APPLE__ and darwin version ident for OSX.
Christian Kamm <kamm incasoftware de>
parents:
535
diff
changeset
|
29 #ifndef isnan |
0d2db7efa105
Add isnan for __APPLE__ and darwin version ident for OSX.
Christian Kamm <kamm incasoftware de>
parents:
535
diff
changeset
|
30 int isnan(double); |
0d2db7efa105
Add isnan for __APPLE__ and darwin version ident for OSX.
Christian Kamm <kamm incasoftware de>
parents:
535
diff
changeset
|
31 #endif |
0d2db7efa105
Add isnan for __APPLE__ and darwin version ident for OSX.
Christian Kamm <kamm incasoftware de>
parents:
535
diff
changeset
|
32 #endif |
0d2db7efa105
Add isnan for __APPLE__ and darwin version ident for OSX.
Christian Kamm <kamm incasoftware de>
parents:
535
diff
changeset
|
33 |
159 | 34 #if IN_GCC |
35 // Issues with using -include total.h (defines integer_t) and then complex.h fails... | |
36 #undef integer_t | |
37 #endif | |
38 | |
39 #ifdef __APPLE__ | |
40 #define integer_t dmd_integer_t | |
41 #endif | |
42 | |
43 #if IN_GCC || IN_LLVM | |
44 #include "mem.h" | |
45 #elif _WIN32 | |
46 #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
|
47 #elif POSIX |
159 | 48 #include "../root/mem.h" |
49 #endif | |
50 | |
51 //#include "port.h" | |
52 #include "mtype.h" | |
53 #include "init.h" | |
54 #include "expression.h" | |
55 #include "template.h" | |
56 #include "utf.h" | |
57 #include "enum.h" | |
58 #include "scope.h" | |
59 #include "statement.h" | |
60 #include "declaration.h" | |
61 #include "aggregate.h" | |
62 #include "import.h" | |
63 #include "id.h" | |
64 #include "dsymbol.h" | |
65 #include "module.h" | |
66 #include "attrib.h" | |
67 #include "hdrgen.h" | |
68 #include "parse.h" | |
69 | |
70 Expression *createTypeInfoArray(Scope *sc, Expression *args[], int dim); | |
71 | |
72 #define LOGSEMANTIC 0 | |
73 | |
74 /********************************** | |
75 * Set operator precedence for each operator. | |
76 */ | |
77 | |
78 // Operator precedence - greater values are higher precedence | |
79 | |
80 enum PREC | |
81 { | |
82 PREC_zero, | |
83 PREC_expr, | |
84 PREC_assign, | |
85 PREC_cond, | |
86 PREC_oror, | |
87 PREC_andand, | |
88 PREC_or, | |
89 PREC_xor, | |
90 PREC_and, | |
91 PREC_equal, | |
92 PREC_rel, | |
93 PREC_shift, | |
94 PREC_add, | |
95 PREC_mul, | |
96 PREC_unary, | |
97 PREC_primary, | |
98 }; | |
99 | |
100 enum PREC precedence[TOKMAX]; | |
101 | |
102 void initPrecedence() | |
103 { | |
104 precedence[TOKdotvar] = PREC_primary; | |
105 precedence[TOKimport] = PREC_primary; | |
106 precedence[TOKidentifier] = PREC_primary; | |
107 precedence[TOKthis] = PREC_primary; | |
108 precedence[TOKsuper] = PREC_primary; | |
109 precedence[TOKint64] = PREC_primary; | |
110 precedence[TOKfloat64] = PREC_primary; | |
111 precedence[TOKnull] = PREC_primary; | |
112 precedence[TOKstring] = PREC_primary; | |
113 precedence[TOKarrayliteral] = PREC_primary; | |
114 precedence[TOKtypedot] = PREC_primary; | |
115 precedence[TOKtypeid] = PREC_primary; | |
116 precedence[TOKis] = PREC_primary; | |
117 precedence[TOKassert] = PREC_primary; | |
118 precedence[TOKfunction] = PREC_primary; | |
119 precedence[TOKvar] = PREC_primary; | |
336 | 120 #if DMDV2 |
121 precedence[TOKdefault] = PREC_primary; | |
122 #endif | |
159 | 123 |
124 // post | |
125 precedence[TOKdotti] = PREC_primary; | |
126 precedence[TOKdot] = PREC_primary; | |
127 // precedence[TOKarrow] = PREC_primary; | |
128 precedence[TOKplusplus] = PREC_primary; | |
129 precedence[TOKminusminus] = PREC_primary; | |
130 precedence[TOKcall] = PREC_primary; | |
131 precedence[TOKslice] = PREC_primary; | |
132 precedence[TOKarray] = PREC_primary; | |
133 | |
134 precedence[TOKaddress] = PREC_unary; | |
135 precedence[TOKstar] = PREC_unary; | |
136 precedence[TOKneg] = PREC_unary; | |
137 precedence[TOKuadd] = PREC_unary; | |
138 precedence[TOKnot] = PREC_unary; | |
139 precedence[TOKtobool] = PREC_add; | |
140 precedence[TOKtilde] = PREC_unary; | |
141 precedence[TOKdelete] = PREC_unary; | |
142 precedence[TOKnew] = PREC_unary; | |
143 precedence[TOKcast] = PREC_unary; | |
144 | |
145 precedence[TOKmul] = PREC_mul; | |
146 precedence[TOKdiv] = PREC_mul; | |
147 precedence[TOKmod] = PREC_mul; | |
148 | |
149 precedence[TOKadd] = PREC_add; | |
150 precedence[TOKmin] = PREC_add; | |
151 precedence[TOKcat] = PREC_add; | |
152 | |
153 precedence[TOKshl] = PREC_shift; | |
154 precedence[TOKshr] = PREC_shift; | |
155 precedence[TOKushr] = PREC_shift; | |
156 | |
157 precedence[TOKlt] = PREC_rel; | |
158 precedence[TOKle] = PREC_rel; | |
159 precedence[TOKgt] = PREC_rel; | |
160 precedence[TOKge] = PREC_rel; | |
161 precedence[TOKunord] = PREC_rel; | |
162 precedence[TOKlg] = PREC_rel; | |
163 precedence[TOKleg] = PREC_rel; | |
164 precedence[TOKule] = PREC_rel; | |
165 precedence[TOKul] = PREC_rel; | |
166 precedence[TOKuge] = PREC_rel; | |
167 precedence[TOKug] = PREC_rel; | |
168 precedence[TOKue] = PREC_rel; | |
169 precedence[TOKin] = PREC_rel; | |
170 | |
171 precedence[TOKequal] = PREC_equal; | |
172 precedence[TOKnotequal] = PREC_equal; | |
173 precedence[TOKidentity] = PREC_equal; | |
174 precedence[TOKnotidentity] = PREC_equal; | |
175 | |
176 precedence[TOKand] = PREC_and; | |
177 | |
178 precedence[TOKxor] = PREC_xor; | |
179 | |
180 precedence[TOKor] = PREC_or; | |
181 | |
182 precedence[TOKandand] = PREC_andand; | |
183 | |
184 precedence[TOKoror] = PREC_oror; | |
185 | |
186 precedence[TOKquestion] = PREC_cond; | |
187 | |
188 precedence[TOKassign] = PREC_assign; | |
189 precedence[TOKconstruct] = PREC_assign; | |
190 precedence[TOKblit] = PREC_assign; | |
191 precedence[TOKaddass] = PREC_assign; | |
192 precedence[TOKminass] = PREC_assign; | |
193 precedence[TOKcatass] = PREC_assign; | |
194 precedence[TOKmulass] = PREC_assign; | |
195 precedence[TOKdivass] = PREC_assign; | |
196 precedence[TOKmodass] = PREC_assign; | |
197 precedence[TOKshlass] = PREC_assign; | |
198 precedence[TOKshrass] = PREC_assign; | |
199 precedence[TOKushrass] = PREC_assign; | |
200 precedence[TOKandass] = PREC_assign; | |
201 precedence[TOKorass] = PREC_assign; | |
202 precedence[TOKxorass] = PREC_assign; | |
203 | |
204 precedence[TOKcomma] = PREC_expr; | |
205 } | |
206 | |
336 | 207 /************************************************************* |
208 * Given var, we need to get the | |
209 * right 'this' pointer if var is in an outer class, but our | |
210 * existing 'this' pointer is in an inner class. | |
211 * Input: | |
212 * e1 existing 'this' | |
213 * ad struct or class we need the correct 'this' for | |
214 * var the specific member of ad we're accessing | |
215 */ | |
216 | |
217 Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad, | |
218 Expression *e1, Declaration *var) | |
219 { | |
220 //printf("\ngetRightThis(e1 = %s, ad = %s, var = %s)\n", e1->toChars(), ad->toChars(), var->toChars()); | |
221 L1: | |
222 Type *t = e1->type->toBasetype(); | |
223 //printf("e1->type = %s, var->type = %s\n", e1->type->toChars(), var->type->toChars()); | |
224 | |
225 /* If e1 is not the 'this' pointer for ad | |
226 */ | |
227 if (ad && | |
228 !(t->ty == Tpointer && t->nextOf()->ty == Tstruct && | |
229 ((TypeStruct *)t->nextOf())->sym == ad) | |
230 && | |
231 !(t->ty == Tstruct && | |
232 ((TypeStruct *)t)->sym == ad) | |
233 ) | |
234 { | |
235 ClassDeclaration *cd = ad->isClassDeclaration(); | |
236 ClassDeclaration *tcd = t->isClassHandle(); | |
237 | |
238 /* e1 is the right this if ad is a base class of e1 | |
239 */ | |
240 if (!cd || !tcd || | |
241 !(tcd == cd || cd->isBaseOf(tcd, NULL)) | |
242 ) | |
243 { | |
244 /* Only classes can be inner classes with an 'outer' | |
245 * member pointing to the enclosing class instance | |
246 */ | |
247 if (tcd && tcd->isNested()) | |
248 { /* e1 is the 'this' pointer for an inner class: tcd. | |
249 * Rewrite it as the 'this' pointer for the outer class. | |
250 */ | |
251 | |
252 e1 = new DotVarExp(loc, e1, tcd->vthis); | |
253 e1->type = tcd->vthis->type; | |
254 // Do not call checkNestedRef() | |
255 //e1 = e1->semantic(sc); | |
256 | |
257 // Skip up over nested functions, and get the enclosing | |
258 // class type. | |
259 int n = 0; | |
260 Dsymbol *s; | |
261 for (s = tcd->toParent(); | |
262 s && s->isFuncDeclaration(); | |
263 s = s->toParent()) | |
264 { FuncDeclaration *f = s->isFuncDeclaration(); | |
265 if (f->vthis) | |
266 { | |
267 //printf("rewriting e1 to %s's this\n", f->toChars()); | |
268 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
|
269 |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
639
diff
changeset
|
270 // 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
|
271 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
|
272 |
336 | 273 e1 = new VarExp(loc, f->vthis); |
274 } | |
275 } | |
276 if (s && s->isClassDeclaration()) | |
277 { e1->type = s->isClassDeclaration()->type; | |
278 if (n > 1) | |
279 e1 = e1->semantic(sc); | |
280 } | |
281 else | |
282 e1 = e1->semantic(sc); | |
283 goto L1; | |
284 } | |
285 /* Can't find a path from e1 to ad | |
286 */ | |
287 e1->error("this for %s needs to be type %s not type %s", | |
288 var->toChars(), ad->toChars(), t->toChars()); | |
289 } | |
290 } | |
291 return e1; | |
292 } | |
293 | |
159 | 294 /***************************************** |
295 * Determine if 'this' is available. | |
296 * If it is, return the FuncDeclaration that has it. | |
297 */ | |
298 | |
299 FuncDeclaration *hasThis(Scope *sc) | |
300 { FuncDeclaration *fd; | |
301 FuncDeclaration *fdthis; | |
302 | |
303 //printf("hasThis()\n"); | |
304 fdthis = sc->parent->isFuncDeclaration(); | |
305 //printf("fdthis = %p, '%s'\n", fdthis, fdthis ? fdthis->toChars() : ""); | |
306 | |
307 // Go upwards until we find the enclosing member function | |
308 fd = fdthis; | |
309 while (1) | |
310 { | |
311 if (!fd) | |
312 { | |
313 goto Lno; | |
314 } | |
315 if (!fd->isNested()) | |
316 break; | |
317 | |
318 Dsymbol *parent = fd->parent; | |
319 while (parent) | |
320 { | |
321 TemplateInstance *ti = parent->isTemplateInstance(); | |
322 if (ti) | |
323 parent = ti->parent; | |
324 else | |
325 break; | |
326 } | |
327 | |
328 fd = fd->parent->isFuncDeclaration(); | |
329 } | |
330 | |
331 if (!fd->isThis()) | |
332 { //printf("test '%s'\n", fd->toChars()); | |
333 goto Lno; | |
334 } | |
335 | |
336 assert(fd->vthis); | |
337 return fd; | |
338 | |
339 Lno: | |
340 return NULL; // don't have 'this' available | |
341 } | |
342 | |
343 | |
344 /*************************************** | |
345 * Pull out any properties. | |
346 */ | |
347 | |
348 Expression *resolveProperties(Scope *sc, Expression *e) | |
349 { | |
350 //printf("resolveProperties(%s)\n", e->toChars()); | |
351 if (e->type) | |
352 { | |
353 Type *t = e->type->toBasetype(); | |
354 | |
355 if (t->ty == Tfunction) | |
356 { | |
357 e = new CallExp(e->loc, e); | |
358 e = e->semantic(sc); | |
359 } | |
360 | |
361 /* Look for e being a lazy parameter; rewrite as delegate call | |
362 */ | |
363 else if (e->op == TOKvar) | |
364 { VarExp *ve = (VarExp *)e; | |
365 | |
366 if (ve->var->storage_class & STClazy) | |
367 { | |
368 e = new CallExp(e->loc, e); | |
369 e = e->semantic(sc); | |
370 } | |
371 } | |
372 | |
373 else if (e->op == TOKdotexp) | |
374 { | |
375 e->error("expression has no value"); | |
376 } | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
377 |
159 | 378 } |
379 return e; | |
380 } | |
381 | |
382 /****************************** | |
383 * Perform semantic() on an array of Expressions. | |
384 */ | |
385 | |
386 void arrayExpressionSemantic(Expressions *exps, Scope *sc) | |
387 { | |
388 if (exps) | |
389 { | |
390 for (size_t i = 0; i < exps->dim; i++) | |
391 { Expression *e = (Expression *)exps->data[i]; | |
392 | |
393 e = e->semantic(sc); | |
394 exps->data[i] = (void *)e; | |
395 } | |
396 } | |
397 } | |
398 | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
399 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
400 /****************************** |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
401 * 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
|
402 */ |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
403 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
404 #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
|
405 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
|
406 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
407 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
|
408 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
409 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
|
410 { 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
|
411 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
|
412 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
|
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 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
|
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 #endif |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
418 |
159 | 419 /**************************************** |
420 * Expand tuples. | |
421 */ | |
422 | |
423 void expandTuples(Expressions *exps) | |
424 { | |
425 //printf("expandTuples()\n"); | |
426 if (exps) | |
427 { | |
428 for (size_t i = 0; i < exps->dim; i++) | |
429 { Expression *arg = (Expression *)exps->data[i]; | |
430 if (!arg) | |
431 continue; | |
432 | |
433 // Look for tuple with 0 members | |
434 if (arg->op == TOKtype) | |
435 { TypeExp *e = (TypeExp *)arg; | |
436 if (e->type->toBasetype()->ty == Ttuple) | |
437 { TypeTuple *tt = (TypeTuple *)e->type->toBasetype(); | |
438 | |
439 if (!tt->arguments || tt->arguments->dim == 0) | |
440 { | |
441 exps->remove(i); | |
442 if (i == exps->dim) | |
443 return; | |
444 i--; | |
445 continue; | |
446 } | |
447 } | |
448 } | |
449 | |
450 // Inline expand all the tuples | |
451 while (arg->op == TOKtuple) | |
452 { TupleExp *te = (TupleExp *)arg; | |
453 | |
454 exps->remove(i); // remove arg | |
455 exps->insert(i, te->exps); // replace with tuple contents | |
456 if (i == exps->dim) | |
457 return; // empty tuple, no more arguments | |
458 arg = (Expression *)exps->data[i]; | |
459 } | |
460 } | |
461 } | |
462 } | |
463 | |
464 /**************************************** | |
465 * Preprocess arguments to function. | |
466 */ | |
467 | |
468 void preFunctionArguments(Loc loc, Scope *sc, Expressions *exps) | |
469 { | |
470 if (exps) | |
471 { | |
472 expandTuples(exps); | |
473 | |
474 for (size_t i = 0; i < exps->dim; i++) | |
475 { Expression *arg = (Expression *)exps->data[i]; | |
476 | |
477 if (!arg->type) | |
478 { | |
479 #ifdef DEBUG | |
480 if (!global.gag) | |
481 printf("1: \n"); | |
482 #endif | |
483 arg->error("%s is not an expression", arg->toChars()); | |
484 arg = new IntegerExp(arg->loc, 0, Type::tint32); | |
485 } | |
486 | |
487 arg = resolveProperties(sc, arg); | |
488 exps->data[i] = (void *) arg; | |
489 | |
490 //arg->rvalue(); | |
491 #if 0 | |
492 if (arg->type->ty == Tfunction) | |
493 { | |
494 arg = new AddrExp(arg->loc, arg); | |
495 arg = arg->semantic(sc); | |
496 exps->data[i] = (void *) arg; | |
497 } | |
498 #endif | |
499 } | |
500 } | |
501 } | |
502 | |
336 | 503 /********************************************* |
504 * Call copy constructor for struct value argument. | |
505 */ | |
506 #if DMDV2 | |
507 Expression *callCpCtor(Loc loc, Scope *sc, Expression *e) | |
508 { | |
509 Type *tb = e->type->toBasetype(); | |
510 assert(tb->ty == Tstruct); | |
511 StructDeclaration *sd = ((TypeStruct *)tb)->sym; | |
512 if (sd->cpctor) | |
513 { | |
514 /* Create a variable tmp, and replace the argument e with: | |
515 * (tmp = e),tmp | |
516 * and let AssignExp() handle the construction. | |
517 * This is not the most efficent, ideally tmp would be constructed | |
518 * directly onto the stack. | |
519 */ | |
520 Identifier *idtmp = Lexer::uniqueId("__tmp"); | |
521 VarDeclaration *tmp = new VarDeclaration(loc, tb, idtmp, new ExpInitializer(0, e)); | |
522 Expression *ae = new DeclarationExp(loc, tmp); | |
523 e = new CommaExp(loc, ae, new VarExp(loc, tmp)); | |
524 e = e->semantic(sc); | |
525 } | |
526 return e; | |
527 } | |
528 #endif | |
159 | 529 |
530 /**************************************** | |
531 * Now that we know the exact type of the function we're calling, | |
532 * 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
|
533 * 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
|
534 * 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
|
535 * 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
|
536 * 4. add hidden _arguments[] argument |
159 | 537 */ |
538 | |
539 void functionArguments(Loc loc, Scope *sc, TypeFunction *tf, Expressions *arguments) | |
540 { | |
541 unsigned n; | |
542 int done; | |
543 Type *tb; | |
544 | |
545 //printf("functionArguments()\n"); | |
546 assert(arguments); | |
547 size_t nargs = arguments ? arguments->dim : 0; | |
548 size_t nparams = Argument::dim(tf->parameters); | |
549 | |
550 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
|
551 error(loc, "expected %"PRIuSIZE" arguments, not %"PRIuSIZE, nparams, nargs); |
159 | 552 |
553 n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams) | |
554 | |
555 done = 0; | |
556 for (size_t i = 0; i < n; i++) | |
557 { | |
558 Expression *arg; | |
559 | |
560 if (i < nargs) | |
561 arg = (Expression *)arguments->data[i]; | |
562 else | |
563 arg = NULL; | |
564 | |
565 if (i < nparams) | |
566 { | |
567 Argument *p = Argument::getNth(tf->parameters, i); | |
568 | |
569 if (!arg) | |
570 { | |
571 if (!p->defaultArg) | |
572 { | |
573 if (tf->varargs == 2 && i + 1 == nparams) | |
574 goto L2; | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
575 error(loc, "expected %"PRIuSIZE" arguments, not %"PRIuSIZE, nparams, nargs); |
159 | 576 break; |
577 } | |
336 | 578 arg = p->defaultArg; |
579 #if DMDV2 | |
580 if (arg->op == TOKdefault) | |
581 { DefaultInitExp *de = (DefaultInitExp *)arg; | |
582 arg = de->resolve(loc, sc); | |
583 } | |
584 else | |
585 #endif | |
586 arg = arg->copy(); | |
159 | 587 arguments->push(arg); |
588 nargs++; | |
589 } | |
590 | |
591 if (tf->varargs == 2 && i + 1 == nparams) | |
592 { | |
593 //printf("\t\tvarargs == 2, p->type = '%s'\n", p->type->toChars()); | |
594 if (arg->implicitConvTo(p->type)) | |
595 { | |
596 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
|
597 error(loc, "expected %"PRIuSIZE" arguments, not %"PRIuSIZE, nparams, nargs); |
159 | 598 goto L1; |
599 } | |
600 L2: | |
601 Type *tb = p->type->toBasetype(); | |
602 Type *tret = p->isLazyArray(); | |
603 switch (tb->ty) | |
604 { | |
605 case Tsarray: | |
606 case Tarray: | |
607 { // Create a static array variable v of type arg->type | |
608 #ifdef IN_GCC | |
609 /* GCC 4.0 does not like zero length arrays used like | |
610 this; pass a null array value instead. Could also | |
611 just make a one-element array. */ | |
612 if (nargs - i == 0) | |
613 { | |
614 arg = new NullExp(loc); | |
615 break; | |
616 } | |
617 #endif | |
618 static int idn; | |
619 char name[10 + sizeof(idn)*3 + 1]; | |
620 sprintf(name, "__arrayArg%d", ++idn); | |
621 Identifier *id = Lexer::idPool(name); | |
622 Type *t = new TypeSArray(tb->next, new IntegerExp(nargs - i)); | |
623 t = t->semantic(loc, sc); | |
624 VarDeclaration *v = new VarDeclaration(loc, t, id, new VoidInitializer(loc)); | |
625 v->semantic(sc); | |
626 v->parent = sc->parent; | |
627 //sc->insert(v); | |
628 | |
629 Expression *c = new DeclarationExp(0, v); | |
630 c->type = v->type; | |
631 | |
632 for (size_t u = i; u < nargs; u++) | |
633 { Expression *a = (Expression *)arguments->data[u]; | |
634 if (tret && !tb->next->equals(a->type)) | |
635 a = a->toDelegate(sc, tret); | |
636 | |
637 Expression *e = new VarExp(loc, v); | |
638 e = new IndexExp(loc, e, new IntegerExp(u + 1 - nparams)); | |
639 e = new AssignExp(loc, e, a); | |
640 if (c) | |
641 c = new CommaExp(loc, c, e); | |
642 else | |
643 c = e; | |
644 } | |
645 arg = new VarExp(loc, v); | |
646 if (c) | |
647 arg = new CommaExp(loc, c, arg); | |
648 break; | |
649 } | |
650 case Tclass: | |
651 { /* Set arg to be: | |
652 * new Tclass(arg0, arg1, ..., argn) | |
653 */ | |
654 Expressions *args = new Expressions(); | |
655 args->setDim(nargs - i); | |
656 for (size_t u = i; u < nargs; u++) | |
657 args->data[u - i] = arguments->data[u]; | |
658 arg = new NewExp(loc, NULL, NULL, p->type, args); | |
659 break; | |
660 } | |
661 default: | |
662 if (!arg) | |
663 { error(loc, "not enough arguments"); | |
664 return; | |
665 } | |
666 break; | |
667 } | |
668 arg = arg->semantic(sc); | |
669 //printf("\targ = '%s'\n", arg->toChars()); | |
670 arguments->setDim(i + 1); | |
671 done = 1; | |
672 } | |
673 | |
674 L1: | |
675 if (!(p->storageClass & STClazy && p->type->ty == Tvoid)) | |
676 arg = arg->implicitCastTo(sc, p->type); | |
677 if (p->storageClass & (STCout | STCref)) | |
678 { | |
679 // BUG: should check that argument to ref is type 'invariant' | |
680 // BUG: assignments to ref should also be type 'invariant' | |
681 arg = arg->modifiableLvalue(sc, arg); | |
682 | |
683 //if (arg->op == TOKslice) | |
684 //arg->error("cannot modify slice %s", arg->toChars()); | |
685 } | |
686 | |
723
55f6c2e454d7
Implemented correct parameter order according to x86-32 ABI documentation.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
717
diff
changeset
|
687 // 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
|
688 #if !IN_LLVM |
159 | 689 // Convert static arrays to pointers |
690 tb = arg->type->toBasetype(); | |
691 if (tb->ty == Tsarray) | |
692 { | |
693 arg = arg->checkToPointer(); | |
694 } | |
723
55f6c2e454d7
Implemented correct parameter order according to x86-32 ABI documentation.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
717
diff
changeset
|
695 #endif |
55f6c2e454d7
Implemented correct parameter order according to x86-32 ABI documentation.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
717
diff
changeset
|
696 |
159 | 697 |
698 // Convert lazy argument to a delegate | |
699 if (p->storageClass & STClazy) | |
700 { | |
701 arg = arg->toDelegate(sc, p->type); | |
702 } | |
703 } | |
704 else | |
705 { | |
706 | |
707 // 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
|
708 // 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
|
709 if (tf->linkage != LINKd && tf->linkage != LINKintrinsic) |
159 | 710 { |
711 // Promote bytes, words, etc., to ints | |
712 arg = arg->integralPromotions(sc); | |
713 | |
714 // Promote floats to doubles | |
715 switch (arg->type->ty) | |
716 { | |
717 case Tfloat32: | |
718 arg = arg->castTo(sc, Type::tfloat64); | |
719 break; | |
720 | |
721 case Timaginary32: | |
722 arg = arg->castTo(sc, Type::timaginary64); | |
723 break; | |
724 } | |
725 } | |
726 | |
727 // Convert static arrays to dynamic arrays | |
728 tb = arg->type->toBasetype(); | |
729 if (tb->ty == Tsarray) | |
730 { TypeSArray *ts = (TypeSArray *)tb; | |
336 | 731 Type *ta = ts->next->arrayOf(); |
159 | 732 if (ts->size(arg->loc) == 0) |
733 { arg = new NullExp(arg->loc); | |
734 arg->type = ta; | |
735 } | |
736 else | |
737 arg = arg->castTo(sc, ta); | |
738 } | |
336 | 739 #if DMDV2 |
740 if (tb->ty == Tstruct) | |
741 { | |
742 arg = callCpCtor(loc, sc, arg); | |
743 } | |
744 | |
745 // Give error for overloaded function addresses | |
746 if (arg->op == TOKsymoff) | |
747 { SymOffExp *se = (SymOffExp *)arg; | |
748 if (se->hasOverloads && !se->var->isFuncDeclaration()->isUnique()) | |
749 arg->error("function %s is overloaded", arg->toChars()); | |
750 } | |
751 #endif | |
159 | 752 arg->rvalue(); |
753 } | |
754 arg = arg->optimize(WANTvalue); | |
755 arguments->data[i] = (void *) arg; | |
756 if (done) | |
757 break; | |
758 } | |
759 | |
760 #if !IN_LLVM | |
761 // If D linkage and variadic, add _arguments[] as first argument | |
762 if (tf->linkage == LINKd && tf->varargs == 1) | |
763 { | |
764 Expression *e; | |
765 | |
766 e = createTypeInfoArray(sc, (Expression **)&arguments->data[nparams], | |
767 arguments->dim - nparams); | |
768 arguments->insert(0, e); | |
769 } | |
770 #endif | |
771 } | |
772 | |
773 /************************************************** | |
774 * Write expression out to buf, but wrap it | |
775 * in ( ) if its precedence is less than pr. | |
776 */ | |
777 | |
778 void expToCBuffer(OutBuffer *buf, HdrGenState *hgs, Expression *e, enum PREC pr) | |
779 { | |
336 | 780 //if (precedence[e->op] == 0) e->dump(0); |
159 | 781 if (precedence[e->op] < pr) |
782 { | |
783 buf->writeByte('('); | |
784 e->toCBuffer(buf, hgs); | |
785 buf->writeByte(')'); | |
786 } | |
787 else | |
788 e->toCBuffer(buf, hgs); | |
789 } | |
790 | |
791 /************************************************** | |
792 * Write out argument list to buf. | |
793 */ | |
794 | |
795 void argsToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs) | |
796 { | |
797 if (arguments) | |
798 { | |
799 for (size_t i = 0; i < arguments->dim; i++) | |
800 { Expression *arg = (Expression *)arguments->data[i]; | |
801 | |
802 if (arg) | |
803 { if (i) | |
804 buf->writeByte(','); | |
805 expToCBuffer(buf, hgs, arg, PREC_assign); | |
806 } | |
807 } | |
808 } | |
809 } | |
810 | |
811 /************************************************** | |
812 * Write out argument types to buf. | |
813 */ | |
814 | |
815 void argExpTypesToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs) | |
816 { | |
817 if (arguments) | |
818 { OutBuffer argbuf; | |
819 | |
820 for (size_t i = 0; i < arguments->dim; i++) | |
821 { Expression *arg = (Expression *)arguments->data[i]; | |
822 | |
823 if (i) | |
824 buf->writeByte(','); | |
825 argbuf.reset(); | |
826 arg->type->toCBuffer2(&argbuf, hgs, 0); | |
827 buf->write(&argbuf); | |
828 } | |
829 } | |
830 } | |
831 | |
832 /******************************** Expression **************************/ | |
833 | |
834 Expression::Expression(Loc loc, enum TOK op, int size) | |
835 : loc(loc) | |
836 { | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
837 //printf("Expression::Expression(op = %d) this = %p\n", op, this); |
159 | 838 this->loc = loc; |
839 this->op = op; | |
840 this->size = size; | |
841 type = NULL; | |
842 } | |
843 | |
844 Expression *Expression::syntaxCopy() | |
845 { | |
846 //printf("Expression::syntaxCopy()\n"); | |
847 //dump(0); | |
848 return copy(); | |
849 } | |
850 | |
851 /********************************* | |
852 * Does *not* do a deep copy. | |
853 */ | |
854 | |
855 Expression *Expression::copy() | |
856 { | |
857 Expression *e; | |
858 if (!size) | |
859 { | |
860 #ifdef DEBUG | |
861 fprintf(stdmsg, "No expression copy for: %s\n", toChars()); | |
862 printf("op = %d\n", op); | |
863 dump(0); | |
864 #endif | |
865 assert(0); | |
866 } | |
867 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
|
868 //printf("Expression::copy(op = %d) e = %p\n", op, e); |
159 | 869 return (Expression *)memcpy(e, this, size); |
870 } | |
871 | |
872 /************************** | |
873 * Semantically analyze Expression. | |
874 * Determine types, fold constants, etc. | |
875 */ | |
876 | |
877 Expression *Expression::semantic(Scope *sc) | |
878 { | |
879 #if LOGSEMANTIC | |
336 | 880 printf("Expression::semantic() %s\n", toChars()); |
159 | 881 #endif |
882 if (type) | |
883 type = type->semantic(loc, sc); | |
884 else | |
885 type = Type::tvoid; | |
886 return this; | |
887 } | |
888 | |
889 void Expression::print() | |
890 { | |
891 fprintf(stdmsg, "%s\n", toChars()); | |
892 fflush(stdmsg); | |
893 } | |
894 | |
895 char *Expression::toChars() | |
896 { OutBuffer *buf; | |
897 HdrGenState hgs; | |
898 | |
899 memset(&hgs, 0, sizeof(hgs)); | |
900 buf = new OutBuffer(); | |
901 toCBuffer(buf, &hgs); | |
902 return buf->toChars(); | |
903 } | |
904 | |
905 void Expression::error(const char *format, ...) | |
906 { | |
907 va_list ap; | |
908 va_start(ap, format); | |
909 ::verror(loc, format, ap); | |
910 va_end( ap ); | |
911 } | |
912 | |
913 void Expression::rvalue() | |
914 { | |
915 if (type && type->toBasetype()->ty == Tvoid) | |
916 { error("expression %s is void and has no value", toChars()); | |
917 #if 0 | |
918 dump(0); | |
919 halt(); | |
920 #endif | |
336 | 921 type = Type::tint32; |
159 | 922 } |
923 } | |
924 | |
925 Expression *Expression::combine(Expression *e1, Expression *e2) | |
926 { | |
927 if (e1) | |
928 { | |
929 if (e2) | |
930 { | |
931 e1 = new CommaExp(e1->loc, e1, e2); | |
932 e1->type = e2->type; | |
933 } | |
934 } | |
935 else | |
936 e1 = e2; | |
937 return e1; | |
938 } | |
939 | |
940 integer_t Expression::toInteger() | |
941 { | |
942 //printf("Expression %s\n", Token::toChars(op)); | |
943 error("Integer constant expression expected instead of %s", toChars()); | |
944 return 0; | |
945 } | |
946 | |
947 uinteger_t Expression::toUInteger() | |
948 { | |
949 //printf("Expression %s\n", Token::toChars(op)); | |
950 return (uinteger_t)toInteger(); | |
951 } | |
952 | |
953 real_t Expression::toReal() | |
954 { | |
955 error("Floating point constant expression expected instead of %s", toChars()); | |
956 return 0; | |
957 } | |
958 | |
959 real_t Expression::toImaginary() | |
960 { | |
961 error("Floating point constant expression expected instead of %s", toChars()); | |
962 return 0; | |
963 } | |
964 | |
965 complex_t Expression::toComplex() | |
966 { | |
967 error("Floating point constant expression expected instead of %s", toChars()); | |
968 #ifdef IN_GCC | |
969 return complex_t(real_t(0)); // %% nicer | |
970 #else | |
971 return 0; | |
972 #endif | |
973 } | |
974 | |
975 void Expression::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
976 { | |
977 buf->writestring(Token::toChars(op)); | |
978 } | |
979 | |
980 void Expression::toMangleBuffer(OutBuffer *buf) | |
981 { | |
982 error("expression %s is not a valid template value argument", toChars()); | |
983 } | |
984 | |
985 /******************************* | |
986 * Give error if we're not an lvalue. | |
987 * If we can, convert expression to be an lvalue. | |
988 */ | |
989 | |
990 Expression *Expression::toLvalue(Scope *sc, Expression *e) | |
991 { | |
992 if (!e) | |
993 e = this; | |
994 else if (!loc.filename) | |
995 loc = e->loc; | |
996 error("%s is not an lvalue", e->toChars()); | |
997 return this; | |
998 } | |
999 | |
1000 Expression *Expression::modifiableLvalue(Scope *sc, Expression *e) | |
1001 { | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
1002 //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
|
1003 |
159 | 1004 // See if this expression is a modifiable lvalue (i.e. not const) |
1005 return toLvalue(sc, e); | |
1006 } | |
1007 | |
1008 /************************************ | |
1009 * Detect cases where pointers to the stack can 'escape' the | |
1010 * lifetime of the stack frame. | |
1011 */ | |
1012 | |
1013 void Expression::checkEscape() | |
1014 { | |
1015 } | |
1016 | |
1017 void Expression::checkScalar() | |
1018 { | |
1019 if (!type->isscalar()) | |
1020 error("'%s' is not a scalar, it is a %s", toChars(), type->toChars()); | |
1021 } | |
1022 | |
1023 void Expression::checkNoBool() | |
1024 { | |
1025 if (type->toBasetype()->ty == Tbool) | |
1026 error("operation not allowed on bool '%s'", toChars()); | |
1027 } | |
1028 | |
1029 Expression *Expression::checkIntegral() | |
1030 { | |
1031 if (!type->isintegral()) | |
1032 { error("'%s' is not of integral type, it is a %s", toChars(), type->toChars()); | |
1033 return new IntegerExp(0); | |
1034 } | |
1035 return this; | |
1036 } | |
1037 | |
1038 Expression *Expression::checkArithmetic() | |
1039 { | |
1040 if (!type->isintegral() && !type->isfloating()) | |
1041 { error("'%s' is not of arithmetic type, it is a %s", toChars(), type->toChars()); | |
1042 return new IntegerExp(0); | |
1043 } | |
1044 return this; | |
1045 } | |
1046 | |
1047 void Expression::checkDeprecated(Scope *sc, Dsymbol *s) | |
1048 { | |
1049 s->checkDeprecated(loc, sc); | |
1050 } | |
1051 | |
1052 /******************************** | |
1053 * Check for expressions that have no use. | |
1054 * Input: | |
1055 * flag 0 not going to use the result, so issue error message if no | |
1056 * side effects | |
1057 * 1 the result of the expression is used, but still check | |
1058 * for useless subexpressions | |
1059 * 2 do not issue error messages, just return !=0 if expression | |
1060 * has side effects | |
1061 */ | |
1062 | |
1063 int Expression::checkSideEffect(int flag) | |
1064 { | |
1065 if (flag == 0) | |
1066 { if (op == TOKimport) | |
1067 { | |
1068 error("%s has no effect", toChars()); | |
1069 } | |
1070 else | |
1071 error("%s has no effect in expression (%s)", | |
1072 Token::toChars(op), toChars()); | |
1073 } | |
1074 return 0; | |
1075 } | |
1076 | |
1077 /***************************** | |
1078 * Check that expression can be tested for true or false. | |
1079 */ | |
1080 | |
1081 Expression *Expression::checkToBoolean() | |
1082 { | |
1083 // Default is 'yes' - do nothing | |
1084 | |
1085 #ifdef DEBUG | |
1086 if (!type) | |
1087 dump(0); | |
1088 #endif | |
1089 | |
1090 if (!type->checkBoolean()) | |
1091 { | |
1092 error("expression %s of type %s does not have a boolean value", toChars(), type->toChars()); | |
1093 } | |
1094 return this; | |
1095 } | |
1096 | |
1097 /**************************** | |
1098 */ | |
1099 | |
1100 Expression *Expression::checkToPointer() | |
1101 { | |
1102 Expression *e; | |
1103 Type *tb; | |
1104 | |
1105 //printf("Expression::checkToPointer()\n"); | |
1106 e = this; | |
1107 | |
1108 // If C static array, convert to pointer | |
1109 tb = type->toBasetype(); | |
1110 if (tb->ty == Tsarray) | |
1111 { TypeSArray *ts = (TypeSArray *)tb; | |
1112 if (ts->size(loc) == 0) | |
1113 e = new NullExp(loc); | |
1114 else | |
1115 e = new AddrExp(loc, this); | |
336 | 1116 e->type = ts->next->pointerTo(); |
159 | 1117 } |
1118 return e; | |
1119 } | |
1120 | |
1121 /****************************** | |
1122 * Take address of expression. | |
1123 */ | |
1124 | |
1125 Expression *Expression::addressOf(Scope *sc) | |
1126 { | |
1127 Expression *e; | |
1128 | |
1129 //printf("Expression::addressOf()\n"); | |
1130 e = toLvalue(sc, NULL); | |
1131 e = new AddrExp(loc, e); | |
1132 e->type = type->pointerTo(); | |
1133 return e; | |
1134 } | |
1135 | |
1136 /****************************** | |
1137 * If this is a reference, dereference it. | |
1138 */ | |
1139 | |
1140 Expression *Expression::deref() | |
1141 { | |
1142 //printf("Expression::deref()\n"); | |
1143 if (type->ty == Treference) | |
1144 { Expression *e; | |
1145 | |
1146 e = new PtrExp(loc, this); | |
336 | 1147 e->type = ((TypeReference *)type)->next; |
159 | 1148 return e; |
1149 } | |
1150 return this; | |
1151 } | |
1152 | |
1153 /******************************** | |
1154 * Does this expression statically evaluate to a boolean TRUE or FALSE? | |
1155 */ | |
1156 | |
1157 int Expression::isBool(int result) | |
1158 { | |
1159 return FALSE; | |
1160 } | |
1161 | |
1162 /******************************** | |
1163 * Does this expression result in either a 1 or a 0? | |
1164 */ | |
1165 | |
1166 int Expression::isBit() | |
1167 { | |
1168 return FALSE; | |
1169 } | |
1170 | |
336 | 1171 /******************************** |
1172 * Can this expression throw an exception? | |
1173 * Valid only after semantic() pass. | |
1174 */ | |
1175 | |
1176 int Expression::canThrow() | |
1177 { | |
1178 return TRUE; | |
1179 } | |
1180 | |
1181 | |
1182 | |
159 | 1183 Expressions *Expression::arraySyntaxCopy(Expressions *exps) |
1184 { Expressions *a = NULL; | |
1185 | |
1186 if (exps) | |
1187 { | |
1188 a = new Expressions(); | |
1189 a->setDim(exps->dim); | |
1190 for (int i = 0; i < a->dim; i++) | |
1191 { Expression *e = (Expression *)exps->data[i]; | |
1192 | |
1193 e = e->syntaxCopy(); | |
1194 a->data[i] = e; | |
1195 } | |
1196 } | |
1197 return a; | |
1198 } | |
1199 | |
1200 /******************************** IntegerExp **************************/ | |
1201 | |
1202 IntegerExp::IntegerExp(Loc loc, integer_t value, Type *type) | |
1203 : Expression(loc, TOKint64, sizeof(IntegerExp)) | |
1204 { | |
1205 //printf("IntegerExp(value = %lld, type = '%s')\n", value, type ? type->toChars() : ""); | |
1206 if (type && !type->isscalar()) | |
1207 { | |
336 | 1208 //printf("%s, loc = %d\n", toChars(), loc.linnum); |
159 | 1209 error("integral constant must be scalar type, not %s", type->toChars()); |
1210 type = Type::terror; | |
1211 } | |
1212 this->type = type; | |
1213 this->value = value; | |
1214 } | |
1215 | |
1216 IntegerExp::IntegerExp(integer_t value) | |
1217 : Expression(0, TOKint64, sizeof(IntegerExp)) | |
1218 { | |
1219 this->type = Type::tint32; | |
1220 this->value = value; | |
1221 } | |
1222 | |
1223 int IntegerExp::equals(Object *o) | |
1224 { IntegerExp *ne; | |
1225 | |
1226 if (this == o || | |
1227 (((Expression *)o)->op == TOKint64 && | |
1228 ((ne = (IntegerExp *)o), type->equals(ne->type)) && | |
1229 value == ne->value)) | |
1230 return 1; | |
1231 return 0; | |
1232 } | |
1233 | |
1234 char *IntegerExp::toChars() | |
1235 { | |
1236 #if 1 | |
1237 return Expression::toChars(); | |
1238 #else | |
1239 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
|
1240 sprintf(buffer, "%lld", value); |
159 | 1241 return buffer; |
1242 #endif | |
1243 } | |
1244 | |
1245 integer_t IntegerExp::toInteger() | |
1246 { Type *t; | |
1247 | |
1248 t = type; | |
1249 while (t) | |
1250 { | |
1251 switch (t->ty) | |
1252 { | |
1253 case Tbit: | |
1254 case Tbool: value = (value != 0); break; | |
1255 case Tint8: value = (d_int8) value; break; | |
1256 case Tchar: | |
1257 case Tuns8: value = (d_uns8) value; break; | |
1258 case Tint16: value = (d_int16) value; break; | |
1259 case Twchar: | |
1260 case Tuns16: value = (d_uns16) value; break; | |
1261 case Tint32: value = (d_int32) value; break; | |
1262 case Tpointer: | |
1263 case Tdchar: | |
1264 case Tuns32: value = (d_uns32) value; break; | |
1265 case Tint64: value = (d_int64) value; break; | |
1266 case Tuns64: value = (d_uns64) value; break; | |
1267 | |
1268 case Tenum: | |
1269 { | |
1270 TypeEnum *te = (TypeEnum *)t; | |
1271 t = te->sym->memtype; | |
1272 continue; | |
1273 } | |
1274 | |
1275 case Ttypedef: | |
1276 { | |
1277 TypeTypedef *tt = (TypeTypedef *)t; | |
1278 t = tt->sym->basetype; | |
1279 continue; | |
1280 } | |
1281 | |
1282 default: | |
336 | 1283 /* This can happen if errors, such as |
1284 * the type is painted on like in fromConstInitializer(). | |
1285 */ | |
1286 if (!global.errors) | |
1287 { type->print(); | |
1288 assert(0); | |
1289 } | |
159 | 1290 break; |
1291 } | |
1292 break; | |
1293 } | |
1294 return value; | |
1295 } | |
1296 | |
1297 real_t IntegerExp::toReal() | |
1298 { | |
1299 Type *t; | |
1300 | |
1301 toInteger(); | |
1302 t = type->toBasetype(); | |
1303 if (t->ty == Tuns64) | |
1304 return (real_t)(d_uns64)value; | |
1305 else | |
1306 return (real_t)(d_int64)value; | |
1307 } | |
1308 | |
1309 real_t IntegerExp::toImaginary() | |
1310 { | |
1311 return (real_t) 0; | |
1312 } | |
1313 | |
1314 complex_t IntegerExp::toComplex() | |
1315 { | |
1316 return toReal(); | |
1317 } | |
1318 | |
1319 int IntegerExp::isBool(int result) | |
1320 { | |
1321 return result ? value != 0 : value == 0; | |
1322 } | |
1323 | |
1324 Expression *IntegerExp::semantic(Scope *sc) | |
1325 { | |
1326 if (!type) | |
1327 { | |
1328 // Determine what the type of this number is | |
1329 integer_t number = value; | |
1330 | |
1331 if (number & 0x8000000000000000LL) | |
1332 type = Type::tuns64; | |
1333 else if (number & 0xFFFFFFFF80000000LL) | |
1334 type = Type::tint64; | |
1335 else | |
1336 type = Type::tint32; | |
1337 } | |
1338 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
|
1339 { 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
|
1340 type = type->semantic(loc, sc); |
159 | 1341 } |
1342 return this; | |
1343 } | |
1344 | |
1345 Expression *IntegerExp::toLvalue(Scope *sc, Expression *e) | |
1346 { | |
1347 if (!e) | |
1348 e = this; | |
1349 else if (!loc.filename) | |
1350 loc = e->loc; | |
1351 e->error("constant %s is not an lvalue", e->toChars()); | |
1352 return this; | |
1353 } | |
1354 | |
1355 void IntegerExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
1356 { | |
1357 integer_t v = toInteger(); | |
1358 | |
1359 if (type) | |
1360 { Type *t = type; | |
1361 | |
1362 L1: | |
1363 switch (t->ty) | |
1364 { | |
1365 case Tenum: | |
1366 { TypeEnum *te = (TypeEnum *)t; | |
1367 buf->printf("cast(%s)", te->sym->toChars()); | |
1368 t = te->sym->memtype; | |
1369 goto L1; | |
1370 } | |
1371 | |
1372 case Ttypedef: | |
1373 { TypeTypedef *tt = (TypeTypedef *)t; | |
1374 buf->printf("cast(%s)", tt->sym->toChars()); | |
1375 t = tt->sym->basetype; | |
1376 goto L1; | |
1377 } | |
1378 | |
1379 case Twchar: // BUG: need to cast(wchar) | |
1380 case Tdchar: // BUG: need to cast(dchar) | |
1381 if ((uinteger_t)v > 0xFF) | |
1382 { | |
1383 buf->printf("'\\U%08x'", v); | |
1384 break; | |
1385 } | |
1386 case Tchar: | |
1387 if (v == '\'') | |
1388 buf->writestring("'\\''"); | |
1389 else if (isprint(v) && v != '\\') | |
1390 buf->printf("'%c'", (int)v); | |
1391 else | |
1392 buf->printf("'\\x%02x'", (int)v); | |
1393 break; | |
1394 | |
1395 case Tint8: | |
1396 buf->writestring("cast(byte)"); | |
1397 goto L2; | |
1398 | |
1399 case Tint16: | |
1400 buf->writestring("cast(short)"); | |
1401 goto L2; | |
1402 | |
1403 case Tint32: | |
1404 L2: | |
1405 buf->printf("%d", (int)v); | |
1406 break; | |
1407 | |
1408 case Tuns8: | |
1409 buf->writestring("cast(ubyte)"); | |
1410 goto L3; | |
1411 | |
1412 case Tuns16: | |
1413 buf->writestring("cast(ushort)"); | |
1414 goto L3; | |
1415 | |
1416 case Tuns32: | |
1417 L3: | |
1418 buf->printf("%du", (unsigned)v); | |
1419 break; | |
1420 | |
1421 case Tint64: | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
1422 buf->printf("%lldL", v); |
159 | 1423 break; |
1424 | |
1425 case Tuns64: | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
1426 buf->printf("%lluLU", v); |
159 | 1427 break; |
1428 | |
1429 case Tbit: | |
1430 case Tbool: | |
1431 buf->writestring((char *)(v ? "true" : "false")); | |
1432 break; | |
1433 | |
1434 case Tpointer: | |
1435 buf->writestring("cast("); | |
1436 buf->writestring(t->toChars()); | |
1437 buf->writeByte(')'); | |
1438 goto L3; | |
1439 | |
1440 default: | |
336 | 1441 /* This can happen if errors, such as |
1442 * the type is painted on like in fromConstInitializer(). | |
1443 */ | |
1444 if (!global.errors) | |
1445 { | |
159 | 1446 #ifdef DEBUG |
336 | 1447 t->print(); |
159 | 1448 #endif |
336 | 1449 assert(0); |
1450 } | |
1451 break; | |
159 | 1452 } |
1453 } | |
1454 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
|
1455 buf->printf("0x%llx", v); |
159 | 1456 else |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
1457 buf->printf("%lld", v); |
159 | 1458 } |
1459 | |
1460 void IntegerExp::toMangleBuffer(OutBuffer *buf) | |
1461 { | |
1462 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
|
1463 buf->printf("N%lld", -value); |
159 | 1464 else |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
1465 buf->printf("%lld", value); |
159 | 1466 } |
1467 | |
1468 /******************************** RealExp **************************/ | |
1469 | |
1470 RealExp::RealExp(Loc loc, real_t value, Type *type) | |
1471 : Expression(loc, TOKfloat64, sizeof(RealExp)) | |
1472 { | |
1473 //printf("RealExp::RealExp(%Lg)\n", value); | |
1474 this->value = value; | |
1475 this->type = type; | |
1476 } | |
1477 | |
1478 char *RealExp::toChars() | |
1479 { | |
1480 char buffer[sizeof(value) * 3 + 8 + 1 + 1]; | |
1481 | |
1482 #ifdef IN_GCC | |
1483 value.format(buffer, sizeof(buffer)); | |
1484 if (type->isimaginary()) | |
1485 strcat(buffer, "i"); | |
1486 #else | |
1487 sprintf(buffer, type->isimaginary() ? "%Lgi" : "%Lg", value); | |
1488 #endif | |
1489 assert(strlen(buffer) < sizeof(buffer)); | |
1490 return mem.strdup(buffer); | |
1491 } | |
1492 | |
1493 integer_t RealExp::toInteger() | |
1494 { | |
1495 #ifdef IN_GCC | |
1496 return toReal().toInt(); | |
1497 #else | |
1498 return (sinteger_t) toReal(); | |
1499 #endif | |
1500 } | |
1501 | |
1502 uinteger_t RealExp::toUInteger() | |
1503 { | |
1504 #ifdef IN_GCC | |
1505 return (uinteger_t) toReal().toInt(); | |
1506 #else | |
1507 return (uinteger_t) toReal(); | |
1508 #endif | |
1509 } | |
1510 | |
1511 real_t RealExp::toReal() | |
1512 { | |
1513 return type->isreal() ? value : 0; | |
1514 } | |
1515 | |
1516 real_t RealExp::toImaginary() | |
1517 { | |
1518 return type->isreal() ? 0 : value; | |
1519 } | |
1520 | |
1521 complex_t RealExp::toComplex() | |
1522 { | |
1523 #ifdef __DMC__ | |
1524 return toReal() + toImaginary() * I; | |
1525 #else | |
1526 return complex_t(toReal(), toImaginary()); | |
1527 #endif | |
1528 } | |
1529 | |
1530 /******************************** | |
1531 * Test to see if two reals are the same. | |
1532 * Regard NaN's as equivalent. | |
1533 * Regard +0 and -0 as different. | |
1534 */ | |
1535 | |
1536 int RealEquals(real_t x1, real_t x2) | |
1537 { | |
421
1c65b5477eaa
Fix real comparison for real: allow +0 to be distinguished from -0.
Christian Kamm <kamm incasoftware de>
parents:
420
diff
changeset
|
1538 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
|
1539 (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
|
1540 // 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
|
1541 (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
|
1542 // 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
|
1543 (x1 != 0. && x1 == x2); |
159 | 1544 } |
1545 | |
1546 int RealExp::equals(Object *o) | |
1547 { RealExp *ne; | |
1548 | |
1549 if (this == o || | |
1550 (((Expression *)o)->op == TOKfloat64 && | |
1551 ((ne = (RealExp *)o), type->equals(ne->type)) && | |
1552 RealEquals(value, ne->value) | |
1553 ) | |
1554 ) | |
1555 return 1; | |
1556 return 0; | |
1557 } | |
1558 | |
1559 Expression *RealExp::semantic(Scope *sc) | |
1560 { | |
1561 if (!type) | |
1562 type = Type::tfloat64; | |
1563 else | |
1564 type = type->semantic(loc, sc); | |
1565 return this; | |
1566 } | |
1567 | |
1568 int RealExp::isBool(int result) | |
1569 { | |
1570 #ifdef IN_GCC | |
1571 return result ? (! value.isZero()) : (value.isZero()); | |
1572 #else | |
1573 return result ? (value != 0) | |
1574 : (value == 0); | |
1575 #endif | |
1576 } | |
1577 | |
1578 void floatToBuffer(OutBuffer *buf, Type *type, real_t value) | |
1579 { | |
1580 /* In order to get an exact representation, try converting it | |
1581 * to decimal then back again. If it matches, use it. | |
1582 * If it doesn't, fall back to hex, which is | |
1583 * always exact. | |
1584 */ | |
1585 char buffer[25]; | |
1586 sprintf(buffer, "%Lg", value); | |
1587 assert(strlen(buffer) < sizeof(buffer)); | |
1588 #if _WIN32 && __DMC__ | |
1589 char *save = __locale_decpoint; | |
1590 __locale_decpoint = "."; | |
1591 real_t r = strtold(buffer, NULL); | |
1592 __locale_decpoint = save; | |
1593 #else | |
1594 real_t r = strtold(buffer, NULL); | |
1595 #endif | |
1596 if (r == value) // if exact duplication | |
1597 buf->writestring(buffer); | |
1598 else | |
1599 buf->printf("%La", value); // ensure exact duplication | |
1600 | |
1601 if (type) | |
1602 { | |
1603 Type *t = type->toBasetype(); | |
1604 switch (t->ty) | |
1605 { | |
1606 case Tfloat32: | |
1607 case Timaginary32: | |
1608 case Tcomplex32: | |
1609 buf->writeByte('F'); | |
1610 break; | |
1611 | |
1612 case Tfloat80: | |
1613 case Timaginary80: | |
1614 case Tcomplex80: | |
1615 buf->writeByte('L'); | |
1616 break; | |
1617 | |
1618 default: | |
1619 break; | |
1620 } | |
1621 if (t->isimaginary()) | |
1622 buf->writeByte('i'); | |
1623 } | |
1624 } | |
1625 | |
1626 void RealExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
1627 { | |
1628 floatToBuffer(buf, type, value); | |
1629 } | |
1630 | |
1631 void realToMangleBuffer(OutBuffer *buf, real_t value) | |
1632 { | |
1633 /* Rely on %A to get portable mangling. | |
1634 * Must munge result to get only identifier characters. | |
1635 * | |
1636 * Possible values from %A => mangled result | |
1637 * NAN => NAN | |
1638 * -INF => NINF | |
1639 * INF => INF | |
1640 * -0X1.1BC18BA997B95P+79 => N11BC18BA997B95P79 | |
1641 * 0X1.9P+2 => 19P2 | |
1642 */ | |
1643 | |
1644 if (isnan(value)) | |
1645 buf->writestring("NAN"); // no -NAN bugs | |
1646 else | |
1647 { | |
1648 char buffer[32]; | |
1649 int n = sprintf(buffer, "%LA", value); | |
1650 assert(n > 0 && n < sizeof(buffer)); | |
1651 for (int i = 0; i < n; i++) | |
1652 { char c = buffer[i]; | |
1653 | |
1654 switch (c) | |
1655 { | |
1656 case '-': | |
1657 buf->writeByte('N'); | |
1658 break; | |
1659 | |
1660 case '+': | |
1661 case 'X': | |
1662 case '.': | |
1663 break; | |
1664 | |
1665 case '0': | |
1666 if (i < 2) | |
1667 break; // skip leading 0X | |
1668 default: | |
1669 buf->writeByte(c); | |
1670 break; | |
1671 } | |
1672 } | |
1673 } | |
1674 } | |
1675 | |
1676 void RealExp::toMangleBuffer(OutBuffer *buf) | |
1677 { | |
1678 buf->writeByte('e'); | |
1679 realToMangleBuffer(buf, value); | |
1680 } | |
1681 | |
1682 | |
1683 /******************************** ComplexExp **************************/ | |
1684 | |
1685 ComplexExp::ComplexExp(Loc loc, complex_t value, Type *type) | |
1686 : Expression(loc, TOKcomplex80, sizeof(ComplexExp)) | |
1687 { | |
1688 this->value = value; | |
1689 this->type = type; | |
1690 //printf("ComplexExp::ComplexExp(%s)\n", toChars()); | |
1691 } | |
1692 | |
1693 char *ComplexExp::toChars() | |
1694 { | |
1695 char buffer[sizeof(value) * 3 + 8 + 1]; | |
1696 | |
1697 #ifdef IN_GCC | |
1698 char buf1[sizeof(value) * 3 + 8 + 1]; | |
1699 char buf2[sizeof(value) * 3 + 8 + 1]; | |
1700 creall(value).format(buf1, sizeof(buf1)); | |
1701 cimagl(value).format(buf2, sizeof(buf2)); | |
1702 sprintf(buffer, "(%s+%si)", buf1, buf2); | |
1703 #else | |
1704 sprintf(buffer, "(%Lg+%Lgi)", creall(value), cimagl(value)); | |
1705 assert(strlen(buffer) < sizeof(buffer)); | |
1706 #endif | |
1707 return mem.strdup(buffer); | |
1708 } | |
1709 | |
1710 integer_t ComplexExp::toInteger() | |
1711 { | |
1712 #ifdef IN_GCC | |
1713 return (sinteger_t) toReal().toInt(); | |
1714 #else | |
1715 return (sinteger_t) toReal(); | |
1716 #endif | |
1717 } | |
1718 | |
1719 uinteger_t ComplexExp::toUInteger() | |
1720 { | |
1721 #ifdef IN_GCC | |
1722 return (uinteger_t) toReal().toInt(); | |
1723 #else | |
1724 return (uinteger_t) toReal(); | |
1725 #endif | |
1726 } | |
1727 | |
1728 real_t ComplexExp::toReal() | |
1729 { | |
1730 return creall(value); | |
1731 } | |
1732 | |
1733 real_t ComplexExp::toImaginary() | |
1734 { | |
1735 return cimagl(value); | |
1736 } | |
1737 | |
1738 complex_t ComplexExp::toComplex() | |
1739 { | |
1740 return value; | |
1741 } | |
1742 | |
1743 int ComplexExp::equals(Object *o) | |
1744 { ComplexExp *ne; | |
1745 | |
1746 if (this == o || | |
1747 (((Expression *)o)->op == TOKcomplex80 && | |
1748 ((ne = (ComplexExp *)o), type->equals(ne->type)) && | |
1749 RealEquals(creall(value), creall(ne->value)) && | |
1750 RealEquals(cimagl(value), cimagl(ne->value)) | |
1751 ) | |
1752 ) | |
1753 return 1; | |
1754 return 0; | |
1755 } | |
1756 | |
1757 Expression *ComplexExp::semantic(Scope *sc) | |
1758 { | |
1759 if (!type) | |
1760 type = Type::tcomplex80; | |
1761 else | |
1762 type = type->semantic(loc, sc); | |
1763 return this; | |
1764 } | |
1765 | |
1766 int ComplexExp::isBool(int result) | |
1767 { | |
1768 if (result) | |
1769 return (bool)(value); | |
1770 else | |
1771 return !value; | |
1772 } | |
1773 | |
1774 void ComplexExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
1775 { | |
1776 /* Print as: | |
1777 * (re+imi) | |
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 buf->printf("(%s+%si)", buf1, buf2); | |
1785 #else | |
1786 buf->writeByte('('); | |
1787 floatToBuffer(buf, type, creall(value)); | |
1788 buf->writeByte('+'); | |
1789 floatToBuffer(buf, type, cimagl(value)); | |
1790 buf->writestring("i)"); | |
1791 #endif | |
1792 } | |
1793 | |
1794 void ComplexExp::toMangleBuffer(OutBuffer *buf) | |
1795 { | |
1796 buf->writeByte('c'); | |
1797 real_t r = toReal(); | |
1798 realToMangleBuffer(buf, r); | |
1799 buf->writeByte('c'); // separate the two | |
1800 r = toImaginary(); | |
1801 realToMangleBuffer(buf, r); | |
1802 } | |
1803 | |
1804 /******************************** IdentifierExp **************************/ | |
1805 | |
1806 IdentifierExp::IdentifierExp(Loc loc, Identifier *ident) | |
1807 : Expression(loc, TOKidentifier, sizeof(IdentifierExp)) | |
1808 { | |
1809 this->ident = ident; | |
1810 } | |
1811 | |
1812 Expression *IdentifierExp::semantic(Scope *sc) | |
1813 { | |
1814 Dsymbol *s; | |
1815 Dsymbol *scopesym; | |
1816 | |
1817 #if LOGSEMANTIC | |
1818 printf("IdentifierExp::semantic('%s')\n", ident->toChars()); | |
1819 #endif | |
1820 s = sc->search(loc, ident, &scopesym); | |
1821 if (s) | |
1822 { Expression *e; | |
1823 WithScopeSymbol *withsym; | |
1824 | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
1825 /* 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
|
1826 */ |
159 | 1827 withsym = scopesym->isWithScopeSymbol(); |
1828 if (withsym) | |
1829 { | |
1830 s = s->toAlias(); | |
1831 | |
1832 // Same as wthis.ident | |
1833 if (s->needThis() || s->isTemplateDeclaration()) | |
1834 { | |
1835 e = new VarExp(loc, withsym->withstate->wthis); | |
1836 e = new DotIdExp(loc, e, ident); | |
1837 } | |
1838 else | |
1839 { Type *t = withsym->withstate->wthis->type; | |
1840 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
|
1841 t = ((TypePointer *)t)->next; |
159 | 1842 e = new TypeDotIdExp(loc, t, ident); |
1843 } | |
1844 } | |
1845 else | |
1846 { | |
1847 if (!s->parent && scopesym->isArrayScopeSymbol()) | |
1848 { // Kludge to run semantic() here because | |
1849 // ArrayScopeSymbol::search() doesn't have access to sc. | |
1850 s->semantic(sc); | |
1851 } | |
1852 // Look to see if f is really a function template | |
1853 FuncDeclaration *f = s->isFuncDeclaration(); | |
1854 if (f && f->parent) | |
1855 { TemplateInstance *ti = f->parent->isTemplateInstance(); | |
1856 | |
1857 if (ti && | |
1858 !ti->isTemplateMixin() && | |
1859 (ti->name == f->ident || | |
1860 ti->toAlias()->ident == f->ident) | |
1861 && | |
1862 ti->tempdecl && ti->tempdecl->onemember) | |
1863 { | |
1864 TemplateDeclaration *tempdecl = ti->tempdecl; | |
1865 if (tempdecl->overroot) // if not start of overloaded list of TemplateDeclaration's | |
1866 tempdecl = tempdecl->overroot; // then get the start | |
1867 e = new TemplateExp(loc, tempdecl); | |
1868 e = e->semantic(sc); | |
1869 return e; | |
1870 } | |
1871 } | |
1872 e = new DsymbolExp(loc, s); | |
1873 } | |
1874 return e->semantic(sc); | |
1875 } | |
1876 error("undefined identifier %s", ident->toChars()); | |
1877 type = Type::terror; | |
1878 return this; | |
1879 } | |
1880 | |
1881 char *IdentifierExp::toChars() | |
1882 { | |
1883 return ident->toChars(); | |
1884 } | |
1885 | |
1886 void IdentifierExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
1887 { | |
1888 if (hgs->hdrgen) | |
1889 buf->writestring(ident->toHChars2()); | |
1890 else | |
1891 buf->writestring(ident->toChars()); | |
1892 } | |
1893 | |
1894 Expression *IdentifierExp::toLvalue(Scope *sc, Expression *e) | |
1895 { | |
1896 #if 0 | |
1897 tym = tybasic(e1->ET->Tty); | |
1898 if (!(tyscalar(tym) || | |
1899 tym == TYstruct || | |
1900 tym == TYarray && e->Eoper == TOKaddr)) | |
1901 synerr(EM_lvalue); // lvalue expected | |
1902 #endif | |
1903 return this; | |
1904 } | |
1905 | |
1906 /******************************** DollarExp **************************/ | |
1907 | |
1908 DollarExp::DollarExp(Loc loc) | |
1909 : IdentifierExp(loc, Id::dollar) | |
1910 { | |
1911 } | |
1912 | |
1913 /******************************** DsymbolExp **************************/ | |
1914 | |
1915 DsymbolExp::DsymbolExp(Loc loc, Dsymbol *s) | |
1916 : Expression(loc, TOKdsymbol, sizeof(DsymbolExp)) | |
1917 { | |
1918 this->s = s; | |
1919 } | |
1920 | |
1921 Expression *DsymbolExp::semantic(Scope *sc) | |
1922 { | |
1923 #if LOGSEMANTIC | |
1924 printf("DsymbolExp::semantic('%s')\n", s->toChars()); | |
1925 #endif | |
1926 | |
1927 Lagain: | |
1928 EnumMember *em; | |
1929 Expression *e; | |
1930 VarDeclaration *v; | |
1931 FuncDeclaration *f; | |
1932 FuncLiteralDeclaration *fld; | |
1933 Declaration *d; | |
1934 ClassDeclaration *cd; | |
1935 ClassDeclaration *thiscd = NULL; | |
1936 Import *imp; | |
1937 Package *pkg; | |
1938 Type *t; | |
1939 | |
1940 //printf("DsymbolExp:: %p '%s' is a symbol\n", this, toChars()); | |
1941 //printf("s = '%s', s->kind = '%s'\n", s->toChars(), s->kind()); | |
1942 if (type) | |
1943 return this; | |
1944 if (!s->isFuncDeclaration()) // functions are checked after overloading | |
1945 checkDeprecated(sc, s); | |
1946 s = s->toAlias(); | |
1947 //printf("s = '%s', s->kind = '%s', s->needThis() = %p\n", s->toChars(), s->kind(), s->needThis()); | |
1948 if (!s->isFuncDeclaration()) | |
1949 checkDeprecated(sc, s); | |
1950 | |
1951 if (sc->func) | |
1952 thiscd = sc->func->parent->isClassDeclaration(); | |
1953 | |
1954 // BUG: This should happen after overload resolution for functions, not before | |
1955 if (s->needThis()) | |
1956 { | |
1957 if (hasThis(sc) /*&& !s->isFuncDeclaration()*/) | |
1958 { | |
1959 // Supply an implicit 'this', as in | |
1960 // this.ident | |
1961 | |
1962 DotVarExp *de; | |
1963 | |
1964 de = new DotVarExp(loc, new ThisExp(loc), s->isDeclaration()); | |
1965 return de->semantic(sc); | |
1966 } | |
1967 } | |
1968 | |
1969 em = s->isEnumMember(); | |
1970 if (em) | |
1971 { | |
1972 e = em->value->copy(); | |
1973 e = e->semantic(sc); | |
1974 return e; | |
1975 } | |
1976 v = s->isVarDeclaration(); | |
1977 if (v) | |
1978 { | |
1979 //printf("Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars()); | |
1980 if (!type) | |
1981 { type = v->type; | |
1982 if (!v->type) | |
1983 { error("forward reference of %s", v->toChars()); | |
1984 type = Type::terror; | |
1985 } | |
1986 } | |
1987 if (v->isConst() && type->toBasetype()->ty != Tsarray) | |
1988 { | |
1989 if (v->init) | |
1990 { | |
1991 if (v->inuse) | |
1992 { | |
1993 error("circular reference to '%s'", v->toChars()); | |
1994 type = Type::tint32; | |
1995 return this; | |
1996 } | |
1997 ExpInitializer *ei = v->init->isExpInitializer(); | |
1998 if (ei) | |
1999 { | |
2000 e = ei->exp->copy(); // make copy so we can change loc | |
2001 if (e->op == TOKstring || !e->type) | |
2002 e = e->semantic(sc); | |
2003 e = e->implicitCastTo(sc, type); | |
2004 e->loc = loc; | |
2005 return e; | |
2006 } | |
2007 } | |
2008 else | |
2009 { | |
2010 e = type->defaultInit(); | |
2011 e->loc = loc; | |
2012 return e; | |
2013 } | |
2014 } | |
2015 e = new VarExp(loc, v); | |
2016 e->type = type; | |
2017 e = e->semantic(sc); | |
2018 return e->deref(); | |
2019 } | |
2020 fld = s->isFuncLiteralDeclaration(); | |
2021 if (fld) | |
2022 { //printf("'%s' is a function literal\n", fld->toChars()); | |
2023 e = new FuncExp(loc, fld); | |
2024 return e->semantic(sc); | |
2025 } | |
2026 f = s->isFuncDeclaration(); | |
2027 if (f) | |
2028 { //printf("'%s' is a function\n", f->toChars()); | |
2029 return new VarExp(loc, f); | |
2030 } | |
2031 cd = s->isClassDeclaration(); | |
2032 if (cd && thiscd && cd->isBaseOf(thiscd, NULL) && sc->func->needThis()) | |
2033 { | |
2034 // We need to add an implicit 'this' if cd is this class or a base class. | |
2035 DotTypeExp *dte; | |
2036 | |
2037 dte = new DotTypeExp(loc, new ThisExp(loc), s); | |
2038 return dte->semantic(sc); | |
2039 } | |
2040 imp = s->isImport(); | |
2041 if (imp) | |
2042 { | |
2043 ScopeExp *ie; | |
2044 | |
2045 ie = new ScopeExp(loc, imp->pkg); | |
2046 return ie->semantic(sc); | |
2047 } | |
2048 pkg = s->isPackage(); | |
2049 if (pkg) | |
2050 { | |
2051 ScopeExp *ie; | |
2052 | |
2053 ie = new ScopeExp(loc, pkg); | |
2054 return ie->semantic(sc); | |
2055 } | |
2056 Module *mod = s->isModule(); | |
2057 if (mod) | |
2058 { | |
2059 ScopeExp *ie; | |
2060 | |
2061 ie = new ScopeExp(loc, mod); | |
2062 return ie->semantic(sc); | |
2063 } | |
2064 | |
2065 t = s->getType(); | |
2066 if (t) | |
2067 { | |
2068 return new TypeExp(loc, t); | |
2069 } | |
2070 | |
2071 TupleDeclaration *tup = s->isTupleDeclaration(); | |
2072 if (tup) | |
2073 { | |
2074 e = new TupleExp(loc, tup); | |
2075 e = e->semantic(sc); | |
2076 return e; | |
2077 } | |
2078 | |
2079 TemplateInstance *ti = s->isTemplateInstance(); | |
2080 if (ti && !global.errors) | |
2081 { if (!ti->semanticdone) | |
2082 ti->semantic(sc); | |
2083 s = ti->inst->toAlias(); | |
2084 if (!s->isTemplateInstance()) | |
2085 goto Lagain; | |
2086 e = new ScopeExp(loc, ti); | |
2087 e = e->semantic(sc); | |
2088 return e; | |
2089 } | |
2090 | |
2091 TemplateDeclaration *td = s->isTemplateDeclaration(); | |
2092 if (td) | |
2093 { | |
2094 e = new TemplateExp(loc, td); | |
2095 e = e->semantic(sc); | |
2096 return e; | |
2097 } | |
2098 | |
2099 Lerr: | |
2100 error("%s '%s' is not a variable", s->kind(), s->toChars()); | |
2101 type = Type::terror; | |
2102 return this; | |
2103 } | |
2104 | |
2105 char *DsymbolExp::toChars() | |
2106 { | |
2107 return s->toChars(); | |
2108 } | |
2109 | |
2110 void DsymbolExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
2111 { | |
2112 buf->writestring(s->toChars()); | |
2113 } | |
2114 | |
2115 Expression *DsymbolExp::toLvalue(Scope *sc, Expression *e) | |
2116 { | |
2117 #if 0 | |
2118 tym = tybasic(e1->ET->Tty); | |
2119 if (!(tyscalar(tym) || | |
2120 tym == TYstruct || | |
2121 tym == TYarray && e->Eoper == TOKaddr)) | |
2122 synerr(EM_lvalue); // lvalue expected | |
2123 #endif | |
2124 return this; | |
2125 } | |
2126 | |
2127 /******************************** ThisExp **************************/ | |
2128 | |
2129 ThisExp::ThisExp(Loc loc) | |
2130 : Expression(loc, TOKthis, sizeof(ThisExp)) | |
2131 { | |
2132 var = NULL; | |
2133 } | |
2134 | |
2135 Expression *ThisExp::semantic(Scope *sc) | |
2136 { FuncDeclaration *fd; | |
2137 FuncDeclaration *fdthis; | |
2138 int nested = 0; | |
2139 | |
2140 #if LOGSEMANTIC | |
2141 printf("ThisExp::semantic()\n"); | |
2142 #endif | |
2143 if (type) | |
2144 { //assert(global.errors || var); | |
2145 return this; | |
2146 } | |
2147 | |
2148 /* Special case for typeof(this) and typeof(super) since both | |
2149 * should work even if they are not inside a non-static member function | |
2150 */ | |
2151 if (sc->intypeof) | |
2152 { | |
2153 // Find enclosing struct or class | |
2154 for (Dsymbol *s = sc->parent; 1; s = s->parent) | |
2155 { | |
2156 ClassDeclaration *cd; | |
2157 StructDeclaration *sd; | |
2158 | |
2159 if (!s) | |
2160 { | |
2161 error("%s is not in a struct or class scope", toChars()); | |
2162 goto Lerr; | |
2163 } | |
2164 cd = s->isClassDeclaration(); | |
2165 if (cd) | |
2166 { | |
2167 type = cd->type; | |
2168 return this; | |
2169 } | |
2170 sd = s->isStructDeclaration(); | |
2171 if (sd) | |
2172 { | |
2173 type = sd->type->pointerTo(); | |
2174 return this; | |
2175 } | |
2176 } | |
2177 } | |
2178 | |
2179 fdthis = sc->parent->isFuncDeclaration(); | |
2180 fd = hasThis(sc); // fd is the uplevel function with the 'this' variable | |
2181 if (!fd) | |
2182 goto Lerr; | |
2183 | |
2184 assert(fd->vthis); | |
2185 var = fd->vthis; | |
2186 assert(var->parent); | |
2187 type = var->type; | |
2188 var->isVarDeclaration()->checkNestedReference(sc, loc); | |
2189 #if 0 | |
2190 if (fd != fdthis) // if nested | |
2191 { | |
2192 fdthis->getLevel(loc, fd); | |
2193 fd->vthis->nestedref = 1; | |
2194 fd->nestedFrameRef = 1; | |
2195 } | |
2196 #endif | |
336 | 2197 if (!sc->intypeof) |
2198 sc->callSuper |= CSXthis; | |
159 | 2199 return this; |
2200 | |
2201 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
|
2202 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
|
2203 type = Type::terror; |
159 | 2204 return this; |
2205 } | |
2206 | |
2207 int ThisExp::isBool(int result) | |
2208 { | |
2209 return result ? TRUE : FALSE; | |
2210 } | |
2211 | |
2212 void ThisExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
2213 { | |
2214 buf->writestring("this"); | |
2215 } | |
2216 | |
2217 Expression *ThisExp::toLvalue(Scope *sc, Expression *e) | |
2218 { | |
2219 return this; | |
2220 } | |
2221 | |
2222 /******************************** SuperExp **************************/ | |
2223 | |
2224 SuperExp::SuperExp(Loc loc) | |
2225 : ThisExp(loc) | |
2226 { | |
2227 op = TOKsuper; | |
2228 } | |
2229 | |
2230 Expression *SuperExp::semantic(Scope *sc) | |
2231 { FuncDeclaration *fd; | |
2232 FuncDeclaration *fdthis; | |
2233 ClassDeclaration *cd; | |
2234 Dsymbol *s; | |
2235 | |
2236 #if LOGSEMANTIC | |
2237 printf("SuperExp::semantic('%s')\n", toChars()); | |
2238 #endif | |
2239 if (type) | |
2240 return this; | |
2241 | |
2242 /* Special case for typeof(this) and typeof(super) since both | |
2243 * should work even if they are not inside a non-static member function | |
2244 */ | |
2245 if (sc->intypeof) | |
2246 { | |
2247 // Find enclosing class | |
2248 for (Dsymbol *s = sc->parent; 1; s = s->parent) | |
2249 { | |
2250 ClassDeclaration *cd; | |
2251 | |
2252 if (!s) | |
2253 { | |
2254 error("%s is not in a class scope", toChars()); | |
2255 goto Lerr; | |
2256 } | |
2257 cd = s->isClassDeclaration(); | |
2258 if (cd) | |
2259 { | |
2260 cd = cd->baseClass; | |
2261 if (!cd) | |
2262 { error("class %s has no 'super'", s->toChars()); | |
2263 goto Lerr; | |
2264 } | |
2265 type = cd->type; | |
2266 return this; | |
2267 } | |
2268 } | |
2269 } | |
2270 | |
2271 fdthis = sc->parent->isFuncDeclaration(); | |
2272 fd = hasThis(sc); | |
2273 if (!fd) | |
2274 goto Lerr; | |
2275 assert(fd->vthis); | |
2276 var = fd->vthis; | |
2277 assert(var->parent); | |
2278 | |
2279 s = fd->toParent(); | |
2280 while (s && s->isTemplateInstance()) | |
2281 s = s->toParent(); | |
2282 assert(s); | |
2283 cd = s->isClassDeclaration(); | |
2284 //printf("parent is %s %s\n", fd->toParent()->kind(), fd->toParent()->toChars()); | |
2285 if (!cd) | |
2286 goto Lerr; | |
2287 if (!cd->baseClass) | |
2288 { | |
2289 error("no base class for %s", cd->toChars()); | |
2290 type = fd->vthis->type; | |
2291 } | |
2292 else | |
2293 { | |
2294 type = cd->baseClass->type; | |
2295 } | |
2296 | |
2297 var->isVarDeclaration()->checkNestedReference(sc, loc); | |
2298 #if 0 | |
2299 if (fd != fdthis) | |
2300 { | |
2301 fdthis->getLevel(loc, fd); | |
2302 fd->vthis->nestedref = 1; | |
2303 fd->nestedFrameRef = 1; | |
2304 } | |
2305 #endif | |
2306 | |
336 | 2307 if (!sc->intypeof) |
2308 sc->callSuper |= CSXsuper; | |
159 | 2309 return this; |
2310 | |
2311 | |
2312 Lerr: | |
2313 error("'super' is only allowed in non-static class member functions"); | |
2314 type = Type::tint32; | |
2315 return this; | |
2316 } | |
2317 | |
2318 void SuperExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
2319 { | |
2320 buf->writestring("super"); | |
2321 } | |
2322 | |
2323 | |
2324 /******************************** NullExp **************************/ | |
2325 | |
2326 NullExp::NullExp(Loc loc) | |
2327 : Expression(loc, TOKnull, sizeof(NullExp)) | |
2328 { | |
2329 committed = 0; | |
2330 } | |
2331 | |
2332 Expression *NullExp::semantic(Scope *sc) | |
2333 { | |
2334 #if LOGSEMANTIC | |
2335 printf("NullExp::semantic('%s')\n", toChars()); | |
2336 #endif | |
2337 // NULL is the same as (void *)0 | |
2338 if (!type) | |
2339 type = Type::tvoid->pointerTo(); | |
2340 return this; | |
2341 } | |
2342 | |
2343 int NullExp::isBool(int result) | |
2344 { | |
2345 return result ? FALSE : TRUE; | |
2346 } | |
2347 | |
2348 void NullExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
2349 { | |
2350 buf->writestring("null"); | |
2351 } | |
2352 | |
2353 void NullExp::toMangleBuffer(OutBuffer *buf) | |
2354 { | |
2355 buf->writeByte('n'); | |
2356 } | |
2357 | |
2358 /******************************** StringExp **************************/ | |
2359 | |
2360 StringExp::StringExp(Loc loc, char *string) | |
2361 : Expression(loc, TOKstring, sizeof(StringExp)) | |
2362 { | |
2363 this->string = string; | |
2364 this->len = strlen(string); | |
2365 this->sz = 1; | |
2366 this->committed = 0; | |
2367 this->postfix = 0; | |
2368 } | |
2369 | |
2370 StringExp::StringExp(Loc loc, void *string, size_t len) | |
2371 : Expression(loc, TOKstring, sizeof(StringExp)) | |
2372 { | |
2373 this->string = string; | |
2374 this->len = len; | |
2375 this->sz = 1; | |
2376 this->committed = 0; | |
2377 this->postfix = 0; | |
2378 } | |
2379 | |
2380 StringExp::StringExp(Loc loc, void *string, size_t len, unsigned char postfix) | |
2381 : Expression(loc, TOKstring, sizeof(StringExp)) | |
2382 { | |
2383 this->string = string; | |
2384 this->len = len; | |
2385 this->sz = 1; | |
2386 this->committed = 0; | |
2387 this->postfix = postfix; | |
2388 } | |
2389 | |
2390 #if 0 | |
2391 Expression *StringExp::syntaxCopy() | |
2392 { | |
2393 printf("StringExp::syntaxCopy() %s\n", toChars()); | |
2394 return copy(); | |
2395 } | |
2396 #endif | |
2397 | |
2398 int StringExp::equals(Object *o) | |
2399 { | |
2400 //printf("StringExp::equals('%s')\n", o->toChars()); | |
2401 if (o && o->dyncast() == DYNCAST_EXPRESSION) | |
2402 { Expression *e = (Expression *)o; | |
2403 | |
2404 if (e->op == TOKstring) | |
2405 { | |
2406 return compare(o) == 0; | |
2407 } | |
2408 } | |
2409 return FALSE; | |
2410 } | |
2411 | |
2412 char *StringExp::toChars() | |
2413 { | |
2414 OutBuffer buf; | |
2415 HdrGenState hgs; | |
2416 char *p; | |
2417 | |
2418 memset(&hgs, 0, sizeof(hgs)); | |
2419 toCBuffer(&buf, &hgs); | |
2420 buf.writeByte(0); | |
2421 p = (char *)buf.data; | |
2422 buf.data = NULL; | |
2423 return p; | |
2424 } | |
2425 | |
2426 Expression *StringExp::semantic(Scope *sc) | |
2427 { | |
2428 #if LOGSEMANTIC | |
2429 printf("StringExp::semantic() %s\n", toChars()); | |
2430 #endif | |
2431 if (!type) | |
2432 { OutBuffer buffer; | |
2433 size_t newlen = 0; | |
2434 char *p; | |
2435 size_t u; | |
2436 unsigned c; | |
2437 | |
2438 switch (postfix) | |
2439 { | |
2440 case 'd': | |
2441 for (u = 0; u < len;) | |
2442 { | |
2443 p = utf_decodeChar((unsigned char *)string, len, &u, &c); | |
2444 if (p) | |
2445 { error("%s", p); | |
2446 break; | |
2447 } | |
2448 else | |
2449 { buffer.write4(c); | |
2450 newlen++; | |
2451 } | |
2452 } | |
2453 buffer.write4(0); | |
2454 string = buffer.extractData(); | |
2455 len = newlen; | |
2456 sz = 4; | |
2457 type = new TypeSArray(Type::tdchar, new IntegerExp(loc, len, Type::tindex)); | |
2458 committed = 1; | |
2459 break; | |
2460 | |
2461 case 'w': | |
2462 for (u = 0; u < len;) | |
2463 { | |
2464 p = utf_decodeChar((unsigned char *)string, len, &u, &c); | |
2465 if (p) | |
2466 { error("%s", p); | |
2467 break; | |
2468 } | |
2469 else | |
2470 { buffer.writeUTF16(c); | |
2471 newlen++; | |
2472 if (c >= 0x10000) | |
2473 newlen++; | |
2474 } | |
2475 } | |
2476 buffer.writeUTF16(0); | |
2477 string = buffer.extractData(); | |
2478 len = newlen; | |
2479 sz = 2; | |
2480 type = new TypeSArray(Type::twchar, new IntegerExp(loc, len, Type::tindex)); | |
2481 committed = 1; | |
2482 break; | |
2483 | |
2484 case 'c': | |
2485 committed = 1; | |
2486 default: | |
2487 type = new TypeSArray(Type::tchar, new IntegerExp(loc, len, Type::tindex)); | |
2488 break; | |
2489 } | |
2490 type = type->semantic(loc, sc); | |
2491 } | |
2492 return this; | |
2493 } | |
2494 | |
2495 /**************************************** | |
2496 * Convert string to char[]. | |
2497 */ | |
2498 | |
2499 StringExp *StringExp::toUTF8(Scope *sc) | |
2500 { | |
2501 if (sz != 1) | |
2502 { // Convert to UTF-8 string | |
2503 committed = 0; | |
2504 Expression *e = castTo(sc, Type::tchar->arrayOf()); | |
2505 e = e->optimize(WANTvalue); | |
2506 assert(e->op == TOKstring); | |
2507 StringExp *se = (StringExp *)e; | |
2508 assert(se->sz == 1); | |
2509 return se; | |
2510 } | |
2511 return this; | |
2512 } | |
2513 | |
2514 int StringExp::compare(Object *obj) | |
2515 { | |
2516 // Used to sort case statement expressions so we can do an efficient lookup | |
2517 StringExp *se2 = (StringExp *)(obj); | |
2518 | |
2519 // This is a kludge so isExpression() in template.c will return 5 | |
2520 // for StringExp's. | |
2521 if (!se2) | |
2522 return 5; | |
2523 | |
2524 assert(se2->op == TOKstring); | |
2525 | |
2526 int len1 = len; | |
2527 int len2 = se2->len; | |
2528 | |
2529 if (len1 == len2) | |
2530 { | |
2531 switch (sz) | |
2532 { | |
2533 case 1: | |
2534 return strcmp((char *)string, (char *)se2->string); | |
2535 | |
2536 case 2: | |
2537 { unsigned u; | |
2538 d_wchar *s1 = (d_wchar *)string; | |
2539 d_wchar *s2 = (d_wchar *)se2->string; | |
2540 | |
2541 for (u = 0; u < len; u++) | |
2542 { | |
2543 if (s1[u] != s2[u]) | |
2544 return s1[u] - s2[u]; | |
2545 } | |
2546 } | |
2547 | |
2548 case 4: | |
2549 { unsigned u; | |
2550 d_dchar *s1 = (d_dchar *)string; | |
2551 d_dchar *s2 = (d_dchar *)se2->string; | |
2552 | |
2553 for (u = 0; u < len; u++) | |
2554 { | |
2555 if (s1[u] != s2[u]) | |
2556 return s1[u] - s2[u]; | |
2557 } | |
2558 } | |
2559 break; | |
2560 | |
2561 default: | |
2562 assert(0); | |
2563 } | |
2564 } | |
2565 return len1 - len2; | |
2566 } | |
2567 | |
2568 int StringExp::isBool(int result) | |
2569 { | |
2570 return result ? TRUE : FALSE; | |
2571 } | |
2572 | |
2573 unsigned StringExp::charAt(size_t i) | |
2574 { unsigned value; | |
2575 | |
2576 switch (sz) | |
2577 { | |
2578 case 1: | |
2579 value = ((unsigned char *)string)[i]; | |
2580 break; | |
2581 | |
2582 case 2: | |
2583 value = ((unsigned short *)string)[i]; | |
2584 break; | |
2585 | |
2586 case 4: | |
2587 value = ((unsigned int *)string)[i]; | |
2588 break; | |
2589 | |
2590 default: | |
2591 assert(0); | |
2592 break; | |
2593 } | |
2594 return value; | |
2595 } | |
2596 | |
2597 void StringExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
2598 { | |
2599 buf->writeByte('"'); | |
2600 for (size_t i = 0; i < len; i++) | |
2601 { unsigned c = charAt(i); | |
2602 | |
2603 switch (c) | |
2604 { | |
2605 case '"': | |
2606 case '\\': | |
2607 if (!hgs->console) | |
2608 buf->writeByte('\\'); | |
2609 default: | |
2610 if (c <= 0xFF) | |
2611 { if (c <= 0x7F && (isprint(c) || hgs->console)) | |
2612 buf->writeByte(c); | |
2613 else | |
2614 buf->printf("\\x%02x", c); | |
2615 } | |
2616 else if (c <= 0xFFFF) | |
2617 buf->printf("\\x%02x\\x%02x", c & 0xFF, c >> 8); | |
2618 else | |
2619 buf->printf("\\x%02x\\x%02x\\x%02x\\x%02x", | |
2620 c & 0xFF, (c >> 8) & 0xFF, (c >> 16) & 0xFF, c >> 24); | |
2621 break; | |
2622 } | |
2623 } | |
2624 buf->writeByte('"'); | |
2625 if (postfix) | |
2626 buf->writeByte(postfix); | |
2627 } | |
2628 | |
2629 void StringExp::toMangleBuffer(OutBuffer *buf) | |
2630 { char m; | |
2631 OutBuffer tmp; | |
2632 char *p; | |
2633 unsigned c; | |
2634 size_t u; | |
2635 unsigned char *q; | |
2636 unsigned qlen; | |
2637 | |
2638 /* Write string in UTF-8 format | |
2639 */ | |
2640 switch (sz) | |
2641 { case 1: | |
2642 m = 'a'; | |
2643 q = (unsigned char *)string; | |
2644 qlen = len; | |
2645 break; | |
2646 case 2: | |
2647 m = 'w'; | |
2648 for (u = 0; u < len; ) | |
2649 { | |
2650 p = utf_decodeWchar((unsigned short *)string, len, &u, &c); | |
2651 if (p) | |
2652 error("%s", p); | |
2653 else | |
2654 tmp.writeUTF8(c); | |
2655 } | |
2656 q = tmp.data; | |
2657 qlen = tmp.offset; | |
2658 break; | |
2659 case 4: | |
2660 m = 'd'; | |
2661 for (u = 0; u < len; u++) | |
2662 { | |
2663 c = ((unsigned *)string)[u]; | |
2664 if (!utf_isValidDchar(c)) | |
2665 error("invalid UCS-32 char \\U%08x", c); | |
2666 else | |
2667 tmp.writeUTF8(c); | |
2668 } | |
2669 q = tmp.data; | |
2670 qlen = tmp.offset; | |
2671 break; | |
2672 default: | |
2673 assert(0); | |
2674 } | |
2675 buf->writeByte(m); | |
2676 buf->printf("%d_", qlen); | |
2677 for (size_t i = 0; i < qlen; i++) | |
2678 buf->printf("%02x", q[i]); | |
2679 } | |
2680 | |
2681 /************************ ArrayLiteralExp ************************************/ | |
2682 | |
2683 // [ e1, e2, e3, ... ] | |
2684 | |
2685 ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expressions *elements) | |
2686 : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp)) | |
2687 { | |
2688 this->elements = elements; | |
2689 } | |
2690 | |
2691 ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expression *e) | |
2692 : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp)) | |
2693 { | |
2694 elements = new Expressions; | |
2695 elements->push(e); | |
2696 } | |
2697 | |
2698 Expression *ArrayLiteralExp::syntaxCopy() | |
2699 { | |
2700 return new ArrayLiteralExp(loc, arraySyntaxCopy(elements)); | |
2701 } | |
2702 | |
2703 Expression *ArrayLiteralExp::semantic(Scope *sc) | |
2704 { Expression *e; | |
2705 Type *t0 = NULL; | |
2706 | |
2707 #if LOGSEMANTIC | |
2708 printf("ArrayLiteralExp::semantic('%s')\n", toChars()); | |
2709 #endif | |
2710 if (type) | |
2711 return this; | |
2712 | |
2713 // Run semantic() on each element | |
2714 for (int i = 0; i < elements->dim; i++) | |
2715 { e = (Expression *)elements->data[i]; | |
2716 e = e->semantic(sc); | |
2717 elements->data[i] = (void *)e; | |
2718 } | |
2719 expandTuples(elements); | |
2720 for (int i = 0; i < elements->dim; i++) | |
2721 { e = (Expression *)elements->data[i]; | |
2722 | |
2723 if (!e->type) | |
2724 error("%s has no value", e->toChars()); | |
2725 e = resolveProperties(sc, e); | |
2726 | |
2727 unsigned char committed = 1; | |
2728 if (e->op == TOKstring) | |
2729 committed = ((StringExp *)e)->committed; | |
2730 | |
2731 if (!t0) | |
2732 { t0 = e->type; | |
2733 // Convert any static arrays to dynamic arrays | |
2734 if (t0->ty == Tsarray) | |
2735 { | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
2736 t0 = ((TypeSArray *)t0)->next->arrayOf(); |
159 | 2737 e = e->implicitCastTo(sc, t0); |
2738 } | |
2739 } | |
2740 else | |
2741 e = e->implicitCastTo(sc, t0); | |
2742 if (!committed && e->op == TOKstring) | |
2743 { StringExp *se = (StringExp *)e; | |
2744 se->committed = 0; | |
2745 } | |
2746 elements->data[i] = (void *)e; | |
2747 } | |
2748 | |
2749 if (!t0) | |
2750 t0 = Type::tvoid; | |
2751 type = new TypeSArray(t0, new IntegerExp(elements->dim)); | |
2752 type = type->semantic(loc, sc); | |
2753 return this; | |
2754 } | |
2755 | |
2756 int ArrayLiteralExp::checkSideEffect(int flag) | |
2757 { int f = 0; | |
2758 | |
2759 for (size_t i = 0; i < elements->dim; i++) | |
2760 { Expression *e = (Expression *)elements->data[i]; | |
2761 | |
2762 f |= e->checkSideEffect(2); | |
2763 } | |
2764 if (flag == 0 && f == 0) | |
2765 Expression::checkSideEffect(0); | |
2766 return f; | |
2767 } | |
2768 | |
2769 int ArrayLiteralExp::isBool(int result) | |
2770 { | |
2771 size_t dim = elements ? elements->dim : 0; | |
2772 return result ? (dim != 0) : (dim == 0); | |
2773 } | |
2774 | |
2775 void ArrayLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
2776 { | |
2777 buf->writeByte('['); | |
2778 argsToCBuffer(buf, elements, hgs); | |
2779 buf->writeByte(']'); | |
2780 } | |
2781 | |
2782 void ArrayLiteralExp::toMangleBuffer(OutBuffer *buf) | |
2783 { | |
2784 size_t dim = elements ? elements->dim : 0; | |
2785 buf->printf("A%u", dim); | |
2786 for (size_t i = 0; i < dim; i++) | |
2787 { Expression *e = (Expression *)elements->data[i]; | |
2788 e->toMangleBuffer(buf); | |
2789 } | |
2790 } | |
2791 | |
2792 /************************ AssocArrayLiteralExp ************************************/ | |
2793 | |
2794 // [ key0 : value0, key1 : value1, ... ] | |
2795 | |
2796 AssocArrayLiteralExp::AssocArrayLiteralExp(Loc loc, | |
2797 Expressions *keys, Expressions *values) | |
2798 : Expression(loc, TOKassocarrayliteral, sizeof(AssocArrayLiteralExp)) | |
2799 { | |
2800 assert(keys->dim == values->dim); | |
2801 this->keys = keys; | |
2802 this->values = values; | |
2803 } | |
2804 | |
2805 Expression *AssocArrayLiteralExp::syntaxCopy() | |
2806 { | |
2807 return new AssocArrayLiteralExp(loc, | |
2808 arraySyntaxCopy(keys), arraySyntaxCopy(values)); | |
2809 } | |
2810 | |
2811 Expression *AssocArrayLiteralExp::semantic(Scope *sc) | |
2812 { Expression *e; | |
2813 Type *tkey = NULL; | |
2814 Type *tvalue = NULL; | |
2815 | |
2816 #if LOGSEMANTIC | |
2817 printf("AssocArrayLiteralExp::semantic('%s')\n", toChars()); | |
2818 #endif | |
2819 | |
2820 // Run semantic() on each element | |
2821 for (size_t i = 0; i < keys->dim; i++) | |
2822 { Expression *key = (Expression *)keys->data[i]; | |
2823 Expression *value = (Expression *)values->data[i]; | |
2824 | |
2825 key = key->semantic(sc); | |
2826 value = value->semantic(sc); | |
2827 | |
2828 keys->data[i] = (void *)key; | |
2829 values->data[i] = (void *)value; | |
2830 } | |
2831 expandTuples(keys); | |
2832 expandTuples(values); | |
2833 if (keys->dim != values->dim) | |
2834 { | |
2835 error("number of keys is %u, must match number of values %u", keys->dim, values->dim); | |
2836 keys->setDim(0); | |
2837 values->setDim(0); | |
2838 } | |
2839 for (size_t i = 0; i < keys->dim; i++) | |
2840 { Expression *key = (Expression *)keys->data[i]; | |
2841 Expression *value = (Expression *)values->data[i]; | |
2842 | |
2843 if (!key->type) | |
2844 error("%s has no value", key->toChars()); | |
2845 if (!value->type) | |
2846 error("%s has no value", value->toChars()); | |
2847 key = resolveProperties(sc, key); | |
2848 value = resolveProperties(sc, value); | |
2849 | |
2850 if (!tkey) | |
2851 tkey = key->type; | |
2852 else | |
2853 key = key->implicitCastTo(sc, tkey); | |
2854 keys->data[i] = (void *)key; | |
2855 | |
2856 if (!tvalue) | |
2857 tvalue = value->type; | |
2858 else | |
2859 value = value->implicitCastTo(sc, tvalue); | |
2860 values->data[i] = (void *)value; | |
2861 } | |
2862 | |
2863 if (!tkey) | |
2864 tkey = Type::tvoid; | |
2865 if (!tvalue) | |
2866 tvalue = Type::tvoid; | |
2867 type = new TypeAArray(tvalue, tkey); | |
2868 type = type->semantic(loc, sc); | |
2869 return this; | |
2870 } | |
2871 | |
2872 int AssocArrayLiteralExp::checkSideEffect(int flag) | |
2873 { int f = 0; | |
2874 | |
2875 for (size_t i = 0; i < keys->dim; i++) | |
2876 { Expression *key = (Expression *)keys->data[i]; | |
2877 Expression *value = (Expression *)values->data[i]; | |
2878 | |
2879 f |= key->checkSideEffect(2); | |
2880 f |= value->checkSideEffect(2); | |
2881 } | |
2882 if (flag == 0 && f == 0) | |
2883 Expression::checkSideEffect(0); | |
2884 return f; | |
2885 } | |
2886 | |
2887 int AssocArrayLiteralExp::isBool(int result) | |
2888 { | |
2889 size_t dim = keys->dim; | |
2890 return result ? (dim != 0) : (dim == 0); | |
2891 } | |
2892 | |
2893 void AssocArrayLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
2894 { | |
2895 buf->writeByte('['); | |
2896 for (size_t i = 0; i < keys->dim; i++) | |
2897 { Expression *key = (Expression *)keys->data[i]; | |
2898 Expression *value = (Expression *)values->data[i]; | |
2899 | |
2900 if (i) | |
2901 buf->writeByte(','); | |
2902 expToCBuffer(buf, hgs, key, PREC_assign); | |
2903 buf->writeByte(':'); | |
2904 expToCBuffer(buf, hgs, value, PREC_assign); | |
2905 } | |
2906 buf->writeByte(']'); | |
2907 } | |
2908 | |
2909 void AssocArrayLiteralExp::toMangleBuffer(OutBuffer *buf) | |
2910 { | |
2911 size_t dim = keys->dim; | |
2912 buf->printf("A%u", dim); | |
2913 for (size_t i = 0; i < dim; i++) | |
2914 { Expression *key = (Expression *)keys->data[i]; | |
2915 Expression *value = (Expression *)values->data[i]; | |
2916 | |
2917 key->toMangleBuffer(buf); | |
2918 value->toMangleBuffer(buf); | |
2919 } | |
2920 } | |
2921 | |
2922 /************************ StructLiteralExp ************************************/ | |
2923 | |
2924 // sd( e1, e2, e3, ... ) | |
2925 | |
2926 StructLiteralExp::StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *elements) | |
2927 : Expression(loc, TOKstructliteral, sizeof(StructLiteralExp)) | |
2928 { | |
2929 this->sd = sd; | |
2930 this->elements = elements; | |
2931 this->sym = NULL; | |
2932 this->soffset = 0; | |
2933 this->fillHoles = 1; | |
2934 } | |
2935 | |
2936 Expression *StructLiteralExp::syntaxCopy() | |
2937 { | |
2938 return new StructLiteralExp(loc, sd, arraySyntaxCopy(elements)); | |
2939 } | |
2940 | |
2941 Expression *StructLiteralExp::semantic(Scope *sc) | |
2942 { Expression *e; | |
2943 | |
2944 #if LOGSEMANTIC | |
2945 printf("StructLiteralExp::semantic('%s')\n", toChars()); | |
2946 #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
|
2947 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
|
2948 return this; |
159 | 2949 |
2950 // Run semantic() on each element | |
2951 for (size_t i = 0; i < elements->dim; i++) | |
2952 { e = (Expression *)elements->data[i]; | |
2953 if (!e) | |
2954 continue; | |
2955 e = e->semantic(sc); | |
2956 elements->data[i] = (void *)e; | |
2957 } | |
2958 expandTuples(elements); | |
2959 size_t offset = 0; | |
2960 for (size_t i = 0; i < elements->dim; i++) | |
2961 { e = (Expression *)elements->data[i]; | |
2962 if (!e) | |
2963 continue; | |
2964 | |
2965 if (!e->type) | |
2966 error("%s has no value", e->toChars()); | |
2967 e = resolveProperties(sc, e); | |
2968 if (i >= sd->fields.dim) | |
2969 { error("more initializers than fields of %s", sd->toChars()); | |
2970 break; | |
2971 } | |
2972 Dsymbol *s = (Dsymbol *)sd->fields.data[i]; | |
2973 VarDeclaration *v = s->isVarDeclaration(); | |
2974 assert(v); | |
2975 if (v->offset < offset) | |
2976 error("overlapping initialization for %s", v->toChars()); | |
2977 offset = v->offset + v->type->size(); | |
2978 | |
2979 Type *telem = v->type; | |
2980 while (!e->implicitConvTo(telem) && telem->toBasetype()->ty == Tsarray) | |
2981 { /* Static array initialization, as in: | |
2982 * T[3][5] = e; | |
2983 */ | |
2984 telem = telem->toBasetype()->nextOf(); | |
2985 } | |
2986 | |
2987 e = e->implicitCastTo(sc, telem); | |
2988 | |
2989 elements->data[i] = (void *)e; | |
2990 } | |
2991 | |
2992 /* Fill out remainder of elements[] with default initializers for fields[] | |
2993 */ | |
2994 for (size_t i = elements->dim; i < sd->fields.dim; i++) | |
2995 { Dsymbol *s = (Dsymbol *)sd->fields.data[i]; | |
2996 VarDeclaration *v = s->isVarDeclaration(); | |
2997 assert(v); | |
2998 | |
2999 if (v->offset < offset) | |
3000 { e = NULL; | |
3001 sd->hasUnions = 1; | |
3002 } | |
3003 else | |
3004 { | |
3005 if (v->init) | |
3006 { e = v->init->toExpression(); | |
3007 if (!e) | |
3008 error("cannot make expression out of initializer for %s", v->toChars()); | |
3009 } | |
3010 else | |
3011 { e = v->type->defaultInit(); | |
3012 e->loc = loc; | |
3013 } | |
3014 offset = v->offset + v->type->size(); | |
3015 } | |
3016 elements->push(e); | |
3017 } | |
3018 | |
3019 type = sd->type; | |
3020 return this; | |
3021 } | |
3022 | |
3023 /************************************** | |
3024 * Gets expression at offset of type. | |
3025 * Returns NULL if not found. | |
3026 */ | |
3027 | |
3028 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
|
3029 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
3030 //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
|
3031 // /*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
|
3032 Expression *e = NULL; |
159 | 3033 int i = getFieldIndex(type, offset); |
3034 | |
3035 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
|
3036 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
3037 //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
|
3038 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
|
3039 e = (Expression *)elements->data[i]; |
159 | 3040 if (e) |
3041 { | |
3042 e = e->copy(); | |
3043 e->type = type; | |
3044 } | |
3045 } | |
3046 return e; | |
3047 } | |
3048 | |
3049 /************************************ | |
3050 * Get index of field. | |
3051 * Returns -1 if not found. | |
3052 */ | |
3053 | |
3054 int StructLiteralExp::getFieldIndex(Type *type, unsigned offset) | |
3055 { | |
3056 /* Find which field offset is by looking at the field offsets | |
3057 */ | |
3058 for (size_t i = 0; i < sd->fields.dim; i++) | |
3059 { | |
3060 Dsymbol *s = (Dsymbol *)sd->fields.data[i]; | |
3061 VarDeclaration *v = s->isVarDeclaration(); | |
3062 assert(v); | |
3063 | |
3064 if (offset == v->offset && | |
3065 type->size() == v->type->size()) | |
3066 { Expression *e = (Expression *)elements->data[i]; | |
3067 if (e) | |
3068 { | |
3069 return i; | |
3070 } | |
3071 break; | |
3072 } | |
3073 } | |
3074 return -1; | |
3075 } | |
3076 | |
3077 | |
3078 Expression *StructLiteralExp::toLvalue(Scope *sc, Expression *e) | |
3079 { | |
3080 return this; | |
3081 } | |
3082 | |
3083 | |
3084 int StructLiteralExp::checkSideEffect(int flag) | |
3085 { int f = 0; | |
3086 | |
3087 for (size_t i = 0; i < elements->dim; i++) | |
3088 { Expression *e = (Expression *)elements->data[i]; | |
3089 if (!e) | |
3090 continue; | |
3091 | |
3092 f |= e->checkSideEffect(2); | |
3093 } | |
3094 if (flag == 0 && f == 0) | |
3095 Expression::checkSideEffect(0); | |
3096 return f; | |
3097 } | |
3098 | |
3099 void StructLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3100 { | |
3101 buf->writestring(sd->toChars()); | |
3102 buf->writeByte('('); | |
3103 argsToCBuffer(buf, elements, hgs); | |
3104 buf->writeByte(')'); | |
3105 } | |
3106 | |
3107 void StructLiteralExp::toMangleBuffer(OutBuffer *buf) | |
3108 { | |
3109 size_t dim = elements ? elements->dim : 0; | |
3110 buf->printf("S%u", dim); | |
3111 for (size_t i = 0; i < dim; i++) | |
3112 { Expression *e = (Expression *)elements->data[i]; | |
3113 if (e) | |
3114 e->toMangleBuffer(buf); | |
3115 else | |
3116 buf->writeByte('v'); // 'v' for void | |
3117 } | |
3118 } | |
3119 | |
3120 /************************ TypeDotIdExp ************************************/ | |
3121 | |
3122 /* Things like: | |
3123 * int.size | |
3124 * foo.size | |
3125 * (foo).size | |
3126 * cast(foo).size | |
3127 */ | |
3128 | |
3129 TypeDotIdExp::TypeDotIdExp(Loc loc, Type *type, Identifier *ident) | |
3130 : Expression(loc, TOKtypedot, sizeof(TypeDotIdExp)) | |
3131 { | |
3132 this->type = type; | |
3133 this->ident = ident; | |
3134 } | |
3135 | |
3136 Expression *TypeDotIdExp::syntaxCopy() | |
3137 { | |
3138 TypeDotIdExp *te = new TypeDotIdExp(loc, type->syntaxCopy(), ident); | |
3139 return te; | |
3140 } | |
3141 | |
3142 Expression *TypeDotIdExp::semantic(Scope *sc) | |
3143 { Expression *e; | |
3144 | |
3145 #if LOGSEMANTIC | |
3146 printf("TypeDotIdExp::semantic()\n"); | |
3147 #endif | |
3148 e = new DotIdExp(loc, new TypeExp(loc, type), ident); | |
3149 e = e->semantic(sc); | |
3150 return e; | |
3151 } | |
3152 | |
3153 void TypeDotIdExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3154 { | |
3155 buf->writeByte('('); | |
3156 type->toCBuffer(buf, NULL, hgs); | |
3157 buf->writeByte(')'); | |
3158 buf->writeByte('.'); | |
3159 buf->writestring(ident->toChars()); | |
3160 } | |
3161 | |
3162 /************************************************************/ | |
3163 | |
3164 // Mainly just a placeholder | |
3165 | |
3166 TypeExp::TypeExp(Loc loc, Type *type) | |
3167 : Expression(loc, TOKtype, sizeof(TypeExp)) | |
3168 { | |
3169 //printf("TypeExp::TypeExp(%s)\n", type->toChars()); | |
3170 this->type = type; | |
3171 } | |
3172 | |
3173 Expression *TypeExp::semantic(Scope *sc) | |
3174 { | |
3175 //printf("TypeExp::semantic(%s)\n", type->toChars()); | |
3176 type = type->semantic(loc, sc); | |
3177 return this; | |
3178 } | |
3179 | |
3180 void TypeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3181 { | |
3182 type->toCBuffer(buf, NULL, hgs); | |
3183 } | |
3184 | |
3185 /************************************************************/ | |
3186 | |
3187 // Mainly just a placeholder | |
3188 | |
3189 ScopeExp::ScopeExp(Loc loc, ScopeDsymbol *pkg) | |
3190 : Expression(loc, TOKimport, sizeof(ScopeExp)) | |
3191 { | |
3192 //printf("ScopeExp::ScopeExp(pkg = '%s')\n", pkg->toChars()); | |
3193 //static int count; if (++count == 38) *(char*)0=0; | |
3194 this->sds = pkg; | |
3195 } | |
3196 | |
3197 Expression *ScopeExp::syntaxCopy() | |
3198 { | |
3199 ScopeExp *se = new ScopeExp(loc, (ScopeDsymbol *)sds->syntaxCopy(NULL)); | |
3200 return se; | |
3201 } | |
3202 | |
3203 Expression *ScopeExp::semantic(Scope *sc) | |
3204 { | |
3205 TemplateInstance *ti; | |
3206 ScopeDsymbol *sds2; | |
3207 | |
3208 #if LOGSEMANTIC | |
3209 printf("+ScopeExp::semantic('%s')\n", toChars()); | |
3210 #endif | |
3211 Lagain: | |
3212 ti = sds->isTemplateInstance(); | |
3213 if (ti && !global.errors) | |
3214 { Dsymbol *s; | |
3215 if (!ti->semanticdone) | |
3216 ti->semantic(sc); | |
3217 s = ti->inst->toAlias(); | |
3218 sds2 = s->isScopeDsymbol(); | |
3219 if (!sds2) | |
3220 { Expression *e; | |
3221 | |
3222 //printf("s = %s, '%s'\n", s->kind(), s->toChars()); | |
3223 if (ti->withsym) | |
3224 { | |
3225 // Same as wthis.s | |
3226 e = new VarExp(loc, ti->withsym->withstate->wthis); | |
3227 e = new DotVarExp(loc, e, s->isDeclaration()); | |
3228 } | |
3229 else | |
3230 e = new DsymbolExp(loc, s); | |
3231 e = e->semantic(sc); | |
3232 //printf("-1ScopeExp::semantic()\n"); | |
3233 return e; | |
3234 } | |
3235 if (sds2 != sds) | |
3236 { | |
3237 sds = sds2; | |
3238 goto Lagain; | |
3239 } | |
3240 //printf("sds = %s, '%s'\n", sds->kind(), sds->toChars()); | |
3241 } | |
3242 else | |
3243 { | |
3244 //printf("sds = %s, '%s'\n", sds->kind(), sds->toChars()); | |
3245 //printf("\tparent = '%s'\n", sds->parent->toChars()); | |
3246 sds->semantic(sc); | |
3247 } | |
3248 type = Type::tvoid; | |
3249 //printf("-2ScopeExp::semantic() %s\n", toChars()); | |
3250 return this; | |
3251 } | |
3252 | |
3253 void ScopeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3254 { | |
3255 if (sds->isTemplateInstance()) | |
3256 { | |
3257 sds->toCBuffer(buf, hgs); | |
3258 } | |
3259 else | |
3260 { | |
3261 buf->writestring(sds->kind()); | |
3262 buf->writestring(" "); | |
3263 buf->writestring(sds->toChars()); | |
3264 } | |
3265 } | |
3266 | |
3267 /********************** TemplateExp **************************************/ | |
3268 | |
3269 // Mainly just a placeholder | |
3270 | |
3271 TemplateExp::TemplateExp(Loc loc, TemplateDeclaration *td) | |
3272 : Expression(loc, TOKtemplate, sizeof(TemplateExp)) | |
3273 { | |
3274 //printf("TemplateExp(): %s\n", td->toChars()); | |
3275 this->td = td; | |
3276 } | |
3277 | |
3278 void TemplateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3279 { | |
3280 buf->writestring(td->toChars()); | |
3281 } | |
3282 | |
3283 void TemplateExp::rvalue() | |
3284 { | |
3285 error("template %s has no value", toChars()); | |
3286 } | |
3287 | |
3288 /********************** NewExp **************************************/ | |
3289 | |
3290 NewExp::NewExp(Loc loc, Expression *thisexp, Expressions *newargs, | |
3291 Type *newtype, Expressions *arguments) | |
3292 : Expression(loc, TOKnew, sizeof(NewExp)) | |
3293 { | |
3294 this->thisexp = thisexp; | |
3295 this->newargs = newargs; | |
3296 this->newtype = newtype; | |
3297 this->arguments = arguments; | |
3298 member = NULL; | |
3299 allocator = NULL; | |
3300 onstack = 0; | |
3301 } | |
3302 | |
3303 Expression *NewExp::syntaxCopy() | |
3304 { | |
3305 return new NewExp(loc, | |
3306 thisexp ? thisexp->syntaxCopy() : NULL, | |
3307 arraySyntaxCopy(newargs), | |
3308 newtype->syntaxCopy(), arraySyntaxCopy(arguments)); | |
3309 } | |
3310 | |
3311 | |
3312 Expression *NewExp::semantic(Scope *sc) | |
3313 { int i; | |
3314 Type *tb; | |
3315 ClassDeclaration *cdthis = NULL; | |
3316 | |
3317 #if LOGSEMANTIC | |
3318 printf("NewExp::semantic() %s\n", toChars()); | |
3319 if (thisexp) | |
3320 printf("\tthisexp = %s\n", thisexp->toChars()); | |
3321 printf("\tnewtype: %s\n", newtype->toChars()); | |
3322 #endif | |
3323 if (type) // if semantic() already run | |
3324 return this; | |
3325 | |
3326 Lagain: | |
3327 if (thisexp) | |
3328 { thisexp = thisexp->semantic(sc); | |
3329 cdthis = thisexp->type->isClassHandle(); | |
3330 if (cdthis) | |
3331 { | |
3332 sc = sc->push(cdthis); | |
3333 type = newtype->semantic(loc, sc); | |
3334 sc = sc->pop(); | |
3335 } | |
3336 else | |
3337 { | |
3338 error("'this' for nested class must be a class type, not %s", thisexp->type->toChars()); | |
3339 type = newtype->semantic(loc, sc); | |
3340 } | |
3341 } | |
3342 else | |
3343 type = newtype->semantic(loc, sc); | |
3344 newtype = type; // in case type gets cast to something else | |
3345 tb = type->toBasetype(); | |
3346 //printf("tb: %s, deco = %s\n", tb->toChars(), tb->deco); | |
3347 | |
3348 arrayExpressionSemantic(newargs, sc); | |
3349 preFunctionArguments(loc, sc, newargs); | |
3350 arrayExpressionSemantic(arguments, sc); | |
3351 preFunctionArguments(loc, sc, arguments); | |
3352 | |
3353 if (thisexp && tb->ty != Tclass) | |
3354 error("e.new is only for allocating nested classes, not %s", tb->toChars()); | |
3355 | |
3356 if (tb->ty == Tclass) | |
3357 { TypeFunction *tf; | |
3358 | |
3359 TypeClass *tc = (TypeClass *)(tb); | |
3360 ClassDeclaration *cd = tc->sym->isClassDeclaration(); | |
3361 if (cd->isInterfaceDeclaration()) | |
3362 error("cannot create instance of interface %s", cd->toChars()); | |
3363 else if (cd->isAbstract()) | |
3364 { error("cannot create instance of abstract class %s", cd->toChars()); | |
3365 for (int i = 0; i < cd->vtbl.dim; i++) | |
3366 { FuncDeclaration *fd = ((Dsymbol *)cd->vtbl.data[i])->isFuncDeclaration(); | |
3367 if (fd && fd->isAbstract()) | |
3368 error("function %s is abstract", fd->toChars()); | |
3369 } | |
3370 } | |
3371 checkDeprecated(sc, cd); | |
3372 if (cd->isNested()) | |
3373 { /* We need a 'this' pointer for the nested class. | |
3374 * Ensure we have the right one. | |
3375 */ | |
3376 Dsymbol *s = cd->toParent2(); | |
3377 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
|
3378 FuncDeclaration *fdn = s->isFuncDeclaration(); |
159 | 3379 |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
3380 //printf("cd isNested, cdn = %s\n", cdn ? cdn->toChars() : "null"); |
159 | 3381 if (cdn) |
3382 { | |
3383 if (!cdthis) | |
3384 { | |
3385 // Supply an implicit 'this' and try again | |
3386 thisexp = new ThisExp(loc); | |
3387 for (Dsymbol *sp = sc->parent; 1; sp = sp->parent) | |
3388 { if (!sp) | |
3389 { | |
3390 error("outer class %s 'this' needed to 'new' nested class %s", cdn->toChars(), cd->toChars()); | |
3391 break; | |
3392 } | |
3393 ClassDeclaration *cdp = sp->isClassDeclaration(); | |
3394 if (!cdp) | |
3395 continue; | |
3396 if (cdp == cdn || cdn->isBaseOf(cdp, NULL)) | |
3397 break; | |
3398 // Add a '.outer' and try again | |
3399 thisexp = new DotIdExp(loc, thisexp, Id::outer); | |
3400 } | |
3401 if (!global.errors) | |
3402 goto Lagain; | |
3403 } | |
3404 if (cdthis) | |
3405 { | |
3406 //printf("cdthis = %s\n", cdthis->toChars()); | |
3407 if (cdthis != cdn && !cdn->isBaseOf(cdthis, NULL)) | |
3408 error("'this' for nested class must be of type %s, not %s", cdn->toChars(), thisexp->type->toChars()); | |
3409 } | |
3410 #if 0 | |
3411 else | |
3412 { | |
3413 for (Dsymbol *sf = sc->func; 1; sf= sf->toParent2()->isFuncDeclaration()) | |
3414 { | |
3415 if (!sf) | |
3416 { | |
3417 error("outer class %s 'this' needed to 'new' nested class %s", cdn->toChars(), cd->toChars()); | |
3418 break; | |
3419 } | |
3420 printf("sf = %s\n", sf->toChars()); | |
3421 AggregateDeclaration *ad = sf->isThis(); | |
3422 if (ad && (ad == cdn || cdn->isBaseOf(ad->isClassDeclaration(), NULL))) | |
3423 break; | |
3424 } | |
3425 } | |
3426 #endif | |
3427 } | |
3428 else if (thisexp) | |
3429 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
|
3430 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
|
3431 { |
8aebdf56c455
Move check for access of context for nested class from backend into frontend.
Christian Kamm <kamm incasoftware de>
parents:
599
diff
changeset
|
3432 // 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
|
3433 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
|
3434 { |
8aebdf56c455
Move check for access of context for nested class from backend into frontend.
Christian Kamm <kamm incasoftware de>
parents:
599
diff
changeset
|
3435 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
|
3436 break; |
8aebdf56c455
Move check for access of context for nested class from backend into frontend.
Christian Kamm <kamm incasoftware de>
parents:
599
diff
changeset
|
3437 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
|
3438 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
|
3439 { |
8aebdf56c455
Move check for access of context for nested class from backend into frontend.
Christian Kamm <kamm incasoftware de>
parents:
599
diff
changeset
|
3440 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
|
3441 break; |
8aebdf56c455
Move check for access of context for nested class from backend into frontend.
Christian Kamm <kamm incasoftware de>
parents:
599
diff
changeset
|
3442 } |
8aebdf56c455
Move check for access of context for nested class from backend into frontend.
Christian Kamm <kamm incasoftware de>
parents:
599
diff
changeset
|
3443 } |
8aebdf56c455
Move check for access of context for nested class from backend into frontend.
Christian Kamm <kamm incasoftware de>
parents:
599
diff
changeset
|
3444 |
8aebdf56c455
Move check for access of context for nested class from backend into frontend.
Christian Kamm <kamm incasoftware de>
parents:
599
diff
changeset
|
3445 } |
159 | 3446 } |
3447 else if (thisexp) | |
3448 error("e.new is only for allocating nested classes"); | |
3449 | |
3450 FuncDeclaration *f = cd->ctor; | |
3451 if (f) | |
3452 { | |
3453 assert(f); | |
3454 f = f->overloadResolve(loc, arguments); | |
3455 checkDeprecated(sc, f); | |
3456 member = f->isCtorDeclaration(); | |
3457 assert(member); | |
3458 | |
3459 cd->accessCheck(loc, sc, member); | |
3460 | |
3461 tf = (TypeFunction *)f->type; | |
3462 type = tf->next; | |
3463 | |
3464 if (!arguments) | |
3465 arguments = new Expressions(); | |
3466 functionArguments(loc, sc, tf, arguments); | |
3467 } | |
3468 else | |
3469 { | |
3470 if (arguments && arguments->dim) | |
3471 error("no constructor for %s", cd->toChars()); | |
3472 } | |
3473 | |
3474 if (cd->aggNew) | |
3475 { Expression *e; | |
3476 | |
3477 f = cd->aggNew; | |
3478 | |
3479 // Prepend the uint size argument to newargs[] | |
3480 e = new IntegerExp(loc, cd->size(loc), Type::tuns32); | |
3481 if (!newargs) | |
3482 newargs = new Expressions(); | |
3483 newargs->shift(e); | |
3484 | |
3485 f = f->overloadResolve(loc, newargs); | |
3486 allocator = f->isNewDeclaration(); | |
3487 assert(allocator); | |
3488 | |
3489 tf = (TypeFunction *)f->type; | |
3490 functionArguments(loc, sc, tf, newargs); | |
3491 } | |
3492 else | |
3493 { | |
3494 if (newargs && newargs->dim) | |
3495 error("no allocator for %s", cd->toChars()); | |
3496 } | |
3497 | |
3498 } | |
3499 else if (tb->ty == Tstruct) | |
3500 { | |
3501 TypeStruct *ts = (TypeStruct *)tb; | |
3502 StructDeclaration *sd = ts->sym; | |
3503 FuncDeclaration *f = sd->aggNew; | |
3504 TypeFunction *tf; | |
3505 | |
3506 if (arguments && arguments->dim) | |
3507 error("no constructor for %s", type->toChars()); | |
3508 | |
3509 if (f) | |
3510 { | |
3511 Expression *e; | |
3512 | |
3513 // Prepend the uint size argument to newargs[] | |
3514 e = new IntegerExp(loc, sd->size(loc), Type::tuns32); | |
3515 if (!newargs) | |
3516 newargs = new Expressions(); | |
3517 newargs->shift(e); | |
3518 | |
3519 f = f->overloadResolve(loc, newargs); | |
3520 allocator = f->isNewDeclaration(); | |
3521 assert(allocator); | |
3522 | |
3523 tf = (TypeFunction *)f->type; | |
3524 functionArguments(loc, sc, tf, newargs); | |
3525 | |
3526 e = new VarExp(loc, f); | |
3527 e = new CallExp(loc, e, newargs); | |
3528 e = e->semantic(sc); | |
3529 e->type = type->pointerTo(); | |
3530 return e; | |
3531 } | |
3532 | |
3533 type = type->pointerTo(); | |
3534 } | |
3535 else if (tb->ty == Tarray && (arguments && arguments->dim)) | |
3536 { | |
3537 for (size_t i = 0; i < arguments->dim; i++) | |
3538 { | |
3539 if (tb->ty != Tarray) | |
3540 { error("too many arguments for array"); | |
3541 arguments->dim = i; | |
3542 break; | |
3543 } | |
3544 | |
3545 Expression *arg = (Expression *)arguments->data[i]; | |
3546 arg = resolveProperties(sc, arg); | |
3547 arg = arg->implicitCastTo(sc, Type::tsize_t); | |
3548 if (arg->op == TOKint64 && (long long)arg->toInteger() < 0) | |
3549 error("negative array index %s", arg->toChars()); | |
3550 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
|
3551 tb = ((TypeDArray *)tb)->next->toBasetype(); |
159 | 3552 } |
3553 } | |
3554 else if (tb->isscalar()) | |
3555 { | |
3556 if (arguments && arguments->dim) | |
3557 error("no constructor for %s", type->toChars()); | |
3558 | |
3559 type = type->pointerTo(); | |
3560 } | |
3561 else | |
3562 { | |
3563 error("new can only create structs, dynamic arrays or class objects, not %s's", type->toChars()); | |
3564 type = type->pointerTo(); | |
3565 } | |
3566 | |
3567 //printf("NewExp: '%s'\n", toChars()); | |
3568 //printf("NewExp:type '%s'\n", type->toChars()); | |
3569 | |
3570 return this; | |
3571 } | |
3572 | |
3573 int NewExp::checkSideEffect(int flag) | |
3574 { | |
3575 return 1; | |
3576 } | |
3577 | |
3578 void NewExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3579 { int i; | |
3580 | |
3581 if (thisexp) | |
3582 { expToCBuffer(buf, hgs, thisexp, PREC_primary); | |
3583 buf->writeByte('.'); | |
3584 } | |
3585 buf->writestring("new "); | |
3586 if (newargs && newargs->dim) | |
3587 { | |
3588 buf->writeByte('('); | |
3589 argsToCBuffer(buf, newargs, hgs); | |
3590 buf->writeByte(')'); | |
3591 } | |
3592 newtype->toCBuffer(buf, NULL, hgs); | |
3593 if (arguments && arguments->dim) | |
3594 { | |
3595 buf->writeByte('('); | |
3596 argsToCBuffer(buf, arguments, hgs); | |
3597 buf->writeByte(')'); | |
3598 } | |
3599 } | |
3600 | |
3601 /********************** NewAnonClassExp **************************************/ | |
3602 | |
3603 NewAnonClassExp::NewAnonClassExp(Loc loc, Expression *thisexp, | |
3604 Expressions *newargs, ClassDeclaration *cd, Expressions *arguments) | |
3605 : Expression(loc, TOKnewanonclass, sizeof(NewAnonClassExp)) | |
3606 { | |
3607 this->thisexp = thisexp; | |
3608 this->newargs = newargs; | |
3609 this->cd = cd; | |
3610 this->arguments = arguments; | |
3611 } | |
3612 | |
3613 Expression *NewAnonClassExp::syntaxCopy() | |
3614 { | |
3615 return new NewAnonClassExp(loc, | |
3616 thisexp ? thisexp->syntaxCopy() : NULL, | |
3617 arraySyntaxCopy(newargs), | |
3618 (ClassDeclaration *)cd->syntaxCopy(NULL), | |
3619 arraySyntaxCopy(arguments)); | |
3620 } | |
3621 | |
3622 | |
3623 Expression *NewAnonClassExp::semantic(Scope *sc) | |
3624 { | |
3625 #if LOGSEMANTIC | |
3626 printf("NewAnonClassExp::semantic() %s\n", toChars()); | |
336 | 3627 //printf("thisexp = %p\n", thisexp); |
159 | 3628 //printf("type: %s\n", type->toChars()); |
3629 #endif | |
3630 | |
3631 Expression *d = new DeclarationExp(loc, cd); | |
3632 d = d->semantic(sc); | |
3633 | |
3634 Expression *n = new NewExp(loc, thisexp, newargs, cd->type, arguments); | |
3635 | |
3636 Expression *c = new CommaExp(loc, d, n); | |
3637 return c->semantic(sc); | |
3638 } | |
3639 | |
3640 int NewAnonClassExp::checkSideEffect(int flag) | |
3641 { | |
3642 return 1; | |
3643 } | |
3644 | |
3645 void NewAnonClassExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3646 { int i; | |
3647 | |
3648 if (thisexp) | |
3649 { expToCBuffer(buf, hgs, thisexp, PREC_primary); | |
3650 buf->writeByte('.'); | |
3651 } | |
3652 buf->writestring("new"); | |
3653 if (newargs && newargs->dim) | |
3654 { | |
3655 buf->writeByte('('); | |
3656 argsToCBuffer(buf, newargs, hgs); | |
3657 buf->writeByte(')'); | |
3658 } | |
3659 buf->writestring(" class "); | |
3660 if (arguments && arguments->dim) | |
3661 { | |
3662 buf->writeByte('('); | |
3663 argsToCBuffer(buf, arguments, hgs); | |
3664 buf->writeByte(')'); | |
3665 } | |
3666 //buf->writestring(" { }"); | |
3667 if (cd) | |
3668 { | |
3669 cd->toCBuffer(buf, hgs); | |
3670 } | |
3671 } | |
3672 | |
3673 /********************** SymOffExp **************************************/ | |
3674 | |
3675 SymOffExp::SymOffExp(Loc loc, Declaration *var, unsigned offset) | |
3676 : Expression(loc, TOKsymoff, sizeof(SymOffExp)) | |
3677 { | |
3678 assert(var); | |
3679 this->var = var; | |
3680 this->offset = offset; | |
3681 VarDeclaration *v = var->isVarDeclaration(); | |
3682 if (v && v->needThis()) | |
3683 error("need 'this' for address of %s", v->toChars()); | |
3684 } | |
3685 | |
3686 Expression *SymOffExp::semantic(Scope *sc) | |
3687 { | |
3688 #if LOGSEMANTIC | |
3689 printf("SymOffExp::semantic('%s')\n", toChars()); | |
3690 #endif | |
3691 //var->semantic(sc); | |
3692 if (!type) | |
3693 type = var->type->pointerTo(); | |
3694 VarDeclaration *v = var->isVarDeclaration(); | |
3695 if (v) | |
3696 { | |
3697 v->checkNestedReference(sc, loc); | |
3698 } | |
3699 return this; | |
3700 } | |
3701 | |
3702 int SymOffExp::isBool(int result) | |
3703 { | |
3704 return result ? TRUE : FALSE; | |
3705 } | |
3706 | |
3707 void SymOffExp::checkEscape() | |
3708 { | |
3709 VarDeclaration *v = var->isVarDeclaration(); | |
3710 if (v) | |
3711 { | |
3712 if (!v->isDataseg()) | |
3713 error("escaping reference to local variable %s", v->toChars()); | |
3714 } | |
3715 } | |
3716 | |
3717 void SymOffExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3718 { | |
3719 if (offset) | |
3720 buf->printf("(& %s+%u)", var->toChars(), offset); | |
3721 else | |
3722 buf->printf("& %s", var->toChars()); | |
3723 } | |
3724 | |
3725 /******************************** VarExp **************************/ | |
3726 | |
3727 VarExp::VarExp(Loc loc, Declaration *var) | |
3728 : Expression(loc, TOKvar, sizeof(VarExp)) | |
3729 { | |
3730 //printf("VarExp(this = %p, '%s')\n", this, var->toChars()); | |
3731 this->var = var; | |
3732 this->type = var->type; | |
3733 } | |
3734 | |
3735 int VarExp::equals(Object *o) | |
3736 { VarExp *ne; | |
3737 | |
3738 if (this == o || | |
3739 (((Expression *)o)->op == TOKvar && | |
3740 ((ne = (VarExp *)o), type->equals(ne->type)) && | |
3741 var == ne->var)) | |
3742 return 1; | |
3743 return 0; | |
3744 } | |
3745 | |
3746 Expression *VarExp::semantic(Scope *sc) | |
3747 { FuncLiteralDeclaration *fd; | |
3748 | |
3749 #if LOGSEMANTIC | |
3750 printf("VarExp::semantic(%s)\n", toChars()); | |
3751 #endif | |
3752 if (!type) | |
3753 { type = var->type; | |
3754 #if 0 | |
3755 if (var->storage_class & STClazy) | |
3756 { | |
3757 TypeFunction *tf = new TypeFunction(NULL, type, 0, LINKd); | |
3758 type = new TypeDelegate(tf); | |
3759 type = type->semantic(loc, sc); | |
3760 } | |
3761 #endif | |
3762 } | |
3763 | |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
639
diff
changeset
|
3764 // LDC: Fixes bug 1161, http://d.puremagic.com/issues/show_bug.cgi?id=1161 |
163
a8cd9bc1021a
[svn r179] lots and lots of fixes, much more of tango now compiles/works.
lindquist
parents:
159
diff
changeset
|
3765 // check access to VarDeclaration |
a8cd9bc1021a
[svn r179] lots and lots of fixes, much more of tango now compiles/works.
lindquist
parents:
159
diff
changeset
|
3766 accessCheck(loc, sc, NULL, var); |
a8cd9bc1021a
[svn r179] lots and lots of fixes, much more of tango now compiles/works.
lindquist
parents:
159
diff
changeset
|
3767 |
159 | 3768 VarDeclaration *v = var->isVarDeclaration(); |
3769 if (v) | |
3770 { | |
3771 if (v->isConst() && type->toBasetype()->ty != Tsarray && v->init) | |
3772 { | |
3773 ExpInitializer *ei = v->init->isExpInitializer(); | |
3774 if (ei) | |
3775 { | |
3776 //ei->exp->implicitCastTo(sc, type)->print(); | |
3777 return ei->exp->implicitCastTo(sc, type); | |
3778 } | |
3779 } | |
3780 v->checkNestedReference(sc, loc); | |
3781 } | |
3782 #if 0 | |
3783 else if ((fd = var->isFuncLiteralDeclaration()) != NULL) | |
3784 { Expression *e; | |
3785 e = new FuncExp(loc, fd); | |
3786 e->type = type; | |
3787 return e; | |
3788 } | |
3789 #endif | |
3790 return this; | |
3791 } | |
3792 | |
3793 char *VarExp::toChars() | |
3794 { | |
3795 return var->toChars(); | |
3796 } | |
3797 | |
3798 void VarExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
3799 { | |
3800 buf->writestring(var->toChars()); | |
3801 } | |
3802 | |
3803 void VarExp::checkEscape() | |
3804 { | |
3805 VarDeclaration *v = var->isVarDeclaration(); | |
3806 if (v) | |
3807 { Type *tb = v->type->toBasetype(); | |
3808 // if reference type | |
3809 if (tb->ty == Tarray || tb->ty == Tsarray || tb->ty == Tclass) | |
3810 { | |
3811 if ((v->isAuto() || v->isScope()) && !v->noauto) | |
3812 error("escaping reference to auto local %s", v->toChars()); | |
3813 else if (v->storage_class & STCvariadic) | |
3814 error("escaping reference to variadic parameter %s", v->toChars()); | |
3815 } | |
3816 } | |
3817 } | |
3818 | |
3819 Expression *VarExp::toLvalue(Scope *sc, Expression *e) | |
3820 { | |
3821 #if 0 | |
3822 tym = tybasic(e1->ET->Tty); | |
3823 if (!(tyscalar(tym) || | |
3824 tym == TYstruct || | |
3825 tym == TYarray && e->Eoper == TOKaddr)) | |
3826 synerr(EM_lvalue); // lvalue expected | |
3827 #endif | |
3828 if (var->storage_class & STClazy) | |
3829 error("lazy variables cannot be lvalues"); | |
3830 return this; | |
3831 } | |
3832 | |
3833 Expression *VarExp::modifiableLvalue(Scope *sc, Expression *e) | |
3834 { | |
3835 //printf("VarExp::modifiableLvalue('%s')\n", var->toChars()); | |
3836 if (sc->incontract && var->isParameter()) | |
3837 error("cannot modify parameter '%s' in contract", var->toChars()); | |
3838 | |
3839 if (type && type->toBasetype()->ty == Tsarray) | |
3840 error("cannot change reference to static array '%s'", var->toChars()); | |
3841 | |
3842 VarDeclaration *v = var->isVarDeclaration(); | |
3843 if (v && v->canassign == 0 && | |
3844 (var->isConst() || (global.params.Dversion > 1 && var->isFinal()))) | |
3845 error("cannot modify final variable '%s'", var->toChars()); | |
3846 | |
3847 if (var->isCtorinit()) | |
3848 { // It's only modifiable if inside the right constructor | |
3849 Dsymbol *s = sc->func; | |
3850 while (1) | |
3851 { | |
3852 FuncDeclaration *fd = NULL; | |
3853 if (s) | |
3854 fd = s->isFuncDeclaration(); | |
3855 if (fd && | |
3856 ((fd->isCtorDeclaration() && var->storage_class & STCfield) || | |
3857 (fd->isStaticCtorDeclaration() && !(var->storage_class & STCfield))) && | |
3858 fd->toParent() == var->toParent() | |
3859 ) | |
3860 { | |
3861 VarDeclaration *v = var->isVarDeclaration(); | |
3862 assert(v); | |
3863 v->ctorinit = 1; | |
3864 //printf("setting ctorinit\n"); | |
3865 } | |
3866 else | |
3867 { | |
3868 if (s) | |
3869 { s = s->toParent2(); | |
3870 continue; | |
3871 } | |
3872 else | |
3873 { | |
3874 const char *p = var->isStatic() ? "static " : ""; | |
3875 error("can only initialize %sconst %s inside %sconstructor", | |
3876 p, var->toChars(), p); | |
3877 } | |
3878 } | |
3879 break; | |
3880 } | |
3881 } | |
3882 | |
3883 // See if this expression is a modifiable lvalue (i.e. not const) | |
3884 return toLvalue(sc, e); | |
3885 } | |
3886 | |
3887 | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
3888 /******************************** OverExp **************************/ |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
3889 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
3890 #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
|
3891 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
|
3892 : 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
|
3893 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
3894 //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
|
3895 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
|
3896 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
|
3897 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
3898 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
3899 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
|
3900 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
3901 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
|
3902 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
3903 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
3904 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
|
3905 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
3906 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
|
3907 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
3908 #endif |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
3909 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
3910 |
159 | 3911 /******************************** TupleExp **************************/ |
3912 | |
3913 TupleExp::TupleExp(Loc loc, Expressions *exps) | |
3914 : Expression(loc, TOKtuple, sizeof(TupleExp)) | |
3915 { | |
3916 //printf("TupleExp(this = %p)\n", this); | |
3917 this->exps = exps; | |
3918 this->type = NULL; | |
3919 } | |
3920 | |
3921 | |
3922 TupleExp::TupleExp(Loc loc, TupleDeclaration *tup) | |
3923 : Expression(loc, TOKtuple, sizeof(TupleExp)) | |
3924 { | |
3925 exps = new Expressions(); | |
3926 type = NULL; | |
3927 | |
3928 exps->reserve(tup->objects->dim); | |
3929 for (size_t i = 0; i < tup->objects->dim; i++) | |
3930 { Object *o = (Object *)tup->objects->data[i]; | |
3931 if (o->dyncast() == DYNCAST_EXPRESSION) | |
3932 { | |
3933 Expression *e = (Expression *)o; | |
3934 e = e->syntaxCopy(); | |
3935 exps->push(e); | |
3936 } | |
3937 else if (o->dyncast() == DYNCAST_DSYMBOL) | |
3938 { | |
3939 Dsymbol *s = (Dsymbol *)o; | |
3940 Expression *e = new DsymbolExp(loc, s); | |
3941 exps->push(e); | |
3942 } | |
3943 else if (o->dyncast() == DYNCAST_TYPE) | |
3944 { | |
3945 Type *t = (Type *)o; | |
3946 Expression *e = new TypeExp(loc, t); | |
3947 exps->push(e); | |
3948 } | |
3949 else | |
3950 { | |
3951 error("%s is not an expression", o->toChars()); | |
3952 } | |
3953 } | |
3954 } | |
3955 | |
3956 int TupleExp::equals(Object *o) | |
3957 { TupleExp *ne; | |
3958 | |
3959 if (this == o) | |
3960 return 1; | |
3961 if (((Expression *)o)->op == TOKtuple) | |
3962 { | |
3963 TupleExp *te = (TupleExp *)o; | |
3964 if (exps->dim != te->exps->dim) | |
3965 return 0; | |
3966 for (size_t i = 0; i < exps->dim; i++) | |
3967 { Expression *e1 = (Expression *)exps->data[i]; | |
3968 Expression *e2 = (Expression *)te->exps->data[i]; | |
3969 | |
3970 if (!e1->equals(e2)) | |
3971 return 0; | |
3972 } | |
3973 return 1; | |
3974 } | |
3975 return 0; | |
3976 } | |
3977 | |
3978 Expression *TupleExp::syntaxCopy() | |
3979 { | |
3980 return new TupleExp(loc, arraySyntaxCopy(exps)); | |
3981 } | |
3982 | |
3983 Expression *TupleExp::semantic(Scope *sc) | |
3984 { | |
3985 #if LOGSEMANTIC | |
3986 printf("+TupleExp::semantic(%s)\n", toChars()); | |
3987 #endif | |
3988 if (type) | |
3989 return this; | |
3990 | |
3991 // Run semantic() on each argument | |
3992 for (size_t i = 0; i < exps->dim; i++) | |
3993 { Expression *e = (Expression *)exps->data[i]; | |
3994 | |
3995 e = e->semantic(sc); | |
3996 if (!e->type) | |
3997 { error("%s has no value", e->toChars()); | |
3998 e->type = Type::terror; | |
3999 } | |
4000 exps->data[i] = (void *)e; | |
4001 } | |
4002 | |
4003 expandTuples(exps); | |
4004 if (0 && exps->dim == 1) | |
4005 { | |
4006 return (Expression *)exps->data[0]; | |
4007 } | |
4008 type = new TypeTuple(exps); | |
4009 //printf("-TupleExp::semantic(%s)\n", toChars()); | |
4010 return this; | |
4011 } | |
4012 | |
4013 void TupleExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
4014 { | |
4015 buf->writestring("tuple("); | |
4016 argsToCBuffer(buf, exps, hgs); | |
4017 buf->writeByte(')'); | |
4018 } | |
4019 | |
4020 int TupleExp::checkSideEffect(int flag) | |
4021 { int f = 0; | |
4022 | |
4023 for (int i = 0; i < exps->dim; i++) | |
4024 { Expression *e = (Expression *)exps->data[i]; | |
4025 | |
4026 f |= e->checkSideEffect(2); | |
4027 } | |
4028 if (flag == 0 && f == 0) | |
4029 Expression::checkSideEffect(0); | |
4030 return f; | |
4031 } | |
4032 | |
4033 void TupleExp::checkEscape() | |
4034 { | |
4035 for (size_t i = 0; i < exps->dim; i++) | |
4036 { Expression *e = (Expression *)exps->data[i]; | |
4037 e->checkEscape(); | |
4038 } | |
4039 } | |
4040 | |
4041 /******************************** FuncExp *********************************/ | |
4042 | |
4043 FuncExp::FuncExp(Loc loc, FuncLiteralDeclaration *fd) | |
4044 : Expression(loc, TOKfunction, sizeof(FuncExp)) | |
4045 { | |
4046 this->fd = fd; | |
4047 } | |
4048 | |
4049 Expression *FuncExp::syntaxCopy() | |
4050 { | |
4051 return new FuncExp(loc, (FuncLiteralDeclaration *)fd->syntaxCopy(NULL)); | |
4052 } | |
4053 | |
4054 Expression *FuncExp::semantic(Scope *sc) | |
4055 { | |
4056 #if LOGSEMANTIC | |
4057 printf("FuncExp::semantic(%s)\n", toChars()); | |
4058 #endif | |
4059 if (!type) | |
4060 { | |
4061 fd->semantic(sc); | |
4062 fd->parent = sc->parent; | |
4063 if (global.errors) | |
4064 { | |
4065 if (!fd->type->next) | |
4066 fd->type->next = Type::terror; | |
4067 } | |
4068 else | |
4069 { | |
4070 fd->semantic2(sc); | |
4071 if (!global.errors) | |
4072 { | |
4073 fd->semantic3(sc); | |
4074 | |
4075 if (!global.errors && global.params.useInline) | |
4076 fd->inlineScan(); | |
4077 } | |
4078 } | |
4079 | |
4080 // Type is a "delegate to" or "pointer to" the function literal | |
4081 if (fd->isNested()) | |
4082 { | |
4083 type = new TypeDelegate(fd->type); | |
4084 type = type->semantic(loc, sc); | |
4085 } | |
4086 else | |
4087 { | |
4088 type = fd->type->pointerTo(); | |
4089 } | |
4090 } | |
4091 return this; | |
4092 } | |
4093 | |
4094 char *FuncExp::toChars() | |
4095 { | |
4096 return fd->toChars(); | |
4097 } | |
4098 | |
4099 void FuncExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
4100 { | |
4101 buf->writestring(fd->toChars()); | |
4102 } | |
4103 | |
4104 | |
4105 /******************************** DeclarationExp **************************/ | |
4106 | |
4107 DeclarationExp::DeclarationExp(Loc loc, Dsymbol *declaration) | |
4108 : Expression(loc, TOKdeclaration, sizeof(DeclarationExp)) | |
4109 { | |
4110 this->declaration = declaration; | |
4111 } | |
4112 | |
4113 Expression *DeclarationExp::syntaxCopy() | |
4114 { | |
4115 return new DeclarationExp(loc, declaration->syntaxCopy(NULL)); | |
4116 } | |
4117 | |
4118 Expression *DeclarationExp::semantic(Scope *sc) | |
4119 { | |
4120 if (type) | |
4121 return this; | |
4122 | |
4123 #if LOGSEMANTIC | |
4124 printf("DeclarationExp::semantic() %s\n", toChars()); | |
4125 #endif | |
4126 | |
4127 /* This is here to support extern(linkage) declaration, | |
4128 * where the extern(linkage) winds up being an AttribDeclaration | |
4129 * wrapper. | |
4130 */ | |
4131 Dsymbol *s = declaration; | |
4132 | |
4133 AttribDeclaration *ad = declaration->isAttribDeclaration(); | |
4134 if (ad) | |
4135 { | |
4136 if (ad->decl && ad->decl->dim == 1) | |
4137 s = (Dsymbol *)ad->decl->data[0]; | |
4138 } | |
4139 | |
4140 if (s->isVarDeclaration()) | |
4141 { // Do semantic() on initializer first, so: | |
4142 // int a = a; | |
4143 // will be illegal. | |
4144 declaration->semantic(sc); | |
4145 s->parent = sc->parent; | |
4146 } | |
4147 | |
4148 //printf("inserting '%s' %p into sc = %p\n", s->toChars(), s, sc); | |
4149 // Insert into both local scope and function scope. | |
4150 // Must be unique in both. | |
4151 if (s->ident) | |
4152 { | |
4153 if (!sc->insert(s)) | |
4154 error("declaration %s is already defined", s->toPrettyChars()); | |
4155 else if (sc->func) | |
4156 { VarDeclaration *v = s->isVarDeclaration(); | |
4157 if ((s->isFuncDeclaration() /*|| v && v->storage_class & STCstatic*/) && | |
4158 !sc->func->localsymtab->insert(s)) | |
4159 error("declaration %s is already defined in another scope in %s", s->toPrettyChars(), sc->func->toChars()); | |
4160 else if (!global.params.useDeprecated) | |
4161 { // Disallow shadowing | |
4162 | |
4163 for (Scope *scx = sc->enclosing; scx && scx->func == sc->func; scx = scx->enclosing) | |
4164 { Dsymbol *s2; | |
4165 | |
4166 if (scx->scopesym && scx->scopesym->symtab && | |
4167 (s2 = scx->scopesym->symtab->lookup(s->ident)) != NULL && | |
4168 s != s2) | |
4169 { | |
4170 error("shadowing declaration %s is deprecated", s->toPrettyChars()); | |
4171 } | |
4172 } | |
4173 } | |
4174 } | |
4175 } | |
4176 if (!s->isVarDeclaration()) | |
4177 { | |
4178 declaration->semantic(sc); | |
4179 s->parent = sc->parent; | |
4180 } | |
4181 if (!global.errors) | |
4182 { | |
4183 declaration->semantic2(sc); | |
4184 if (!global.errors) | |
4185 { | |
4186 declaration->semantic3(sc); | |
4187 | |
4188 if (!global.errors && global.params.useInline) | |
4189 declaration->inlineScan(); | |
4190 } | |
4191 } | |
4192 | |
4193 type = Type::tvoid; | |
4194 return this; | |
4195 } | |
4196 | |
4197 int DeclarationExp::checkSideEffect(int flag) | |
4198 { | |
4199 return 1; | |
4200 } | |
4201 | |
4202 void DeclarationExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
4203 { | |
4204 declaration->toCBuffer(buf, hgs); | |
4205 } | |
4206 | |
4207 | |
4208 /************************ TypeidExp ************************************/ | |
4209 | |
4210 /* | |
4211 * typeid(int) | |
4212 */ | |
4213 | |
4214 TypeidExp::TypeidExp(Loc loc, Type *typeidType) | |
4215 : Expression(loc, TOKtypeid, sizeof(TypeidExp)) | |
4216 { | |
4217 this->typeidType = typeidType; | |
4218 } | |
4219 | |
4220 | |
4221 Expression *TypeidExp::syntaxCopy() | |
4222 { | |
4223 return new TypeidExp(loc, typeidType->syntaxCopy()); | |
4224 } | |
4225 | |
4226 | |
4227 Expression *TypeidExp::semantic(Scope *sc) | |
4228 { Expression *e; | |
4229 | |
4230 #if LOGSEMANTIC | |
4231 printf("TypeidExp::semantic()\n"); | |
4232 #endif | |
4233 typeidType = typeidType->semantic(loc, sc); | |
4234 e = typeidType->getTypeInfo(sc); | |
336 | 4235 if (e->loc.linnum == 0) |
4236 e->loc = loc; // so there's at least some line number info | |
159 | 4237 return e; |
4238 } | |
4239 | |
4240 void TypeidExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
4241 { | |
4242 buf->writestring("typeid("); | |
4243 typeidType->toCBuffer(buf, NULL, hgs); | |
4244 buf->writeByte(')'); | |
4245 } | |
4246 | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4247 /************************ TraitsExp ************************************/ |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4248 #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
|
4249 /* |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4250 * __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
|
4251 */ |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4252 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4253 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
|
4254 : 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
|
4255 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4256 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
|
4257 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
|
4258 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4259 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4260 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4261 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
|
4262 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4263 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
|
4264 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4265 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4266 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4267 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
|
4268 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4269 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
|
4270 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
|
4271 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
|
4272 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4273 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
|
4274 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4275 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
|
4276 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
|
4277 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
|
4278 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4279 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4280 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
|
4281 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4282 #endif |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4283 |
159 | 4284 /************************************************************/ |
4285 | |
4286 HaltExp::HaltExp(Loc loc) | |
4287 : Expression(loc, TOKhalt, sizeof(HaltExp)) | |
4288 { | |
4289 } | |
4290 | |
4291 Expression *HaltExp::semantic(Scope *sc) | |
4292 { | |
4293 #if LOGSEMANTIC | |
4294 printf("HaltExp::semantic()\n"); | |
4295 #endif | |
4296 type = Type::tvoid; | |
4297 return this; | |
4298 } | |
4299 | |
4300 int HaltExp::checkSideEffect(int flag) | |
4301 { | |
4302 return 1; | |
4303 } | |
4304 | |
4305 void HaltExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
4306 { | |
4307 buf->writestring("halt"); | |
4308 } | |
4309 | |
4310 /************************************************************/ | |
4311 | |
4312 IsExp::IsExp(Loc loc, Type *targ, Identifier *id, enum TOK tok, | |
4313 Type *tspec, enum TOK tok2) | |
4314 : Expression(loc, TOKis, sizeof(IsExp)) | |
4315 { | |
4316 this->targ = targ; | |
4317 this->id = id; | |
4318 this->tok = tok; | |
4319 this->tspec = tspec; | |
4320 this->tok2 = tok2; | |
4321 } | |
4322 | |
4323 Expression *IsExp::syntaxCopy() | |
4324 { | |
4325 return new IsExp(loc, | |
4326 targ->syntaxCopy(), | |
4327 id, | |
4328 tok, | |
4329 tspec ? tspec->syntaxCopy() : NULL, | |
4330 tok2); | |
4331 } | |
4332 | |
4333 Expression *IsExp::semantic(Scope *sc) | |
4334 { Type *tded; | |
4335 | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4336 /* 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
|
4337 * 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
|
4338 */ |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4339 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4340 //printf("IsExp::semantic(%s)\n", toChars()); |
159 | 4341 if (id && !(sc->flags & SCOPEstaticif)) |
4342 error("can only declare type aliases within static if conditionals"); | |
4343 | |
4344 unsigned errors_save = global.errors; | |
4345 global.errors = 0; | |
4346 global.gag++; // suppress printing of error messages | |
4347 targ = targ->semantic(loc, sc); | |
4348 global.gag--; | |
4349 unsigned gerrors = global.errors; | |
4350 global.errors = errors_save; | |
4351 | |
4352 if (gerrors) // if any errors happened | |
4353 { // then condition is false | |
4354 goto Lno; | |
4355 } | |
4356 else if (tok2 != TOKreserved) | |
4357 { | |
4358 switch (tok2) | |
4359 { | |
4360 case TOKtypedef: | |
4361 if (targ->ty != Ttypedef) | |
4362 goto Lno; | |
4363 tded = ((TypeTypedef *)targ)->sym->basetype; | |
4364 break; | |
4365 | |
4366 case TOKstruct: | |
4367 if (targ->ty != Tstruct) | |
4368 goto Lno; | |
4369 if (((TypeStruct *)targ)->sym->isUnionDeclaration()) | |
4370 goto Lno; | |
4371 tded = targ; | |
4372 break; | |
4373 | |
4374 case TOKunion: | |
4375 if (targ->ty != Tstruct) | |
4376 goto Lno; | |
4377 if (!((TypeStruct *)targ)->sym->isUnionDeclaration()) | |
4378 goto Lno; | |
4379 tded = targ; | |
4380 break; | |
4381 | |
4382 case TOKclass: | |
4383 if (targ->ty != Tclass) | |
4384 goto Lno; | |
4385 if (((TypeClass *)targ)->sym->isInterfaceDeclaration()) | |
4386 goto Lno; | |
4387 tded = targ; | |
4388 break; | |
4389 | |
4390 case TOKinterface: | |
4391 if (targ->ty != Tclass) | |
4392 goto Lno; | |
4393 if (!((TypeClass *)targ)->sym->isInterfaceDeclaration()) | |
4394 goto Lno; | |
4395 tded = targ; | |
4396 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
|
4397 #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
|
4398 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
|
4399 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
|
4400 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
|
4401 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
|
4402 break; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4403 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4404 case TOKinvariant: |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4405 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
|
4406 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
|
4407 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
|
4408 break; |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4409 #endif |
159 | 4410 |
4411 case TOKsuper: | |
4412 // If class or interface, get the base class and interfaces | |
4413 if (targ->ty != Tclass) | |
4414 goto Lno; | |
4415 else | |
4416 { ClassDeclaration *cd = ((TypeClass *)targ)->sym; | |
4417 Arguments *args = new Arguments; | |
4418 args->reserve(cd->baseclasses.dim); | |
4419 for (size_t i = 0; i < cd->baseclasses.dim; i++) | |
4420 { BaseClass *b = (BaseClass *)cd->baseclasses.data[i]; | |
4421 args->push(new Argument(STCin, b->type, NULL, NULL)); | |
4422 } | |
4423 tded = new TypeTuple(args); | |
4424 } | |
4425 break; | |
4426 | |
4427 case TOKenum: | |
4428 if (targ->ty != Tenum) | |
4429 goto Lno; | |
4430 tded = ((TypeEnum *)targ)->sym->memtype; | |
4431 break; | |
4432 | |
4433 case TOKdelegate: | |
4434 if (targ->ty != Tdelegate) | |
4435 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
|
4436 tded = ((TypeDelegate *)targ)->next; // the underlying function type |
159 | 4437 break; |
4438 | |
4439 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
|
4440 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4441 if (targ->ty != Tfunction) |
159 | 4442 goto Lno; |
4443 tded = targ; | |
4444 | |
4445 /* Generate tuple from function parameter types. | |
4446 */ | |
4447 assert(tded->ty == Tfunction); | |
4448 Arguments *params = ((TypeFunction *)tded)->parameters; | |
4449 size_t dim = Argument::dim(params); | |
4450 Arguments *args = new Arguments; | |
4451 args->reserve(dim); | |
4452 for (size_t i = 0; i < dim; i++) | |
4453 { Argument *arg = Argument::getNth(params, i); | |
4454 assert(arg && arg->type); | |
4455 args->push(new Argument(arg->storageClass, arg->type, NULL, NULL)); | |
4456 } | |
4457 tded = new TypeTuple(args); | |
4458 break; | |
4459 } | |
4460 case TOKreturn: | |
4461 /* Get the 'return type' for the function, | |
4462 * delegate, or pointer to function. | |
4463 */ | |
4464 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
|
4465 tded = ((TypeFunction *)targ)->next; |
159 | 4466 else if (targ->ty == Tdelegate) |
4467 tded = targ->next->next; | |
4468 else if (targ->ty == Tpointer && targ->next->ty == Tfunction) | |
4469 tded = targ->next->next; | |
4470 else | |
4471 goto Lno; | |
4472 break; | |
4473 | |
4474 default: | |
4475 assert(0); | |
4476 } | |
4477 goto Lyes; | |
4478 } | |
4479 else if (id && tspec) | |
4480 { | |
4481 /* Evaluate to TRUE if targ matches tspec. | |
4482 * If TRUE, declare id as an alias for the specialized type. | |
4483 */ | |
4484 | |
4485 MATCH m; | |
4486 TemplateTypeParameter tp(loc, id, NULL, NULL); | |
4487 | |
4488 TemplateParameters parameters; | |
4489 parameters.setDim(1); | |
4490 parameters.data[0] = (void *)&tp; | |
4491 | |
4492 Objects dedtypes; | |
4493 dedtypes.setDim(1); | |
4494 dedtypes.data[0] = NULL; | |
4495 | |
4496 m = targ->deduceType(NULL, tspec, ¶meters, &dedtypes); | |
4497 if (m == MATCHnomatch || | |
4498 (m != MATCHexact && tok == TOKequal)) | |
4499 goto Lno; | |
4500 else | |
4501 { | |
4502 assert(dedtypes.dim == 1); | |
4503 tded = (Type *)dedtypes.data[0]; | |
4504 if (!tded) | |
4505 tded = targ; | |
4506 goto Lyes; | |
4507 } | |
4508 } | |
4509 else if (id) | |
4510 { | |
4511 /* Declare id as an alias for type targ. Evaluate to TRUE | |
4512 */ | |
4513 tded = targ; | |
4514 goto Lyes; | |
4515 } | |
4516 else if (tspec) | |
4517 { | |
4518 /* Evaluate to TRUE if targ matches tspec | |
4519 */ | |
4520 tspec = tspec->semantic(loc, sc); | |
4521 //printf("targ = %s\n", targ->toChars()); | |
4522 //printf("tspec = %s\n", tspec->toChars()); | |
4523 if (tok == TOKcolon) | |
4524 { if (targ->implicitConvTo(tspec)) | |
4525 goto Lyes; | |
4526 else | |
4527 goto Lno; | |
4528 } | |
4529 else /* == */ | |
4530 { if (targ->equals(tspec)) | |
4531 goto Lyes; | |
4532 else | |
4533 goto Lno; | |
4534 } | |
4535 } | |
4536 | |
4537 Lyes: | |
4538 if (id) | |
4539 { | |
4540 Dsymbol *s = new AliasDeclaration(loc, id, tded); | |
4541 s->semantic(sc); | |
4542 sc->insert(s); | |
4543 if (sc->sd) | |
4544 s->addMember(sc, sc->sd, 1); | |
4545 } | |
4546 return new IntegerExp(1); | |
4547 | |
4548 Lno: | |
4549 return new IntegerExp(0); | |
4550 } | |
4551 | |
4552 void IsExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
4553 { | |
4554 buf->writestring("is("); | |
4555 targ->toCBuffer(buf, id, hgs); | |
4556 if (tok2 != TOKreserved) | |
4557 { | |
4558 buf->printf(" %s %s", Token::toChars(tok), Token::toChars(tok2)); | |
4559 } | |
4560 else if (tspec) | |
4561 { | |
4562 if (tok == TOKcolon) | |
4563 buf->writestring(" : "); | |
4564 else | |
4565 buf->writestring(" == "); | |
4566 tspec->toCBuffer(buf, NULL, hgs); | |
4567 } | |
336 | 4568 #if DMDV2 |
159 | 4569 if (parameters) |
4570 { // First parameter is already output, so start with second | |
4571 for (int i = 1; i < parameters->dim; i++) | |
4572 { | |
4573 buf->writeByte(','); | |
4574 TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; | |
4575 tp->toCBuffer(buf, hgs); | |
4576 } | |
4577 } | |
4578 #endif | |
4579 buf->writeByte(')'); | |
4580 } | |
4581 | |
4582 | |
4583 /************************************************************/ | |
4584 | |
4585 UnaExp::UnaExp(Loc loc, enum TOK op, int size, Expression *e1) | |
4586 : Expression(loc, op, size) | |
4587 { | |
4588 this->e1 = e1; | |
4589 } | |
4590 | |
4591 Expression *UnaExp::syntaxCopy() | |
4592 { UnaExp *e; | |
4593 | |
4594 e = (UnaExp *)copy(); | |
4595 e->type = NULL; | |
4596 e->e1 = e->e1->syntaxCopy(); | |
4597 return e; | |
4598 } | |
4599 | |
4600 Expression *UnaExp::semantic(Scope *sc) | |
4601 { | |
4602 #if LOGSEMANTIC | |
4603 printf("UnaExp::semantic('%s')\n", toChars()); | |
4604 #endif | |
4605 e1 = e1->semantic(sc); | |
4606 // if (!e1->type) | |
4607 // error("%s has no value", e1->toChars()); | |
4608 return this; | |
4609 } | |
4610 | |
4611 void UnaExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
4612 { | |
4613 buf->writestring(Token::toChars(op)); | |
4614 expToCBuffer(buf, hgs, e1, precedence[op]); | |
4615 } | |
4616 | |
4617 /************************************************************/ | |
4618 | |
4619 BinExp::BinExp(Loc loc, enum TOK op, int size, Expression *e1, Expression *e2) | |
4620 : Expression(loc, op, size) | |
4621 { | |
4622 this->e1 = e1; | |
4623 this->e2 = e2; | |
4624 } | |
4625 | |
4626 Expression *BinExp::syntaxCopy() | |
4627 { BinExp *e; | |
4628 | |
4629 e = (BinExp *)copy(); | |
4630 e->type = NULL; | |
4631 e->e1 = e->e1->syntaxCopy(); | |
4632 e->e2 = e->e2->syntaxCopy(); | |
4633 return e; | |
4634 } | |
4635 | |
4636 Expression *BinExp::semantic(Scope *sc) | |
4637 { | |
4638 #if LOGSEMANTIC | |
4639 printf("BinExp::semantic('%s')\n", toChars()); | |
4640 #endif | |
4641 e1 = e1->semantic(sc); | |
717
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
4642 if (!e1->type && |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
4643 !(op == TOKassign && e1->op == TOKdottd)) // a.template = e2 |
159 | 4644 { |
4645 error("%s has no value", e1->toChars()); | |
4646 e1->type = Type::terror; | |
4647 } | |
4648 e2 = e2->semantic(sc); | |
4649 if (!e2->type) | |
4650 { | |
4651 error("%s has no value", e2->toChars()); | |
4652 e2->type = Type::terror; | |
4653 } | |
4654 return this; | |
4655 } | |
4656 | |
4657 Expression *BinExp::semanticp(Scope *sc) | |
4658 { | |
4659 BinExp::semantic(sc); | |
4660 e1 = resolveProperties(sc, e1); | |
4661 e2 = resolveProperties(sc, e2); | |
4662 return this; | |
4663 } | |
4664 | |
4665 /*************************** | |
4666 * Common semantic routine for some xxxAssignExp's. | |
4667 */ | |
4668 | |
4669 Expression *BinExp::commonSemanticAssign(Scope *sc) | |
4670 { Expression *e; | |
4671 | |
4672 if (!type) | |
4673 { | |
4674 BinExp::semantic(sc); | |
4675 e2 = resolveProperties(sc, e2); | |
4676 | |
4677 e = op_overload(sc); | |
4678 if (e) | |
4679 return e; | |
4680 | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4681 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
|
4682 { // 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
|
4683 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
|
4684 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
|
4685 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
|
4686 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4687 |
159 | 4688 e1 = e1->modifiableLvalue(sc, e1); |
4689 e1->checkScalar(); | |
4690 type = e1->type; | |
4691 if (type->toBasetype()->ty == Tbool) | |
4692 { | |
4693 error("operator not allowed on bool expression %s", toChars()); | |
4694 } | |
4695 typeCombine(sc); | |
4696 e1->checkArithmetic(); | |
4697 e2->checkArithmetic(); | |
4698 | |
4699 if (op == TOKmodass && e2->type->iscomplex()) | |
4700 { error("cannot perform modulo complex arithmetic"); | |
4701 return new IntegerExp(0); | |
4702 } | |
4703 } | |
4704 return this; | |
4705 } | |
4706 | |
4707 Expression *BinExp::commonSemanticAssignIntegral(Scope *sc) | |
4708 { Expression *e; | |
4709 | |
4710 if (!type) | |
4711 { | |
4712 BinExp::semantic(sc); | |
4713 e2 = resolveProperties(sc, e2); | |
4714 | |
4715 e = op_overload(sc); | |
4716 if (e) | |
4717 return e; | |
4718 | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4719 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
|
4720 { // 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
|
4721 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
|
4722 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
|
4723 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
|
4724 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
4725 |
159 | 4726 e1 = e1->modifiableLvalue(sc, e1); |
4727 e1->checkScalar(); | |
4728 type = e1->type; | |
4729 if (type->toBasetype()->ty == Tbool) | |
4730 { | |
4731 e2 = e2->implicitCastTo(sc, type); | |
4732 } | |
4733 | |
4734 typeCombine(sc); | |
4735 e1->checkIntegral(); | |
4736 e2->checkIntegral(); | |
4737 } | |
4738 return this; | |
4739 } | |
4740 | |
4741 int BinExp::checkSideEffect(int flag) | |
4742 { | |
4743 if (op == TOKplusplus || | |
4744 op == TOKminusminus || | |
4745 op == TOKassign || | |
4746 op == TOKconstruct || | |
4747 op == TOKblit || | |
4748 op == TOKaddass || | |
4749 op == TOKminass || | |
4750 op == TOKcatass || | |
4751 op == TOKmulass || | |
4752 op == TOKdivass || | |
4753 op == TOKmodass || | |
4754 op == TOKshlass || | |
4755 op == TOKshrass || | |
4756 op == TOKushrass || | |
4757 op == TOKandass || | |
4758 op == TOKorass || | |
4759 op == TOKxorass || | |
4760 op == TOKin || | |
4761 op == TOKremove) | |
4762 return 1; | |
4763 return Expression::checkSideEffect(flag); | |
4764 } | |
4765 | |
4766 void BinExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
4767 { | |
4768 expToCBuffer(buf, hgs, e1, precedence[op]); | |
4769 buf->writeByte(' '); | |
4770 buf->writestring(Token::toChars(op)); | |
4771 buf->writeByte(' '); | |
4772 expToCBuffer(buf, hgs, e2, (enum PREC)(precedence[op] + 1)); | |
4773 } | |
4774 | |
4775 int BinExp::isunsigned() | |
4776 { | |
4777 return e1->type->isunsigned() || e2->type->isunsigned(); | |
4778 } | |
4779 | |
4780 void BinExp::incompatibleTypes() | |
4781 { | |
4782 error("incompatible types for ((%s) %s (%s)): '%s' and '%s'", | |
4783 e1->toChars(), Token::toChars(op), e2->toChars(), | |
4784 e1->type->toChars(), e2->type->toChars()); | |
4785 } | |
4786 | |
4787 /************************************************************/ | |
4788 | |
4789 CompileExp::CompileExp(Loc loc, Expression *e) | |
4790 : UnaExp(loc, TOKmixin, sizeof(CompileExp), e) | |
4791 { | |
4792 } | |
4793 | |
4794 Expression *CompileExp::semantic(Scope *sc) | |
4795 { | |
4796 #if LOGSEMANTIC | |
4797 printf("CompileExp::semantic('%s')\n", toChars()); | |
4798 #endif | |
4799 UnaExp::semantic(sc); | |
4800 e1 = resolveProperties(sc, e1); | |
4801 e1 = e1->optimize(WANTvalue | WANTinterpret); | |
4802 if (e1->op != TOKstring) | |
4803 { error("argument to mixin must be a string, not (%s)", e1->toChars()); | |
4804 type = Type::terror; | |
4805 return this; | |
4806 } | |
4807 StringExp *se = (StringExp *)e1; | |
4808 se = se->toUTF8(sc); | |
4809 Parser p(sc->module, (unsigned char *)se->string, se->len, 0); | |
4810 p.loc = loc; | |
4811 p.nextToken(); | |
4812 Expression *e = p.parseExpression(); | |
4813 if (p.token.value != TOKeof) | |
4814 error("incomplete mixin expression (%s)", se->toChars()); | |
4815 return e->semantic(sc); | |
4816 } | |
4817 | |
4818 void CompileExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
4819 { | |
4820 buf->writestring("mixin("); | |
4821 expToCBuffer(buf, hgs, e1, PREC_assign); | |
4822 buf->writeByte(')'); | |
4823 } | |
4824 | |
4825 /************************************************************/ | |
4826 | |
4827 FileExp::FileExp(Loc loc, Expression *e) | |
4828 : UnaExp(loc, TOKmixin, sizeof(FileExp), e) | |
4829 { | |
4830 } | |
4831 | |
4832 Expression *FileExp::semantic(Scope *sc) | |
4833 { char *name; | |
4834 StringExp *se; | |
4835 | |
4836 #if LOGSEMANTIC | |
4837 printf("FileExp::semantic('%s')\n", toChars()); | |
4838 #endif | |
4839 UnaExp::semantic(sc); | |
4840 e1 = resolveProperties(sc, e1); | |
4841 e1 = e1->optimize(WANTvalue); | |
4842 if (e1->op != TOKstring) | |
4843 { error("file name argument must be a string, not (%s)", e1->toChars()); | |
4844 goto Lerror; | |
4845 } | |
4846 se = (StringExp *)e1; | |
4847 se = se->toUTF8(sc); | |
4848 name = (char *)se->string; | |
4849 | |
4850 if (!global.params.fileImppath) | |
4851 { error("need -Jpath switch to import text file %s", name); | |
4852 goto Lerror; | |
4853 } | |
4854 | |
4855 if (name != FileName::name(name)) | |
4856 { error("use -Jpath switch to provide path for filename %s", name); | |
4857 goto Lerror; | |
4858 } | |
4859 | |
4860 name = FileName::searchPath(global.filePath, name, 0); | |
4861 if (!name) | |
4862 { error("file %s cannot be found, check -Jpath", se->toChars()); | |
4863 goto Lerror; | |
4864 } | |
4865 | |
4866 if (global.params.verbose) | |
794
661384d6a936
Fix warnings on x86-64. By fvbommel.
Christian Kamm <kamm incasoftware de>
parents:
779
diff
changeset
|
4867 printf("file %s\t(%s)\n", (char*)se->string, name); |
159 | 4868 |
4869 { File f(name); | |
4870 if (f.read()) | |
4871 { error("cannot read file %s", f.toChars()); | |
4872 goto Lerror; | |
4873 } | |
4874 else | |
4875 { | |
4876 f.ref = 1; | |
4877 se = new StringExp(loc, f.buffer, f.len); | |
4878 } | |
4879 } | |
4880 Lret: | |
4881 return se->semantic(sc); | |
4882 | |
4883 Lerror: | |
4884 se = new StringExp(loc, ""); | |
4885 goto Lret; | |
4886 } | |
4887 | |
4888 void FileExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
4889 { | |
4890 buf->writestring("import("); | |
4891 expToCBuffer(buf, hgs, e1, PREC_assign); | |
4892 buf->writeByte(')'); | |
4893 } | |
4894 | |
4895 /************************************************************/ | |
4896 | |
4897 AssertExp::AssertExp(Loc loc, Expression *e, Expression *msg) | |
4898 : UnaExp(loc, TOKassert, sizeof(AssertExp), e) | |
4899 { | |
4900 this->msg = msg; | |
4901 } | |
4902 | |
4903 Expression *AssertExp::syntaxCopy() | |
4904 { | |
4905 AssertExp *ae = new AssertExp(loc, e1->syntaxCopy(), | |
4906 msg ? msg->syntaxCopy() : NULL); | |
4907 return ae; | |
4908 } | |
4909 | |
4910 Expression *AssertExp::semantic(Scope *sc) | |
4911 { | |
4912 #if LOGSEMANTIC | |
4913 printf("AssertExp::semantic('%s')\n", toChars()); | |
4914 #endif | |
4915 UnaExp::semantic(sc); | |
4916 e1 = resolveProperties(sc, e1); | |
4917 // BUG: see if we can do compile time elimination of the Assert | |
4918 e1 = e1->optimize(WANTvalue); | |
4919 e1 = e1->checkToBoolean(); | |
4920 if (msg) | |
4921 { | |
4922 msg = msg->semantic(sc); | |
4923 msg = resolveProperties(sc, msg); | |
4924 msg = msg->implicitCastTo(sc, Type::tchar->arrayOf()); | |
4925 msg = msg->optimize(WANTvalue); | |
4926 } | |
4927 if (e1->isBool(FALSE)) | |
4928 { | |
4929 FuncDeclaration *fd = sc->parent->isFuncDeclaration(); | |
4930 fd->hasReturnExp |= 4; | |
4931 | |
4932 if (!global.params.useAssert) | |
4933 { Expression *e = new HaltExp(loc); | |
4934 e = e->semantic(sc); | |
4935 return e; | |
4936 } | |
4937 } | |
4938 type = Type::tvoid; | |
4939 return this; | |
4940 } | |
4941 | |
4942 int AssertExp::checkSideEffect(int flag) | |
4943 { | |
4944 return 1; | |
4945 } | |
4946 | |
4947 void AssertExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
4948 { | |
4949 buf->writestring("assert("); | |
4950 expToCBuffer(buf, hgs, e1, PREC_assign); | |
4951 if (msg) | |
4952 { | |
4953 buf->writeByte(','); | |
4954 expToCBuffer(buf, hgs, msg, PREC_assign); | |
4955 } | |
4956 buf->writeByte(')'); | |
4957 } | |
4958 | |
4959 /************************************************************/ | |
4960 | |
4961 DotIdExp::DotIdExp(Loc loc, Expression *e, Identifier *ident) | |
4962 : UnaExp(loc, TOKdot, sizeof(DotIdExp), e) | |
4963 { | |
4964 this->ident = ident; | |
4965 } | |
4966 | |
4967 Expression *DotIdExp::semantic(Scope *sc) | |
4968 { Expression *e; | |
4969 Expression *eleft; | |
4970 Expression *eright; | |
4971 | |
4972 #if LOGSEMANTIC | |
4973 printf("DotIdExp::semantic(this = %p, '%s')\n", this, toChars()); | |
4974 //printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op)); | |
4975 #endif | |
4976 | |
4977 //{ static int z; fflush(stdout); if (++z == 10) *(char*)0=0; } | |
4978 | |
4979 #if 0 | |
4980 /* Don't do semantic analysis if we'll be converting | |
4981 * it to a string. | |
4982 */ | |
4983 if (ident == Id::stringof) | |
4984 { char *s = e1->toChars(); | |
4985 e = new StringExp(loc, s, strlen(s), 'c'); | |
4986 e = e->semantic(sc); | |
4987 return e; | |
4988 } | |
4989 #endif | |
4990 | |
4991 /* Special case: rewrite this.id and super.id | |
4992 * to be classtype.id and baseclasstype.id | |
4993 * if we have no this pointer. | |
4994 */ | |
4995 if ((e1->op == TOKthis || e1->op == TOKsuper) && !hasThis(sc)) | |
4996 { ClassDeclaration *cd; | |
4997 StructDeclaration *sd; | |
4998 AggregateDeclaration *ad; | |
4999 | |
5000 ad = sc->getStructClassScope(); | |
5001 if (ad) | |
5002 { | |
5003 cd = ad->isClassDeclaration(); | |
5004 if (cd) | |
5005 { | |
5006 if (e1->op == TOKthis) | |
5007 { | |
5008 e = new TypeDotIdExp(loc, cd->type, ident); | |
5009 return e->semantic(sc); | |
5010 } | |
5011 else if (cd->baseClass && e1->op == TOKsuper) | |
5012 { | |
5013 e = new TypeDotIdExp(loc, cd->baseClass->type, ident); | |
5014 return e->semantic(sc); | |
5015 } | |
5016 } | |
5017 else | |
5018 { | |
5019 sd = ad->isStructDeclaration(); | |
5020 if (sd) | |
5021 { | |
5022 if (e1->op == TOKthis) | |
5023 { | |
5024 e = new TypeDotIdExp(loc, sd->type, ident); | |
5025 return e->semantic(sc); | |
5026 } | |
5027 } | |
5028 } | |
5029 } | |
5030 } | |
5031 | |
5032 UnaExp::semantic(sc); | |
5033 | |
5034 if (e1->op == TOKdotexp) | |
5035 { | |
5036 DotExp *de = (DotExp *)e1; | |
5037 eleft = de->e1; | |
5038 eright = de->e2; | |
5039 } | |
5040 else | |
5041 { | |
5042 e1 = resolveProperties(sc, e1); | |
5043 eleft = NULL; | |
5044 eright = e1; | |
5045 } | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5046 #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
|
5047 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
|
5048 { /* '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
|
5049 */ |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5050 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
|
5051 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
|
5052 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
|
5053 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
|
5054 { 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
|
5055 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
|
5056 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
|
5057 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
|
5058 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5059 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
|
5060 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
|
5061 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
|
5062 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5063 #endif |
159 | 5064 |
5065 if (e1->op == TOKtuple && ident == Id::length) | |
5066 { | |
5067 TupleExp *te = (TupleExp *)e1; | |
5068 e = new IntegerExp(loc, te->exps->dim, Type::tsize_t); | |
5069 return e; | |
5070 } | |
5071 | |
5072 if (eright->op == TOKimport) // also used for template alias's | |
5073 { | |
5074 Dsymbol *s; | |
5075 ScopeExp *ie = (ScopeExp *)eright; | |
5076 | |
5077 s = ie->sds->search(loc, ident, 0); | |
5078 if (s) | |
5079 { | |
5080 s = s->toAlias(); | |
5081 checkDeprecated(sc, s); | |
5082 | |
5083 EnumMember *em = s->isEnumMember(); | |
5084 if (em) | |
5085 { | |
5086 e = em->value; | |
5087 e = e->semantic(sc); | |
5088 return e; | |
5089 } | |
5090 | |
5091 VarDeclaration *v = s->isVarDeclaration(); | |
5092 if (v) | |
5093 { | |
5094 //printf("DotIdExp:: Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars()); | |
5095 if (v->inuse) | |
5096 { | |
5097 error("circular reference to '%s'", v->toChars()); | |
5098 type = Type::tint32; | |
5099 return this; | |
5100 } | |
5101 type = v->type; | |
5102 if (v->isConst()) | |
5103 { | |
5104 if (v->init) | |
5105 { | |
5106 ExpInitializer *ei = v->init->isExpInitializer(); | |
5107 if (ei) | |
5108 { | |
5109 //printf("\tei: %p (%s)\n", ei->exp, ei->exp->toChars()); | |
5110 //ei->exp = ei->exp->semantic(sc); | |
5111 if (ei->exp->type == type) | |
5112 { | |
5113 e = ei->exp->copy(); // make copy so we can change loc | |
5114 e->loc = loc; | |
5115 return e; | |
5116 } | |
5117 } | |
5118 } | |
5119 else if (type->isscalar()) | |
5120 { | |
5121 e = type->defaultInit(); | |
5122 e->loc = loc; | |
5123 return e; | |
5124 } | |
5125 } | |
5126 if (v->needThis()) | |
5127 { | |
5128 if (!eleft) | |
5129 eleft = new ThisExp(loc); | |
5130 e = new DotVarExp(loc, eleft, v); | |
5131 e = e->semantic(sc); | |
5132 } | |
5133 else | |
5134 { | |
5135 e = new VarExp(loc, v); | |
5136 if (eleft) | |
5137 { e = new CommaExp(loc, eleft, e); | |
5138 e->type = v->type; | |
5139 } | |
5140 } | |
5141 return e->deref(); | |
5142 } | |
5143 | |
5144 FuncDeclaration *f = s->isFuncDeclaration(); | |
5145 if (f) | |
5146 { | |
5147 //printf("it's a function\n"); | |
5148 if (f->needThis()) | |
5149 { | |
5150 if (!eleft) | |
5151 eleft = new ThisExp(loc); | |
5152 e = new DotVarExp(loc, eleft, f); | |
5153 e = e->semantic(sc); | |
5154 } | |
5155 else | |
5156 { | |
5157 e = new VarExp(loc, f); | |
5158 if (eleft) | |
5159 { e = new CommaExp(loc, eleft, e); | |
5160 e->type = f->type; | |
5161 } | |
5162 } | |
5163 return e; | |
5164 } | |
5165 | |
5166 Type *t = s->getType(); | |
5167 if (t) | |
5168 { | |
5169 return new TypeExp(loc, t); | |
5170 } | |
5171 | |
336 | 5172 TupleDeclaration *tup = s->isTupleDeclaration(); |
5173 if (tup) | |
5174 { | |
5175 if (eleft) | |
5176 error("cannot have e.tuple"); | |
5177 e = new TupleExp(loc, tup); | |
5178 e = e->semantic(sc); | |
5179 return e; | |
5180 } | |
5181 | |
159 | 5182 ScopeDsymbol *sds = s->isScopeDsymbol(); |
5183 if (sds) | |
5184 { | |
5185 //printf("it's a ScopeDsymbol\n"); | |
5186 e = new ScopeExp(loc, sds); | |
5187 e = e->semantic(sc); | |
5188 if (eleft) | |
5189 e = new DotExp(loc, eleft, e); | |
5190 return e; | |
5191 } | |
5192 | |
5193 Import *imp = s->isImport(); | |
5194 if (imp) | |
5195 { | |
5196 ScopeExp *ie; | |
5197 | |
5198 ie = new ScopeExp(loc, imp->pkg); | |
5199 return ie->semantic(sc); | |
5200 } | |
5201 | |
5202 // BUG: handle other cases like in IdentifierExp::semantic() | |
5203 #ifdef DEBUG | |
5204 printf("s = '%s', kind = '%s'\n", s->toChars(), s->kind()); | |
5205 #endif | |
5206 assert(0); | |
5207 } | |
5208 else if (ident == Id::stringof) | |
5209 { char *s = ie->toChars(); | |
5210 e = new StringExp(loc, s, strlen(s), 'c'); | |
5211 e = e->semantic(sc); | |
5212 return e; | |
5213 } | |
5214 error("undefined identifier %s", toChars()); | |
5215 type = Type::tvoid; | |
5216 return this; | |
5217 } | |
5218 else if (e1->type->ty == Tpointer && | |
5219 ident != Id::init && ident != Id::__sizeof && | |
5220 ident != Id::alignof && ident != Id::offsetof && | |
5221 ident != Id::mangleof && ident != Id::stringof) | |
5222 { | |
5223 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
|
5224 e->type = ((TypePointer *)e1->type)->next; |
159 | 5225 return e->type->dotExp(sc, e, ident); |
5226 } | |
5227 else | |
5228 { | |
5229 e = e1->type->dotExp(sc, e1, ident); | |
5230 e = e->semantic(sc); | |
5231 return e; | |
5232 } | |
5233 } | |
5234 | |
5235 void DotIdExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
5236 { | |
5237 //printf("DotIdExp::toCBuffer()\n"); | |
5238 expToCBuffer(buf, hgs, e1, PREC_primary); | |
5239 buf->writeByte('.'); | |
5240 buf->writestring(ident->toChars()); | |
5241 } | |
5242 | |
5243 /********************** DotTemplateExp ***********************************/ | |
5244 | |
5245 // Mainly just a placeholder | |
5246 | |
5247 DotTemplateExp::DotTemplateExp(Loc loc, Expression *e, TemplateDeclaration *td) | |
5248 : UnaExp(loc, TOKdottd, sizeof(DotTemplateExp), e) | |
5249 | |
5250 { | |
5251 this->td = td; | |
5252 } | |
5253 | |
5254 void DotTemplateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
5255 { | |
5256 expToCBuffer(buf, hgs, e1, PREC_primary); | |
5257 buf->writeByte('.'); | |
5258 buf->writestring(td->toChars()); | |
5259 } | |
5260 | |
5261 | |
5262 /************************************************************/ | |
5263 | |
5264 DotVarExp::DotVarExp(Loc loc, Expression *e, Declaration *v) | |
5265 : UnaExp(loc, TOKdotvar, sizeof(DotVarExp), e) | |
5266 { | |
5267 //printf("DotVarExp()\n"); | |
5268 this->var = v; | |
5269 } | |
5270 | |
5271 Expression *DotVarExp::semantic(Scope *sc) | |
5272 { | |
5273 #if LOGSEMANTIC | |
5274 printf("DotVarExp::semantic('%s')\n", toChars()); | |
5275 #endif | |
5276 if (!type) | |
5277 { | |
5278 var = var->toAlias()->isDeclaration(); | |
5279 | |
5280 TupleDeclaration *tup = var->isTupleDeclaration(); | |
5281 if (tup) | |
5282 { /* Replace: | |
5283 * e1.tuple(a, b, c) | |
5284 * with: | |
5285 * tuple(e1.a, e1.b, e1.c) | |
5286 */ | |
5287 Expressions *exps = new Expressions; | |
5288 | |
5289 exps->reserve(tup->objects->dim); | |
5290 for (size_t i = 0; i < tup->objects->dim; i++) | |
5291 { Object *o = (Object *)tup->objects->data[i]; | |
5292 if (o->dyncast() != DYNCAST_EXPRESSION) | |
5293 { | |
5294 error("%s is not an expression", o->toChars()); | |
5295 } | |
5296 else | |
5297 { | |
5298 Expression *e = (Expression *)o; | |
5299 if (e->op != TOKdsymbol) | |
5300 error("%s is not a member", e->toChars()); | |
5301 else | |
5302 { DsymbolExp *ve = (DsymbolExp *)e; | |
5303 | |
5304 e = new DotVarExp(loc, e1, ve->s->isDeclaration()); | |
5305 exps->push(e); | |
5306 } | |
5307 } | |
5308 } | |
5309 Expression *e = new TupleExp(loc, exps); | |
5310 e = e->semantic(sc); | |
5311 return e; | |
5312 } | |
5313 | |
5314 e1 = e1->semantic(sc); | |
5315 type = var->type; | |
5316 if (!type && global.errors) | |
5317 { // var is goofed up, just return 0 | |
5318 return new IntegerExp(0); | |
5319 } | |
5320 assert(type); | |
5321 | |
5322 if (!var->isFuncDeclaration()) // for functions, do checks after overload resolution | |
5323 { | |
5324 AggregateDeclaration *ad = var->toParent()->isAggregateDeclaration(); | |
336 | 5325 e1 = getRightThis(loc, sc, ad, e1, var); |
5326 if (!sc->noaccesscheck) | |
5327 accessCheck(loc, sc, e1, var); | |
5328 | |
5329 VarDeclaration *v = var->isVarDeclaration(); | |
5330 if (v && v->isConst()) | |
5331 { ExpInitializer *ei = v->getExpInitializer(); | |
5332 if (ei) | |
5333 { Expression *e = ei->exp->copy(); | |
5334 e = e->semantic(sc); | |
5335 return e; | |
159 | 5336 } |
5337 } | |
5338 } | |
5339 } | |
5340 //printf("-DotVarExp::semantic('%s')\n", toChars()); | |
5341 return this; | |
5342 } | |
5343 | |
5344 Expression *DotVarExp::toLvalue(Scope *sc, Expression *e) | |
5345 { | |
5346 //printf("DotVarExp::toLvalue(%s)\n", toChars()); | |
5347 return this; | |
5348 } | |
5349 | |
5350 Expression *DotVarExp::modifiableLvalue(Scope *sc, Expression *e) | |
5351 { | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5352 #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
|
5353 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
|
5354 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
|
5355 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
|
5356 #endif |
159 | 5357 |
5358 if (var->isCtorinit()) | |
5359 { // It's only modifiable if inside the right constructor | |
5360 Dsymbol *s = sc->func; | |
5361 while (1) | |
5362 { | |
5363 FuncDeclaration *fd = NULL; | |
5364 if (s) | |
5365 fd = s->isFuncDeclaration(); | |
5366 if (fd && | |
5367 ((fd->isCtorDeclaration() && var->storage_class & STCfield) || | |
5368 (fd->isStaticCtorDeclaration() && !(var->storage_class & STCfield))) && | |
5369 fd->toParent() == var->toParent() && | |
5370 e1->op == TOKthis | |
5371 ) | |
5372 { | |
5373 VarDeclaration *v = var->isVarDeclaration(); | |
5374 assert(v); | |
5375 v->ctorinit = 1; | |
5376 //printf("setting ctorinit\n"); | |
5377 } | |
5378 else | |
5379 { | |
5380 if (s) | |
5381 { s = s->toParent2(); | |
5382 continue; | |
5383 } | |
5384 else | |
5385 { | |
5386 const char *p = var->isStatic() ? "static " : ""; | |
5387 error("can only initialize %sconst member %s inside %sconstructor", | |
5388 p, var->toChars(), p); | |
5389 } | |
5390 } | |
5391 break; | |
5392 } | |
5393 } | |
5394 return this; | |
5395 } | |
5396 | |
5397 void DotVarExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
5398 { | |
5399 expToCBuffer(buf, hgs, e1, PREC_primary); | |
5400 buf->writeByte('.'); | |
5401 buf->writestring(var->toChars()); | |
5402 } | |
5403 | |
5404 /************************************************************/ | |
5405 | |
5406 /* Things like: | |
5407 * foo.bar!(args) | |
5408 */ | |
5409 | |
5410 DotTemplateInstanceExp::DotTemplateInstanceExp(Loc loc, Expression *e, TemplateInstance *ti) | |
5411 : UnaExp(loc, TOKdotti, sizeof(DotTemplateInstanceExp), e) | |
5412 { | |
5413 //printf("DotTemplateInstanceExp()\n"); | |
5414 this->ti = ti; | |
5415 } | |
5416 | |
5417 Expression *DotTemplateInstanceExp::syntaxCopy() | |
5418 { | |
5419 DotTemplateInstanceExp *de = new DotTemplateInstanceExp(loc, | |
5420 e1->syntaxCopy(), | |
5421 (TemplateInstance *)ti->syntaxCopy(NULL)); | |
5422 return de; | |
5423 } | |
5424 | |
5425 Expression *DotTemplateInstanceExp::semantic(Scope *sc) | |
5426 { Dsymbol *s; | |
5427 Dsymbol *s2; | |
5428 TemplateDeclaration *td; | |
5429 Expression *e; | |
5430 Identifier *id; | |
5431 Type *t1; | |
5432 Expression *eleft = NULL; | |
5433 Expression *eright; | |
5434 | |
5435 #if LOGSEMANTIC | |
5436 printf("DotTemplateInstanceExp::semantic('%s')\n", toChars()); | |
5437 #endif | |
5438 //e1->print(); | |
5439 //print(); | |
5440 e1 = e1->semantic(sc); | |
5441 t1 = e1->type; | |
5442 if (t1) | |
5443 t1 = t1->toBasetype(); | |
5444 //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
|
5445 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5446 /* 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
|
5447 * 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
|
5448 * 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
|
5449 */ |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5450 |
159 | 5451 if (e1->op == TOKdotexp) |
5452 { DotExp *de = (DotExp *)e1; | |
5453 eleft = de->e1; | |
5454 eright = de->e2; | |
5455 } | |
5456 else | |
5457 { eleft = NULL; | |
5458 eright = e1; | |
5459 } | |
5460 if (eright->op == TOKimport) | |
5461 { | |
5462 s = ((ScopeExp *)eright)->sds; | |
5463 } | |
5464 else if (e1->op == TOKtype) | |
5465 { | |
5466 s = t1->isClassHandle(); | |
5467 if (!s) | |
5468 { if (t1->ty == Tstruct) | |
5469 s = ((TypeStruct *)t1)->sym; | |
5470 else | |
5471 goto L1; | |
5472 } | |
5473 } | |
5474 else if (t1 && (t1->ty == Tstruct || t1->ty == Tclass)) | |
5475 { | |
5476 s = t1->toDsymbol(sc); | |
5477 eleft = e1; | |
5478 } | |
5479 else if (t1 && t1->ty == Tpointer) | |
5480 { | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5481 t1 = ((TypePointer *)t1)->next->toBasetype(); |
159 | 5482 if (t1->ty != Tstruct) |
5483 goto L1; | |
5484 s = t1->toDsymbol(sc); | |
5485 eleft = e1; | |
5486 } | |
5487 else | |
5488 { | |
5489 L1: | |
5490 error("template %s is not a member of %s", ti->toChars(), e1->toChars()); | |
5491 goto Lerr; | |
5492 } | |
5493 | |
5494 assert(s); | |
5495 id = ti->name; | |
5496 s2 = s->search(loc, id, 0); | |
5497 if (!s2) | |
5498 { error("template identifier %s is not a member of %s %s", id->toChars(), s->kind(), s->ident->toChars()); | |
5499 goto Lerr; | |
5500 } | |
5501 s = s2; | |
5502 s->semantic(sc); | |
5503 s = s->toAlias(); | |
5504 td = s->isTemplateDeclaration(); | |
5505 if (!td) | |
5506 { | |
5507 error("%s is not a template", id->toChars()); | |
5508 goto Lerr; | |
5509 } | |
5510 if (global.errors) | |
5511 goto Lerr; | |
5512 | |
5513 ti->tempdecl = td; | |
5514 | |
5515 if (eleft) | |
5516 { Declaration *v; | |
5517 | |
5518 ti->semantic(sc); | |
5519 s = ti->inst->toAlias(); | |
5520 v = s->isDeclaration(); | |
5521 if (v) | |
5522 { e = new DotVarExp(loc, eleft, v); | |
5523 e = e->semantic(sc); | |
5524 return e; | |
5525 } | |
5526 } | |
5527 | |
5528 e = new ScopeExp(loc, ti); | |
5529 if (eleft) | |
5530 { | |
5531 e = new DotExp(loc, eleft, e); | |
5532 } | |
5533 e = e->semantic(sc); | |
5534 return e; | |
5535 | |
5536 Lerr: | |
336 | 5537 return new IntegerExp(loc, 0, Type::tint32); |
159 | 5538 } |
5539 | |
5540 void DotTemplateInstanceExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
5541 { | |
5542 expToCBuffer(buf, hgs, e1, PREC_primary); | |
5543 buf->writeByte('.'); | |
5544 ti->toCBuffer(buf, hgs); | |
5545 } | |
5546 | |
5547 /************************************************************/ | |
5548 | |
5549 DelegateExp::DelegateExp(Loc loc, Expression *e, FuncDeclaration *f) | |
5550 : UnaExp(loc, TOKdelegate, sizeof(DelegateExp), e) | |
5551 { | |
5552 this->func = f; | |
5553 } | |
5554 | |
5555 Expression *DelegateExp::semantic(Scope *sc) | |
5556 { | |
5557 #if LOGSEMANTIC | |
5558 printf("DelegateExp::semantic('%s')\n", toChars()); | |
5559 #endif | |
5560 if (!type) | |
5561 { | |
5562 e1 = e1->semantic(sc); | |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
639
diff
changeset
|
5563 // 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
|
5564 type = new TypeDelegate(func->type->syntaxCopy()); |
159 | 5565 type = type->semantic(loc, sc); |
5566 AggregateDeclaration *ad = func->toParent()->isAggregateDeclaration(); | |
336 | 5567 if (func->needThis()) |
5568 e1 = getRightThis(loc, sc, ad, e1, func); | |
159 | 5569 } |
5570 return this; | |
5571 } | |
5572 | |
5573 void DelegateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
5574 { | |
5575 buf->writeByte('&'); | |
5576 if (!func->isNested()) | |
5577 { | |
5578 expToCBuffer(buf, hgs, e1, PREC_primary); | |
5579 buf->writeByte('.'); | |
5580 } | |
5581 buf->writestring(func->toChars()); | |
5582 } | |
5583 | |
5584 /************************************************************/ | |
5585 | |
5586 DotTypeExp::DotTypeExp(Loc loc, Expression *e, Dsymbol *s) | |
5587 : UnaExp(loc, TOKdottype, sizeof(DotTypeExp), e) | |
5588 { | |
5589 this->sym = s; | |
5590 this->type = s->getType(); | |
5591 } | |
5592 | |
5593 Expression *DotTypeExp::semantic(Scope *sc) | |
5594 { | |
5595 #if LOGSEMANTIC | |
5596 printf("DotTypeExp::semantic('%s')\n", toChars()); | |
5597 #endif | |
5598 UnaExp::semantic(sc); | |
5599 return this; | |
5600 } | |
5601 | |
5602 void DotTypeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
5603 { | |
5604 expToCBuffer(buf, hgs, e1, PREC_primary); | |
5605 buf->writeByte('.'); | |
5606 buf->writestring(sym->toChars()); | |
5607 } | |
5608 | |
5609 /************************************************************/ | |
5610 | |
5611 CallExp::CallExp(Loc loc, Expression *e, Expressions *exps) | |
5612 : UnaExp(loc, TOKcall, sizeof(CallExp), e) | |
5613 { | |
5614 this->arguments = exps; | |
5615 } | |
5616 | |
5617 CallExp::CallExp(Loc loc, Expression *e) | |
5618 : UnaExp(loc, TOKcall, sizeof(CallExp), e) | |
5619 { | |
5620 this->arguments = NULL; | |
5621 } | |
5622 | |
5623 CallExp::CallExp(Loc loc, Expression *e, Expression *earg1) | |
5624 : UnaExp(loc, TOKcall, sizeof(CallExp), e) | |
5625 { | |
5626 Expressions *arguments = new Expressions(); | |
5627 arguments->setDim(1); | |
5628 arguments->data[0] = (void *)earg1; | |
5629 | |
5630 this->arguments = arguments; | |
5631 } | |
5632 | |
5633 CallExp::CallExp(Loc loc, Expression *e, Expression *earg1, Expression *earg2) | |
5634 : UnaExp(loc, TOKcall, sizeof(CallExp), e) | |
5635 { | |
5636 Expressions *arguments = new Expressions(); | |
5637 arguments->setDim(2); | |
5638 arguments->data[0] = (void *)earg1; | |
5639 arguments->data[1] = (void *)earg2; | |
5640 | |
5641 this->arguments = arguments; | |
5642 } | |
5643 | |
5644 Expression *CallExp::syntaxCopy() | |
5645 { | |
5646 return new CallExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments)); | |
5647 } | |
5648 | |
5649 | |
5650 Expression *CallExp::semantic(Scope *sc) | |
5651 { | |
5652 TypeFunction *tf; | |
5653 FuncDeclaration *f; | |
5654 int i; | |
5655 Type *t1; | |
5656 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
|
5657 Objects *targsi = NULL; // initial list of template arguments |
159 | 5658 |
5659 #if LOGSEMANTIC | |
5660 printf("CallExp::semantic() %s\n", toChars()); | |
5661 #endif | |
5662 if (type) | |
5663 return this; // semantic() already run | |
5664 #if 0 | |
5665 if (arguments && arguments->dim) | |
5666 { | |
5667 Expression *earg = (Expression *)arguments->data[0]; | |
5668 earg->print(); | |
5669 if (earg->type) earg->type->print(); | |
5670 } | |
5671 #endif | |
5672 | |
5673 if (e1->op == TOKdelegate) | |
5674 { DelegateExp *de = (DelegateExp *)e1; | |
5675 | |
5676 e1 = new DotVarExp(de->loc, de->e1, de->func); | |
5677 return semantic(sc); | |
5678 } | |
5679 | |
5680 /* Transform: | |
5681 * array.id(args) into id(array,args) | |
5682 * aa.remove(arg) into delete aa[arg] | |
5683 */ | |
5684 if (e1->op == TOKdot) | |
5685 { | |
5686 // BUG: we should handle array.a.b.c.e(args) too | |
5687 | |
5688 DotIdExp *dotid = (DotIdExp *)(e1); | |
5689 dotid->e1 = dotid->e1->semantic(sc); | |
5690 assert(dotid->e1); | |
5691 if (dotid->e1->type) | |
5692 { | |
5693 TY e1ty = dotid->e1->type->toBasetype()->ty; | |
5694 if (e1ty == Taarray && dotid->ident == Id::remove) | |
5695 { | |
5696 if (!arguments || arguments->dim != 1) | |
5697 { error("expected key as argument to aa.remove()"); | |
5698 goto Lagain; | |
5699 } | |
5700 Expression *key = (Expression *)arguments->data[0]; | |
5701 key = key->semantic(sc); | |
5702 key = resolveProperties(sc, key); | |
5703 key->rvalue(); | |
5704 | |
5705 TypeAArray *taa = (TypeAArray *)dotid->e1->type->toBasetype(); | |
5706 key = key->implicitCastTo(sc, taa->index); | |
5707 key = key->implicitCastTo(sc, taa->key); | |
5708 | |
5709 return new RemoveExp(loc, dotid->e1, key); | |
5710 } | |
5711 else if (e1ty == Tarray || e1ty == Tsarray || e1ty == Taarray) | |
5712 { | |
5713 if (!arguments) | |
5714 arguments = new Expressions(); | |
5715 arguments->shift(dotid->e1); | |
5716 e1 = new IdentifierExp(dotid->loc, dotid->ident); | |
5717 } | |
5718 } | |
5719 } | |
5720 | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5721 #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
|
5722 /* 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
|
5723 * 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
|
5724 */ |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5725 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
|
5726 { 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
|
5727 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
|
5728 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
|
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 /* 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
|
5731 * 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
|
5732 */ |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5733 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
|
5734 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
|
5735 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
|
5736 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
|
5737 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
|
5738 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
|
5739 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5740 /* 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
|
5741 */ |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5742 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
|
5743 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
|
5744 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
|
5745 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5746 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5747 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5748 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5749 /* 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
|
5750 * 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
|
5751 */ |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5752 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
|
5753 { 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
|
5754 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
|
5755 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
|
5756 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5757 /* 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
|
5758 * 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
|
5759 */ |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5760 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
|
5761 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
|
5762 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
|
5763 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
|
5764 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
|
5765 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
|
5766 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
|
5767 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5768 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
|
5769 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
|
5770 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
|
5771 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5772 else |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5773 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
|
5774 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5775 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5776 #endif |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
5777 |
159 | 5778 istemp = 0; |
5779 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
|
5780 //printf("Lagain: %s\n", toChars()); |
159 | 5781 f = NULL; |
5782 if (e1->op == TOKthis || e1->op == TOKsuper) | |
5783 { | |
5784 // semantic() run later for these | |
5785 } | |
5786 else | |
5787 { | |
5788 UnaExp::semantic(sc); | |
5789 | |
5790 /* Look for e1 being a lazy parameter | |
5791 */ | |
5792 if (e1->op == TOKvar) | |
5793 { VarExp *ve = (VarExp *)e1; | |
5794 | |
5795 if (ve->var->storage_class & STClazy) | |
5796 { | |
5797 TypeFunction *tf = new TypeFunction(NULL, ve->var->type, 0, LINKd); | |
5798 TypeDelegate *t = new TypeDelegate(tf); | |
5799 ve->type = t->semantic(loc, sc); | |
5800 } | |
5801 } | |
5802 | |
5803 if (e1->op == TOKimport) | |
5804 { // Perhaps this should be moved to ScopeExp::semantic() | |
5805 ScopeExp *se = (ScopeExp *)e1; | |
5806 e1 = new DsymbolExp(loc, se->sds); | |
5807 e1 = e1->semantic(sc); | |
5808 } | |
5809 #if 1 // patch for #540 by Oskar Linde | |
5810 else if (e1->op == TOKdotexp) | |
5811 { | |
5812 DotExp *de = (DotExp *) e1; | |
5813 | |
5814 if (de->e2->op == TOKimport) | |
5815 { // This should *really* be moved to ScopeExp::semantic() | |
5816 ScopeExp *se = (ScopeExp *)de->e2; | |
5817 de->e2 = new DsymbolExp(loc, se->sds); | |
5818 de->e2 = de->e2->semantic(sc); | |
5819 } | |
5820 | |
5821 if (de->e2->op == TOKtemplate) | |
5822 { TemplateExp *te = (TemplateExp *) de->e2; | |
5823 e1 = new DotTemplateExp(loc,de->e1,te->td); | |
5824 } | |
5825 } | |
5826 #endif | |
5827 } | |
5828 | |
5829 if (e1->op == TOKcomma) | |
5830 { | |
5831 CommaExp *ce = (CommaExp *)e1; | |
5832 | |
5833 e1 = ce->e2; | |
5834 e1->type = ce->type; | |
5835 ce->e2 = this; | |
5836 ce->type = NULL; | |
5837 return ce->semantic(sc); | |
5838 } | |
5839 | |
5840 t1 = NULL; | |
5841 if (e1->type) | |
5842 t1 = e1->type->toBasetype(); | |
5843 | |
5844 // Check for call operator overload | |
5845 if (t1) | |
5846 { AggregateDeclaration *ad; | |
5847 | |
5848 if (t1->ty == Tstruct) | |
5849 { | |
5850 ad = ((TypeStruct *)t1)->sym; | |
5851 if (search_function(ad, Id::call)) | |
5852 goto L1; // overload of opCall, therefore it's a call | |
5853 | |
5854 if (e1->op != TOKtype) | |
5855 error("%s %s does not overload ()", ad->kind(), ad->toChars()); | |
5856 /* It's a struct literal | |
5857 */ | |
5858 Expression *e = new StructLiteralExp(loc, (StructDeclaration *)ad, arguments); | |
5859 e = e->semantic(sc); | |
5860 e->type = e1->type; // in case e1->type was a typedef | |
5861 return e; | |
5862 } | |
5863 else if (t1->ty == Tclass) | |
5864 { | |
5865 ad = ((TypeClass *)t1)->sym; | |
5866 goto L1; | |
5867 L1: | |
5868 // Rewrite as e1.call(arguments) | |
5869 Expression *e = new DotIdExp(loc, e1, Id::call); | |
5870 e = new CallExp(loc, e, arguments); | |
5871 e = e->semantic(sc); | |
5872 return e; | |
5873 } | |
5874 } | |
5875 | |
5876 arrayExpressionSemantic(arguments, sc); | |
5877 preFunctionArguments(loc, sc, arguments); | |
5878 | |
5879 if (e1->op == TOKdotvar && t1->ty == Tfunction || | |
5880 e1->op == TOKdottd) | |
5881 { | |
5882 DotVarExp *dve; | |
5883 DotTemplateExp *dte; | |
5884 AggregateDeclaration *ad; | |
5885 UnaExp *ue = (UnaExp *)(e1); | |
336 | 5886 |
159 | 5887 if (e1->op == TOKdotvar) |
5888 { // Do overload resolution | |
5889 dve = (DotVarExp *)(e1); | |
5890 | |
5891 f = dve->var->isFuncDeclaration(); | |
5892 assert(f); | |
5893 f = f->overloadResolve(loc, arguments); | |
5894 | |
5895 ad = f->toParent()->isAggregateDeclaration(); | |
5896 } | |
5897 else | |
5898 { dte = (DotTemplateExp *)(e1); | |
5899 TemplateDeclaration *td = dte->td; | |
5900 assert(td); | |
5901 if (!arguments) | |
5902 // Should fix deduceFunctionTemplate() so it works on NULL argument | |
5903 arguments = new Expressions(); | |
5904 f = td->deduceFunctionTemplate(sc, loc, NULL, arguments); | |
5905 if (!f) | |
5906 { type = Type::terror; | |
5907 return this; | |
5908 } | |
5909 ad = td->toParent()->isAggregateDeclaration(); | |
5910 } | |
336 | 5911 if (f->needThis()) |
5912 { | |
5913 ue->e1 = getRightThis(loc, sc, ad, ue->e1, f); | |
5914 } | |
5915 | |
5916 /* Cannot call public functions from inside invariant | |
5917 * (because then the invariant would have infinite recursion) | |
159 | 5918 */ |
336 | 5919 if (sc->func && sc->func->isInvariantDeclaration() && |
5920 ue->e1->op == TOKthis && | |
5921 f->addPostInvariant() | |
159 | 5922 ) |
5923 { | |
336 | 5924 error("cannot call public/export function %s from invariant", f->toChars()); |
159 | 5925 } |
5926 | |
5927 checkDeprecated(sc, f); | |
5928 accessCheck(loc, sc, ue->e1, f); | |
5929 if (!f->needThis()) | |
5930 { | |
5931 VarExp *ve = new VarExp(loc, f); | |
5932 e1 = new CommaExp(loc, ue->e1, ve); | |
5933 e1->type = f->type; | |
5934 } | |
5935 else | |
5936 { | |
5937 if (e1->op == TOKdotvar) | |
5938 dve->var = f; | |
5939 else | |
5940 e1 = new DotVarExp(loc, dte->e1, f); | |
5941 e1->type = f->type; | |
5942 | |
5943 // See if we need to adjust the 'this' pointer | |
5944 AggregateDeclaration *ad = f->isThis(); | |
5945 ClassDeclaration *cd = ue->e1->type->isClassHandle(); | |
5946 if (ad && cd && ad->isClassDeclaration() && ad != cd && | |
5947 ue->e1->op != TOKsuper) | |
5948 { | |
5949 ue->e1 = ue->e1->castTo(sc, ad->type); //new CastExp(loc, ue->e1, ad->type); | |
5950 ue->e1 = ue->e1->semantic(sc); | |
5951 } | |
5952 } | |
5953 t1 = e1->type; | |
5954 } | |
5955 else if (e1->op == TOKsuper) | |
5956 { | |
5957 // Base class constructor call | |
5958 ClassDeclaration *cd = NULL; | |
5959 | |
5960 if (sc->func) | |
5961 cd = sc->func->toParent()->isClassDeclaration(); | |
5962 if (!cd || !cd->baseClass || !sc->func->isCtorDeclaration()) | |
5963 { | |
5964 error("super class constructor call must be in a constructor"); | |
5965 type = Type::terror; | |
5966 return this; | |
5967 } | |
5968 else | |
5969 { | |
5970 f = cd->baseClass->ctor; | |
5971 if (!f) | |
5972 { error("no super class constructor for %s", cd->baseClass->toChars()); | |
5973 type = Type::terror; | |
5974 return this; | |
5975 } | |
5976 else | |
5977 { | |
336 | 5978 if (!sc->intypeof) |
5979 { | |
159 | 5980 #if 0 |
336 | 5981 if (sc->callSuper & (CSXthis | CSXsuper)) |
5982 error("reference to this before super()"); | |
159 | 5983 #endif |
336 | 5984 if (sc->noctor || sc->callSuper & CSXlabel) |
5985 error("constructor calls not allowed in loops or after labels"); | |
5986 if (sc->callSuper & (CSXsuper_ctor | CSXthis_ctor)) | |
5987 error("multiple constructor calls"); | |
5988 sc->callSuper |= CSXany_ctor | CSXsuper_ctor; | |
5989 } | |
159 | 5990 |
5991 f = f->overloadResolve(loc, arguments); | |
5992 checkDeprecated(sc, f); | |
5993 e1 = new DotVarExp(e1->loc, e1, f); | |
5994 e1 = e1->semantic(sc); | |
5995 t1 = e1->type; | |
5996 } | |
5997 } | |
5998 } | |
5999 else if (e1->op == TOKthis) | |
6000 { | |
6001 // same class constructor call | |
6002 ClassDeclaration *cd = NULL; | |
6003 | |
6004 if (sc->func) | |
6005 cd = sc->func->toParent()->isClassDeclaration(); | |
6006 if (!cd || !sc->func->isCtorDeclaration()) | |
6007 { | |
6008 error("class constructor call must be in a constructor"); | |
6009 type = Type::terror; | |
6010 return this; | |
6011 } | |
6012 else | |
6013 { | |
336 | 6014 if (!sc->intypeof) |
6015 { | |
159 | 6016 #if 0 |
336 | 6017 if (sc->callSuper & (CSXthis | CSXsuper)) |
6018 error("reference to this before super()"); | |
159 | 6019 #endif |
336 | 6020 if (sc->noctor || sc->callSuper & CSXlabel) |
6021 error("constructor calls not allowed in loops or after labels"); | |
6022 if (sc->callSuper & (CSXsuper_ctor | CSXthis_ctor)) | |
6023 error("multiple constructor calls"); | |
6024 sc->callSuper |= CSXany_ctor | CSXthis_ctor; | |
6025 } | |
159 | 6026 |
6027 f = cd->ctor; | |
6028 f = f->overloadResolve(loc, arguments); | |
6029 checkDeprecated(sc, f); | |
6030 e1 = new DotVarExp(e1->loc, e1, f); | |
6031 e1 = e1->semantic(sc); | |
6032 t1 = e1->type; | |
6033 | |
6034 // BUG: this should really be done by checking the static | |
6035 // call graph | |
6036 if (f == sc->func) | |
6037 error("cyclic constructor call"); | |
6038 } | |
6039 } | |
6040 else if (!t1) | |
6041 { | |
6042 error("function expected before (), not '%s'", e1->toChars()); | |
6043 type = Type::terror; | |
6044 return this; | |
6045 } | |
6046 else if (t1->ty != Tfunction) | |
6047 { | |
6048 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
|
6049 { 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
|
6050 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
|
6051 tf = (TypeFunction *)(td->next); |
159 | 6052 goto Lcheckargs; |
6053 } | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6054 else if (t1->ty == Tpointer && ((TypePointer *)t1)->next->ty == Tfunction) |
159 | 6055 { Expression *e; |
6056 | |
6057 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
|
6058 t1 = ((TypePointer *)t1)->next; |
159 | 6059 e->type = t1; |
6060 e1 = e; | |
6061 } | |
6062 else if (e1->op == TOKtemplate) | |
6063 { | |
6064 TemplateExp *te = (TemplateExp *)e1; | |
6065 f = te->td->deduceFunctionTemplate(sc, loc, NULL, arguments); | |
6066 if (!f) | |
6067 { type = Type::terror; | |
6068 return this; | |
6069 } | |
6070 if (f->needThis() && hasThis(sc)) | |
6071 { | |
6072 // Supply an implicit 'this', as in | |
6073 // this.ident | |
6074 | |
6075 e1 = new DotTemplateExp(loc, (new ThisExp(loc))->semantic(sc), te->td); | |
6076 goto Lagain; | |
6077 } | |
6078 | |
6079 e1 = new VarExp(loc, f); | |
6080 goto Lagain; | |
6081 } | |
6082 else | |
6083 { error("function expected before (), not %s of type %s", e1->toChars(), e1->type->toChars()); | |
6084 type = Type::terror; | |
6085 return this; | |
6086 } | |
6087 } | |
6088 else if (e1->op == TOKvar) | |
6089 { | |
6090 // Do overload resolution | |
6091 VarExp *ve = (VarExp *)e1; | |
6092 | |
6093 f = ve->var->isFuncDeclaration(); | |
6094 assert(f); | |
6095 | |
6096 // Look to see if f is really a function template | |
6097 if (0 && !istemp && f->parent) | |
6098 { TemplateInstance *ti = f->parent->isTemplateInstance(); | |
6099 | |
6100 if (ti && | |
6101 (ti->name == f->ident || | |
6102 ti->toAlias()->ident == f->ident) | |
6103 && | |
6104 ti->tempdecl) | |
6105 { | |
6106 /* This is so that one can refer to the enclosing | |
6107 * template, even if it has the same name as a member | |
6108 * of the template, if it has a !(arguments) | |
6109 */ | |
6110 TemplateDeclaration *tempdecl = ti->tempdecl; | |
6111 if (tempdecl->overroot) // if not start of overloaded list of TemplateDeclaration's | |
6112 tempdecl = tempdecl->overroot; // then get the start | |
6113 e1 = new TemplateExp(loc, tempdecl); | |
6114 istemp = 1; | |
6115 goto Lagain; | |
6116 } | |
6117 } | |
6118 | |
6119 f = f->overloadResolve(loc, arguments); | |
6120 checkDeprecated(sc, f); | |
6121 | |
6122 if (f->needThis() && hasThis(sc)) | |
6123 { | |
6124 // Supply an implicit 'this', as in | |
6125 // this.ident | |
6126 | |
6127 e1 = new DotVarExp(loc, new ThisExp(loc), f); | |
6128 goto Lagain; | |
6129 } | |
6130 | |
6131 accessCheck(loc, sc, NULL, f); | |
6132 | |
6133 ve->var = f; | |
6134 ve->type = f->type; | |
6135 t1 = f->type; | |
6136 } | |
6137 assert(t1->ty == Tfunction); | |
6138 tf = (TypeFunction *)(t1); | |
6139 | |
6140 Lcheckargs: | |
6141 assert(tf->ty == Tfunction); | |
6142 type = tf->next; | |
6143 | |
6144 if (!arguments) | |
6145 arguments = new Expressions(); | |
6146 functionArguments(loc, sc, tf, arguments); | |
6147 | |
6148 assert(type); | |
6149 | |
6150 if (f && f->tintro) | |
6151 { | |
6152 Type *t = type; | |
6153 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
|
6154 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
|
6155 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6156 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
|
6157 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6158 type = tf->next; |
159 | 6159 return castTo(sc, t); |
6160 } | |
6161 } | |
6162 | |
6163 return this; | |
6164 } | |
6165 | |
6166 int CallExp::checkSideEffect(int flag) | |
6167 { | |
6168 return 1; | |
6169 } | |
6170 | |
6171 Expression *CallExp::toLvalue(Scope *sc, Expression *e) | |
6172 { | |
6173 if (type->toBasetype()->ty == Tstruct) | |
6174 return this; | |
6175 else | |
6176 return Expression::toLvalue(sc, e); | |
6177 } | |
6178 | |
6179 void CallExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
6180 { int i; | |
6181 | |
6182 expToCBuffer(buf, hgs, e1, precedence[op]); | |
6183 buf->writeByte('('); | |
6184 argsToCBuffer(buf, arguments, hgs); | |
6185 buf->writeByte(')'); | |
6186 } | |
6187 | |
6188 | |
6189 /************************************************************/ | |
6190 | |
6191 AddrExp::AddrExp(Loc loc, Expression *e) | |
6192 : UnaExp(loc, TOKaddress, sizeof(AddrExp), e) | |
6193 { | |
6194 } | |
6195 | |
6196 Expression *AddrExp::semantic(Scope *sc) | |
6197 { | |
6198 #if LOGSEMANTIC | |
6199 printf("AddrExp::semantic('%s')\n", toChars()); | |
6200 #endif | |
6201 if (!type) | |
6202 { | |
6203 UnaExp::semantic(sc); | |
6204 e1 = e1->toLvalue(sc, NULL); | |
6205 if (!e1->type) | |
6206 { | |
6207 error("cannot take address of %s", e1->toChars()); | |
6208 type = Type::tint32; | |
6209 return this; | |
6210 } | |
6211 type = e1->type->pointerTo(); | |
6212 | |
6213 // See if this should really be a delegate | |
6214 if (e1->op == TOKdotvar) | |
6215 { | |
6216 DotVarExp *dve = (DotVarExp *)e1; | |
6217 FuncDeclaration *f = dve->var->isFuncDeclaration(); | |
6218 | |
6219 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
|
6220 { Expression *e = new DelegateExp(loc, dve->e1, f); |
159 | 6221 e = e->semantic(sc); |
6222 return e; | |
6223 } | |
6224 } | |
6225 else if (e1->op == TOKvar) | |
6226 { | |
6227 VarExp *dve = (VarExp *)e1; | |
6228 FuncDeclaration *f = dve->var->isFuncDeclaration(); | |
6229 VarDeclaration *v = dve->var->isVarDeclaration(); | |
6230 | |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
639
diff
changeset
|
6231 // 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
|
6232 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
|
6233 { |
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
|
6234 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
|
6235 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
|
6236 } |
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
|
6237 |
159 | 6238 if (f && f->isNested()) |
6239 { Expression *e; | |
6240 | |
6241 e = new DelegateExp(loc, e1, f); | |
6242 e = e->semantic(sc); | |
6243 return e; | |
6244 } | |
6245 } | |
6246 else if (e1->op == TOKarray) | |
6247 { | |
6248 if (e1->type->toBasetype()->ty == Tbit) | |
6249 error("cannot take address of bit in array"); | |
6250 } | |
6251 return optimize(WANTvalue); | |
6252 } | |
6253 return this; | |
6254 } | |
6255 | |
6256 /************************************************************/ | |
6257 | |
6258 PtrExp::PtrExp(Loc loc, Expression *e) | |
6259 : UnaExp(loc, TOKstar, sizeof(PtrExp), e) | |
6260 { | |
6261 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
|
6262 type = ((TypePointer *)e->type)->next; |
159 | 6263 } |
6264 | |
6265 PtrExp::PtrExp(Loc loc, Expression *e, Type *t) | |
6266 : UnaExp(loc, TOKstar, sizeof(PtrExp), e) | |
6267 { | |
6268 type = t; | |
6269 } | |
6270 | |
6271 Expression *PtrExp::semantic(Scope *sc) | |
6272 { Type *tb; | |
6273 | |
6274 #if LOGSEMANTIC | |
6275 printf("PtrExp::semantic('%s')\n", toChars()); | |
6276 #endif | |
6277 UnaExp::semantic(sc); | |
6278 e1 = resolveProperties(sc, e1); | |
6279 if (type) | |
6280 return this; | |
6281 if (!e1->type) | |
6282 printf("PtrExp::semantic('%s')\n", toChars()); | |
6283 tb = e1->type->toBasetype(); | |
6284 switch (tb->ty) | |
6285 { | |
6286 case Tpointer: | |
6287 type = tb->next; | |
6288 if (type->isbit()) | |
6289 { Expression *e; | |
6290 | |
6291 // Rewrite *p as p[0] | |
6292 e = new IndexExp(loc, e1, new IntegerExp(0)); | |
6293 return e->semantic(sc); | |
6294 } | |
6295 break; | |
6296 | |
6297 case Tsarray: | |
6298 case Tarray: | |
6299 type = tb->next; | |
6300 e1 = e1->castTo(sc, type->pointerTo()); | |
6301 break; | |
6302 | |
6303 default: | |
6304 error("can only * a pointer, not a '%s'", e1->type->toChars()); | |
6305 type = Type::tint32; | |
6306 break; | |
6307 } | |
6308 rvalue(); | |
6309 return this; | |
6310 } | |
6311 | |
6312 Expression *PtrExp::toLvalue(Scope *sc, Expression *e) | |
6313 { | |
6314 #if 0 | |
6315 tym = tybasic(e1->ET->Tty); | |
6316 if (!(tyscalar(tym) || | |
6317 tym == TYstruct || | |
6318 tym == TYarray && e->Eoper == TOKaddr)) | |
6319 synerr(EM_lvalue); // lvalue expected | |
6320 #endif | |
6321 return this; | |
6322 } | |
6323 | |
6324 void PtrExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
6325 { | |
6326 buf->writeByte('*'); | |
6327 expToCBuffer(buf, hgs, e1, precedence[op]); | |
6328 } | |
6329 | |
6330 /************************************************************/ | |
6331 | |
6332 NegExp::NegExp(Loc loc, Expression *e) | |
6333 : UnaExp(loc, TOKneg, sizeof(NegExp), e) | |
6334 { | |
6335 } | |
6336 | |
6337 Expression *NegExp::semantic(Scope *sc) | |
6338 { Expression *e; | |
6339 | |
6340 #if LOGSEMANTIC | |
6341 printf("NegExp::semantic('%s')\n", toChars()); | |
6342 #endif | |
6343 if (!type) | |
6344 { | |
6345 UnaExp::semantic(sc); | |
6346 e1 = resolveProperties(sc, e1); | |
6347 e = op_overload(sc); | |
6348 if (e) | |
6349 return e; | |
6350 | |
6351 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
|
6352 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
|
6353 e1->checkArithmetic(); |
159 | 6354 type = e1->type; |
6355 } | |
6356 return this; | |
6357 } | |
6358 | |
6359 /************************************************************/ | |
6360 | |
6361 UAddExp::UAddExp(Loc loc, Expression *e) | |
6362 : UnaExp(loc, TOKuadd, sizeof(UAddExp), e) | |
6363 { | |
6364 } | |
6365 | |
6366 Expression *UAddExp::semantic(Scope *sc) | |
6367 { Expression *e; | |
6368 | |
6369 #if LOGSEMANTIC | |
6370 printf("UAddExp::semantic('%s')\n", toChars()); | |
6371 #endif | |
6372 assert(!type); | |
6373 UnaExp::semantic(sc); | |
6374 e1 = resolveProperties(sc, e1); | |
6375 e = op_overload(sc); | |
6376 if (e) | |
6377 return e; | |
6378 e1->checkNoBool(); | |
6379 e1->checkArithmetic(); | |
6380 return e1; | |
6381 } | |
6382 | |
6383 /************************************************************/ | |
6384 | |
6385 ComExp::ComExp(Loc loc, Expression *e) | |
6386 : UnaExp(loc, TOKtilde, sizeof(ComExp), e) | |
6387 { | |
6388 } | |
6389 | |
6390 Expression *ComExp::semantic(Scope *sc) | |
6391 { Expression *e; | |
6392 | |
6393 if (!type) | |
6394 { | |
6395 UnaExp::semantic(sc); | |
6396 e1 = resolveProperties(sc, e1); | |
6397 e = op_overload(sc); | |
6398 if (e) | |
6399 return e; | |
6400 | |
6401 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
|
6402 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
|
6403 e1 = e1->checkIntegral(); |
159 | 6404 type = e1->type; |
6405 } | |
6406 return this; | |
6407 } | |
6408 | |
6409 /************************************************************/ | |
6410 | |
6411 NotExp::NotExp(Loc loc, Expression *e) | |
6412 : UnaExp(loc, TOKnot, sizeof(NotExp), e) | |
6413 { | |
6414 } | |
6415 | |
6416 Expression *NotExp::semantic(Scope *sc) | |
6417 { | |
6418 UnaExp::semantic(sc); | |
6419 e1 = resolveProperties(sc, e1); | |
6420 e1 = e1->checkToBoolean(); | |
6421 type = Type::tboolean; | |
6422 return this; | |
6423 } | |
6424 | |
6425 int NotExp::isBit() | |
6426 { | |
6427 return TRUE; | |
6428 } | |
6429 | |
6430 | |
6431 | |
6432 /************************************************************/ | |
6433 | |
6434 BoolExp::BoolExp(Loc loc, Expression *e, Type *t) | |
6435 : UnaExp(loc, TOKtobool, sizeof(BoolExp), e) | |
6436 { | |
6437 type = t; | |
6438 } | |
6439 | |
6440 Expression *BoolExp::semantic(Scope *sc) | |
6441 { | |
6442 UnaExp::semantic(sc); | |
6443 e1 = resolveProperties(sc, e1); | |
6444 e1 = e1->checkToBoolean(); | |
6445 type = Type::tboolean; | |
6446 return this; | |
6447 } | |
6448 | |
6449 int BoolExp::isBit() | |
6450 { | |
6451 return TRUE; | |
6452 } | |
6453 | |
6454 /************************************************************/ | |
6455 | |
6456 DeleteExp::DeleteExp(Loc loc, Expression *e) | |
6457 : UnaExp(loc, TOKdelete, sizeof(DeleteExp), e) | |
6458 { | |
6459 } | |
6460 | |
6461 Expression *DeleteExp::semantic(Scope *sc) | |
6462 { | |
6463 Type *tb; | |
6464 | |
6465 UnaExp::semantic(sc); | |
6466 e1 = resolveProperties(sc, e1); | |
6467 e1 = e1->toLvalue(sc, NULL); | |
6468 type = Type::tvoid; | |
6469 | |
6470 tb = e1->type->toBasetype(); | |
6471 switch (tb->ty) | |
6472 { case Tclass: | |
6473 { TypeClass *tc = (TypeClass *)tb; | |
6474 ClassDeclaration *cd = tc->sym; | |
6475 | |
6476 if (cd->isCOMinterface()) | |
6477 { /* Because COM classes are deleted by IUnknown.Release() | |
6478 */ | |
6479 error("cannot delete instance of COM interface %s", cd->toChars()); | |
6480 } | |
6481 break; | |
6482 } | |
6483 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
|
6484 tb = ((TypePointer *)tb)->next->toBasetype(); |
159 | 6485 if (tb->ty == Tstruct) |
6486 { | |
6487 TypeStruct *ts = (TypeStruct *)tb; | |
6488 StructDeclaration *sd = ts->sym; | |
6489 FuncDeclaration *f = sd->aggDelete; | |
6490 | |
6491 if (f) | |
6492 { | |
6493 Type *tpv = Type::tvoid->pointerTo(); | |
6494 | |
6495 Expression *e = e1->castTo(sc, tpv); | |
6496 Expression *ec = new VarExp(loc, f); | |
6497 e = new CallExp(loc, ec, e); | |
6498 return e->semantic(sc); | |
6499 } | |
6500 } | |
6501 break; | |
6502 | |
6503 case Tarray: | |
6504 break; | |
6505 | |
6506 default: | |
6507 if (e1->op == TOKindex) | |
6508 { | |
6509 IndexExp *ae = (IndexExp *)(e1); | |
6510 Type *tb1 = ae->e1->type->toBasetype(); | |
6511 if (tb1->ty == Taarray) | |
6512 break; | |
6513 } | |
6514 error("cannot delete type %s", e1->type->toChars()); | |
6515 break; | |
6516 } | |
6517 | |
6518 if (e1->op == TOKindex) | |
6519 { | |
6520 IndexExp *ae = (IndexExp *)(e1); | |
6521 Type *tb1 = ae->e1->type->toBasetype(); | |
6522 if (tb1->ty == Taarray) | |
6523 { if (!global.params.useDeprecated) | |
6524 error("delete aa[key] deprecated, use aa.remove(key)"); | |
6525 } | |
6526 } | |
6527 | |
6528 return this; | |
6529 } | |
6530 | |
6531 int DeleteExp::checkSideEffect(int flag) | |
6532 { | |
6533 return 1; | |
6534 } | |
6535 | |
6536 Expression *DeleteExp::checkToBoolean() | |
6537 { | |
6538 error("delete does not give a boolean result"); | |
6539 return this; | |
6540 } | |
6541 | |
6542 void DeleteExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
6543 { | |
6544 buf->writestring("delete "); | |
6545 expToCBuffer(buf, hgs, e1, precedence[op]); | |
6546 } | |
6547 | |
6548 /************************************************************/ | |
6549 | |
6550 CastExp::CastExp(Loc loc, Expression *e, Type *t) | |
6551 : UnaExp(loc, TOKcast, sizeof(CastExp), e) | |
6552 { | |
6553 to = t; | |
6554 } | |
6555 | |
6556 Expression *CastExp::syntaxCopy() | |
6557 { | |
6558 return new CastExp(loc, e1->syntaxCopy(), to->syntaxCopy()); | |
6559 } | |
6560 | |
6561 | |
6562 Expression *CastExp::semantic(Scope *sc) | |
6563 { Expression *e; | |
6564 BinExp *b; | |
6565 UnaExp *u; | |
6566 | |
6567 #if LOGSEMANTIC | |
6568 printf("CastExp::semantic('%s')\n", toChars()); | |
6569 #endif | |
6570 | |
6571 //static int x; assert(++x < 10); | |
6572 | |
6573 if (type) | |
6574 return this; | |
6575 UnaExp::semantic(sc); | |
6576 if (e1->type) // if not a tuple | |
6577 { | |
6578 e1 = resolveProperties(sc, e1); | |
6579 to = to->semantic(loc, sc); | |
6580 | |
6581 e = op_overload(sc); | |
6582 if (e) | |
6583 { | |
6584 return e->implicitCastTo(sc, to); | |
6585 } | |
6586 | |
6587 Type *tob = to->toBasetype(); | |
6588 if (tob->ty == Tstruct && | |
6589 !tob->equals(e1->type->toBasetype()) && | |
6590 ((TypeStruct *)to)->sym->search(0, Id::call, 0) | |
6591 ) | |
6592 { | |
6593 /* Look to replace: | |
6594 * cast(S)t | |
6595 * with: | |
6596 * S(t) | |
6597 */ | |
6598 | |
6599 // Rewrite as to.call(e1) | |
6600 e = new TypeExp(loc, to); | |
6601 e = new DotIdExp(loc, e, Id::call); | |
6602 e = new CallExp(loc, e, e1); | |
6603 e = e->semantic(sc); | |
6604 return e; | |
6605 } | |
6606 } | |
6607 e = e1->castTo(sc, to); | |
6608 return e; | |
6609 } | |
6610 | |
6611 int CastExp::checkSideEffect(int flag) | |
6612 { | |
6613 /* if not: | |
6614 * cast(void) | |
6615 * cast(classtype)func() | |
6616 */ | |
6617 if (!to->equals(Type::tvoid) && | |
6618 !(to->ty == Tclass && e1->op == TOKcall && e1->type->ty == Tclass)) | |
6619 return Expression::checkSideEffect(flag); | |
6620 return 1; | |
6621 } | |
6622 | |
6623 void CastExp::checkEscape() | |
6624 { Type *tb = type->toBasetype(); | |
6625 if (tb->ty == Tarray && e1->op == TOKvar && | |
6626 e1->type->toBasetype()->ty == Tsarray) | |
6627 { VarExp *ve = (VarExp *)e1; | |
6628 VarDeclaration *v = ve->var->isVarDeclaration(); | |
6629 if (v) | |
6630 { | |
6631 if (!v->isDataseg() && !v->isParameter()) | |
6632 error("escaping reference to local %s", v->toChars()); | |
6633 } | |
6634 } | |
6635 } | |
6636 | |
6637 void CastExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
6638 { | |
6639 buf->writestring("cast("); | |
6640 to->toCBuffer(buf, NULL, hgs); | |
6641 buf->writeByte(')'); | |
6642 expToCBuffer(buf, hgs, e1, precedence[op]); | |
6643 } | |
6644 | |
6645 | |
6646 /************************************************************/ | |
6647 | |
6648 SliceExp::SliceExp(Loc loc, Expression *e1, Expression *lwr, Expression *upr) | |
6649 : UnaExp(loc, TOKslice, sizeof(SliceExp), e1) | |
6650 { | |
6651 this->upr = upr; | |
6652 this->lwr = lwr; | |
6653 lengthVar = NULL; | |
6654 } | |
6655 | |
6656 Expression *SliceExp::syntaxCopy() | |
6657 { | |
6658 Expression *lwr = NULL; | |
6659 if (this->lwr) | |
6660 lwr = this->lwr->syntaxCopy(); | |
6661 | |
6662 Expression *upr = NULL; | |
6663 if (this->upr) | |
6664 upr = this->upr->syntaxCopy(); | |
6665 | |
6666 return new SliceExp(loc, e1->syntaxCopy(), lwr, upr); | |
6667 } | |
6668 | |
6669 Expression *SliceExp::semantic(Scope *sc) | |
6670 { Expression *e; | |
6671 AggregateDeclaration *ad; | |
6672 //FuncDeclaration *fd; | |
6673 ScopeDsymbol *sym; | |
6674 | |
6675 #if LOGSEMANTIC | |
6676 printf("SliceExp::semantic('%s')\n", toChars()); | |
6677 #endif | |
6678 if (type) | |
6679 return this; | |
6680 | |
6681 UnaExp::semantic(sc); | |
6682 e1 = resolveProperties(sc, e1); | |
6683 | |
6684 e = this; | |
6685 | |
6686 Type *t = e1->type->toBasetype(); | |
6687 if (t->ty == Tpointer) | |
6688 { | |
6689 if (!lwr || !upr) | |
6690 error("need upper and lower bound to slice pointer"); | |
6691 } | |
6692 else if (t->ty == Tarray) | |
6693 { | |
6694 } | |
6695 else if (t->ty == Tsarray) | |
6696 { | |
6697 } | |
6698 else if (t->ty == Tclass) | |
6699 { | |
6700 ad = ((TypeClass *)t)->sym; | |
6701 goto L1; | |
6702 } | |
6703 else if (t->ty == Tstruct) | |
6704 { | |
6705 ad = ((TypeStruct *)t)->sym; | |
6706 | |
6707 L1: | |
6708 if (search_function(ad, Id::slice)) | |
6709 { | |
6710 // Rewrite as e1.slice(lwr, upr) | |
6711 e = new DotIdExp(loc, e1, Id::slice); | |
6712 | |
6713 if (lwr) | |
6714 { | |
6715 assert(upr); | |
6716 e = new CallExp(loc, e, lwr, upr); | |
6717 } | |
6718 else | |
6719 { assert(!upr); | |
6720 e = new CallExp(loc, e); | |
6721 } | |
6722 e = e->semantic(sc); | |
6723 return e; | |
6724 } | |
6725 goto Lerror; | |
6726 } | |
6727 else if (t->ty == Ttuple) | |
6728 { | |
6729 if (!lwr && !upr) | |
6730 return e1; | |
6731 if (!lwr || !upr) | |
6732 { error("need upper and lower bound to slice tuple"); | |
6733 goto Lerror; | |
6734 } | |
6735 } | |
6736 else | |
6737 goto Lerror; | |
6738 | |
6739 if (t->ty == Tsarray || t->ty == Tarray || t->ty == Ttuple) | |
6740 { | |
6741 sym = new ArrayScopeSymbol(this); | |
6742 sym->loc = loc; | |
6743 sym->parent = sc->scopesym; | |
6744 sc = sc->push(sym); | |
6745 } | |
6746 | |
6747 if (lwr) | |
6748 { lwr = lwr->semantic(sc); | |
6749 lwr = resolveProperties(sc, lwr); | |
6750 lwr = lwr->implicitCastTo(sc, Type::tsize_t); | |
6751 } | |
6752 if (upr) | |
6753 { upr = upr->semantic(sc); | |
6754 upr = resolveProperties(sc, upr); | |
6755 upr = upr->implicitCastTo(sc, Type::tsize_t); | |
6756 } | |
6757 | |
6758 if (t->ty == Tsarray || t->ty == Tarray || t->ty == Ttuple) | |
6759 sc->pop(); | |
6760 | |
6761 if (t->ty == Ttuple) | |
6762 { | |
6763 lwr = lwr->optimize(WANTvalue); | |
6764 upr = upr->optimize(WANTvalue); | |
6765 uinteger_t i1 = lwr->toUInteger(); | |
6766 uinteger_t i2 = upr->toUInteger(); | |
6767 | |
6768 size_t length; | |
6769 TupleExp *te; | |
6770 TypeTuple *tup; | |
6771 | |
6772 if (e1->op == TOKtuple) // slicing an expression tuple | |
6773 { te = (TupleExp *)e1; | |
6774 length = te->exps->dim; | |
6775 } | |
6776 else if (e1->op == TOKtype) // slicing a type tuple | |
6777 { tup = (TypeTuple *)t; | |
6778 length = Argument::dim(tup->arguments); | |
6779 } | |
6780 else | |
6781 assert(0); | |
6782 | |
6783 if (i1 <= i2 && i2 <= length) | |
6784 { size_t j1 = (size_t) i1; | |
6785 size_t j2 = (size_t) i2; | |
6786 | |
6787 if (e1->op == TOKtuple) | |
6788 { Expressions *exps = new Expressions; | |
6789 exps->setDim(j2 - j1); | |
6790 for (size_t i = 0; i < j2 - j1; i++) | |
6791 { Expression *e = (Expression *)te->exps->data[j1 + i]; | |
6792 exps->data[i] = (void *)e; | |
6793 } | |
6794 e = new TupleExp(loc, exps); | |
6795 } | |
6796 else | |
6797 { Arguments *args = new Arguments; | |
6798 args->reserve(j2 - j1); | |
6799 for (size_t i = j1; i < j2; i++) | |
6800 { Argument *arg = Argument::getNth(tup->arguments, i); | |
6801 args->push(arg); | |
6802 } | |
6803 e = new TypeExp(e1->loc, new TypeTuple(args)); | |
6804 } | |
6805 e = e->semantic(sc); | |
6806 } | |
6807 else | |
6808 { | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
6809 error("string slice [%llu .. %llu] is out of bounds", i1, i2); |
159 | 6810 e = e1; |
6811 } | |
6812 return e; | |
6813 } | |
6814 | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
6815 type = t->nextOf()->arrayOf(); |
159 | 6816 return e; |
6817 | |
6818 Lerror: | |
6819 char *s; | |
6820 if (t->ty == Tvoid) | |
6821 s = e1->toChars(); | |
6822 else | |
6823 s = t->toChars(); | |
6824 error("%s cannot be sliced with []", s); | |
6825 type = Type::terror; | |
6826 return e; | |
6827 } | |
6828 | |
6829 void SliceExp::checkEscape() | |
6830 { | |
6831 e1->checkEscape(); | |
6832 } | |
6833 | |
6834 Expression *SliceExp::toLvalue(Scope *sc, Expression *e) | |
6835 { | |
6836 return this; | |
6837 } | |
6838 | |
6839 Expression *SliceExp::modifiableLvalue(Scope *sc, Expression *e) | |
6840 { | |
6841 error("slice expression %s is not a modifiable lvalue", toChars()); | |
6842 return this; | |
6843 } | |
6844 | |
6845 void SliceExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
6846 { | |
6847 expToCBuffer(buf, hgs, e1, precedence[op]); | |
6848 buf->writeByte('['); | |
6849 if (upr || lwr) | |
6850 { | |
6851 if (lwr) | |
6852 expToCBuffer(buf, hgs, lwr, PREC_assign); | |
6853 else | |
6854 buf->writeByte('0'); | |
6855 buf->writestring(".."); | |
6856 if (upr) | |
6857 expToCBuffer(buf, hgs, upr, PREC_assign); | |
6858 else | |
6859 buf->writestring("length"); // BUG: should be array.length | |
6860 } | |
6861 buf->writeByte(']'); | |
6862 } | |
6863 | |
6864 /********************** ArrayLength **************************************/ | |
6865 | |
6866 ArrayLengthExp::ArrayLengthExp(Loc loc, Expression *e1) | |
6867 : UnaExp(loc, TOKarraylength, sizeof(ArrayLengthExp), e1) | |
6868 { | |
6869 } | |
6870 | |
6871 Expression *ArrayLengthExp::semantic(Scope *sc) | |
6872 { Expression *e; | |
6873 | |
6874 #if LOGSEMANTIC | |
6875 printf("ArrayLengthExp::semantic('%s')\n", toChars()); | |
6876 #endif | |
6877 if (!type) | |
6878 { | |
6879 UnaExp::semantic(sc); | |
6880 e1 = resolveProperties(sc, e1); | |
6881 | |
6882 type = Type::tsize_t; | |
6883 } | |
6884 return this; | |
6885 } | |
6886 | |
6887 void ArrayLengthExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
6888 { | |
6889 expToCBuffer(buf, hgs, e1, PREC_primary); | |
6890 buf->writestring(".length"); | |
6891 } | |
6892 | |
6893 /*********************** ArrayExp *************************************/ | |
6894 | |
6895 // e1 [ i1, i2, i3, ... ] | |
6896 | |
6897 ArrayExp::ArrayExp(Loc loc, Expression *e1, Expressions *args) | |
6898 : UnaExp(loc, TOKarray, sizeof(ArrayExp), e1) | |
6899 { | |
6900 arguments = args; | |
6901 } | |
6902 | |
6903 Expression *ArrayExp::syntaxCopy() | |
6904 { | |
6905 return new ArrayExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments)); | |
6906 } | |
6907 | |
6908 Expression *ArrayExp::semantic(Scope *sc) | |
6909 { Expression *e; | |
6910 Type *t1; | |
6911 | |
6912 #if LOGSEMANTIC | |
6913 printf("ArrayExp::semantic('%s')\n", toChars()); | |
6914 #endif | |
6915 UnaExp::semantic(sc); | |
6916 e1 = resolveProperties(sc, e1); | |
6917 | |
6918 t1 = e1->type->toBasetype(); | |
6919 if (t1->ty != Tclass && t1->ty != Tstruct) | |
6920 { // Convert to IndexExp | |
6921 if (arguments->dim != 1) | |
6922 error("only one index allowed to index %s", t1->toChars()); | |
6923 e = new IndexExp(loc, e1, (Expression *)arguments->data[0]); | |
6924 return e->semantic(sc); | |
6925 } | |
6926 | |
6927 // Run semantic() on each argument | |
6928 for (size_t i = 0; i < arguments->dim; i++) | |
6929 { e = (Expression *)arguments->data[i]; | |
6930 | |
6931 e = e->semantic(sc); | |
6932 if (!e->type) | |
6933 error("%s has no value", e->toChars()); | |
6934 arguments->data[i] = (void *)e; | |
6935 } | |
6936 | |
6937 expandTuples(arguments); | |
6938 assert(arguments && arguments->dim); | |
6939 | |
6940 e = op_overload(sc); | |
6941 if (!e) | |
6942 { error("no [] operator overload for type %s", e1->type->toChars()); | |
6943 e = e1; | |
6944 } | |
6945 return e; | |
6946 } | |
6947 | |
6948 | |
6949 Expression *ArrayExp::toLvalue(Scope *sc, Expression *e) | |
6950 { | |
6951 if (type && type->toBasetype()->ty == Tvoid) | |
6952 error("voids have no value"); | |
6953 return this; | |
6954 } | |
6955 | |
6956 | |
6957 void ArrayExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
6958 { int i; | |
6959 | |
6960 expToCBuffer(buf, hgs, e1, PREC_primary); | |
6961 buf->writeByte('['); | |
6962 argsToCBuffer(buf, arguments, hgs); | |
6963 buf->writeByte(']'); | |
6964 } | |
6965 | |
6966 /************************* DotExp ***********************************/ | |
6967 | |
6968 DotExp::DotExp(Loc loc, Expression *e1, Expression *e2) | |
6969 : BinExp(loc, TOKdotexp, sizeof(DotExp), e1, e2) | |
6970 { | |
6971 } | |
6972 | |
6973 Expression *DotExp::semantic(Scope *sc) | |
6974 { | |
6975 #if LOGSEMANTIC | |
6976 printf("DotExp::semantic('%s')\n", toChars()); | |
6977 if (type) printf("\ttype = %s\n", type->toChars()); | |
6978 #endif | |
6979 e1 = e1->semantic(sc); | |
6980 e2 = e2->semantic(sc); | |
6981 if (e2->op == TOKimport) | |
6982 { | |
6983 ScopeExp *se = (ScopeExp *)e2; | |
6984 TemplateDeclaration *td = se->sds->isTemplateDeclaration(); | |
6985 if (td) | |
6986 { Expression *e = new DotTemplateExp(loc, e1, td); | |
6987 e = e->semantic(sc); | |
6988 return e; | |
6989 } | |
6990 } | |
6991 if (!type) | |
6992 type = e2->type; | |
6993 return this; | |
6994 } | |
6995 | |
6996 | |
6997 /************************* CommaExp ***********************************/ | |
6998 | |
6999 CommaExp::CommaExp(Loc loc, Expression *e1, Expression *e2) | |
7000 : BinExp(loc, TOKcomma, sizeof(CommaExp), e1, e2) | |
7001 { | |
7002 } | |
7003 | |
7004 Expression *CommaExp::semantic(Scope *sc) | |
7005 { | |
7006 if (!type) | |
7007 { BinExp::semanticp(sc); | |
7008 type = e2->type; | |
7009 } | |
7010 return this; | |
7011 } | |
7012 | |
7013 void CommaExp::checkEscape() | |
7014 { | |
7015 e2->checkEscape(); | |
7016 } | |
7017 | |
7018 Expression *CommaExp::toLvalue(Scope *sc, Expression *e) | |
7019 { | |
7020 e2 = e2->toLvalue(sc, NULL); | |
7021 return this; | |
7022 } | |
7023 | |
7024 Expression *CommaExp::modifiableLvalue(Scope *sc, Expression *e) | |
7025 { | |
7026 e2 = e2->modifiableLvalue(sc, e); | |
7027 return this; | |
7028 } | |
7029 | |
7030 int CommaExp::isBool(int result) | |
7031 { | |
7032 return e2->isBool(result); | |
7033 } | |
7034 | |
7035 int CommaExp::checkSideEffect(int flag) | |
7036 { | |
7037 if (flag == 2) | |
7038 return e1->checkSideEffect(2) || e2->checkSideEffect(2); | |
7039 else | |
7040 { | |
7041 // Don't check e1 until we cast(void) the a,b code generation | |
7042 return e2->checkSideEffect(flag); | |
7043 } | |
7044 } | |
7045 | |
7046 /************************** IndexExp **********************************/ | |
7047 | |
7048 // e1 [ e2 ] | |
7049 | |
7050 IndexExp::IndexExp(Loc loc, Expression *e1, Expression *e2) | |
7051 : BinExp(loc, TOKindex, sizeof(IndexExp), e1, e2) | |
7052 { | |
7053 //printf("IndexExp::IndexExp('%s')\n", toChars()); | |
7054 lengthVar = NULL; | |
7055 modifiable = 0; // assume it is an rvalue | |
7056 } | |
7057 | |
7058 Expression *IndexExp::semantic(Scope *sc) | |
7059 { Expression *e; | |
7060 BinExp *b; | |
7061 UnaExp *u; | |
7062 Type *t1; | |
7063 ScopeDsymbol *sym; | |
7064 | |
7065 #if LOGSEMANTIC | |
7066 printf("IndexExp::semantic('%s')\n", toChars()); | |
7067 #endif | |
7068 if (type) | |
7069 return this; | |
7070 if (!e1->type) | |
7071 e1 = e1->semantic(sc); | |
7072 assert(e1->type); // semantic() should already be run on it | |
7073 e = this; | |
7074 | |
7075 // Note that unlike C we do not implement the int[ptr] | |
7076 | |
7077 t1 = e1->type->toBasetype(); | |
7078 | |
7079 if (t1->ty == Tsarray || t1->ty == Tarray || t1->ty == Ttuple) | |
7080 { // Create scope for 'length' variable | |
7081 sym = new ArrayScopeSymbol(this); | |
7082 sym->loc = loc; | |
7083 sym->parent = sc->scopesym; | |
7084 sc = sc->push(sym); | |
7085 } | |
7086 | |
7087 e2 = e2->semantic(sc); | |
7088 if (!e2->type) | |
7089 { | |
7090 error("%s has no value", e2->toChars()); | |
7091 e2->type = Type::terror; | |
7092 } | |
7093 e2 = resolveProperties(sc, e2); | |
7094 | |
7095 if (t1->ty == Tsarray || t1->ty == Tarray || t1->ty == Ttuple) | |
7096 sc = sc->pop(); | |
7097 | |
7098 switch (t1->ty) | |
7099 { | |
7100 case Tpointer: | |
7101 case Tarray: | |
7102 e2 = e2->implicitCastTo(sc, Type::tsize_t); | |
7103 e->type = t1->next; | |
7104 break; | |
7105 | |
7106 case Tsarray: | |
7107 { | |
7108 e2 = e2->implicitCastTo(sc, Type::tsize_t); | |
7109 | |
7110 TypeSArray *tsa = (TypeSArray *)t1; | |
7111 | |
7112 #if 0 // Don't do now, because it might be short-circuit evaluated | |
7113 // Do compile time array bounds checking if possible | |
7114 e2 = e2->optimize(WANTvalue); | |
7115 if (e2->op == TOKint64) | |
7116 { | |
7117 integer_t index = e2->toInteger(); | |
7118 integer_t length = tsa->dim->toInteger(); | |
7119 if (index < 0 || index >= length) | |
7120 error("array index [%lld] is outside array bounds [0 .. %lld]", | |
7121 index, length); | |
7122 } | |
7123 #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
|
7124 e->type = t1->nextOf(); |
159 | 7125 break; |
7126 } | |
7127 | |
7128 case Taarray: | |
7129 { TypeAArray *taa = (TypeAArray *)t1; | |
7130 | |
7131 e2 = e2->implicitCastTo(sc, taa->index); // type checking | |
7132 e2 = e2->implicitCastTo(sc, taa->key); // actual argument type | |
7133 type = taa->next; | |
7134 break; | |
7135 } | |
7136 | |
7137 case Ttuple: | |
7138 { | |
7139 e2 = e2->implicitCastTo(sc, Type::tsize_t); | |
7140 e2 = e2->optimize(WANTvalue); | |
7141 uinteger_t index = e2->toUInteger(); | |
7142 size_t length; | |
7143 TupleExp *te; | |
7144 TypeTuple *tup; | |
7145 | |
7146 if (e1->op == TOKtuple) | |
7147 { te = (TupleExp *)e1; | |
7148 length = te->exps->dim; | |
7149 } | |
7150 else if (e1->op == TOKtype) | |
7151 { | |
7152 tup = (TypeTuple *)t1; | |
7153 length = Argument::dim(tup->arguments); | |
7154 } | |
7155 else | |
7156 assert(0); | |
7157 | |
7158 if (index < length) | |
7159 { | |
7160 | |
7161 if (e1->op == TOKtuple) | |
7162 e = (Expression *)te->exps->data[(size_t)index]; | |
7163 else | |
7164 e = new TypeExp(e1->loc, Argument::getNth(tup->arguments, (size_t)index)->type); | |
7165 } | |
7166 else | |
7167 { | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
7168 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
|
7169 index, length); |
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
285
diff
changeset
|
7170 e = e1; |
159 | 7171 } |
7172 break; | |
7173 } | |
7174 | |
7175 default: | |
7176 error("%s must be an array or pointer type, not %s", | |
7177 e1->toChars(), e1->type->toChars()); | |
7178 type = Type::tint32; | |
7179 break; | |
7180 } | |
7181 return e; | |
7182 } | |
7183 | |
7184 Expression *IndexExp::toLvalue(Scope *sc, Expression *e) | |
7185 { | |
7186 // if (type && type->toBasetype()->ty == Tvoid) | |
7187 // error("voids have no value"); | |
7188 return this; | |
7189 } | |
7190 | |
7191 Expression *IndexExp::modifiableLvalue(Scope *sc, Expression *e) | |
7192 { | |
7193 //printf("IndexExp::modifiableLvalue(%s)\n", toChars()); | |
7194 modifiable = 1; | |
7195 if (e1->op == TOKstring) | |
7196 error("string literals are immutable"); | |
7197 if (e1->type->toBasetype()->ty == Taarray) | |
7198 e1 = e1->modifiableLvalue(sc, e1); | |
7199 return toLvalue(sc, e); | |
7200 } | |
7201 | |
7202 void IndexExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
7203 { | |
7204 expToCBuffer(buf, hgs, e1, PREC_primary); | |
7205 buf->writeByte('['); | |
7206 expToCBuffer(buf, hgs, e2, PREC_assign); | |
7207 buf->writeByte(']'); | |
7208 } | |
7209 | |
7210 | |
7211 /************************* PostExp ***********************************/ | |
7212 | |
7213 PostExp::PostExp(enum TOK op, Loc loc, Expression *e) | |
7214 : BinExp(loc, op, sizeof(PostExp), e, | |
7215 new IntegerExp(loc, 1, Type::tint32)) | |
7216 { | |
7217 } | |
7218 | |
7219 Expression *PostExp::semantic(Scope *sc) | |
7220 { Expression *e = this; | |
7221 | |
7222 if (!type) | |
7223 { | |
7224 BinExp::semantic(sc); | |
7225 e2 = resolveProperties(sc, e2); | |
7226 | |
7227 e = op_overload(sc); | |
7228 if (e) | |
7229 return e; | |
7230 | |
7231 e = this; | |
7232 e1 = e1->modifiableLvalue(sc, e1); | |
7233 e1->checkScalar(); | |
7234 e1->checkNoBool(); | |
7235 if (e1->type->ty == Tpointer) | |
7236 e = scaleFactor(sc); | |
7237 else | |
7238 e2 = e2->castTo(sc, e1->type); | |
7239 e->type = e1->type; | |
7240 } | |
7241 return e; | |
7242 } | |
7243 | |
7244 void PostExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
7245 { | |
7246 expToCBuffer(buf, hgs, e1, precedence[op]); | |
7247 buf->writestring((op == TOKplusplus) ? (char *)"++" : (char *)"--"); | |
7248 } | |
7249 | |
7250 /************************************************************/ | |
7251 | |
7252 /* Can be TOKconstruct too */ | |
7253 | |
7254 AssignExp::AssignExp(Loc loc, Expression *e1, Expression *e2) | |
7255 : BinExp(loc, TOKassign, sizeof(AssignExp), e1, e2) | |
7256 { | |
7257 ismemset = 0; | |
7258 } | |
7259 | |
7260 Expression *AssignExp::semantic(Scope *sc) | |
7261 { Type *t1; | |
7262 Expression *e1old = e1; | |
7263 | |
7264 #if LOGSEMANTIC | |
7265 printf("AssignExp::semantic('%s')\n", toChars()); | |
7266 #endif | |
7267 //printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op)); | |
7268 | |
7269 /* Look for operator overloading of a[i]=value. | |
7270 * Do it before semantic() otherwise the a[i] will have been | |
7271 * converted to a.opIndex() already. | |
7272 */ | |
7273 if (e1->op == TOKarray) | |
7274 { Type *t1; | |
7275 ArrayExp *ae = (ArrayExp *)e1; | |
7276 AggregateDeclaration *ad; | |
7277 Identifier *id = Id::index; | |
7278 | |
7279 ae->e1 = ae->e1->semantic(sc); | |
7280 t1 = ae->e1->type->toBasetype(); | |
7281 if (t1->ty == Tstruct) | |
7282 { | |
7283 ad = ((TypeStruct *)t1)->sym; | |
7284 goto L1; | |
7285 } | |
7286 else if (t1->ty == Tclass) | |
7287 { | |
7288 ad = ((TypeClass *)t1)->sym; | |
7289 L1: | |
7290 // Rewrite (a[i] = value) to (a.opIndexAssign(value, i)) | |
7291 if (search_function(ad, Id::indexass)) | |
7292 { Expression *e = new DotIdExp(loc, ae->e1, Id::indexass); | |
7293 Expressions *a = (Expressions *)ae->arguments->copy(); | |
7294 | |
7295 a->insert(0, e2); | |
7296 e = new CallExp(loc, e, a); | |
7297 e = e->semantic(sc); | |
7298 return e; | |
7299 } | |
7300 else | |
7301 { | |
7302 // Rewrite (a[i] = value) to (a.opIndex(i, value)) | |
7303 if (search_function(ad, id)) | |
7304 { Expression *e = new DotIdExp(loc, ae->e1, id); | |
7305 | |
7306 if (1 || !global.params.useDeprecated) | |
7307 error("operator [] assignment overload with opIndex(i, value) illegal, use opIndexAssign(value, i)"); | |
7308 | |
7309 e = new CallExp(loc, e, (Expression *)ae->arguments->data[0], e2); | |
7310 e = e->semantic(sc); | |
7311 return e; | |
7312 } | |
7313 } | |
7314 } | |
7315 } | |
7316 /* Look for operator overloading of a[i..j]=value. | |
7317 * Do it before semantic() otherwise the a[i..j] will have been | |
7318 * converted to a.opSlice() already. | |
7319 */ | |
7320 if (e1->op == TOKslice) | |
7321 { Type *t1; | |
7322 SliceExp *ae = (SliceExp *)e1; | |
7323 AggregateDeclaration *ad; | |
7324 Identifier *id = Id::index; | |
7325 | |
7326 ae->e1 = ae->e1->semantic(sc); | |
7327 ae->e1 = resolveProperties(sc, ae->e1); | |
7328 t1 = ae->e1->type->toBasetype(); | |
7329 if (t1->ty == Tstruct) | |
7330 { | |
7331 ad = ((TypeStruct *)t1)->sym; | |
7332 goto L2; | |
7333 } | |
7334 else if (t1->ty == Tclass) | |
7335 { | |
7336 ad = ((TypeClass *)t1)->sym; | |
7337 L2: | |
7338 // Rewrite (a[i..j] = value) to (a.opIndexAssign(value, i, j)) | |
7339 if (search_function(ad, Id::sliceass)) | |
7340 { Expression *e = new DotIdExp(loc, ae->e1, Id::sliceass); | |
7341 Expressions *a = new Expressions(); | |
7342 | |
7343 a->push(e2); | |
7344 if (ae->lwr) | |
7345 { a->push(ae->lwr); | |
7346 assert(ae->upr); | |
7347 a->push(ae->upr); | |
7348 } | |
7349 else | |
7350 assert(!ae->upr); | |
7351 e = new CallExp(loc, e, a); | |
7352 e = e->semantic(sc); | |
7353 return e; | |
7354 } | |
7355 } | |
7356 } | |
7357 | |
7358 BinExp::semantic(sc); | |
717
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
7359 |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
7360 if (e1->op == TOKdottd) |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
7361 { // 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
|
7362 Expression *e = new CallExp(loc, e1, e2); |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
7363 e = e->semantic(sc); |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
7364 return e; |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
7365 } |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
664
diff
changeset
|
7366 |
159 | 7367 e2 = resolveProperties(sc, e2); |
7368 assert(e1->type); | |
7369 | |
7370 /* Rewrite tuple assignment as a tuple of assignments. | |
7371 */ | |
7372 if (e1->op == TOKtuple && e2->op == TOKtuple) | |
7373 { TupleExp *tup1 = (TupleExp *)e1; | |
7374 TupleExp *tup2 = (TupleExp *)e2; | |
7375 size_t dim = tup1->exps->dim; | |
7376 if (dim != tup2->exps->dim) | |
7377 { | |
7378 error("mismatched tuple lengths, %d and %d", (int)dim, (int)tup2->exps->dim); | |
7379 } | |
7380 else | |
7381 { Expressions *exps = new Expressions; | |
7382 exps->setDim(dim); | |
7383 | |
7384 for (int i = 0; i < dim; i++) | |
7385 { Expression *ex1 = (Expression *)tup1->exps->data[i]; | |
7386 Expression *ex2 = (Expression *)tup2->exps->data[i]; | |
7387 exps->data[i] = (void *) new AssignExp(loc, ex1, ex2); | |
7388 } | |
7389 Expression *e = new TupleExp(loc, exps); | |
7390 e = e->semantic(sc); | |
7391 return e; | |
7392 } | |
7393 } | |
7394 | |
7395 t1 = e1->type->toBasetype(); | |
7396 | |
7397 if (t1->ty == Tfunction) | |
7398 { // Rewrite f=value to f(value) | |
7399 Expression *e; | |
7400 | |
7401 e = new CallExp(loc, e1, e2); | |
7402 e = e->semantic(sc); | |
7403 return e; | |
7404 } | |
7405 | |
7406 /* If it is an assignment from a 'foreign' type, | |
7407 * check for operator overloading. | |
7408 */ | |
7409 if (t1->ty == Tclass || t1->ty == Tstruct) | |
7410 { | |
7411 if (!e2->type->implicitConvTo(e1->type)) | |
7412 { | |
7413 Expression *e = op_overload(sc); | |
7414 if (e) | |
7415 return e; | |
7416 } | |
7417 } | |
7418 | |
7419 e2->rvalue(); | |
7420 | |
7421 if (e1->op == TOKarraylength) | |
7422 { | |
7423 // e1 is not an lvalue, but we let code generator handle it | |
7424 ArrayLengthExp *ale = (ArrayLengthExp *)e1; | |
7425 | |
7426 ale->e1 = ale->e1->modifiableLvalue(sc, e1); | |
7427 } | |
7428 else if (e1->op == TOKslice) | |
7429 ; | |
7430 else | |
7431 { // Try to do a decent error message with the expression | |
7432 // before it got constant folded | |
7433 e1 = e1->modifiableLvalue(sc, e1old); | |
7434 } | |
7435 | |
7436 if (e1->op == TOKslice && | |
7437 t1->nextOf() && | |
7438 e2->implicitConvTo(t1->nextOf()) | |
7439 // !(t1->nextOf()->equals(e2->type->nextOf())) | |
7440 ) | |
7441 { // memset | |
7442 ismemset = 1; // make it easy for back end to tell what this is | |
7443 e2 = e2->implicitCastTo(sc, t1->next); | |
7444 } | |
7445 else if (t1->ty == Tsarray) | |
7446 { | |
7447 error("cannot assign to static array %s", e1->toChars()); | |
7448 } | |
7449 else | |
7450 { | |
7451 e2 = e2->implicitCastTo(sc, e1->type); | |
7452 } | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7453 |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7454 /* 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
|
7455 */ |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7456 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
|
7457 (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
|
7458 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
|
7459 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
|
7460 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
|
7461 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
|
7462 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7463 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
|
7464 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
|
7465 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7466 |
159 | 7467 type = e1->type; |
7468 assert(type); | |
7469 return this; | |
7470 } | |
7471 | |
7472 Expression *AssignExp::checkToBoolean() | |
7473 { | |
7474 // Things like: | |
7475 // if (a = b) ... | |
7476 // are usually mistakes. | |
7477 | |
7478 error("'=' does not give a boolean result"); | |
7479 return this; | |
7480 } | |
7481 | |
7482 /************************************************************/ | |
7483 | |
7484 AddAssignExp::AddAssignExp(Loc loc, Expression *e1, Expression *e2) | |
7485 : BinExp(loc, TOKaddass, sizeof(AddAssignExp), e1, e2) | |
7486 { | |
7487 } | |
7488 | |
7489 Expression *AddAssignExp::semantic(Scope *sc) | |
7490 { Expression *e; | |
7491 | |
7492 if (type) | |
7493 return this; | |
7494 | |
7495 BinExp::semantic(sc); | |
7496 e2 = resolveProperties(sc, e2); | |
7497 | |
7498 e = op_overload(sc); | |
7499 if (e) | |
7500 return e; | |
7501 | |
7502 Type *tb1 = e1->type->toBasetype(); | |
7503 Type *tb2 = e2->type->toBasetype(); | |
7504 | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7505 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
|
7506 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7507 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
|
7508 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
|
7509 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
|
7510 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7511 else |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7512 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7513 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
|
7514 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7515 |
159 | 7516 if ((tb1->ty == Tarray || tb1->ty == Tsarray) && |
7517 (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
|
7518 tb1->nextOf()->equals(tb2->nextOf()) |
159 | 7519 ) |
7520 { | |
7521 type = e1->type; | |
7522 e = this; | |
7523 } | |
7524 else | |
7525 { | |
7526 e1->checkScalar(); | |
7527 e1->checkNoBool(); | |
7528 if (tb1->ty == Tpointer && tb2->isintegral()) | |
7529 e = scaleFactor(sc); | |
7530 else if (tb1->ty == Tbit || tb1->ty == Tbool) | |
7531 { | |
7532 #if 0 | |
7533 // Need to rethink this | |
7534 if (e1->op != TOKvar) | |
7535 { // Rewrite e1+=e2 to (v=&e1),*v=*v+e2 | |
7536 VarDeclaration *v; | |
7537 Expression *ea; | |
7538 Expression *ex; | |
7539 | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7540 Identifier *id = Lexer::uniqueId("__name"); |
159 | 7541 |
7542 v = new VarDeclaration(loc, tb1->pointerTo(), id, NULL); | |
7543 v->semantic(sc); | |
7544 if (!sc->insert(v)) | |
7545 assert(0); | |
7546 v->parent = sc->func; | |
7547 | |
7548 ea = new AddrExp(loc, e1); | |
7549 ea = new AssignExp(loc, new VarExp(loc, v), ea); | |
7550 | |
7551 ex = new VarExp(loc, v); | |
7552 ex = new PtrExp(loc, ex); | |
7553 e = new AddExp(loc, ex, e2); | |
7554 e = new CastExp(loc, e, e1->type); | |
7555 e = new AssignExp(loc, ex->syntaxCopy(), e); | |
7556 | |
7557 e = new CommaExp(loc, ea, e); | |
7558 } | |
7559 else | |
7560 #endif | |
7561 { // Rewrite e1+=e2 to e1=e1+e2 | |
7562 // BUG: doesn't account for side effects in e1 | |
7563 // BUG: other assignment operators for bits aren't handled at all | |
7564 e = new AddExp(loc, e1, e2); | |
7565 e = new CastExp(loc, e, e1->type); | |
7566 e = new AssignExp(loc, e1->syntaxCopy(), e); | |
7567 } | |
7568 e = e->semantic(sc); | |
7569 } | |
7570 else | |
7571 { | |
7572 type = e1->type; | |
7573 typeCombine(sc); | |
7574 e1->checkArithmetic(); | |
7575 e2->checkArithmetic(); | |
7576 if (type->isreal() || type->isimaginary()) | |
7577 { | |
7578 assert(global.errors || e2->type->isfloating()); | |
7579 e2 = e2->castTo(sc, e1->type); | |
7580 } | |
7581 e = this; | |
7582 } | |
7583 } | |
7584 return e; | |
7585 } | |
7586 | |
7587 /************************************************************/ | |
7588 | |
7589 MinAssignExp::MinAssignExp(Loc loc, Expression *e1, Expression *e2) | |
7590 : BinExp(loc, TOKminass, sizeof(MinAssignExp), e1, e2) | |
7591 { | |
7592 } | |
7593 | |
7594 Expression *MinAssignExp::semantic(Scope *sc) | |
7595 { Expression *e; | |
7596 | |
7597 if (type) | |
7598 return this; | |
7599 | |
7600 BinExp::semantic(sc); | |
7601 e2 = resolveProperties(sc, e2); | |
7602 | |
7603 e = op_overload(sc); | |
7604 if (e) | |
7605 return e; | |
7606 | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7607 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
|
7608 { // T[] -= ... |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7609 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
|
7610 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
|
7611 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
|
7612 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7613 |
159 | 7614 e1 = e1->modifiableLvalue(sc, e1); |
7615 e1->checkScalar(); | |
7616 e1->checkNoBool(); | |
7617 if (e1->type->ty == Tpointer && e2->type->isintegral()) | |
7618 e = scaleFactor(sc); | |
7619 else | |
7620 { | |
7621 e1 = e1->checkArithmetic(); | |
7622 e2 = e2->checkArithmetic(); | |
7623 type = e1->type; | |
7624 typeCombine(sc); | |
7625 if (type->isreal() || type->isimaginary()) | |
7626 { | |
7627 assert(e2->type->isfloating()); | |
7628 e2 = e2->castTo(sc, e1->type); | |
7629 } | |
7630 e = this; | |
7631 } | |
7632 return e; | |
7633 } | |
7634 | |
7635 /************************************************************/ | |
7636 | |
7637 CatAssignExp::CatAssignExp(Loc loc, Expression *e1, Expression *e2) | |
7638 : BinExp(loc, TOKcatass, sizeof(CatAssignExp), e1, e2) | |
7639 { | |
7640 } | |
7641 | |
7642 Expression *CatAssignExp::semantic(Scope *sc) | |
7643 { Expression *e; | |
7644 | |
7645 BinExp::semantic(sc); | |
7646 e2 = resolveProperties(sc, e2); | |
7647 | |
7648 e = op_overload(sc); | |
7649 if (e) | |
7650 return e; | |
7651 | |
7652 if (e1->op == TOKslice) | |
7653 { SliceExp *se = (SliceExp *)e1; | |
7654 | |
7655 if (se->e1->type->toBasetype()->ty == Tsarray) | |
7656 error("cannot append to static array %s", se->e1->type->toChars()); | |
7657 } | |
7658 | |
7659 e1 = e1->modifiableLvalue(sc, e1); | |
7660 | |
7661 Type *tb1 = e1->type->toBasetype(); | |
7662 Type *tb2 = e2->type->toBasetype(); | |
7663 | |
7664 e2->rvalue(); | |
7665 | |
7666 if ((tb1->ty == Tarray) && | |
7667 (tb2->ty == Tarray || tb2->ty == Tsarray) && | |
7668 e2->implicitConvTo(e1->type) | |
7669 //e1->type->next->equals(e2->type->next) | |
7670 ) | |
7671 { // Append array | |
7672 e2 = e2->castTo(sc, e1->type); | |
7673 type = e1->type; | |
7674 e = this; | |
7675 } | |
7676 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
|
7677 e2->implicitConvTo(tb1->nextOf()) |
159 | 7678 ) |
7679 { // 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
|
7680 e2 = e2->castTo(sc, tb1->nextOf()); |
159 | 7681 type = e1->type; |
7682 e = this; | |
7683 } | |
7684 else | |
7685 { | |
7686 error("cannot append type %s to type %s", tb2->toChars(), tb1->toChars()); | |
7687 type = Type::tint32; | |
7688 e = this; | |
7689 } | |
7690 return e; | |
7691 } | |
7692 | |
7693 /************************************************************/ | |
7694 | |
7695 MulAssignExp::MulAssignExp(Loc loc, Expression *e1, Expression *e2) | |
7696 : BinExp(loc, TOKmulass, sizeof(MulAssignExp), e1, e2) | |
7697 { | |
7698 } | |
7699 | |
7700 Expression *MulAssignExp::semantic(Scope *sc) | |
7701 { Expression *e; | |
7702 | |
7703 BinExp::semantic(sc); | |
7704 e2 = resolveProperties(sc, e2); | |
7705 | |
7706 e = op_overload(sc); | |
7707 if (e) | |
7708 return e; | |
7709 | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7710 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
|
7711 { // T[] -= ... |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7712 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
|
7713 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
|
7714 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
|
7715 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7716 |
159 | 7717 e1 = e1->modifiableLvalue(sc, e1); |
7718 e1->checkScalar(); | |
7719 e1->checkNoBool(); | |
7720 type = e1->type; | |
7721 typeCombine(sc); | |
7722 e1->checkArithmetic(); | |
7723 e2->checkArithmetic(); | |
7724 if (e2->type->isfloating()) | |
7725 { Type *t1; | |
7726 Type *t2; | |
7727 | |
7728 t1 = e1->type; | |
7729 t2 = e2->type; | |
7730 if (t1->isreal()) | |
7731 { | |
7732 if (t2->isimaginary() || t2->iscomplex()) | |
7733 { | |
7734 e2 = e2->castTo(sc, t1); | |
7735 } | |
7736 } | |
7737 else if (t1->isimaginary()) | |
7738 { | |
7739 if (t2->isimaginary() || t2->iscomplex()) | |
7740 { | |
7741 switch (t1->ty) | |
7742 { | |
7743 case Timaginary32: t2 = Type::tfloat32; break; | |
7744 case Timaginary64: t2 = Type::tfloat64; break; | |
7745 case Timaginary80: t2 = Type::tfloat80; break; | |
7746 default: | |
7747 assert(0); | |
7748 } | |
7749 e2 = e2->castTo(sc, t2); | |
7750 } | |
7751 } | |
7752 } | |
7753 return this; | |
7754 } | |
7755 | |
7756 /************************************************************/ | |
7757 | |
7758 DivAssignExp::DivAssignExp(Loc loc, Expression *e1, Expression *e2) | |
7759 : BinExp(loc, TOKdivass, sizeof(DivAssignExp), e1, e2) | |
7760 { | |
7761 } | |
7762 | |
7763 Expression *DivAssignExp::semantic(Scope *sc) | |
7764 { Expression *e; | |
7765 | |
7766 BinExp::semantic(sc); | |
7767 e2 = resolveProperties(sc, e2); | |
7768 | |
7769 e = op_overload(sc); | |
7770 if (e) | |
7771 return e; | |
7772 | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7773 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
|
7774 { // T[] -= ... |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7775 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
|
7776 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
|
7777 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
|
7778 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
7779 |
159 | 7780 e1 = e1->modifiableLvalue(sc, e1); |
7781 e1->checkScalar(); | |
7782 e1->checkNoBool(); | |
7783 type = e1->type; | |
7784 typeCombine(sc); | |
7785 e1->checkArithmetic(); | |
7786 e2->checkArithmetic(); | |
7787 if (e2->type->isimaginary()) | |
7788 { Type *t1; | |
7789 Type *t2; | |
7790 | |
7791 t1 = e1->type; | |
7792 if (t1->isreal()) | |
7793 { // x/iv = i(-x/v) | |
7794 // Therefore, the result is 0 | |
7795 e2 = new CommaExp(loc, e2, new RealExp(loc, 0, t1)); | |
7796 e2->type = t1; | |
7797 e = new AssignExp(loc, e1, e2); | |
7798 e->type = t1; | |
7799 return e; | |
7800 } | |
7801 else if (t1->isimaginary()) | |
7802 { Expression *e; | |
7803 | |
7804 switch (t1->ty) | |
7805 { | |
7806 case Timaginary32: t2 = Type::tfloat32; break; | |
7807 case Timaginary64: t2 = Type::tfloat64; break; | |
7808 case Timaginary80: t2 = Type::tfloat80; break; | |
7809 default: | |
7810 assert(0); | |
7811 } | |
7812 e2 = e2->castTo(sc, t2); | |
7813 e = new AssignExp(loc, e1, e2); | |
7814 e->type = t1; | |
7815 return e; | |
7816 } | |
7817 } | |
7818 return this; | |
7819 } | |
7820 | |
7821 /************************************************************/ | |
7822 | |
7823 ModAssignExp::ModAssignExp(Loc loc, Expression *e1, Expression *e2) | |
7824 : BinExp(loc, TOKmodass, sizeof(ModAssignExp), e1, e2) | |
7825 { | |
7826 } | |
7827 | |
7828 Expression *ModAssignExp::semantic(Scope *sc) | |
7829 { | |
7830 return commonSemanticAssign(sc); | |
7831 } | |
7832 | |
7833 /************************************************************/ | |
7834 | |
7835 ShlAssignExp::ShlAssignExp(Loc loc, Expression *e1, Expression *e2) | |
7836 : BinExp(loc, TOKshlass, sizeof(ShlAssignExp), e1, e2) | |
7837 { | |
7838 } | |
7839 | |
7840 Expression *ShlAssignExp::semantic(Scope *sc) | |
7841 { Expression *e; | |
7842 | |
7843 //printf("ShlAssignExp::semantic()\n"); | |
7844 BinExp::semantic(sc); | |
7845 e2 = resolveProperties(sc, e2); | |
7846 | |
7847 e = op_overload(sc); | |
7848 if (e) | |
7849 return e; | |
7850 | |
7851 e1 = e1->modifiableLvalue(sc, e1); | |
7852 e1->checkScalar(); | |
7853 e1->checkNoBool(); | |
7854 type = e1->type; | |
7855 typeCombine(sc); | |
7856 e1->checkIntegral(); | |
7857 e2 = e2->checkIntegral(); | |
7858 //e2 = e2->castTo(sc, Type::tshiftcnt); | |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
639
diff
changeset
|
7859 e2 = e2->castTo(sc, e1->type); // LDC |
159 | 7860 return this; |
7861 } | |
7862 | |
7863 /************************************************************/ | |
7864 | |
7865 ShrAssignExp::ShrAssignExp(Loc loc, Expression *e1, Expression *e2) | |
7866 : BinExp(loc, TOKshrass, sizeof(ShrAssignExp), e1, e2) | |
7867 { | |
7868 } | |
7869 | |
7870 Expression *ShrAssignExp::semantic(Scope *sc) | |
7871 { Expression *e; | |
7872 | |
7873 BinExp::semantic(sc); | |
7874 e2 = resolveProperties(sc, e2); | |
7875 | |
7876 e = op_overload(sc); | |
7877 if (e) | |
7878 return e; | |
7879 | |
7880 e1 = e1->modifiableLvalue(sc, e1); | |
7881 e1->checkScalar(); | |
7882 e1->checkNoBool(); | |
7883 type = e1->type; | |
7884 typeCombine(sc); | |
7885 e1->checkIntegral(); | |
7886 e2 = e2->checkIntegral(); | |
7887 //e2 = e2->castTo(sc, Type::tshiftcnt); | |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
639
diff
changeset
|
7888 e2 = e2->castTo(sc, e1->type); // LDC |
159 | 7889 return this; |
7890 } | |
7891 | |
7892 /************************************************************/ | |
7893 | |
7894 UshrAssignExp::UshrAssignExp(Loc loc, Expression *e1, Expression *e2) | |
7895 : BinExp(loc, TOKushrass, sizeof(UshrAssignExp), e1, e2) | |
7896 { | |
7897 } | |
7898 | |
7899 Expression *UshrAssignExp::semantic(Scope *sc) | |
7900 { Expression *e; | |
7901 | |
7902 BinExp::semantic(sc); | |
7903 e2 = resolveProperties(sc, e2); | |
7904 | |
7905 e = op_overload(sc); | |
7906 if (e) | |
7907 return e; | |
7908 | |
7909 e1 = e1->modifiableLvalue(sc, e1); | |
7910 e1->checkScalar(); | |
7911 e1->checkNoBool(); | |
7912 type = e1->type; | |
7913 typeCombine(sc); | |
7914 e1->checkIntegral(); | |
7915 e2 = e2->checkIntegral(); | |
7916 //e2 = e2->castTo(sc, Type::tshiftcnt); | |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
639
diff
changeset
|
7917 e2 = e2->castTo(sc, e1->type); // LDC |
159 | 7918 return this; |
7919 } | |
7920 | |
7921 /************************************************************/ | |
7922 | |
7923 AndAssignExp::AndAssignExp(Loc loc, Expression *e1, Expression *e2) | |
7924 : BinExp(loc, TOKandass, sizeof(AndAssignExp), e1, e2) | |
7925 { | |
7926 } | |
7927 | |
7928 Expression *AndAssignExp::semantic(Scope *sc) | |
7929 { | |
7930 return commonSemanticAssignIntegral(sc); | |
7931 } | |
7932 | |
7933 /************************************************************/ | |
7934 | |
7935 OrAssignExp::OrAssignExp(Loc loc, Expression *e1, Expression *e2) | |
7936 : BinExp(loc, TOKorass, sizeof(OrAssignExp), e1, e2) | |
7937 { | |
7938 } | |
7939 | |
7940 Expression *OrAssignExp::semantic(Scope *sc) | |
7941 { | |
7942 return commonSemanticAssignIntegral(sc); | |
7943 } | |
7944 | |
7945 /************************************************************/ | |
7946 | |
7947 XorAssignExp::XorAssignExp(Loc loc, Expression *e1, Expression *e2) | |
7948 : BinExp(loc, TOKxorass, sizeof(XorAssignExp), e1, e2) | |
7949 { | |
7950 } | |
7951 | |
7952 Expression *XorAssignExp::semantic(Scope *sc) | |
7953 { | |
7954 return commonSemanticAssignIntegral(sc); | |
7955 } | |
7956 | |
7957 /************************* AddExp *****************************/ | |
7958 | |
7959 AddExp::AddExp(Loc loc, Expression *e1, Expression *e2) | |
7960 : BinExp(loc, TOKadd, sizeof(AddExp), e1, e2) | |
7961 { | |
7962 } | |
7963 | |
7964 Expression *AddExp::semantic(Scope *sc) | |
7965 { Expression *e; | |
7966 | |
7967 #if LOGSEMANTIC | |
7968 printf("AddExp::semantic('%s')\n", toChars()); | |
7969 #endif | |
7970 if (!type) | |
7971 { | |
7972 BinExp::semanticp(sc); | |
7973 | |
7974 e = op_overload(sc); | |
7975 if (e) | |
7976 return e; | |
7977 | |
7978 Type *tb1 = e1->type->toBasetype(); | |
7979 Type *tb2 = e2->type->toBasetype(); | |
7980 | |
7981 if ((tb1->ty == Tarray || tb1->ty == Tsarray) && | |
7982 (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
|
7983 tb1->nextOf()->equals(tb2->nextOf()) |
159 | 7984 ) |
7985 { | |
7986 type = e1->type; | |
7987 e = this; | |
7988 } | |
7989 else if (tb1->ty == Tpointer && e2->type->isintegral() || | |
7990 tb2->ty == Tpointer && e1->type->isintegral()) | |
7991 e = scaleFactor(sc); | |
7992 else if (tb1->ty == Tpointer && tb2->ty == Tpointer) | |
7993 { | |
7994 incompatibleTypes(); | |
7995 type = e1->type; | |
7996 e = this; | |
7997 } | |
7998 else | |
7999 { | |
8000 typeCombine(sc); | |
8001 if ((e1->type->isreal() && e2->type->isimaginary()) || | |
8002 (e1->type->isimaginary() && e2->type->isreal())) | |
8003 { | |
8004 switch (type->toBasetype()->ty) | |
8005 { | |
8006 case Tfloat32: | |
8007 case Timaginary32: | |
8008 type = Type::tcomplex32; | |
8009 break; | |
8010 | |
8011 case Tfloat64: | |
8012 case Timaginary64: | |
8013 type = Type::tcomplex64; | |
8014 break; | |
8015 | |
8016 case Tfloat80: | |
8017 case Timaginary80: | |
8018 type = Type::tcomplex80; | |
8019 break; | |
8020 | |
8021 default: | |
8022 assert(0); | |
8023 } | |
8024 } | |
8025 e = this; | |
8026 } | |
8027 return e; | |
8028 } | |
8029 return this; | |
8030 } | |
8031 | |
8032 /************************************************************/ | |
8033 | |
8034 MinExp::MinExp(Loc loc, Expression *e1, Expression *e2) | |
8035 : BinExp(loc, TOKmin, sizeof(MinExp), e1, e2) | |
8036 { | |
8037 } | |
8038 | |
8039 Expression *MinExp::semantic(Scope *sc) | |
8040 { Expression *e; | |
8041 Type *t1; | |
8042 Type *t2; | |
8043 | |
8044 #if LOGSEMANTIC | |
8045 printf("MinExp::semantic('%s')\n", toChars()); | |
8046 #endif | |
8047 if (type) | |
8048 return this; | |
8049 | |
8050 BinExp::semanticp(sc); | |
8051 | |
8052 e = op_overload(sc); | |
8053 if (e) | |
8054 return e; | |
8055 | |
8056 e = this; | |
8057 t1 = e1->type->toBasetype(); | |
8058 t2 = e2->type->toBasetype(); | |
8059 if (t1->ty == Tpointer) | |
8060 { | |
8061 if (t2->ty == Tpointer) | |
8062 { // Need to divide the result by the stride | |
8063 // Replace (ptr - ptr) with (ptr - ptr) / stride | |
8064 d_int64 stride; | |
8065 Expression *e; | |
8066 | |
8067 typeCombine(sc); // make sure pointer types are compatible | |
8068 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
|
8069 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
|
8070 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
|
8071 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8072 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
|
8073 } |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8074 else |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8075 { |
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8076 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
|
8077 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
|
8078 } |
159 | 8079 return e; |
8080 } | |
8081 else if (t2->isintegral()) | |
8082 e = scaleFactor(sc); | |
8083 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
|
8084 { error("incompatible types for minus"); |
159 | 8085 return new IntegerExp(0); |
8086 } | |
8087 } | |
8088 else if (t2->ty == Tpointer) | |
8089 { | |
8090 type = e2->type; | |
8091 error("can't subtract pointer from %s", e1->type->toChars()); | |
8092 return new IntegerExp(0); | |
8093 } | |
8094 else | |
8095 { | |
8096 typeCombine(sc); | |
8097 t1 = e1->type->toBasetype(); | |
8098 t2 = e2->type->toBasetype(); | |
8099 if ((t1->isreal() && t2->isimaginary()) || | |
8100 (t1->isimaginary() && t2->isreal())) | |
8101 { | |
8102 switch (type->ty) | |
8103 { | |
8104 case Tfloat32: | |
8105 case Timaginary32: | |
8106 type = Type::tcomplex32; | |
8107 break; | |
8108 | |
8109 case Tfloat64: | |
8110 case Timaginary64: | |
8111 type = Type::tcomplex64; | |
8112 break; | |
8113 | |
8114 case Tfloat80: | |
8115 case Timaginary80: | |
8116 type = Type::tcomplex80; | |
8117 break; | |
8118 | |
8119 default: | |
8120 assert(0); | |
8121 } | |
8122 } | |
8123 } | |
8124 return e; | |
8125 } | |
8126 | |
8127 /************************* CatExp *****************************/ | |
8128 | |
8129 CatExp::CatExp(Loc loc, Expression *e1, Expression *e2) | |
8130 : BinExp(loc, TOKcat, sizeof(CatExp), e1, e2) | |
8131 { | |
8132 } | |
8133 | |
8134 Expression *CatExp::semantic(Scope *sc) | |
8135 { Expression *e; | |
8136 | |
8137 //printf("CatExp::semantic() %s\n", toChars()); | |
8138 if (!type) | |
8139 { | |
8140 BinExp::semanticp(sc); | |
8141 e = op_overload(sc); | |
8142 if (e) | |
8143 return e; | |
8144 | |
8145 Type *tb1 = e1->type->toBasetype(); | |
8146 Type *tb2 = e2->type->toBasetype(); | |
8147 | |
8148 | |
8149 /* BUG: Should handle things like: | |
8150 * char c; | |
8151 * c ~ ' ' | |
8152 * ' ' ~ c; | |
8153 */ | |
8154 | |
8155 #if 0 | |
8156 e1->type->print(); | |
8157 e2->type->print(); | |
8158 #endif | |
8159 if ((tb1->ty == Tsarray || tb1->ty == Tarray) && | |
8160 e2->type->equals(tb1->next)) | |
8161 { | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8162 type = tb1->nextOf()->arrayOf(); |
159 | 8163 if (tb2->ty == Tarray) |
8164 { // Make e2 into [e2] | |
8165 e2 = new ArrayLiteralExp(e2->loc, e2); | |
8166 e2->type = type; | |
8167 } | |
8168 return this; | |
8169 } | |
8170 else if ((tb2->ty == Tsarray || tb2->ty == Tarray) && | |
8171 e1->type->equals(tb2->next)) | |
8172 { | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8173 type = tb2->nextOf()->arrayOf(); |
159 | 8174 if (tb1->ty == Tarray) |
8175 { // Make e1 into [e1] | |
8176 e1 = new ArrayLiteralExp(e1->loc, e1); | |
8177 e1->type = type; | |
8178 } | |
8179 return this; | |
8180 } | |
8181 | |
8182 typeCombine(sc); | |
8183 | |
8184 if (type->toBasetype()->ty == Tsarray) | |
8185 type = type->toBasetype()->next->arrayOf(); | |
8186 #if 0 | |
8187 e1->type->print(); | |
8188 e2->type->print(); | |
8189 type->print(); | |
8190 print(); | |
8191 #endif | |
8192 if (e1->op == TOKstring && e2->op == TOKstring) | |
8193 e = optimize(WANTvalue); | |
8194 else if (e1->type->equals(e2->type) && | |
8195 (e1->type->toBasetype()->ty == Tarray || | |
8196 e1->type->toBasetype()->ty == Tsarray)) | |
8197 { | |
8198 e = this; | |
8199 } | |
8200 else | |
8201 { | |
510
6aee82889553
Merged DMD 1.034, array operations are not yet implemented ;)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
486
diff
changeset
|
8202 //printf("(%s) ~ (%s)\n", e1->toChars(), e2->toChars()); |
159 | 8203 error("Can only concatenate arrays, not (%s ~ %s)", |
8204 e1->type->toChars(), e2->type->toChars()); | |
8205 type = Type::tint32; | |
8206 e = this; | |
8207 } | |
8208 e->type = e->type->semantic(loc, sc); | |
8209 return e; | |
8210 } | |
8211 return this; | |
8212 } | |
8213 | |
8214 /************************************************************/ | |
8215 | |
8216 MulExp::MulExp(Loc loc, Expression *e1, Expression *e2) | |
8217 : BinExp(loc, TOKmul, sizeof(MulExp), e1, e2) | |
8218 { | |
8219 } | |
8220 | |
8221 Expression *MulExp::semantic(Scope *sc) | |
8222 { Expression *e; | |
8223 | |
8224 #if 0 | |
8225 printf("MulExp::semantic() %s\n", toChars()); | |
8226 #endif | |
8227 if (type) | |
8228 { | |
8229 return this; | |
8230 } | |
8231 | |
8232 BinExp::semanticp(sc); | |
8233 e = op_overload(sc); | |
8234 if (e) | |
8235 return e; | |
8236 | |
8237 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
|
8238 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
|
8239 { 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
|
8240 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
|
8241 } |
159 | 8242 if (type->isfloating()) |
8243 { Type *t1 = e1->type; | |
8244 Type *t2 = e2->type; | |
8245 | |
8246 if (t1->isreal()) | |
8247 { | |
8248 type = t2; | |
8249 } | |
8250 else if (t2->isreal()) | |
8251 { | |
8252 type = t1; | |
8253 } | |
8254 else if (t1->isimaginary()) | |
8255 { | |
8256 if (t2->isimaginary()) | |
8257 { Expression *e; | |
8258 | |
8259 switch (t1->ty) | |
8260 { | |
8261 case Timaginary32: type = Type::tfloat32; break; | |
8262 case Timaginary64: type = Type::tfloat64; break; | |
8263 case Timaginary80: type = Type::tfloat80; break; | |
8264 default: assert(0); | |
8265 } | |
8266 | |
8267 // iy * iv = -yv | |
8268 e1->type = type; | |
8269 e2->type = type; | |
8270 e = new NegExp(loc, this); | |
8271 e = e->semantic(sc); | |
8272 return e; | |
8273 } | |
8274 else | |
8275 type = t2; // t2 is complex | |
8276 } | |
8277 else if (t2->isimaginary()) | |
8278 { | |
8279 type = t1; // t1 is complex | |
8280 } | |
8281 } | |
8282 return this; | |
8283 } | |
8284 | |
8285 /************************************************************/ | |
8286 | |
8287 DivExp::DivExp(Loc loc, Expression *e1, Expression *e2) | |
8288 : BinExp(loc, TOKdiv, sizeof(DivExp), e1, e2) | |
8289 { | |
8290 } | |
8291 | |
8292 Expression *DivExp::semantic(Scope *sc) | |
8293 { Expression *e; | |
8294 | |
8295 if (type) | |
8296 return this; | |
8297 | |
8298 BinExp::semanticp(sc); | |
8299 e = op_overload(sc); | |
8300 if (e) | |
8301 return e; | |
8302 | |
8303 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
|
8304 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
|
8305 { 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
|
8306 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
|
8307 } |
159 | 8308 if (type->isfloating()) |
8309 { Type *t1 = e1->type; | |
8310 Type *t2 = e2->type; | |
8311 | |
8312 if (t1->isreal()) | |
8313 { | |
8314 type = t2; | |
8315 if (t2->isimaginary()) | |
8316 { Expression *e; | |
8317 | |
8318 // x/iv = i(-x/v) | |
8319 e2->type = t1; | |
8320 e = new NegExp(loc, this); | |
8321 e = e->semantic(sc); | |
8322 return e; | |
8323 } | |
8324 } | |
8325 else if (t2->isreal()) | |
8326 { | |
8327 type = t1; | |
8328 } | |
8329 else if (t1->isimaginary()) | |
8330 { | |
8331 if (t2->isimaginary()) | |
8332 { | |
8333 switch (t1->ty) | |
8334 { | |
8335 case Timaginary32: type = Type::tfloat32; break; | |
8336 case Timaginary64: type = Type::tfloat64; break; | |
8337 case Timaginary80: type = Type::tfloat80; break; | |
8338 default: assert(0); | |
8339 } | |
8340 } | |
8341 else | |
8342 type = t2; // t2 is complex | |
8343 } | |
8344 else if (t2->isimaginary()) | |
8345 { | |
8346 type = t1; // t1 is complex | |
8347 } | |
8348 } | |
8349 return this; | |
8350 } | |
8351 | |
8352 /************************************************************/ | |
8353 | |
8354 ModExp::ModExp(Loc loc, Expression *e1, Expression *e2) | |
8355 : BinExp(loc, TOKmod, sizeof(ModExp), e1, e2) | |
8356 { | |
8357 } | |
8358 | |
8359 Expression *ModExp::semantic(Scope *sc) | |
8360 { Expression *e; | |
8361 | |
8362 if (type) | |
8363 return this; | |
8364 | |
8365 BinExp::semanticp(sc); | |
8366 e = op_overload(sc); | |
8367 if (e) | |
8368 return e; | |
8369 | |
8370 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
|
8371 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
|
8372 { 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
|
8373 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
|
8374 } |
159 | 8375 if (type->isfloating()) |
8376 { type = e1->type; | |
8377 if (e2->type->iscomplex()) | |
8378 { error("cannot perform modulo complex arithmetic"); | |
8379 return new IntegerExp(0); | |
8380 } | |
8381 } | |
8382 return this; | |
8383 } | |
8384 | |
8385 /************************************************************/ | |
8386 | |
8387 ShlExp::ShlExp(Loc loc, Expression *e1, Expression *e2) | |
8388 : BinExp(loc, TOKshl, sizeof(ShlExp), e1, e2) | |
8389 { | |
8390 } | |
8391 | |
8392 Expression *ShlExp::semantic(Scope *sc) | |
8393 { Expression *e; | |
8394 | |
8395 //printf("ShlExp::semantic(), type = %p\n", type); | |
8396 if (!type) | |
8397 { BinExp::semanticp(sc); | |
8398 e = op_overload(sc); | |
8399 if (e) | |
8400 return e; | |
8401 e1 = e1->checkIntegral(); | |
8402 e2 = e2->checkIntegral(); | |
8403 e1 = e1->integralPromotions(sc); | |
8404 //e2 = e2->castTo(sc, Type::tshiftcnt); | |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
639
diff
changeset
|
8405 e2 = e2->castTo(sc, e1->type); // LDC |
159 | 8406 type = e1->type; |
8407 } | |
8408 return this; | |
8409 } | |
8410 | |
8411 /************************************************************/ | |
8412 | |
8413 ShrExp::ShrExp(Loc loc, Expression *e1, Expression *e2) | |
8414 : BinExp(loc, TOKshr, sizeof(ShrExp), e1, e2) | |
8415 { | |
8416 } | |
8417 | |
8418 Expression *ShrExp::semantic(Scope *sc) | |
8419 { Expression *e; | |
8420 | |
8421 if (!type) | |
8422 { BinExp::semanticp(sc); | |
8423 e = op_overload(sc); | |
8424 if (e) | |
8425 return e; | |
8426 e1 = e1->checkIntegral(); | |
8427 e2 = e2->checkIntegral(); | |
8428 e1 = e1->integralPromotions(sc); | |
8429 //e2 = e2->castTo(sc, Type::tshiftcnt); | |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
639
diff
changeset
|
8430 e2 = e2->castTo(sc, e1->type); // LDC |
159 | 8431 type = e1->type; |
8432 } | |
8433 return this; | |
8434 } | |
8435 | |
8436 /************************************************************/ | |
8437 | |
8438 UshrExp::UshrExp(Loc loc, Expression *e1, Expression *e2) | |
8439 : BinExp(loc, TOKushr, sizeof(UshrExp), e1, e2) | |
8440 { | |
8441 } | |
8442 | |
8443 Expression *UshrExp::semantic(Scope *sc) | |
8444 { Expression *e; | |
8445 | |
8446 if (!type) | |
8447 { BinExp::semanticp(sc); | |
8448 e = op_overload(sc); | |
8449 if (e) | |
8450 return e; | |
8451 e1 = e1->checkIntegral(); | |
8452 e2 = e2->checkIntegral(); | |
8453 e1 = e1->integralPromotions(sc); | |
8454 //e2 = e2->castTo(sc, Type::tshiftcnt); | |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
639
diff
changeset
|
8455 e2 = e2->castTo(sc, e1->type); // LDC |
159 | 8456 type = e1->type; |
8457 } | |
8458 return this; | |
8459 } | |
8460 | |
8461 /************************************************************/ | |
8462 | |
8463 AndExp::AndExp(Loc loc, Expression *e1, Expression *e2) | |
8464 : BinExp(loc, TOKand, sizeof(AndExp), e1, e2) | |
8465 { | |
8466 } | |
8467 | |
8468 Expression *AndExp::semantic(Scope *sc) | |
8469 { Expression *e; | |
8470 | |
8471 if (!type) | |
8472 { BinExp::semanticp(sc); | |
8473 e = op_overload(sc); | |
8474 if (e) | |
8475 return e; | |
8476 if (e1->type->toBasetype()->ty == Tbool && | |
8477 e2->type->toBasetype()->ty == Tbool) | |
8478 { | |
8479 type = e1->type; | |
8480 e = this; | |
8481 } | |
8482 else | |
8483 { | |
8484 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
|
8485 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
|
8486 { 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
|
8487 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
|
8488 } |
159 | 8489 } |
8490 } | |
8491 return this; | |
8492 } | |
8493 | |
8494 /************************************************************/ | |
8495 | |
8496 OrExp::OrExp(Loc loc, Expression *e1, Expression *e2) | |
8497 : BinExp(loc, TOKor, sizeof(OrExp), e1, e2) | |
8498 { | |
8499 } | |
8500 | |
8501 Expression *OrExp::semantic(Scope *sc) | |
8502 { Expression *e; | |
8503 | |
8504 if (!type) | |
8505 { BinExp::semanticp(sc); | |
8506 e = op_overload(sc); | |
8507 if (e) | |
8508 return e; | |
8509 if (e1->type->toBasetype()->ty == Tbool && | |
8510 e2->type->toBasetype()->ty == Tbool) | |
8511 { | |
8512 type = e1->type; | |
8513 e = this; | |
8514 } | |
8515 else | |
8516 { | |
8517 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
|
8518 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
|
8519 { 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
|
8520 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
|
8521 } |
159 | 8522 } |
8523 } | |
8524 return this; | |
8525 } | |
8526 | |
8527 /************************************************************/ | |
8528 | |
8529 XorExp::XorExp(Loc loc, Expression *e1, Expression *e2) | |
8530 : BinExp(loc, TOKxor, sizeof(XorExp), e1, e2) | |
8531 { | |
8532 } | |
8533 | |
8534 Expression *XorExp::semantic(Scope *sc) | |
8535 { Expression *e; | |
8536 | |
8537 if (!type) | |
8538 { BinExp::semanticp(sc); | |
8539 e = op_overload(sc); | |
8540 if (e) | |
8541 return e; | |
8542 if (e1->type->toBasetype()->ty == Tbool && | |
8543 e2->type->toBasetype()->ty == Tbool) | |
8544 { | |
8545 type = e1->type; | |
8546 e = this; | |
8547 } | |
8548 else | |
8549 { | |
8550 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
|
8551 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
|
8552 { 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
|
8553 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
|
8554 } |
159 | 8555 } |
8556 } | |
8557 return this; | |
8558 } | |
8559 | |
8560 | |
8561 /************************************************************/ | |
8562 | |
8563 OrOrExp::OrOrExp(Loc loc, Expression *e1, Expression *e2) | |
8564 : BinExp(loc, TOKoror, sizeof(OrOrExp), e1, e2) | |
8565 { | |
8566 } | |
8567 | |
8568 Expression *OrOrExp::semantic(Scope *sc) | |
8569 { | |
8570 unsigned cs1; | |
8571 | |
8572 // same as for AndAnd | |
8573 e1 = e1->semantic(sc); | |
8574 e1 = resolveProperties(sc, e1); | |
8575 e1 = e1->checkToPointer(); | |
8576 e1 = e1->checkToBoolean(); | |
8577 cs1 = sc->callSuper; | |
8578 | |
8579 if (sc->flags & SCOPEstaticif) | |
8580 { | |
8581 /* If in static if, don't evaluate e2 if we don't have to. | |
8582 */ | |
8583 e1 = e1->optimize(WANTflags); | |
8584 if (e1->isBool(TRUE)) | |
8585 { | |
8586 return new IntegerExp(loc, 1, Type::tboolean); | |
8587 } | |
8588 } | |
8589 | |
8590 e2 = e2->semantic(sc); | |
8591 sc->mergeCallSuper(loc, cs1); | |
8592 e2 = resolveProperties(sc, e2); | |
8593 e2 = e2->checkToPointer(); | |
8594 | |
8595 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
|
8596 if (e2->type->ty == Tvoid) |
159 | 8597 type = Type::tvoid; |
8598 if (e2->op == TOKtype || e2->op == TOKimport) | |
8599 error("%s is not an expression", e2->toChars()); | |
8600 return this; | |
8601 } | |
8602 | |
8603 Expression *OrOrExp::checkToBoolean() | |
8604 { | |
8605 e2 = e2->checkToBoolean(); | |
8606 return this; | |
8607 } | |
8608 | |
8609 int OrOrExp::isBit() | |
8610 { | |
8611 return TRUE; | |
8612 } | |
8613 | |
8614 int OrOrExp::checkSideEffect(int flag) | |
8615 { | |
8616 if (flag == 2) | |
8617 { | |
8618 return e1->checkSideEffect(2) || e2->checkSideEffect(2); | |
8619 } | |
8620 else | |
8621 { e1->checkSideEffect(1); | |
8622 return e2->checkSideEffect(flag); | |
8623 } | |
8624 } | |
8625 | |
8626 /************************************************************/ | |
8627 | |
8628 AndAndExp::AndAndExp(Loc loc, Expression *e1, Expression *e2) | |
8629 : BinExp(loc, TOKandand, sizeof(AndAndExp), e1, e2) | |
8630 { | |
8631 } | |
8632 | |
8633 Expression *AndAndExp::semantic(Scope *sc) | |
8634 { | |
8635 unsigned cs1; | |
8636 | |
8637 // same as for OrOr | |
8638 e1 = e1->semantic(sc); | |
8639 e1 = resolveProperties(sc, e1); | |
8640 e1 = e1->checkToPointer(); | |
8641 e1 = e1->checkToBoolean(); | |
8642 cs1 = sc->callSuper; | |
8643 | |
8644 if (sc->flags & SCOPEstaticif) | |
8645 { | |
8646 /* If in static if, don't evaluate e2 if we don't have to. | |
8647 */ | |
8648 e1 = e1->optimize(WANTflags); | |
8649 if (e1->isBool(FALSE)) | |
8650 { | |
8651 return new IntegerExp(loc, 0, Type::tboolean); | |
8652 } | |
8653 } | |
8654 | |
8655 e2 = e2->semantic(sc); | |
8656 sc->mergeCallSuper(loc, cs1); | |
8657 e2 = resolveProperties(sc, e2); | |
8658 e2 = e2->checkToPointer(); | |
8659 | |
8660 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
|
8661 if (e2->type->ty == Tvoid) |
159 | 8662 type = Type::tvoid; |
8663 if (e2->op == TOKtype || e2->op == TOKimport) | |
8664 error("%s is not an expression", e2->toChars()); | |
8665 return this; | |
8666 } | |
8667 | |
8668 Expression *AndAndExp::checkToBoolean() | |
8669 { | |
8670 e2 = e2->checkToBoolean(); | |
8671 return this; | |
8672 } | |
8673 | |
8674 int AndAndExp::isBit() | |
8675 { | |
8676 return TRUE; | |
8677 } | |
8678 | |
8679 int AndAndExp::checkSideEffect(int flag) | |
8680 { | |
8681 if (flag == 2) | |
8682 { | |
8683 return e1->checkSideEffect(2) || e2->checkSideEffect(2); | |
8684 } | |
8685 else | |
8686 { | |
8687 e1->checkSideEffect(1); | |
8688 return e2->checkSideEffect(flag); | |
8689 } | |
8690 } | |
8691 | |
8692 /************************************************************/ | |
8693 | |
8694 InExp::InExp(Loc loc, Expression *e1, Expression *e2) | |
8695 : BinExp(loc, TOKin, sizeof(InExp), e1, e2) | |
8696 { | |
8697 } | |
8698 | |
8699 Expression *InExp::semantic(Scope *sc) | |
8700 { Expression *e; | |
8701 | |
8702 if (type) | |
8703 return this; | |
8704 | |
8705 BinExp::semanticp(sc); | |
8706 e = op_overload(sc); | |
8707 if (e) | |
8708 return e; | |
8709 | |
8710 //type = Type::tboolean; | |
8711 Type *t2b = e2->type->toBasetype(); | |
8712 if (t2b->ty != Taarray) | |
8713 { | |
8714 error("rvalue of in expression must be an associative array, not %s", e2->type->toChars()); | |
8715 type = Type::terror; | |
8716 } | |
8717 else | |
8718 { | |
8719 TypeAArray *ta = (TypeAArray *)t2b; | |
8720 | |
8721 // Convert key to type of key | |
8722 e1 = e1->implicitCastTo(sc, ta->index); | |
8723 | |
8724 // 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
|
8725 type = ta->nextOf()->pointerTo(); |
159 | 8726 } |
8727 return this; | |
8728 } | |
8729 | |
8730 int InExp::isBit() | |
8731 { | |
8732 return FALSE; | |
8733 } | |
8734 | |
8735 | |
8736 /************************************************************/ | |
8737 | |
8738 /* This deletes the key e1 from the associative array e2 | |
8739 */ | |
8740 | |
8741 RemoveExp::RemoveExp(Loc loc, Expression *e1, Expression *e2) | |
8742 : BinExp(loc, TOKremove, sizeof(RemoveExp), e1, e2) | |
8743 { | |
8744 type = Type::tvoid; | |
8745 } | |
8746 | |
8747 /************************************************************/ | |
8748 | |
8749 CmpExp::CmpExp(enum TOK op, Loc loc, Expression *e1, Expression *e2) | |
8750 : BinExp(loc, op, sizeof(CmpExp), e1, e2) | |
8751 { | |
8752 } | |
8753 | |
8754 Expression *CmpExp::semantic(Scope *sc) | |
8755 { Expression *e; | |
8756 Type *t1; | |
8757 Type *t2; | |
8758 | |
8759 #if LOGSEMANTIC | |
8760 printf("CmpExp::semantic('%s')\n", toChars()); | |
8761 #endif | |
8762 if (type) | |
8763 return this; | |
8764 | |
8765 BinExp::semanticp(sc); | |
8766 | |
8767 if (e1->type->toBasetype()->ty == Tclass && e2->op == TOKnull || | |
8768 e2->type->toBasetype()->ty == Tclass && e1->op == TOKnull) | |
8769 { | |
8770 error("do not use null when comparing class types"); | |
8771 } | |
8772 | |
8773 e = op_overload(sc); | |
8774 if (e) | |
8775 { | |
8776 e = new CmpExp(op, loc, e, new IntegerExp(loc, 0, Type::tint32)); | |
8777 e = e->semantic(sc); | |
8778 return e; | |
8779 } | |
8780 | |
8781 typeCombine(sc); | |
8782 type = Type::tboolean; | |
8783 | |
8784 // Special handling for array comparisons | |
8785 t1 = e1->type->toBasetype(); | |
8786 t2 = e2->type->toBasetype(); | |
8787 if ((t1->ty == Tarray || t1->ty == Tsarray) && | |
8788 (t2->ty == Tarray || t2->ty == Tsarray)) | |
8789 { | |
8790 if (!t1->next->equals(t2->next)) | |
8791 error("array comparison type mismatch, %s vs %s", t1->next->toChars(), t2->next->toChars()); | |
8792 e = this; | |
8793 } | |
8794 else if (t1->ty == Tstruct || t2->ty == Tstruct || | |
8795 (t1->ty == Tclass && t2->ty == Tclass)) | |
8796 { | |
8797 if (t2->ty == Tstruct) | |
8798 error("need member function opCmp() for %s %s to compare", t2->toDsymbol(sc)->kind(), t2->toChars()); | |
8799 else | |
8800 error("need member function opCmp() for %s %s to compare", t1->toDsymbol(sc)->kind(), t1->toChars()); | |
8801 e = this; | |
8802 } | |
8803 #if 1 | |
8804 else if (t1->iscomplex() || t2->iscomplex()) | |
8805 { | |
8806 error("compare not defined for complex operands"); | |
8807 e = new IntegerExp(0); | |
8808 } | |
8809 #endif | |
8810 else | |
8811 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
|
8812 //printf("CmpExp: %s\n", e->toChars()); |
159 | 8813 return e; |
8814 } | |
8815 | |
8816 int CmpExp::isBit() | |
8817 { | |
8818 return TRUE; | |
8819 } | |
8820 | |
8821 | |
8822 /************************************************************/ | |
8823 | |
8824 EqualExp::EqualExp(enum TOK op, Loc loc, Expression *e1, Expression *e2) | |
8825 : BinExp(loc, op, sizeof(EqualExp), e1, e2) | |
8826 { | |
8827 assert(op == TOKequal || op == TOKnotequal); | |
8828 } | |
8829 | |
8830 Expression *EqualExp::semantic(Scope *sc) | |
8831 { Expression *e; | |
8832 Type *t1; | |
8833 Type *t2; | |
8834 | |
8835 //printf("EqualExp::semantic('%s')\n", toChars()); | |
8836 if (type) | |
8837 return this; | |
8838 | |
8839 BinExp::semanticp(sc); | |
8840 | |
8841 /* Before checking for operator overloading, check to see if we're | |
8842 * comparing the addresses of two statics. If so, we can just see | |
8843 * if they are the same symbol. | |
8844 */ | |
8845 if (e1->op == TOKaddress && e2->op == TOKaddress) | |
8846 { AddrExp *ae1 = (AddrExp *)e1; | |
8847 AddrExp *ae2 = (AddrExp *)e2; | |
8848 | |
8849 if (ae1->e1->op == TOKvar && ae2->e1->op == TOKvar) | |
8850 { VarExp *ve1 = (VarExp *)ae1->e1; | |
8851 VarExp *ve2 = (VarExp *)ae2->e1; | |
8852 | |
8853 if (ve1->var == ve2->var /*|| ve1->var->toSymbol() == ve2->var->toSymbol()*/) | |
8854 { | |
8855 // They are the same, result is 'true' for ==, 'false' for != | |
8856 e = new IntegerExp(loc, (op == TOKequal), Type::tboolean); | |
8857 return e; | |
8858 } | |
8859 } | |
8860 } | |
8861 | |
8862 if (e1->type->toBasetype()->ty == Tclass && e2->op == TOKnull || | |
8863 e2->type->toBasetype()->ty == Tclass && e1->op == TOKnull) | |
8864 { | |
8865 error("use '%s' instead of '%s' when comparing with null", | |
8866 Token::toChars(op == TOKequal ? TOKidentity : TOKnotidentity), | |
8867 Token::toChars(op)); | |
8868 } | |
8869 | |
8870 //if (e2->op != TOKnull) | |
8871 { | |
8872 e = op_overload(sc); | |
8873 if (e) | |
8874 { | |
8875 if (op == TOKnotequal) | |
8876 { | |
8877 e = new NotExp(e->loc, e); | |
8878 e = e->semantic(sc); | |
8879 } | |
8880 return e; | |
8881 } | |
8882 } | |
8883 | |
8884 e = typeCombine(sc); | |
8885 type = Type::tboolean; | |
8886 | |
8887 // Special handling for array comparisons | |
8888 t1 = e1->type->toBasetype(); | |
8889 t2 = e2->type->toBasetype(); | |
8890 if ((t1->ty == Tarray || t1->ty == Tsarray) && | |
8891 (t2->ty == Tarray || t2->ty == Tsarray)) | |
8892 { | |
8893 if (!t1->next->equals(t2->next)) | |
8894 error("array comparison type mismatch, %s vs %s", t1->next->toChars(), t2->next->toChars()); | |
8895 } | |
8896 else | |
8897 { | |
8898 if (e1->type != e2->type && e1->type->isfloating() && e2->type->isfloating()) | |
8899 { | |
8900 // Cast both to complex | |
8901 e1 = e1->castTo(sc, Type::tcomplex80); | |
8902 e2 = e2->castTo(sc, Type::tcomplex80); | |
8903 } | |
8904 } | |
8905 return e; | |
8906 } | |
8907 | |
8908 int EqualExp::isBit() | |
8909 { | |
8910 return TRUE; | |
8911 } | |
8912 | |
8913 | |
8914 | |
8915 /************************************************************/ | |
8916 | |
8917 IdentityExp::IdentityExp(enum TOK op, Loc loc, Expression *e1, Expression *e2) | |
8918 : BinExp(loc, op, sizeof(IdentityExp), e1, e2) | |
8919 { | |
8920 } | |
8921 | |
8922 Expression *IdentityExp::semantic(Scope *sc) | |
8923 { | |
8924 if (type) | |
8925 return this; | |
8926 | |
8927 BinExp::semanticp(sc); | |
8928 type = Type::tboolean; | |
8929 typeCombine(sc); | |
8930 if (e1->type != e2->type && e1->type->isfloating() && e2->type->isfloating()) | |
8931 { | |
8932 // Cast both to complex | |
8933 e1 = e1->castTo(sc, Type::tcomplex80); | |
8934 e2 = e2->castTo(sc, Type::tcomplex80); | |
8935 } | |
8936 return this; | |
8937 } | |
8938 | |
8939 int IdentityExp::isBit() | |
8940 { | |
8941 return TRUE; | |
8942 } | |
8943 | |
8944 | |
8945 /****************************************************************/ | |
8946 | |
8947 CondExp::CondExp(Loc loc, Expression *econd, Expression *e1, Expression *e2) | |
8948 : BinExp(loc, TOKquestion, sizeof(CondExp), e1, e2) | |
8949 { | |
8950 this->econd = econd; | |
8951 } | |
8952 | |
8953 Expression *CondExp::syntaxCopy() | |
8954 { | |
8955 return new CondExp(loc, econd->syntaxCopy(), e1->syntaxCopy(), e2->syntaxCopy()); | |
8956 } | |
8957 | |
8958 | |
8959 Expression *CondExp::semantic(Scope *sc) | |
8960 { Type *t1; | |
8961 Type *t2; | |
8962 unsigned cs0; | |
8963 unsigned cs1; | |
8964 | |
8965 #if LOGSEMANTIC | |
8966 printf("CondExp::semantic('%s')\n", toChars()); | |
8967 #endif | |
8968 if (type) | |
8969 return this; | |
8970 | |
8971 econd = econd->semantic(sc); | |
8972 econd = resolveProperties(sc, econd); | |
8973 econd = econd->checkToPointer(); | |
8974 econd = econd->checkToBoolean(); | |
8975 | |
8976 #if 0 /* this cannot work right because the types of e1 and e2 | |
8977 * both contribute to the type of the result. | |
8978 */ | |
8979 if (sc->flags & SCOPEstaticif) | |
8980 { | |
8981 /* If in static if, don't evaluate what we don't have to. | |
8982 */ | |
8983 econd = econd->optimize(WANTflags); | |
8984 if (econd->isBool(TRUE)) | |
8985 { | |
8986 e1 = e1->semantic(sc); | |
8987 e1 = resolveProperties(sc, e1); | |
8988 return e1; | |
8989 } | |
8990 else if (econd->isBool(FALSE)) | |
8991 { | |
8992 e2 = e2->semantic(sc); | |
8993 e2 = resolveProperties(sc, e2); | |
8994 return e2; | |
8995 } | |
8996 } | |
8997 #endif | |
8998 | |
8999 | |
9000 cs0 = sc->callSuper; | |
9001 e1 = e1->semantic(sc); | |
9002 e1 = resolveProperties(sc, e1); | |
9003 cs1 = sc->callSuper; | |
9004 sc->callSuper = cs0; | |
9005 e2 = e2->semantic(sc); | |
9006 e2 = resolveProperties(sc, e2); | |
9007 sc->mergeCallSuper(loc, cs1); | |
9008 | |
9009 | |
9010 // If either operand is void, the result is void | |
9011 t1 = e1->type; | |
9012 t2 = e2->type; | |
9013 if (t1->ty == Tvoid || t2->ty == Tvoid) | |
9014 type = Type::tvoid; | |
9015 else if (t1 == t2) | |
9016 type = t1; | |
9017 else | |
9018 { | |
9019 typeCombine(sc); | |
9020 switch (e1->type->toBasetype()->ty) | |
9021 { | |
9022 case Tcomplex32: | |
9023 case Tcomplex64: | |
9024 case Tcomplex80: | |
9025 e2 = e2->castTo(sc, e1->type); | |
9026 break; | |
9027 } | |
9028 switch (e2->type->toBasetype()->ty) | |
9029 { | |
9030 case Tcomplex32: | |
9031 case Tcomplex64: | |
9032 case Tcomplex80: | |
9033 e1 = e1->castTo(sc, e2->type); | |
9034 break; | |
9035 } | |
9036 } | |
9037 return this; | |
9038 } | |
9039 | |
9040 Expression *CondExp::toLvalue(Scope *sc, Expression *ex) | |
9041 { | |
9042 PtrExp *e; | |
9043 | |
9044 // convert (econd ? e1 : e2) to *(econd ? &e1 : &e2) | |
9045 e = new PtrExp(loc, this, type); | |
9046 | |
9047 e1 = e1->addressOf(sc); | |
9048 //e1 = e1->toLvalue(sc, NULL); | |
9049 | |
9050 e2 = e2->addressOf(sc); | |
9051 //e2 = e2->toLvalue(sc, NULL); | |
9052 | |
9053 typeCombine(sc); | |
9054 | |
9055 type = e2->type; | |
9056 return e; | |
9057 } | |
9058 | |
9059 Expression *CondExp::modifiableLvalue(Scope *sc, Expression *e) | |
9060 { | |
9061 error("conditional expression %s is not a modifiable lvalue", toChars()); | |
9062 return this; | |
9063 } | |
9064 | |
9065 void CondExp::checkEscape() | |
9066 { | |
9067 e1->checkEscape(); | |
9068 e2->checkEscape(); | |
9069 } | |
9070 | |
9071 | |
9072 Expression *CondExp::checkToBoolean() | |
9073 { | |
9074 e1 = e1->checkToBoolean(); | |
9075 e2 = e2->checkToBoolean(); | |
9076 return this; | |
9077 } | |
9078 | |
9079 int CondExp::checkSideEffect(int flag) | |
9080 { | |
9081 if (flag == 2) | |
9082 { | |
9083 return econd->checkSideEffect(2) || | |
9084 e1->checkSideEffect(2) || | |
9085 e2->checkSideEffect(2); | |
9086 } | |
9087 else | |
9088 { | |
9089 econd->checkSideEffect(1); | |
9090 e1->checkSideEffect(flag); | |
9091 return e2->checkSideEffect(flag); | |
9092 } | |
9093 } | |
9094 | |
9095 void CondExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
9096 { | |
9097 expToCBuffer(buf, hgs, econd, PREC_oror); | |
9098 buf->writestring(" ? "); | |
9099 expToCBuffer(buf, hgs, e1, PREC_expr); | |
9100 buf->writestring(" : "); | |
9101 expToCBuffer(buf, hgs, e2, PREC_cond); | |
9102 } | |
9103 | |
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
|
9104 /************************************************************/ |
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
|
9105 |
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
|
9106 #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
|
9107 |
664
eef8ac26c66c
Some missed LLVMDC -> LDC.
Christian Kamm <kamm incasoftware de>
parents:
639
diff
changeset
|
9108 // 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
|
9109 |
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
|
9110 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
|
9111 : 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
|
9112 { |
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
|
9113 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
|
9114 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
|
9115 } |
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
|
9116 |
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
|
9117 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
|
9118 { |
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
|
9119 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
|
9120 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
|
9121 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
|
9122 } |
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
|
9123 |
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
|
9124 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
|
9125 { |
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
|
9126 // 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
|
9127 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
|
9128 } |
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
|
9129 |
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
|
9130 #endif |