Mercurial > projects > ldc
annotate dmd/interpret.c @ 834:f466f475b654
Added proper "need 'this' to access member foo" errors instead of "variable foo not resolved" for some cases, added FIXME for the old error!
Added a bit more information to the runtime's cyclic dependency detection exception.
author | Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> |
---|---|
date | Tue, 09 Dec 2008 01:56:39 +0100 |
parents | 50383e476c7e |
children | 330f999ade44 |
rev | line source |
---|---|
1 | 1 |
2 // Compiler implementation of the D programming language | |
159 | 3 // Copyright (c) 1999-2008 by Digital Mars |
1 | 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 <assert.h> | |
14 | |
15 #include "mem.h" | |
16 | |
17 #include "statement.h" | |
18 #include "expression.h" | |
19 #include "cond.h" | |
20 #include "init.h" | |
21 #include "staticassert.h" | |
22 #include "mtype.h" | |
23 #include "scope.h" | |
24 #include "declaration.h" | |
25 #include "aggregate.h" | |
26 #include "id.h" | |
27 | |
28 #define LOG 0 | |
29 | |
30 struct InterState | |
31 { | |
32 InterState *caller; // calling function's InterState | |
33 FuncDeclaration *fd; // function being interpreted | |
34 Dsymbols vars; // variables used in this function | |
35 Statement *start; // if !=NULL, start execution at this statement | |
36 Statement *gotoTarget; // target of EXP_GOTO_INTERPRET result | |
37 | |
38 InterState(); | |
39 }; | |
40 | |
41 InterState::InterState() | |
42 { | |
43 memset(this, 0, sizeof(InterState)); | |
44 } | |
45 | |
46 Expression *interpret_aaLen(InterState *istate, Expressions *arguments); | |
47 Expression *interpret_aaKeys(InterState *istate, Expressions *arguments); | |
48 Expression *interpret_aaValues(InterState *istate, Expressions *arguments); | |
49 | |
50 /************************************* | |
51 * Attempt to interpret a function given the arguments. | |
52 * Input: | |
53 * istate state for calling function (NULL if none) | |
54 * Return result expression if successful, NULL if not. | |
55 */ | |
56 | |
57 Expression *FuncDeclaration::interpret(InterState *istate, Expressions *arguments) | |
58 { | |
59 #if LOG | |
131 | 60 printf("\n********\nFuncDeclaration::interpret(istate = %p) %s\n", istate, toChars()); |
1 | 61 printf("cantInterpret = %d, semanticRun = %d\n", cantInterpret, semanticRun); |
62 #endif | |
63 if (global.errors) | |
64 return NULL; | |
65 if (ident == Id::aaLen) | |
66 return interpret_aaLen(istate, arguments); | |
67 else if (ident == Id::aaKeys) | |
68 return interpret_aaKeys(istate, arguments); | |
69 else if (ident == Id::aaValues) | |
70 return interpret_aaValues(istate, arguments); | |
71 | |
72 if (cantInterpret || semanticRun == 1) | |
73 return NULL; | |
74 | |
75 if (needThis() || isNested() || !fbody) | |
76 { cantInterpret = 1; | |
77 return NULL; | |
78 } | |
79 | |
80 if (semanticRun == 0 && scope) | |
81 { | |
82 semantic3(scope); | |
658
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
588
diff
changeset
|
83 if (global.errors) // if errors compiling this function |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
588
diff
changeset
|
84 return NULL; |
1 | 85 } |
86 if (semanticRun < 2) | |
87 return NULL; | |
88 | |
89 Type *tb = type->toBasetype(); | |
90 assert(tb->ty == Tfunction); | |
91 TypeFunction *tf = (TypeFunction *)tb; | |
92 Type *tret = tf->next->toBasetype(); | |
93 if (tf->varargs /*|| tret->ty == Tvoid*/) | |
94 { cantInterpret = 1; | |
95 return NULL; | |
96 } | |
97 | |
98 if (tf->parameters) | |
99 { size_t dim = Argument::dim(tf->parameters); | |
100 for (size_t i = 0; i < dim; i++) | |
101 { Argument *arg = Argument::getNth(tf->parameters, i); | |
102 if (arg->storageClass & STClazy) | |
103 { cantInterpret = 1; | |
104 return NULL; | |
105 } | |
106 } | |
107 } | |
108 | |
109 InterState istatex; | |
110 istatex.caller = istate; | |
111 istatex.fd = this; | |
112 | |
159 | 113 Expressions vsave; // place to save previous parameter values |
1 | 114 size_t dim = 0; |
115 if (arguments) | |
116 { | |
117 dim = arguments->dim; | |
118 assert(!dim || parameters->dim == dim); | |
119 vsave.setDim(dim); | |
120 | |
159 | 121 /* Evaluate all the arguments to the function, |
122 * store the results in eargs[] | |
123 */ | |
124 Expressions eargs; | |
125 eargs.setDim(dim); | |
126 | |
1 | 127 for (size_t i = 0; i < dim; i++) |
128 { Expression *earg = (Expression *)arguments->data[i]; | |
129 Argument *arg = Argument::getNth(tf->parameters, i); | |
159 | 130 |
131 if (arg->storageClass & (STCout | STCref)) | |
132 { | |
133 } | |
134 else | |
135 { /* Value parameters | |
136 */ | |
137 Type *ta = arg->type->toBasetype(); | |
138 if (ta->ty == Tsarray && earg->op == TOKaddress) | |
139 { | |
140 /* Static arrays are passed by a simple pointer. | |
141 * Skip past this to get at the actual arg. | |
142 */ | |
143 earg = ((AddrExp *)earg)->e1; | |
144 } | |
145 earg = earg->interpret(istate ? istate : &istatex); | |
146 if (earg == EXP_CANT_INTERPRET) | |
147 return NULL; | |
148 } | |
149 eargs.data[i] = earg; | |
150 } | |
151 | |
152 for (size_t i = 0; i < dim; i++) | |
153 { Expression *earg = (Expression *)eargs.data[i]; | |
154 Argument *arg = Argument::getNth(tf->parameters, i); | |
1 | 155 VarDeclaration *v = (VarDeclaration *)parameters->data[i]; |
156 vsave.data[i] = v->value; | |
157 #if LOG | |
158 printf("arg[%d] = %s\n", i, earg->toChars()); | |
159 #endif | |
160 if (arg->storageClass & (STCout | STCref)) | |
161 { | |
162 /* Bind out or ref parameter to the corresponding | |
163 * variable v2 | |
164 */ | |
165 if (!istate || earg->op != TOKvar) | |
166 return NULL; // can't bind to non-interpreted vars | |
167 | |
168 VarDeclaration *v2; | |
169 while (1) | |
170 { | |
171 VarExp *ve = (VarExp *)earg; | |
172 v2 = ve->var->isVarDeclaration(); | |
173 if (!v2) | |
174 return NULL; | |
175 if (!v2->value || v2->value->op != TOKvar) | |
176 break; | |
177 earg = v2->value; | |
178 } | |
179 | |
180 v->value = new VarExp(earg->loc, v2); | |
181 | |
182 /* Don't restore the value of v2 upon function return | |
183 */ | |
184 assert(istate); | |
185 for (size_t i = 0; i < istate->vars.dim; i++) | |
186 { VarDeclaration *v = (VarDeclaration *)istate->vars.data[i]; | |
187 if (v == v2) | |
188 { istate->vars.data[i] = NULL; | |
189 break; | |
190 } | |
191 } | |
192 } | |
193 else | |
194 { /* Value parameters | |
195 */ | |
196 v->value = earg; | |
197 } | |
198 #if LOG | |
199 printf("interpreted arg[%d] = %s\n", i, earg->toChars()); | |
200 #endif | |
201 } | |
202 } | |
203 | |
204 /* Save the values of the local variables used | |
205 */ | |
206 Expressions valueSaves; | |
207 if (istate) | |
208 { | |
131 | 209 //printf("saving local variables...\n"); |
1 | 210 valueSaves.setDim(istate->vars.dim); |
211 for (size_t i = 0; i < istate->vars.dim; i++) | |
212 { VarDeclaration *v = (VarDeclaration *)istate->vars.data[i]; | |
213 if (v) | |
214 { | |
131 | 215 //printf("\tsaving [%d] %s = %s\n", i, v->toChars(), v->value ? v->value->toChars() : ""); |
1 | 216 valueSaves.data[i] = v->value; |
217 v->value = NULL; | |
218 } | |
219 } | |
220 } | |
221 | |
222 Expression *e = NULL; | |
223 | |
224 while (1) | |
225 { | |
226 e = fbody->interpret(&istatex); | |
227 if (e == EXP_CANT_INTERPRET) | |
228 { | |
229 #if LOG | |
230 printf("function body failed to interpret\n"); | |
231 #endif | |
232 e = NULL; | |
233 } | |
234 | |
235 /* This is how we deal with a recursive statement AST | |
236 * that has arbitrary goto statements in it. | |
237 * Bubble up a 'result' which is the target of the goto | |
238 * statement, then go recursively down the AST looking | |
239 * for that statement, then execute starting there. | |
240 */ | |
241 if (e == EXP_GOTO_INTERPRET) | |
242 { | |
243 istatex.start = istatex.gotoTarget; // set starting statement | |
244 istatex.gotoTarget = NULL; | |
245 } | |
246 else | |
247 break; | |
248 } | |
249 | |
250 /* Restore the parameter values | |
251 */ | |
252 for (size_t i = 0; i < dim; i++) | |
253 { | |
254 VarDeclaration *v = (VarDeclaration *)parameters->data[i]; | |
255 v->value = (Expression *)vsave.data[i]; | |
256 } | |
257 | |
258 if (istate) | |
259 { | |
260 /* Restore the variable values | |
261 */ | |
131 | 262 //printf("restoring local variables...\n"); |
1 | 263 for (size_t i = 0; i < istate->vars.dim; i++) |
264 { VarDeclaration *v = (VarDeclaration *)istate->vars.data[i]; | |
265 if (v) | |
131 | 266 { v->value = (Expression *)valueSaves.data[i]; |
267 //printf("\trestoring [%d] %s = %s\n", i, v->toChars(), v->value ? v->value->toChars() : ""); | |
268 } | |
1 | 269 } |
270 } | |
271 | |
272 return e; | |
273 } | |
274 | |
275 /******************************** Statement ***************************/ | |
276 | |
277 #define START() \ | |
278 if (istate->start) \ | |
279 { if (istate->start != this) \ | |
280 return NULL; \ | |
281 istate->start = NULL; \ | |
282 } | |
283 | |
284 /*********************************** | |
285 * Interpret the statement. | |
286 * Returns: | |
287 * NULL continue to next statement | |
288 * EXP_CANT_INTERPRET cannot interpret statement at compile time | |
289 * !NULL expression from return statement | |
290 */ | |
291 | |
292 Expression *Statement::interpret(InterState *istate) | |
293 { | |
294 #if LOG | |
295 printf("Statement::interpret()\n"); | |
296 #endif | |
297 START() | |
298 return EXP_CANT_INTERPRET; | |
299 } | |
300 | |
301 Expression *ExpStatement::interpret(InterState *istate) | |
302 { | |
303 #if LOG | |
304 printf("ExpStatement::interpret(%s)\n", exp ? exp->toChars() : ""); | |
305 #endif | |
306 START() | |
307 if (exp) | |
308 { | |
309 Expression *e = exp->interpret(istate); | |
310 if (e == EXP_CANT_INTERPRET) | |
311 { | |
19 | 312 //printf("-ExpStatement::interpret(): %p\n", e); |
1 | 313 return EXP_CANT_INTERPRET; |
314 } | |
315 } | |
316 return NULL; | |
317 } | |
318 | |
319 Expression *CompoundStatement::interpret(InterState *istate) | |
320 { Expression *e = NULL; | |
321 | |
322 #if LOG | |
323 printf("CompoundStatement::interpret()\n"); | |
324 #endif | |
325 if (istate->start == this) | |
326 istate->start = NULL; | |
327 if (statements) | |
328 { | |
329 for (size_t i = 0; i < statements->dim; i++) | |
330 { Statement *s = (Statement *)statements->data[i]; | |
331 | |
332 if (s) | |
333 { | |
334 e = s->interpret(istate); | |
335 if (e) | |
336 break; | |
337 } | |
338 } | |
339 } | |
340 #if LOG | |
341 printf("-CompoundStatement::interpret() %p\n", e); | |
342 #endif | |
343 return e; | |
344 } | |
345 | |
346 Expression *UnrolledLoopStatement::interpret(InterState *istate) | |
347 { Expression *e = NULL; | |
348 | |
349 #if LOG | |
350 printf("UnrolledLoopStatement::interpret()\n"); | |
351 #endif | |
352 if (istate->start == this) | |
353 istate->start = NULL; | |
354 if (statements) | |
355 { | |
356 for (size_t i = 0; i < statements->dim; i++) | |
357 { Statement *s = (Statement *)statements->data[i]; | |
358 | |
359 e = s->interpret(istate); | |
360 if (e == EXP_CANT_INTERPRET) | |
361 break; | |
362 if (e == EXP_CONTINUE_INTERPRET) | |
363 { e = NULL; | |
364 continue; | |
365 } | |
366 if (e == EXP_BREAK_INTERPRET) | |
367 { e = NULL; | |
368 break; | |
369 } | |
370 if (e) | |
371 break; | |
372 } | |
373 } | |
374 return e; | |
375 } | |
376 | |
377 Expression *IfStatement::interpret(InterState *istate) | |
378 { | |
379 #if LOG | |
380 printf("IfStatement::interpret(%s)\n", condition->toChars()); | |
381 #endif | |
382 | |
383 if (istate->start == this) | |
384 istate->start = NULL; | |
385 if (istate->start) | |
386 { | |
387 Expression *e = NULL; | |
388 if (ifbody) | |
389 e = ifbody->interpret(istate); | |
390 if (istate->start && elsebody) | |
391 e = elsebody->interpret(istate); | |
392 return e; | |
393 } | |
394 | |
395 Expression *e = condition->interpret(istate); | |
396 assert(e); | |
397 //if (e == EXP_CANT_INTERPRET) printf("cannot interpret\n"); | |
398 if (e != EXP_CANT_INTERPRET) | |
399 { | |
19 | 400 if (e->isBool(TRUE)) |
401 e = ifbody ? ifbody->interpret(istate) : NULL; | |
402 else if (e->isBool(FALSE)) | |
403 e = elsebody ? elsebody->interpret(istate) : NULL; | |
1 | 404 else |
405 { | |
19 | 406 e = EXP_CANT_INTERPRET; |
1 | 407 } |
408 } | |
409 return e; | |
410 } | |
411 | |
412 Expression *ScopeStatement::interpret(InterState *istate) | |
413 { | |
414 #if LOG | |
415 printf("ScopeStatement::interpret()\n"); | |
416 #endif | |
417 if (istate->start == this) | |
418 istate->start = NULL; | |
419 return statement ? statement->interpret(istate) : NULL; | |
420 } | |
421 | |
422 Expression *ReturnStatement::interpret(InterState *istate) | |
423 { | |
424 #if LOG | |
425 printf("ReturnStatement::interpret(%s)\n", exp ? exp->toChars() : ""); | |
426 #endif | |
427 START() | |
428 if (!exp) | |
429 return EXP_VOID_INTERPRET; | |
430 #if LOG | |
431 Expression *e = exp->interpret(istate); | |
432 printf("e = %p\n", e); | |
433 return e; | |
434 #else | |
435 return exp->interpret(istate); | |
436 #endif | |
437 } | |
438 | |
439 Expression *BreakStatement::interpret(InterState *istate) | |
440 { | |
441 #if LOG | |
442 printf("BreakStatement::interpret()\n"); | |
443 #endif | |
444 START() | |
445 if (ident) | |
446 return EXP_CANT_INTERPRET; | |
447 else | |
448 return EXP_BREAK_INTERPRET; | |
449 } | |
450 | |
451 Expression *ContinueStatement::interpret(InterState *istate) | |
452 { | |
453 #if LOG | |
454 printf("ContinueStatement::interpret()\n"); | |
455 #endif | |
456 START() | |
457 if (ident) | |
458 return EXP_CANT_INTERPRET; | |
459 else | |
460 return EXP_CONTINUE_INTERPRET; | |
461 } | |
462 | |
463 Expression *WhileStatement::interpret(InterState *istate) | |
464 { | |
465 #if LOG | |
466 printf("WhileStatement::interpret()\n"); | |
467 #endif | |
468 if (istate->start == this) | |
469 istate->start = NULL; | |
470 Expression *e; | |
471 | |
472 if (istate->start) | |
473 { | |
474 e = body ? body->interpret(istate) : NULL; | |
475 if (istate->start) | |
476 return NULL; | |
477 if (e == EXP_CANT_INTERPRET) | |
478 return e; | |
479 if (e == EXP_BREAK_INTERPRET) | |
480 return NULL; | |
481 if (e != EXP_CONTINUE_INTERPRET) | |
482 return e; | |
483 } | |
484 | |
485 while (1) | |
486 { | |
487 e = condition->interpret(istate); | |
488 if (e == EXP_CANT_INTERPRET) | |
489 break; | |
490 if (!e->isConst()) | |
491 { e = EXP_CANT_INTERPRET; | |
492 break; | |
493 } | |
494 if (e->isBool(TRUE)) | |
495 { e = body ? body->interpret(istate) : NULL; | |
496 if (e == EXP_CANT_INTERPRET) | |
497 break; | |
498 if (e == EXP_CONTINUE_INTERPRET) | |
499 continue; | |
500 if (e == EXP_BREAK_INTERPRET) | |
501 { e = NULL; | |
502 break; | |
503 } | |
504 if (e) | |
505 break; | |
506 } | |
507 else if (e->isBool(FALSE)) | |
508 { e = NULL; | |
509 break; | |
510 } | |
511 else | |
512 assert(0); | |
513 } | |
514 return e; | |
515 } | |
516 | |
517 Expression *DoStatement::interpret(InterState *istate) | |
518 { | |
519 #if LOG | |
520 printf("DoStatement::interpret()\n"); | |
521 #endif | |
522 if (istate->start == this) | |
523 istate->start = NULL; | |
524 Expression *e; | |
525 | |
526 if (istate->start) | |
527 { | |
528 e = body ? body->interpret(istate) : NULL; | |
529 if (istate->start) | |
530 return NULL; | |
531 if (e == EXP_CANT_INTERPRET) | |
532 return e; | |
533 if (e == EXP_BREAK_INTERPRET) | |
534 return NULL; | |
535 if (e == EXP_CONTINUE_INTERPRET) | |
536 goto Lcontinue; | |
537 if (e) | |
538 return e; | |
539 } | |
540 | |
541 while (1) | |
542 { | |
543 e = body ? body->interpret(istate) : NULL; | |
544 if (e == EXP_CANT_INTERPRET) | |
545 break; | |
546 if (e == EXP_BREAK_INTERPRET) | |
547 { e = NULL; | |
548 break; | |
549 } | |
550 if (e && e != EXP_CONTINUE_INTERPRET) | |
551 break; | |
552 | |
553 Lcontinue: | |
554 e = condition->interpret(istate); | |
555 if (e == EXP_CANT_INTERPRET) | |
556 break; | |
557 if (!e->isConst()) | |
558 { e = EXP_CANT_INTERPRET; | |
559 break; | |
560 } | |
561 if (e->isBool(TRUE)) | |
562 { | |
563 } | |
564 else if (e->isBool(FALSE)) | |
565 { e = NULL; | |
566 break; | |
567 } | |
568 else | |
569 assert(0); | |
570 } | |
571 return e; | |
572 } | |
573 | |
574 Expression *ForStatement::interpret(InterState *istate) | |
575 { | |
576 #if LOG | |
577 printf("ForStatement::interpret()\n"); | |
578 #endif | |
579 if (istate->start == this) | |
580 istate->start = NULL; | |
581 Expression *e; | |
582 | |
583 if (init) | |
584 { | |
585 e = init->interpret(istate); | |
586 if (e == EXP_CANT_INTERPRET) | |
587 return e; | |
588 assert(!e); | |
589 } | |
590 | |
591 if (istate->start) | |
592 { | |
593 e = body ? body->interpret(istate) : NULL; | |
594 if (istate->start) | |
595 return NULL; | |
596 if (e == EXP_CANT_INTERPRET) | |
597 return e; | |
598 if (e == EXP_BREAK_INTERPRET) | |
599 return NULL; | |
600 if (e == EXP_CONTINUE_INTERPRET) | |
601 goto Lcontinue; | |
602 if (e) | |
603 return e; | |
604 } | |
605 | |
606 while (1) | |
607 { | |
159 | 608 if (!condition) |
609 goto Lhead; | |
1 | 610 e = condition->interpret(istate); |
611 if (e == EXP_CANT_INTERPRET) | |
612 break; | |
613 if (!e->isConst()) | |
614 { e = EXP_CANT_INTERPRET; | |
615 break; | |
616 } | |
617 if (e->isBool(TRUE)) | |
159 | 618 { |
619 Lhead: | |
620 e = body ? body->interpret(istate) : NULL; | |
1 | 621 if (e == EXP_CANT_INTERPRET) |
622 break; | |
623 if (e == EXP_BREAK_INTERPRET) | |
624 { e = NULL; | |
625 break; | |
626 } | |
627 if (e && e != EXP_CONTINUE_INTERPRET) | |
628 break; | |
629 Lcontinue: | |
159 | 630 if (increment) |
631 { | |
632 e = increment->interpret(istate); | |
633 if (e == EXP_CANT_INTERPRET) | |
634 break; | |
635 } | |
1 | 636 } |
637 else if (e->isBool(FALSE)) | |
638 { e = NULL; | |
639 break; | |
640 } | |
641 else | |
642 assert(0); | |
643 } | |
644 return e; | |
645 } | |
646 | |
647 Expression *ForeachStatement::interpret(InterState *istate) | |
648 { | |
649 #if LOG | |
650 printf("ForeachStatement::interpret()\n"); | |
651 #endif | |
652 if (istate->start == this) | |
653 istate->start = NULL; | |
654 if (istate->start) | |
655 return NULL; | |
656 | |
657 Expression *e = NULL; | |
658 Expression *eaggr; | |
659 | |
660 if (value->isOut() || value->isRef()) | |
661 return EXP_CANT_INTERPRET; | |
662 | |
663 eaggr = aggr->interpret(istate); | |
664 if (eaggr == EXP_CANT_INTERPRET) | |
665 return EXP_CANT_INTERPRET; | |
666 | |
667 Expression *dim = ArrayLength(Type::tsize_t, eaggr); | |
668 if (dim == EXP_CANT_INTERPRET) | |
669 return EXP_CANT_INTERPRET; | |
670 | |
671 Expression *keysave = key ? key->value : NULL; | |
672 Expression *valuesave = value->value; | |
673 | |
674 uinteger_t d = dim->toUInteger(); | |
675 uinteger_t index; | |
676 | |
677 if (op == TOKforeach) | |
678 { | |
679 for (index = 0; index < d; index++) | |
680 { | |
681 Expression *ekey = new IntegerExp(loc, index, Type::tsize_t); | |
682 if (key) | |
683 key->value = ekey; | |
684 e = Index(value->type, eaggr, ekey); | |
685 if (e == EXP_CANT_INTERPRET) | |
686 break; | |
687 value->value = e; | |
688 | |
689 e = body ? body->interpret(istate) : NULL; | |
690 if (e == EXP_CANT_INTERPRET) | |
691 break; | |
692 if (e == EXP_BREAK_INTERPRET) | |
693 { e = NULL; | |
694 break; | |
695 } | |
696 if (e == EXP_CONTINUE_INTERPRET) | |
697 e = NULL; | |
698 else if (e) | |
699 break; | |
700 } | |
701 } | |
702 else // TOKforeach_reverse | |
703 { | |
704 for (index = d; index-- != 0;) | |
705 { | |
706 Expression *ekey = new IntegerExp(loc, index, Type::tsize_t); | |
707 if (key) | |
708 key->value = ekey; | |
709 e = Index(value->type, eaggr, ekey); | |
710 if (e == EXP_CANT_INTERPRET) | |
711 break; | |
712 value->value = e; | |
713 | |
714 e = body ? body->interpret(istate) : NULL; | |
715 if (e == EXP_CANT_INTERPRET) | |
716 break; | |
717 if (e == EXP_BREAK_INTERPRET) | |
718 { e = NULL; | |
719 break; | |
720 } | |
721 if (e == EXP_CONTINUE_INTERPRET) | |
722 e = NULL; | |
723 else if (e) | |
724 break; | |
725 } | |
726 } | |
727 value->value = valuesave; | |
728 if (key) | |
729 key->value = keysave; | |
730 return e; | |
731 } | |
732 | |
336 | 733 #if DMDV2 |
1 | 734 Expression *ForeachRangeStatement::interpret(InterState *istate) |
735 { | |
736 #if LOG | |
737 printf("ForeachRangeStatement::interpret()\n"); | |
738 #endif | |
739 if (istate->start == this) | |
740 istate->start = NULL; | |
741 if (istate->start) | |
742 return NULL; | |
743 | |
744 Expression *e = NULL; | |
745 Expression *elwr = lwr->interpret(istate); | |
746 if (elwr == EXP_CANT_INTERPRET) | |
747 return EXP_CANT_INTERPRET; | |
748 | |
749 Expression *eupr = upr->interpret(istate); | |
750 if (eupr == EXP_CANT_INTERPRET) | |
751 return EXP_CANT_INTERPRET; | |
752 | |
753 Expression *keysave = key->value; | |
754 | |
755 if (op == TOKforeach) | |
756 { | |
757 key->value = elwr; | |
758 | |
759 while (1) | |
760 { | |
761 e = Cmp(TOKlt, key->value->type, key->value, upr); | |
762 if (e == EXP_CANT_INTERPRET) | |
763 break; | |
764 if (e->isBool(TRUE) == FALSE) | |
765 { e = NULL; | |
766 break; | |
767 } | |
768 | |
769 e = body ? body->interpret(istate) : NULL; | |
770 if (e == EXP_CANT_INTERPRET) | |
771 break; | |
772 if (e == EXP_BREAK_INTERPRET) | |
773 { e = NULL; | |
774 break; | |
775 } | |
776 e = Add(key->value->type, key->value, new IntegerExp(loc, 1, key->value->type)); | |
777 if (e == EXP_CANT_INTERPRET) | |
778 break; | |
779 key->value = e; | |
780 } | |
781 } | |
782 else // TOKforeach_reverse | |
783 { | |
784 key->value = eupr; | |
785 | |
786 while (1) | |
787 { | |
788 e = Cmp(TOKgt, key->value->type, key->value, lwr); | |
789 if (e == EXP_CANT_INTERPRET) | |
790 break; | |
791 if (e->isBool(TRUE) == FALSE) | |
792 { e = NULL; | |
793 break; | |
794 } | |
795 | |
796 e = Min(key->value->type, key->value, new IntegerExp(loc, 1, key->value->type)); | |
797 if (e == EXP_CANT_INTERPRET) | |
798 break; | |
799 key->value = e; | |
800 | |
801 e = body ? body->interpret(istate) : NULL; | |
802 if (e == EXP_CANT_INTERPRET) | |
803 break; | |
804 if (e == EXP_BREAK_INTERPRET) | |
805 { e = NULL; | |
806 break; | |
807 } | |
808 } | |
809 } | |
810 key->value = keysave; | |
811 return e; | |
812 } | |
813 #endif | |
814 | |
815 Expression *SwitchStatement::interpret(InterState *istate) | |
816 { | |
817 #if LOG | |
818 printf("SwitchStatement::interpret()\n"); | |
819 #endif | |
820 if (istate->start == this) | |
821 istate->start = NULL; | |
822 Expression *e = NULL; | |
823 | |
824 if (istate->start) | |
825 { | |
826 e = body ? body->interpret(istate) : NULL; | |
827 if (istate->start) | |
828 return NULL; | |
829 if (e == EXP_CANT_INTERPRET) | |
830 return e; | |
831 if (e == EXP_BREAK_INTERPRET) | |
832 return NULL; | |
833 return e; | |
834 } | |
835 | |
836 | |
837 Expression *econdition = condition->interpret(istate); | |
838 if (econdition == EXP_CANT_INTERPRET) | |
839 return EXP_CANT_INTERPRET; | |
840 | |
841 Statement *s = NULL; | |
842 if (cases) | |
843 { | |
844 for (size_t i = 0; i < cases->dim; i++) | |
845 { | |
846 CaseStatement *cs = (CaseStatement *)cases->data[i]; | |
847 e = Equal(TOKequal, Type::tint32, econdition, cs->exp); | |
848 if (e == EXP_CANT_INTERPRET) | |
849 return EXP_CANT_INTERPRET; | |
850 if (e->isBool(TRUE)) | |
851 { s = cs; | |
852 break; | |
853 } | |
854 } | |
855 } | |
856 if (!s) | |
857 { if (hasNoDefault) | |
858 error("no default or case for %s in switch statement", econdition->toChars()); | |
859 s = sdefault; | |
860 } | |
861 | |
862 assert(s); | |
863 istate->start = s; | |
864 e = body ? body->interpret(istate) : NULL; | |
865 assert(!istate->start); | |
866 if (e == EXP_BREAK_INTERPRET) | |
867 return NULL; | |
868 return e; | |
869 } | |
870 | |
871 Expression *CaseStatement::interpret(InterState *istate) | |
872 { | |
873 #if LOG | |
874 printf("CaseStatement::interpret(%s) this = %p\n", exp->toChars(), this); | |
875 #endif | |
876 if (istate->start == this) | |
877 istate->start = NULL; | |
878 if (statement) | |
879 return statement->interpret(istate); | |
880 else | |
881 return NULL; | |
882 } | |
883 | |
884 Expression *DefaultStatement::interpret(InterState *istate) | |
885 { | |
886 #if LOG | |
887 printf("DefaultStatement::interpret()\n"); | |
888 #endif | |
889 if (istate->start == this) | |
890 istate->start = NULL; | |
891 if (statement) | |
892 return statement->interpret(istate); | |
893 else | |
894 return NULL; | |
895 } | |
896 | |
897 Expression *GotoStatement::interpret(InterState *istate) | |
898 { | |
899 #if LOG | |
900 printf("GotoStatement::interpret()\n"); | |
901 #endif | |
902 START() | |
903 assert(label && label->statement); | |
904 istate->gotoTarget = label->statement; | |
905 return EXP_GOTO_INTERPRET; | |
906 } | |
907 | |
908 Expression *GotoCaseStatement::interpret(InterState *istate) | |
909 { | |
910 #if LOG | |
911 printf("GotoCaseStatement::interpret()\n"); | |
912 #endif | |
913 START() | |
914 assert(cs); | |
915 istate->gotoTarget = cs; | |
916 return EXP_GOTO_INTERPRET; | |
917 } | |
918 | |
919 Expression *GotoDefaultStatement::interpret(InterState *istate) | |
920 { | |
921 #if LOG | |
922 printf("GotoDefaultStatement::interpret()\n"); | |
923 #endif | |
924 START() | |
925 assert(sw && sw->sdefault); | |
926 istate->gotoTarget = sw->sdefault; | |
927 return EXP_GOTO_INTERPRET; | |
928 } | |
929 | |
930 Expression *LabelStatement::interpret(InterState *istate) | |
931 { | |
932 #if LOG | |
933 printf("LabelStatement::interpret()\n"); | |
934 #endif | |
935 if (istate->start == this) | |
936 istate->start = NULL; | |
937 return statement ? statement->interpret(istate) : NULL; | |
938 } | |
939 | |
940 /******************************** Expression ***************************/ | |
941 | |
942 Expression *Expression::interpret(InterState *istate) | |
943 { | |
944 #if LOG | |
945 printf("Expression::interpret() %s\n", toChars()); | |
131 | 946 printf("type = %s\n", type->toChars()); |
947 dump(0); | |
1 | 948 #endif |
949 return EXP_CANT_INTERPRET; | |
950 } | |
951 | |
952 Expression *NullExp::interpret(InterState *istate) | |
953 { | |
954 return this; | |
955 } | |
956 | |
957 Expression *IntegerExp::interpret(InterState *istate) | |
958 { | |
959 #if LOG | |
960 printf("IntegerExp::interpret() %s\n", toChars()); | |
961 #endif | |
962 return this; | |
963 } | |
964 | |
965 Expression *RealExp::interpret(InterState *istate) | |
966 { | |
967 #if LOG | |
968 printf("RealExp::interpret() %s\n", toChars()); | |
969 #endif | |
970 return this; | |
971 } | |
972 | |
973 Expression *ComplexExp::interpret(InterState *istate) | |
974 { | |
975 return this; | |
976 } | |
977 | |
978 Expression *StringExp::interpret(InterState *istate) | |
979 { | |
980 #if LOG | |
981 printf("StringExp::interpret() %s\n", toChars()); | |
982 #endif | |
983 return this; | |
984 } | |
985 | |
986 Expression *getVarExp(Loc loc, InterState *istate, Declaration *d) | |
987 { | |
988 Expression *e = EXP_CANT_INTERPRET; | |
989 VarDeclaration *v = d->isVarDeclaration(); | |
990 SymbolDeclaration *s = d->isSymbolDeclaration(); | |
991 if (v) | |
992 { | |
336 | 993 #if DMDV2 |
131 | 994 if ((v->isConst() || v->isInvariant()) && v->init && !v->value) |
995 #else | |
1 | 996 if (v->isConst() && v->init) |
131 | 997 #endif |
1 | 998 { e = v->init->toExpression(); |
19 | 999 if (e && !e->type) |
1 | 1000 e->type = v->type; |
1001 } | |
1002 else | |
1003 { e = v->value; | |
1004 if (!e) | |
1005 error(loc, "variable %s is used before initialization", v->toChars()); | |
1006 else if (e != EXP_CANT_INTERPRET) | |
1007 e = e->interpret(istate); | |
1008 } | |
1009 if (!e) | |
1010 e = EXP_CANT_INTERPRET; | |
1011 } | |
1012 else if (s) | |
1013 { | |
1014 if (s->dsym->toInitializer() == s->sym) | |
1015 { Expressions *exps = new Expressions(); | |
1016 e = new StructLiteralExp(0, s->dsym, exps); | |
1017 e = e->semantic(NULL); | |
1018 } | |
1019 } | |
1020 return e; | |
1021 } | |
1022 | |
1023 Expression *VarExp::interpret(InterState *istate) | |
1024 { | |
1025 #if LOG | |
1026 printf("VarExp::interpret() %s\n", toChars()); | |
1027 #endif | |
1028 return getVarExp(loc, istate, var); | |
1029 } | |
1030 | |
1031 Expression *DeclarationExp::interpret(InterState *istate) | |
1032 { | |
1033 #if LOG | |
1034 printf("DeclarationExp::interpret() %s\n", toChars()); | |
1035 #endif | |
19 | 1036 Expression *e; |
1 | 1037 VarDeclaration *v = declaration->isVarDeclaration(); |
1038 if (v) | |
1039 { | |
1040 Dsymbol *s = v->toAlias(); | |
1041 if (s == v && !v->isStatic() && v->init) | |
1042 { | |
1043 ExpInitializer *ie = v->init->isExpInitializer(); | |
1044 if (ie) | |
1045 e = ie->exp->interpret(istate); | |
1046 else if (v->init->isVoidInitializer()) | |
1047 e = NULL; | |
1048 } | |
336 | 1049 #if DMDV2 |
131 | 1050 else if (s == v && (v->isConst() || v->isInvariant()) && v->init) |
1051 #else | |
1 | 1052 else if (s == v && v->isConst() && v->init) |
131 | 1053 #endif |
1 | 1054 { e = v->init->toExpression(); |
1055 if (!e) | |
1056 e = EXP_CANT_INTERPRET; | |
1057 else if (!e->type) | |
1058 e->type = v->type; | |
1059 } | |
1060 } | |
19 | 1061 else if (declaration->isAttribDeclaration() || |
1062 declaration->isTemplateMixin() || | |
1063 declaration->isTupleDeclaration()) | |
1064 { // These can be made to work, too lazy now | |
1065 e = EXP_CANT_INTERPRET; | |
1066 } | |
1067 else | |
1068 { // Others should not contain executable code, so are trivial to evaluate | |
1069 e = NULL; | |
1070 } | |
1071 #if LOG | |
1072 printf("-DeclarationExp::interpret(): %p\n", e); | |
1073 #endif | |
1 | 1074 return e; |
1075 } | |
1076 | |
1077 Expression *TupleExp::interpret(InterState *istate) | |
1078 { | |
1079 #if LOG | |
1080 printf("TupleExp::interpret() %s\n", toChars()); | |
1081 #endif | |
1082 Expressions *expsx = NULL; | |
1083 | |
1084 for (size_t i = 0; i < exps->dim; i++) | |
1085 { Expression *e = (Expression *)exps->data[i]; | |
1086 Expression *ex; | |
1087 | |
1088 ex = e->interpret(istate); | |
1089 if (ex == EXP_CANT_INTERPRET) | |
1090 { delete expsx; | |
1091 return ex; | |
1092 } | |
1093 | |
1094 /* If any changes, do Copy On Write | |
1095 */ | |
1096 if (ex != e) | |
1097 { | |
1098 if (!expsx) | |
1099 { expsx = new Expressions(); | |
1100 expsx->setDim(exps->dim); | |
1101 for (size_t j = 0; j < i; j++) | |
1102 { | |
1103 expsx->data[j] = exps->data[j]; | |
1104 } | |
1105 } | |
1106 expsx->data[i] = (void *)ex; | |
1107 } | |
1108 } | |
1109 if (expsx) | |
1110 { TupleExp *te = new TupleExp(loc, expsx); | |
1111 expandTuples(te->exps); | |
1112 te->type = new TypeTuple(te->exps); | |
1113 return te; | |
1114 } | |
1115 return this; | |
1116 } | |
1117 | |
1118 Expression *ArrayLiteralExp::interpret(InterState *istate) | |
1119 { Expressions *expsx = NULL; | |
1120 | |
1121 #if LOG | |
1122 printf("ArrayLiteralExp::interpret() %s\n", toChars()); | |
1123 #endif | |
1124 if (elements) | |
1125 { | |
1126 for (size_t i = 0; i < elements->dim; i++) | |
1127 { Expression *e = (Expression *)elements->data[i]; | |
1128 Expression *ex; | |
1129 | |
1130 ex = e->interpret(istate); | |
1131 if (ex == EXP_CANT_INTERPRET) | |
1132 { delete expsx; | |
1133 return EXP_CANT_INTERPRET; | |
1134 } | |
1135 | |
1136 /* If any changes, do Copy On Write | |
1137 */ | |
1138 if (ex != e) | |
1139 { | |
1140 if (!expsx) | |
1141 { expsx = new Expressions(); | |
1142 expsx->setDim(elements->dim); | |
19 | 1143 for (size_t j = 0; j < elements->dim; j++) |
1 | 1144 { |
1145 expsx->data[j] = elements->data[j]; | |
1146 } | |
1147 } | |
1148 expsx->data[i] = (void *)ex; | |
1149 } | |
1150 } | |
1151 } | |
1152 if (elements && expsx) | |
1153 { | |
1154 expandTuples(expsx); | |
1155 if (expsx->dim != elements->dim) | |
1156 { delete expsx; | |
1157 return EXP_CANT_INTERPRET; | |
1158 } | |
1159 ArrayLiteralExp *ae = new ArrayLiteralExp(loc, expsx); | |
1160 ae->type = type; | |
1161 return ae; | |
1162 } | |
1163 return this; | |
1164 } | |
1165 | |
1166 Expression *AssocArrayLiteralExp::interpret(InterState *istate) | |
1167 { Expressions *keysx = keys; | |
1168 Expressions *valuesx = values; | |
1169 | |
1170 #if LOG | |
1171 printf("AssocArrayLiteralExp::interpret() %s\n", toChars()); | |
1172 #endif | |
1173 for (size_t i = 0; i < keys->dim; i++) | |
1174 { Expression *ekey = (Expression *)keys->data[i]; | |
1175 Expression *evalue = (Expression *)values->data[i]; | |
1176 Expression *ex; | |
1177 | |
1178 ex = ekey->interpret(istate); | |
1179 if (ex == EXP_CANT_INTERPRET) | |
1180 goto Lerr; | |
1181 | |
1182 /* If any changes, do Copy On Write | |
1183 */ | |
1184 if (ex != ekey) | |
1185 { | |
1186 if (keysx == keys) | |
1187 keysx = (Expressions *)keys->copy(); | |
1188 keysx->data[i] = (void *)ex; | |
1189 } | |
1190 | |
1191 ex = evalue->interpret(istate); | |
1192 if (ex == EXP_CANT_INTERPRET) | |
1193 goto Lerr; | |
1194 | |
1195 /* If any changes, do Copy On Write | |
1196 */ | |
1197 if (ex != evalue) | |
1198 { | |
1199 if (valuesx == values) | |
1200 valuesx = (Expressions *)values->copy(); | |
1201 valuesx->data[i] = (void *)ex; | |
1202 } | |
1203 } | |
1204 if (keysx != keys) | |
1205 expandTuples(keysx); | |
1206 if (valuesx != values) | |
1207 expandTuples(valuesx); | |
1208 if (keysx->dim != valuesx->dim) | |
1209 goto Lerr; | |
1210 | |
1211 /* Remove duplicate keys | |
1212 */ | |
1213 for (size_t i = 1; i < keysx->dim; i++) | |
1214 { Expression *ekey = (Expression *)keysx->data[i - 1]; | |
1215 | |
1216 for (size_t j = i; j < keysx->dim; j++) | |
1217 { Expression *ekey2 = (Expression *)keysx->data[j]; | |
1218 Expression *ex = Equal(TOKequal, Type::tbool, ekey, ekey2); | |
1219 if (ex == EXP_CANT_INTERPRET) | |
1220 goto Lerr; | |
1221 if (ex->isBool(TRUE)) // if a match | |
1222 { | |
1223 // Remove ekey | |
1224 if (keysx == keys) | |
1225 keysx = (Expressions *)keys->copy(); | |
1226 if (valuesx == values) | |
1227 valuesx = (Expressions *)values->copy(); | |
1228 keysx->remove(i - 1); | |
1229 valuesx->remove(i - 1); | |
1230 i -= 1; // redo the i'th iteration | |
1231 break; | |
1232 } | |
1233 } | |
1234 } | |
1235 | |
1236 if (keysx != keys || valuesx != values) | |
1237 { | |
1238 AssocArrayLiteralExp *ae; | |
1239 ae = new AssocArrayLiteralExp(loc, keysx, valuesx); | |
1240 ae->type = type; | |
1241 return ae; | |
1242 } | |
1243 return this; | |
1244 | |
1245 Lerr: | |
1246 if (keysx != keys) | |
1247 delete keysx; | |
1248 if (valuesx != values) | |
1249 delete values; | |
1250 return EXP_CANT_INTERPRET; | |
1251 } | |
1252 | |
1253 Expression *StructLiteralExp::interpret(InterState *istate) | |
1254 { Expressions *expsx = NULL; | |
1255 | |
1256 #if LOG | |
1257 printf("StructLiteralExp::interpret() %s\n", toChars()); | |
1258 #endif | |
1259 /* We don't know how to deal with overlapping fields | |
1260 */ | |
1261 if (sd->hasUnions) | |
1262 return EXP_CANT_INTERPRET; | |
1263 | |
1264 if (elements) | |
1265 { | |
1266 for (size_t i = 0; i < elements->dim; i++) | |
1267 { Expression *e = (Expression *)elements->data[i]; | |
1268 if (!e) | |
1269 continue; | |
1270 | |
1271 Expression *ex = e->interpret(istate); | |
1272 if (ex == EXP_CANT_INTERPRET) | |
1273 { delete expsx; | |
1274 return EXP_CANT_INTERPRET; | |
1275 } | |
1276 | |
1277 /* If any changes, do Copy On Write | |
1278 */ | |
1279 if (ex != e) | |
1280 { | |
1281 if (!expsx) | |
1282 { expsx = new Expressions(); | |
1283 expsx->setDim(elements->dim); | |
1284 for (size_t j = 0; j < elements->dim; j++) | |
1285 { | |
1286 expsx->data[j] = elements->data[j]; | |
1287 } | |
1288 } | |
1289 expsx->data[i] = (void *)ex; | |
1290 } | |
1291 } | |
1292 } | |
1293 if (elements && expsx) | |
1294 { | |
1295 expandTuples(expsx); | |
1296 if (expsx->dim != elements->dim) | |
1297 { delete expsx; | |
1298 return EXP_CANT_INTERPRET; | |
1299 } | |
1300 StructLiteralExp *se = new StructLiteralExp(loc, sd, expsx); | |
1301 se->type = type; | |
1302 return se; | |
1303 } | |
1304 return this; | |
1305 } | |
1306 | |
1307 Expression *UnaExp::interpretCommon(InterState *istate, Expression *(*fp)(Type *, Expression *)) | |
1308 { Expression *e; | |
1309 Expression *e1; | |
1310 | |
1311 #if LOG | |
1312 printf("UnaExp::interpretCommon() %s\n", toChars()); | |
1313 #endif | |
1314 e1 = this->e1->interpret(istate); | |
1315 if (e1 == EXP_CANT_INTERPRET) | |
1316 goto Lcant; | |
1317 if (e1->isConst() != 1) | |
1318 goto Lcant; | |
1319 | |
1320 e = (*fp)(type, e1); | |
1321 return e; | |
1322 | |
1323 Lcant: | |
1324 return EXP_CANT_INTERPRET; | |
1325 } | |
1326 | |
1327 #define UNA_INTERPRET(op) \ | |
1328 Expression *op##Exp::interpret(InterState *istate) \ | |
1329 { \ | |
1330 return interpretCommon(istate, &op); \ | |
1331 } | |
1332 | |
1333 UNA_INTERPRET(Neg) | |
1334 UNA_INTERPRET(Com) | |
1335 UNA_INTERPRET(Not) | |
1336 UNA_INTERPRET(Bool) | |
1337 | |
1338 | |
1339 typedef Expression *(*fp_t)(Type *, Expression *, Expression *); | |
1340 | |
1341 Expression *BinExp::interpretCommon(InterState *istate, fp_t fp) | |
1342 { Expression *e; | |
1343 Expression *e1; | |
1344 Expression *e2; | |
1345 | |
1346 #if LOG | |
1347 printf("BinExp::interpretCommon() %s\n", toChars()); | |
1348 #endif | |
1349 e1 = this->e1->interpret(istate); | |
1350 if (e1 == EXP_CANT_INTERPRET) | |
1351 goto Lcant; | |
1352 if (e1->isConst() != 1) | |
1353 goto Lcant; | |
1354 | |
1355 e2 = this->e2->interpret(istate); | |
1356 if (e2 == EXP_CANT_INTERPRET) | |
1357 goto Lcant; | |
1358 if (e2->isConst() != 1) | |
1359 goto Lcant; | |
1360 | |
1361 e = (*fp)(type, e1, e2); | |
1362 return e; | |
1363 | |
1364 Lcant: | |
1365 return EXP_CANT_INTERPRET; | |
1366 } | |
1367 | |
1368 #define BIN_INTERPRET(op) \ | |
1369 Expression *op##Exp::interpret(InterState *istate) \ | |
1370 { \ | |
1371 return interpretCommon(istate, &op); \ | |
1372 } | |
1373 | |
1374 BIN_INTERPRET(Add) | |
1375 BIN_INTERPRET(Min) | |
1376 BIN_INTERPRET(Mul) | |
1377 BIN_INTERPRET(Div) | |
1378 BIN_INTERPRET(Mod) | |
1379 BIN_INTERPRET(Shl) | |
1380 BIN_INTERPRET(Shr) | |
1381 BIN_INTERPRET(Ushr) | |
1382 BIN_INTERPRET(And) | |
1383 BIN_INTERPRET(Or) | |
1384 BIN_INTERPRET(Xor) | |
1385 | |
1386 | |
1387 typedef Expression *(*fp2_t)(enum TOK, Type *, Expression *, Expression *); | |
1388 | |
1389 Expression *BinExp::interpretCommon2(InterState *istate, fp2_t fp) | |
1390 { Expression *e; | |
1391 Expression *e1; | |
1392 Expression *e2; | |
1393 | |
1394 #if LOG | |
1395 printf("BinExp::interpretCommon2() %s\n", toChars()); | |
1396 #endif | |
1397 e1 = this->e1->interpret(istate); | |
1398 if (e1 == EXP_CANT_INTERPRET) | |
1399 goto Lcant; | |
1400 if (e1->isConst() != 1 && | |
19 | 1401 e1->op != TOKnull && |
1 | 1402 e1->op != TOKstring && |
1403 e1->op != TOKarrayliteral && | |
1404 e1->op != TOKstructliteral) | |
1405 goto Lcant; | |
1406 | |
1407 e2 = this->e2->interpret(istate); | |
1408 if (e2 == EXP_CANT_INTERPRET) | |
1409 goto Lcant; | |
1410 if (e2->isConst() != 1 && | |
19 | 1411 e2->op != TOKnull && |
1 | 1412 e2->op != TOKstring && |
1413 e2->op != TOKarrayliteral && | |
1414 e2->op != TOKstructliteral) | |
1415 goto Lcant; | |
1416 | |
1417 e = (*fp)(op, type, e1, e2); | |
1418 return e; | |
1419 | |
1420 Lcant: | |
1421 return EXP_CANT_INTERPRET; | |
1422 } | |
1423 | |
1424 #define BIN_INTERPRET2(op) \ | |
1425 Expression *op##Exp::interpret(InterState *istate) \ | |
1426 { \ | |
1427 return interpretCommon2(istate, &op); \ | |
1428 } | |
1429 | |
1430 BIN_INTERPRET2(Equal) | |
1431 BIN_INTERPRET2(Identity) | |
1432 BIN_INTERPRET2(Cmp) | |
1433 | |
1434 Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post) | |
1435 { | |
1436 #if LOG | |
1437 printf("BinExp::interpretAssignCommon() %s\n", toChars()); | |
1438 #endif | |
1439 Expression *e = EXP_CANT_INTERPRET; | |
1440 Expression *e1 = this->e1; | |
1441 | |
1442 if (fp) | |
1443 { | |
1444 if (e1->op == TOKcast) | |
1445 { CastExp *ce = (CastExp *)e1; | |
1446 e1 = ce->e1; | |
1447 } | |
1448 } | |
1449 if (e1 == EXP_CANT_INTERPRET) | |
1450 return e1; | |
1451 Expression *e2 = this->e2->interpret(istate); | |
1452 if (e2 == EXP_CANT_INTERPRET) | |
1453 return e2; | |
1454 | |
1455 /* Assignment to variable of the form: | |
1456 * v = e2 | |
1457 */ | |
1458 if (e1->op == TOKvar) | |
1459 { | |
1460 VarExp *ve = (VarExp *)e1; | |
1461 VarDeclaration *v = ve->var->isVarDeclaration(); | |
1462 if (v && !v->isDataseg()) | |
1463 { | |
1464 /* Chase down rebinding of out and ref | |
1465 */ | |
1466 if (v->value && v->value->op == TOKvar) | |
1467 { | |
131 | 1468 VarExp *ve2 = (VarExp *)v->value; |
1469 if (ve2->var->isSymbolDeclaration()) | |
1470 { | |
1471 /* This can happen if v is a struct initialized to | |
1472 * 0 using an __initZ SymbolDeclaration from | |
1473 * TypeStruct::defaultInit() | |
1474 */ | |
1475 } | |
1476 else | |
1477 v = ve2->var->isVarDeclaration(); | |
1 | 1478 assert(v); |
1479 } | |
1480 | |
1481 Expression *ev = v->value; | |
1482 if (fp && !ev) | |
1483 { error("variable %s is used before initialization", v->toChars()); | |
1484 return e; | |
1485 } | |
1486 if (fp) | |
1487 e2 = (*fp)(v->type, ev, e2); | |
1488 else | |
19 | 1489 { /* Look for special case of struct being initialized with 0. |
1490 */ | |
1491 if (v->type->toBasetype()->ty == Tstruct && e2->op == TOKint64) | |
1492 { | |
1493 e2 = v->type->defaultInit(); | |
1494 } | |
1 | 1495 e2 = Cast(v->type, v->type, e2); |
19 | 1496 } |
1 | 1497 if (e2 != EXP_CANT_INTERPRET) |
1498 { | |
1499 if (!v->isParameter()) | |
1500 { | |
1501 for (size_t i = 0; 1; i++) | |
1502 { | |
1503 if (i == istate->vars.dim) | |
1504 { istate->vars.push(v); | |
131 | 1505 //printf("\tadding %s to istate\n", v->toChars()); |
1 | 1506 break; |
1507 } | |
1508 if (v == (VarDeclaration *)istate->vars.data[i]) | |
1509 break; | |
1510 } | |
1511 } | |
1512 v->value = e2; | |
1513 e = Cast(type, type, post ? ev : e2); | |
1514 } | |
1515 } | |
1516 } | |
1517 /* Assignment to struct member of the form: | |
1518 * *(symoffexp) = e2 | |
1519 */ | |
1520 else if (e1->op == TOKstar && ((PtrExp *)e1)->e1->op == TOKsymoff) | |
1521 { SymOffExp *soe = (SymOffExp *)((PtrExp *)e1)->e1; | |
1522 VarDeclaration *v = soe->var->isVarDeclaration(); | |
1523 | |
1524 if (v->isDataseg()) | |
1525 return EXP_CANT_INTERPRET; | |
1526 if (fp && !v->value) | |
1527 { error("variable %s is used before initialization", v->toChars()); | |
1528 return e; | |
1529 } | |
19 | 1530 Expression *vie = v->value; |
1531 if (vie->op == TOKvar) | |
1532 { | |
1533 Declaration *d = ((VarExp *)vie)->var; | |
1534 vie = getVarExp(e1->loc, istate, d); | |
1535 } | |
1536 if (vie->op != TOKstructliteral) | |
1 | 1537 return EXP_CANT_INTERPRET; |
19 | 1538 StructLiteralExp *se = (StructLiteralExp *)vie; |
1 | 1539 int fieldi = se->getFieldIndex(type, soe->offset); |
1540 if (fieldi == -1) | |
1541 return EXP_CANT_INTERPRET; | |
1542 Expression *ev = se->getField(type, soe->offset); | |
1543 if (fp) | |
1544 e2 = (*fp)(type, ev, e2); | |
1545 else | |
1546 e2 = Cast(type, type, e2); | |
1547 if (e2 == EXP_CANT_INTERPRET) | |
1548 return e2; | |
1549 | |
1550 if (!v->isParameter()) | |
1551 { | |
1552 for (size_t i = 0; 1; i++) | |
1553 { | |
1554 if (i == istate->vars.dim) | |
1555 { istate->vars.push(v); | |
1556 break; | |
1557 } | |
1558 if (v == (VarDeclaration *)istate->vars.data[i]) | |
1559 break; | |
1560 } | |
1561 } | |
1562 | |
1563 /* Create new struct literal reflecting updated fieldi | |
1564 */ | |
1565 Expressions *expsx = new Expressions(); | |
1566 expsx->setDim(se->elements->dim); | |
1567 for (size_t j = 0; j < expsx->dim; j++) | |
1568 { | |
1569 if (j == fieldi) | |
1570 expsx->data[j] = (void *)e2; | |
1571 else | |
1572 expsx->data[j] = se->elements->data[j]; | |
1573 } | |
1574 v->value = new StructLiteralExp(se->loc, se->sd, expsx); | |
1575 v->value->type = se->type; | |
1576 | |
1577 e = Cast(type, type, post ? ev : e2); | |
1578 } | |
1579 /* Assignment to array element of the form: | |
1580 * a[i] = e2 | |
1581 */ | |
1582 else if (e1->op == TOKindex && ((IndexExp *)e1)->e1->op == TOKvar) | |
1583 { IndexExp *ie = (IndexExp *)e1; | |
1584 VarExp *ve = (VarExp *)ie->e1; | |
1585 VarDeclaration *v = ve->var->isVarDeclaration(); | |
1586 | |
1587 if (!v || v->isDataseg()) | |
1588 return EXP_CANT_INTERPRET; | |
1589 if (!v->value) | |
1590 { | |
1591 if (fp) | |
1592 { error("variable %s is used before initialization", v->toChars()); | |
1593 return e; | |
1594 } | |
1595 | |
1596 Type *t = v->type->toBasetype(); | |
1597 if (t->ty == Tsarray) | |
1598 { | |
1599 /* This array was void initialized. Create a | |
1600 * default initializer for it. | |
1601 * What we should do is fill the array literal with | |
1602 * NULL data, so use-before-initialized can be detected. | |
1603 * But we're too lazy at the moment to do it, as that | |
1604 * involves redoing Index() and whoever calls it. | |
1605 */ | |
1606 Expression *ev = v->type->defaultInit(); | |
1607 size_t dim = ((TypeSArray *)t)->dim->toInteger(); | |
1608 Expressions *elements = new Expressions(); | |
1609 elements->setDim(dim); | |
1610 for (size_t i = 0; i < dim; i++) | |
1611 elements->data[i] = (void *)ev; | |
1612 ArrayLiteralExp *ae = new ArrayLiteralExp(0, elements); | |
1613 ae->type = v->type; | |
1614 v->value = ae; | |
1615 } | |
1616 else | |
1617 return EXP_CANT_INTERPRET; | |
1618 } | |
1619 | |
1620 ArrayLiteralExp *ae = NULL; | |
1621 AssocArrayLiteralExp *aae = NULL; | |
1622 StringExp *se = NULL; | |
1623 if (v->value->op == TOKarrayliteral) | |
1624 ae = (ArrayLiteralExp *)v->value; | |
1625 else if (v->value->op == TOKassocarrayliteral) | |
1626 aae = (AssocArrayLiteralExp *)v->value; | |
1627 else if (v->value->op == TOKstring) | |
1628 se = (StringExp *)v->value; | |
1629 else | |
1630 return EXP_CANT_INTERPRET; | |
1631 | |
1632 Expression *index = ie->e2->interpret(istate); | |
1633 if (index == EXP_CANT_INTERPRET) | |
1634 return EXP_CANT_INTERPRET; | |
1635 Expression *ev; | |
1636 if (fp || ae || se) // not for aae, because key might not be there | |
1637 { | |
1638 ev = Index(type, v->value, index); | |
1639 if (ev == EXP_CANT_INTERPRET) | |
1640 return EXP_CANT_INTERPRET; | |
1641 } | |
1642 | |
1643 if (fp) | |
1644 e2 = (*fp)(type, ev, e2); | |
1645 else | |
1646 e2 = Cast(type, type, e2); | |
1647 if (e2 == EXP_CANT_INTERPRET) | |
1648 return e2; | |
1649 | |
1650 if (!v->isParameter()) | |
1651 { | |
1652 for (size_t i = 0; 1; i++) | |
1653 { | |
1654 if (i == istate->vars.dim) | |
1655 { istate->vars.push(v); | |
1656 break; | |
1657 } | |
1658 if (v == (VarDeclaration *)istate->vars.data[i]) | |
1659 break; | |
1660 } | |
1661 } | |
1662 | |
1663 if (ae) | |
1664 { | |
1665 /* Create new array literal reflecting updated elem | |
1666 */ | |
1667 int elemi = index->toInteger(); | |
1668 Expressions *expsx = new Expressions(); | |
1669 expsx->setDim(ae->elements->dim); | |
1670 for (size_t j = 0; j < expsx->dim; j++) | |
1671 { | |
1672 if (j == elemi) | |
1673 expsx->data[j] = (void *)e2; | |
1674 else | |
1675 expsx->data[j] = ae->elements->data[j]; | |
1676 } | |
1677 v->value = new ArrayLiteralExp(ae->loc, expsx); | |
1678 v->value->type = ae->type; | |
1679 } | |
1680 else if (aae) | |
1681 { | |
1682 /* Create new associative array literal reflecting updated key/value | |
1683 */ | |
1684 Expressions *keysx = aae->keys; | |
1685 Expressions *valuesx = new Expressions(); | |
1686 valuesx->setDim(aae->values->dim); | |
1687 int updated = 0; | |
1688 for (size_t j = valuesx->dim; j; ) | |
1689 { j--; | |
1690 Expression *ekey = (Expression *)aae->keys->data[j]; | |
1691 Expression *ex = Equal(TOKequal, Type::tbool, ekey, index); | |
1692 if (ex == EXP_CANT_INTERPRET) | |
1693 return EXP_CANT_INTERPRET; | |
1694 if (ex->isBool(TRUE)) | |
1695 { valuesx->data[j] = (void *)e2; | |
1696 updated = 1; | |
1697 } | |
1698 else | |
1699 valuesx->data[j] = aae->values->data[j]; | |
1700 } | |
1701 if (!updated) | |
1702 { // Append index/e2 to keysx[]/valuesx[] | |
1703 valuesx->push(e2); | |
1704 keysx = (Expressions *)keysx->copy(); | |
1705 keysx->push(index); | |
1706 } | |
1707 v->value = new AssocArrayLiteralExp(aae->loc, keysx, valuesx); | |
1708 v->value->type = aae->type; | |
1709 } | |
1710 else if (se) | |
1711 { | |
1712 /* Create new string literal reflecting updated elem | |
1713 */ | |
1714 int elemi = index->toInteger(); | |
1715 unsigned char *s; | |
1716 s = (unsigned char *)mem.calloc(se->len + 1, se->sz); | |
1717 memcpy(s, se->string, se->len * se->sz); | |
1718 unsigned value = e2->toInteger(); | |
1719 switch (se->sz) | |
1720 { | |
1721 case 1: s[elemi] = value; break; | |
1722 case 2: ((unsigned short *)s)[elemi] = value; break; | |
1723 case 4: ((unsigned *)s)[elemi] = value; break; | |
1724 default: | |
1725 assert(0); | |
1726 break; | |
1727 } | |
1728 StringExp *se2 = new StringExp(se->loc, s, se->len); | |
1729 se2->committed = se->committed; | |
1730 se2->postfix = se->postfix; | |
1731 se2->type = se->type; | |
1732 v->value = se2; | |
1733 } | |
1734 else | |
1735 assert(0); | |
1736 | |
1737 e = Cast(type, type, post ? ev : e2); | |
1738 } | |
1739 else | |
1740 { | |
1741 #ifdef DEBUG | |
1742 dump(0); | |
1743 #endif | |
1744 } | |
1745 return e; | |
1746 } | |
1747 | |
1748 Expression *AssignExp::interpret(InterState *istate) | |
1749 { | |
1750 return interpretAssignCommon(istate, NULL); | |
1751 } | |
1752 | |
1753 #define BIN_ASSIGN_INTERPRET(op) \ | |
1754 Expression *op##AssignExp::interpret(InterState *istate) \ | |
1755 { \ | |
1756 return interpretAssignCommon(istate, &op); \ | |
1757 } | |
1758 | |
1759 BIN_ASSIGN_INTERPRET(Add) | |
1760 BIN_ASSIGN_INTERPRET(Min) | |
1761 BIN_ASSIGN_INTERPRET(Cat) | |
1762 BIN_ASSIGN_INTERPRET(Mul) | |
1763 BIN_ASSIGN_INTERPRET(Div) | |
1764 BIN_ASSIGN_INTERPRET(Mod) | |
1765 BIN_ASSIGN_INTERPRET(Shl) | |
1766 BIN_ASSIGN_INTERPRET(Shr) | |
1767 BIN_ASSIGN_INTERPRET(Ushr) | |
1768 BIN_ASSIGN_INTERPRET(And) | |
1769 BIN_ASSIGN_INTERPRET(Or) | |
1770 BIN_ASSIGN_INTERPRET(Xor) | |
1771 | |
1772 Expression *PostExp::interpret(InterState *istate) | |
1773 { | |
1774 #if LOG | |
1775 printf("PostExp::interpret() %s\n", toChars()); | |
1776 #endif | |
1777 Expression *e; | |
1778 if (op == TOKplusplus) | |
1779 e = interpretAssignCommon(istate, &Add, 1); | |
1780 else | |
1781 e = interpretAssignCommon(istate, &Min, 1); | |
1782 #if LOG | |
1783 if (e == EXP_CANT_INTERPRET) | |
1784 printf("PostExp::interpret() CANT\n"); | |
1785 #endif | |
1786 return e; | |
1787 } | |
1788 | |
1789 Expression *AndAndExp::interpret(InterState *istate) | |
1790 { | |
1791 #if LOG | |
1792 printf("AndAndExp::interpret() %s\n", toChars()); | |
1793 #endif | |
1794 Expression *e = e1->interpret(istate); | |
1795 if (e != EXP_CANT_INTERPRET) | |
1796 { | |
1797 if (e->isBool(FALSE)) | |
1798 e = new IntegerExp(e1->loc, 0, type); | |
1799 else if (e->isBool(TRUE)) | |
1800 { | |
1801 e = e2->interpret(istate); | |
1802 if (e != EXP_CANT_INTERPRET) | |
1803 { | |
1804 if (e->isBool(FALSE)) | |
1805 e = new IntegerExp(e1->loc, 0, type); | |
1806 else if (e->isBool(TRUE)) | |
1807 e = new IntegerExp(e1->loc, 1, type); | |
1808 else | |
1809 e = EXP_CANT_INTERPRET; | |
1810 } | |
1811 } | |
1812 else | |
1813 e = EXP_CANT_INTERPRET; | |
1814 } | |
1815 return e; | |
1816 } | |
1817 | |
1818 Expression *OrOrExp::interpret(InterState *istate) | |
1819 { | |
1820 #if LOG | |
1821 printf("OrOrExp::interpret() %s\n", toChars()); | |
1822 #endif | |
1823 Expression *e = e1->interpret(istate); | |
1824 if (e != EXP_CANT_INTERPRET) | |
1825 { | |
1826 if (e->isBool(TRUE)) | |
1827 e = new IntegerExp(e1->loc, 1, type); | |
1828 else if (e->isBool(FALSE)) | |
1829 { | |
1830 e = e2->interpret(istate); | |
1831 if (e != EXP_CANT_INTERPRET) | |
1832 { | |
1833 if (e->isBool(FALSE)) | |
1834 e = new IntegerExp(e1->loc, 0, type); | |
1835 else if (e->isBool(TRUE)) | |
1836 e = new IntegerExp(e1->loc, 1, type); | |
1837 else | |
1838 e = EXP_CANT_INTERPRET; | |
1839 } | |
1840 } | |
1841 else | |
1842 e = EXP_CANT_INTERPRET; | |
1843 } | |
1844 return e; | |
1845 } | |
1846 | |
1847 | |
1848 Expression *CallExp::interpret(InterState *istate) | |
1849 { Expression *e = EXP_CANT_INTERPRET; | |
1850 | |
1851 #if LOG | |
1852 printf("CallExp::interpret() %s\n", toChars()); | |
1853 #endif | |
1854 if (e1->op == TOKvar) | |
1855 { | |
1856 FuncDeclaration *fd = ((VarExp *)e1)->var->isFuncDeclaration(); | |
1857 if (fd) | |
131 | 1858 { |
336 | 1859 #if DMDV2 |
131 | 1860 enum BUILTIN b = fd->isBuiltin(); |
1861 if (b) | |
1862 { Expressions args; | |
1863 args.setDim(arguments->dim); | |
1864 for (size_t i = 0; i < args.dim; i++) | |
1865 { | |
1866 Expression *earg = (Expression *)arguments->data[i]; | |
1867 earg = earg->interpret(istate); | |
1868 if (earg == EXP_CANT_INTERPRET) | |
1869 return earg; | |
1870 args.data[i] = (void *)earg; | |
1871 } | |
1872 e = eval_builtin(b, &args); | |
1873 if (!e) | |
1874 e = EXP_CANT_INTERPRET; | |
1875 } | |
1876 else | |
1877 #endif | |
1878 // Inline .dup | |
1 | 1879 if (fd->ident == Id::adDup && arguments && arguments->dim == 2) |
1880 { | |
1881 e = (Expression *)arguments->data[1]; | |
1882 e = e->interpret(istate); | |
1883 if (e != EXP_CANT_INTERPRET) | |
1884 { | |
1885 e = expType(type, e); | |
1886 } | |
1887 } | |
1888 else | |
1889 { | |
1890 Expression *eresult = fd->interpret(istate, arguments); | |
1891 if (eresult) | |
1892 e = eresult; | |
131 | 1893 else if (fd->type->toBasetype()->nextOf()->ty == Tvoid && !global.errors) |
1 | 1894 e = EXP_VOID_INTERPRET; |
1895 else | |
1896 error("cannot evaluate %s at compile time", toChars()); | |
1897 } | |
1898 } | |
1899 } | |
1900 return e; | |
1901 } | |
1902 | |
1903 Expression *CommaExp::interpret(InterState *istate) | |
1904 { | |
1905 #if LOG | |
1906 printf("CommaExp::interpret() %s\n", toChars()); | |
1907 #endif | |
1908 Expression *e = e1->interpret(istate); | |
1909 if (e != EXP_CANT_INTERPRET) | |
1910 e = e2->interpret(istate); | |
1911 return e; | |
1912 } | |
1913 | |
1914 Expression *CondExp::interpret(InterState *istate) | |
1915 { | |
1916 #if LOG | |
1917 printf("CondExp::interpret() %s\n", toChars()); | |
1918 #endif | |
1919 Expression *e = econd->interpret(istate); | |
1920 if (e != EXP_CANT_INTERPRET) | |
1921 { | |
1922 if (e->isBool(TRUE)) | |
1923 e = e1->interpret(istate); | |
1924 else if (e->isBool(FALSE)) | |
1925 e = e2->interpret(istate); | |
1926 else | |
1927 e = EXP_CANT_INTERPRET; | |
1928 } | |
1929 return e; | |
1930 } | |
1931 | |
1932 Expression *ArrayLengthExp::interpret(InterState *istate) | |
1933 { Expression *e; | |
1934 Expression *e1; | |
1935 | |
1936 #if LOG | |
1937 printf("ArrayLengthExp::interpret() %s\n", toChars()); | |
1938 #endif | |
1939 e1 = this->e1->interpret(istate); | |
1940 if (e1 == EXP_CANT_INTERPRET) | |
1941 goto Lcant; | |
1942 if (e1->op == TOKstring || e1->op == TOKarrayliteral || e1->op == TOKassocarrayliteral) | |
1943 { | |
1944 e = ArrayLength(type, e1); | |
1945 } | |
19 | 1946 else if (e1->op == TOKnull) |
1947 { | |
1948 e = new IntegerExp(loc, 0, type); | |
1949 } | |
1 | 1950 else |
1951 goto Lcant; | |
1952 return e; | |
1953 | |
1954 Lcant: | |
1955 return EXP_CANT_INTERPRET; | |
1956 } | |
1957 | |
1958 Expression *IndexExp::interpret(InterState *istate) | |
1959 { Expression *e; | |
1960 Expression *e1; | |
1961 Expression *e2; | |
1962 | |
1963 #if LOG | |
1964 printf("IndexExp::interpret() %s\n", toChars()); | |
1965 #endif | |
1966 e1 = this->e1->interpret(istate); | |
1967 if (e1 == EXP_CANT_INTERPRET) | |
1968 goto Lcant; | |
1969 | |
1970 if (e1->op == TOKstring || e1->op == TOKarrayliteral) | |
1971 { | |
1972 /* Set the $ variable | |
1973 */ | |
1974 e = ArrayLength(Type::tsize_t, e1); | |
1975 if (e == EXP_CANT_INTERPRET) | |
1976 goto Lcant; | |
1977 if (lengthVar) | |
1978 lengthVar->value = e; | |
1979 } | |
1980 | |
1981 e2 = this->e2->interpret(istate); | |
1982 if (e2 == EXP_CANT_INTERPRET) | |
1983 goto Lcant; | |
1984 return Index(type, e1, e2); | |
1985 | |
1986 Lcant: | |
1987 return EXP_CANT_INTERPRET; | |
1988 } | |
1989 | |
1990 | |
1991 Expression *SliceExp::interpret(InterState *istate) | |
1992 { Expression *e; | |
1993 Expression *e1; | |
1994 Expression *lwr; | |
1995 Expression *upr; | |
1996 | |
1997 #if LOG | |
1998 printf("SliceExp::interpret() %s\n", toChars()); | |
1999 #endif | |
2000 e1 = this->e1->interpret(istate); | |
2001 if (e1 == EXP_CANT_INTERPRET) | |
2002 goto Lcant; | |
2003 if (!this->lwr) | |
2004 { | |
2005 e = e1->castTo(NULL, type); | |
2006 return e->interpret(istate); | |
2007 } | |
2008 | |
2009 /* Set the $ variable | |
2010 */ | |
2011 e = ArrayLength(Type::tsize_t, e1); | |
2012 if (e == EXP_CANT_INTERPRET) | |
2013 goto Lcant; | |
2014 if (lengthVar) | |
2015 lengthVar->value = e; | |
2016 | |
2017 /* Evaluate lower and upper bounds of slice | |
2018 */ | |
2019 lwr = this->lwr->interpret(istate); | |
2020 if (lwr == EXP_CANT_INTERPRET) | |
2021 goto Lcant; | |
2022 upr = this->upr->interpret(istate); | |
2023 if (upr == EXP_CANT_INTERPRET) | |
2024 goto Lcant; | |
2025 | |
2026 return Slice(type, e1, lwr, upr); | |
2027 | |
2028 Lcant: | |
2029 return EXP_CANT_INTERPRET; | |
2030 } | |
2031 | |
2032 | |
2033 Expression *CatExp::interpret(InterState *istate) | |
2034 { Expression *e; | |
2035 Expression *e1; | |
2036 Expression *e2; | |
2037 | |
2038 #if LOG | |
2039 printf("CatExp::interpret() %s\n", toChars()); | |
2040 #endif | |
2041 e1 = this->e1->interpret(istate); | |
2042 if (e1 == EXP_CANT_INTERPRET) | |
2043 { | |
2044 goto Lcant; | |
2045 } | |
2046 e2 = this->e2->interpret(istate); | |
2047 if (e2 == EXP_CANT_INTERPRET) | |
2048 goto Lcant; | |
2049 return Cat(type, e1, e2); | |
2050 | |
2051 Lcant: | |
2052 #if LOG | |
2053 printf("CatExp::interpret() %s CANT\n", toChars()); | |
2054 #endif | |
2055 return EXP_CANT_INTERPRET; | |
2056 } | |
2057 | |
2058 | |
2059 Expression *CastExp::interpret(InterState *istate) | |
2060 { Expression *e; | |
2061 Expression *e1; | |
2062 | |
2063 #if LOG | |
2064 printf("CastExp::interpret() %s\n", toChars()); | |
2065 #endif | |
2066 e1 = this->e1->interpret(istate); | |
2067 if (e1 == EXP_CANT_INTERPRET) | |
2068 goto Lcant; | |
2069 return Cast(type, to, e1); | |
2070 | |
2071 Lcant: | |
2072 #if LOG | |
2073 printf("CastExp::interpret() %s CANT\n", toChars()); | |
2074 #endif | |
2075 return EXP_CANT_INTERPRET; | |
2076 } | |
2077 | |
2078 | |
2079 Expression *AssertExp::interpret(InterState *istate) | |
2080 { Expression *e; | |
2081 Expression *e1; | |
2082 | |
2083 #if LOG | |
2084 printf("AssertExp::interpret() %s\n", toChars()); | |
2085 #endif | |
2086 e1 = this->e1->interpret(istate); | |
2087 if (e1 == EXP_CANT_INTERPRET) | |
2088 goto Lcant; | |
2089 if (e1->isBool(TRUE)) | |
2090 { | |
2091 } | |
2092 else if (e1->isBool(FALSE)) | |
2093 { | |
2094 if (msg) | |
2095 { | |
2096 e = msg->interpret(istate); | |
2097 if (e == EXP_CANT_INTERPRET) | |
2098 goto Lcant; | |
2099 error("%s", e->toChars()); | |
2100 } | |
2101 else | |
2102 error("%s failed", toChars()); | |
2103 goto Lcant; | |
2104 } | |
2105 else | |
2106 goto Lcant; | |
2107 return e1; | |
2108 | |
2109 Lcant: | |
2110 return EXP_CANT_INTERPRET; | |
2111 } | |
2112 | |
2113 Expression *PtrExp::interpret(InterState *istate) | |
2114 { Expression *e = EXP_CANT_INTERPRET; | |
2115 | |
2116 #if LOG | |
2117 printf("PtrExp::interpret() %s\n", toChars()); | |
2118 #endif | |
2119 | |
2120 // Constant fold *(&structliteral + offset) | |
2121 if (e1->op == TOKadd) | |
2122 { AddExp *ae = (AddExp *)e1; | |
2123 if (ae->e1->op == TOKaddress && ae->e2->op == TOKint64) | |
2124 { AddrExp *ade = (AddrExp *)ae->e1; | |
2125 Expression *ex = ade->e1; | |
2126 ex = ex->interpret(istate); | |
2127 if (ex != EXP_CANT_INTERPRET) | |
2128 { | |
2129 if (ex->op == TOKstructliteral) | |
2130 { StructLiteralExp *se = (StructLiteralExp *)ex; | |
2131 unsigned offset = ae->e2->toInteger(); | |
2132 e = se->getField(type, offset); | |
2133 if (!e) | |
2134 e = EXP_CANT_INTERPRET; | |
2135 return e; | |
2136 } | |
2137 } | |
2138 } | |
2139 e = Ptr(type, e1); | |
2140 } | |
2141 else if (e1->op == TOKsymoff) | |
2142 { SymOffExp *soe = (SymOffExp *)e1; | |
2143 VarDeclaration *v = soe->var->isVarDeclaration(); | |
2144 if (v) | |
2145 { Expression *ev = getVarExp(loc, istate, v); | |
2146 if (ev != EXP_CANT_INTERPRET && ev->op == TOKstructliteral) | |
2147 { StructLiteralExp *se = (StructLiteralExp *)ev; | |
2148 e = se->getField(type, soe->offset); | |
2149 if (!e) | |
2150 e = EXP_CANT_INTERPRET; | |
2151 } | |
2152 } | |
2153 } | |
2154 #if LOG | |
2155 if (e == EXP_CANT_INTERPRET) | |
2156 printf("PtrExp::interpret() %s = EXP_CANT_INTERPRET\n", toChars()); | |
2157 #endif | |
2158 return e; | |
2159 } | |
2160 | |
588
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
2161 Expression *DotVarExp::interpret(InterState *istate) |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
2162 { Expression *e = EXP_CANT_INTERPRET; |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
2163 |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
2164 Expression *ex = e1->interpret(istate); |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
2165 |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
2166 // Constant fold structliteral.member |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
2167 if (ex != EXP_CANT_INTERPRET && ex->op == TOKstructliteral) |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
2168 { StructLiteralExp *se = (StructLiteralExp *)ex; |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
2169 |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
2170 VarDeclaration* v; |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
2171 if (v = var->isVarDeclaration()) |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
2172 { |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
2173 e = se->getField(type, v->offset); |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
2174 if (!e) |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
2175 e = EXP_CANT_INTERPRET; |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
2176 } |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
2177 } |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
2178 |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
2179 return e; |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
2180 } |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
2181 |
1 | 2182 /******************************* Special Functions ***************************/ |
2183 | |
2184 Expression *interpret_aaLen(InterState *istate, Expressions *arguments) | |
2185 { | |
2186 if (!arguments || arguments->dim != 1) | |
2187 return NULL; | |
2188 Expression *earg = (Expression *)arguments->data[0]; | |
2189 earg = earg->interpret(istate); | |
2190 if (earg == EXP_CANT_INTERPRET) | |
2191 return NULL; | |
2192 if (earg->op != TOKassocarrayliteral) | |
2193 return NULL; | |
2194 AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg; | |
2195 Expression *e = new IntegerExp(aae->loc, aae->keys->dim, Type::tsize_t); | |
2196 return e; | |
2197 } | |
2198 | |
2199 Expression *interpret_aaKeys(InterState *istate, Expressions *arguments) | |
2200 { | |
2201 //printf("interpret_aaKeys()\n"); | |
2202 if (!arguments || arguments->dim != 2) | |
2203 return NULL; | |
2204 Expression *earg = (Expression *)arguments->data[0]; | |
2205 earg = earg->interpret(istate); | |
2206 if (earg == EXP_CANT_INTERPRET) | |
2207 return NULL; | |
2208 if (earg->op != TOKassocarrayliteral) | |
2209 return NULL; | |
2210 AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg; | |
2211 Expression *e = new ArrayLiteralExp(aae->loc, aae->keys); | |
2212 return e; | |
2213 } | |
2214 | |
2215 Expression *interpret_aaValues(InterState *istate, Expressions *arguments) | |
2216 { | |
2217 //printf("interpret_aaValues()\n"); | |
2218 if (!arguments || arguments->dim != 3) | |
2219 return NULL; | |
2220 Expression *earg = (Expression *)arguments->data[0]; | |
2221 earg = earg->interpret(istate); | |
2222 if (earg == EXP_CANT_INTERPRET) | |
2223 return NULL; | |
2224 if (earg->op != TOKassocarrayliteral) | |
2225 return NULL; | |
2226 AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg; | |
2227 Expression *e = new ArrayLiteralExp(aae->loc, aae->values); | |
2228 //printf("result is %s\n", e->toChars()); | |
2229 return e; | |
2230 } | |
2231 |