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