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