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