Mercurial > projects > ldc
annotate dmd/interpret.c @ 837:331a176c1f4f
Removed error on naked, not fully complete, but I'll be doing more work on it during this Christmas, and some things do work.
Fixed taking delegate of final class method. see mini/delegate3.d.
author | Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> |
---|---|
date | Tue, 09 Dec 2008 14:07:30 +0100 |
parents | 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 |