1: // Compiler implementation of the D programming language
2: // Copyright (c) 1999-2011 by Digital Mars
3: // All Rights Reserved
4: // written by Walter Bright
5: // http://www.digitalmars.com
6: // License for redistribution is by either the Artistic License
7: // in artistic.txt, or the GNU General Public License in gnu.txt.
8: // See the included readme.txt for details.
9:
10: #include <stdio.h>
11: #include <stdlib.h>
12: static char __file__[] = __FILE__; /* for tassert.h */
13: #include "tassert.h"
14:
15: #include "rmem.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: #include "utf.h"
28:
29: #define LOG 0
30: #define LOGASSIGN 0
31:
32: struct InterState
33: {
34: InterState *caller; // calling function's InterState
35: FuncDeclaration *fd; // function being interpreted
36: VarDeclarations vars; // variables used in this function
37: Statement *start; // if !=NULL, start execution at this statement
38: Statement *gotoTarget; /* target of EXP_GOTO_INTERPRET result; also
39: * target of labelled EXP_BREAK_INTERPRET or
40: * EXP_CONTINUE_INTERPRET. (NULL if no label).
41: */
42: Expression *localThis; // value of 'this', or NULL if none
43: bool awaitingLvalueReturn; // Support for ref return values:
44: // Any return to this function should return an lvalue.
45: InterState();
46: };
47:
48: InterState::InterState()
49: {
50: memset(this, 0, sizeof(InterState));
51: }
52:
53: Expression * resolveReferences(Expression *e, Expression *thisval, bool *isReference = NULL);
54: Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal);
55: VarDeclaration *findParentVar(Expression *e, Expression *thisval);
56: void addVarToInterstate(InterState *istate, VarDeclaration *v);
57: bool needToCopyLiteral(Expression *expr);
58: Expression *copyLiteral(Expression *e);
59: Expression *paintTypeOntoLiteral(Type *type, Expression *lit);
60: bool evaluateIfBuiltin(Expression **result, InterState *istate,
61: FuncDeclaration *fd, Expressions *arguments, Expression *pthis);
62:
63:
64: // Used for debugging only
65: void showCtfeExpr(Expression *e, int level = 0)
66: {
67: for (int i = level; i>0; --i) printf(" ");
68: Expressions *elements = NULL;
69: // We need the struct definition to detect block assignment
70: StructDeclaration *sd = NULL;
71: if (e->op == TOKstructliteral) {
72: elements = ((StructLiteralExp *)e)->elements;
73: sd = ((StructLiteralExp *)e)->sd;
74: printf("STRUCT type = %s %p :\n", e->type->toChars(), e);
75: }
76: else if (e->op == TOKarrayliteral)
77: {
78: elements = ((ArrayLiteralExp *)e)->elements;
79: printf("ARRAY LITERAL type=%s %p:\n", e->type->toChars(), e);
80: }
81: else if (e->op == TOKassocarrayliteral)
82: {
83: printf("AA LITERAL type=%s %p:\n", e->type->toChars(), e);
84: }
85: else if (e->op == TOKstring)
86: {
87: printf("STRING %s %p\n", e->toChars(), ((StringExp *)e)->string);
88: }
89: else if (e->op == TOKslice)
90: {
91: printf("SLICE %p: %s\n", e, e->toChars());
92: showCtfeExpr(((SliceExp *)e)->e1, level + 1);
93: }
94: else if (e->op == TOKvar)
95: {
96: printf("VAR %p %s\n", e, e->toChars());
97: VarDeclaration *v = ((VarExp *)e)->var->isVarDeclaration();
98: if (v && v->getValue())
99: showCtfeExpr(v->getValue(), level + 1);
100: }
101: else printf("VALUE %p: %s\n", e, e->toChars());
102:
103: if (elements)
104: {
105: for (size_t i = 0; i < elements->dim; i++)
106: { Expression *z = elements->tdata()[i];
107: if (sd)
108: {
109: Dsymbol *s = sd->fields.tdata()[i];
110: VarDeclaration *v = s->isVarDeclaration();
111: assert(v);
112: // If it is a void assignment, use the default initializer
113: if (!z) {
114: for (int i = level; i>0; --i) printf(" ");
warning C6246: Local declaration of 'i' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '105' of 'c:\projects\extern\d\dmd\src\interpret.c': Lines: 105
115: printf(" field:void\n");
116: continue;
117: }
118: if ((v->type->ty != z->type->ty) && v->type->ty == Tsarray)
119: {
120: for (int i = level; --i;) printf(" ");
warning C6246: Local declaration of 'i' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '105' of 'c:\projects\extern\d\dmd\src\interpret.c': Lines: 105
121: printf(" field: block initalized static array\n");
122: continue;
123: }
124: }
125: showCtfeExpr(z, level + 1);
126: }
127: }
128: }
129:
130: /*************************************
131: * Attempt to interpret a function given the arguments.
132: * Input:
133: * istate state for calling function (NULL if none)
134: * arguments function arguments
135: * thisarg 'this', if a needThis() function, NULL if not.
136: *
137: * Return result expression if successful, NULL if not.
138: */
139:
140: Expression *FuncDeclaration::interpret(InterState *istate, Expressions *arguments, Expression *thisarg)
141: {
142: #if LOG
143: printf("\n********\nFuncDeclaration::interpret(istate = %p) %s\n", istate, toChars());
144: printf("cantInterpret = %d, semanticRun = %d\n", cantInterpret, semanticRun);
145: #endif
146: if (global.errors)
147: return NULL;
148:
149: if (cantInterpret || semanticRun == PASSsemantic3)
150: return NULL;
151:
152: if (semanticRun < PASSsemantic3 && scope)
153: {
154: int olderrors = global.errors;
155: semantic3(scope);
156: if (olderrors != global.errors) // if errors compiling this function
157: return NULL;
158: }
159: if (semanticRun < PASSsemantic3done)
160: return NULL;
161:
162: Type *tb = type->toBasetype();
163: assert(tb->ty == Tfunction);
164: TypeFunction *tf = (TypeFunction *)tb;
165: Type *tret = tf->next->toBasetype();
166: if (tf->varargs && arguments &&
167: ((parameters && arguments->dim != parameters->dim) || (!parameters && arguments->dim)))
168: { cantInterpret = 1;
169: error("C-style variadic functions are not yet implemented in CTFE");
170: return NULL;
171: }
172:
173: InterState istatex;
174: istatex.caller = istate;
175: istatex.fd = this;
176: istatex.localThis = thisarg;
177:
178: Expressions vsave; // place to save previous parameter values
179: size_t dim = 0;
180: if (needThis() && !thisarg)
181: { // error, no this. Prevent segfault.
182: error("need 'this' to access member %s", toChars());
183: return NULL;
184: }
185: if (thisarg && !istate)
186: { // Check that 'this' aleady has a value
187: if (thisarg->interpret(istate) == EXP_CANT_INTERPRET)
188: return NULL;
189: }
190: if (arguments)
191: {
192: dim = arguments->dim;
193: assert(!dim || (parameters && (parameters->dim == dim)));
194: vsave.setDim(dim);
195:
196: /* Evaluate all the arguments to the function,
197: * store the results in eargs[]
198: */
199: Expressions eargs;
200: eargs.setDim(dim);
201:
202: for (size_t i = 0; i < dim; i++)
203: { Expression *earg = arguments->tdata()[i];
204: Parameter *arg = Parameter::getNth(tf->parameters, i);
205:
206: if (arg->storageClass & (STCout | STCref))
207: {
208: if (!istate && (arg->storageClass & STCout))
209: { // initializing an out parameter involves writing to it.
210: earg->error("global %s cannot be passed as an 'out' parameter at compile time", earg->toChars());
211: return NULL;
212: }
213: // Convert all reference arguments into lvalue references
214: earg = earg->interpret(istate, ctfeNeedLvalueRef);
215: if (earg == EXP_CANT_INTERPRET)
216: return NULL;
217: }
218: else if (arg->storageClass & STClazy)
219: {
220: }
221: else
222: { /* Value parameters
223: */
224: Type *ta = arg->type->toBasetype();
225: if (ta->ty == Tsarray && earg->op == TOKaddress)
226: {
227: /* Static arrays are passed by a simple pointer.
228: * Skip past this to get at the actual arg.
229: */
230: earg = ((AddrExp *)earg)->e1;
231: }
232: earg = earg->interpret(istate);
233: if (earg == EXP_CANT_INTERPRET)
234: return NULL;
235: }
236: eargs.tdata()[i] = earg;
237: }
238:
239: for (size_t i = 0; i < dim; i++)
240: { Expression *earg = eargs.tdata()[i];
241: Parameter *arg = Parameter::getNth(tf->parameters, i);
242: VarDeclaration *v = parameters->tdata()[i];
243: vsave.tdata()[i] = v->getValue();
244: #if LOG
245: printf("arg[%d] = %s\n", i, earg->toChars());
246: #endif
247: if (arg->storageClass & (STCout | STCref) && earg->op==TOKvar)
248: {
249: VarExp *ve = (VarExp *)earg;
250: VarDeclaration *v2 = ve->var->isVarDeclaration();
251: if (!v2)
252: {
253: error("cannot interpret %s as a ref parameter", ve->toChars());
254: return NULL;
255: }
256: v->setValueWithoutChecking(earg);
257: /* Don't restore the value of v2 upon function return
258: */
259: for (size_t i = 0; i < (istate ? istate->vars.dim : 0); i++)
warning C6246: Local declaration of 'i' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '239' of 'c:\projects\extern\d\dmd\src\interpret.c': Lines: 239
260: { VarDeclaration *vx = istate->vars.tdata()[i];
261: if (vx == v2)
262: { istate->vars.tdata()[i] = NULL;
263: break;
264: }
265: }
266: }
267: else
268: { // Value parameters and non-trivial references
269: v->setValueWithoutChecking(earg);
270: }
271: #if LOG || LOGASSIGN
272: printf("interpreted arg[%d] = %s\n", i, earg->toChars());
273: showCtfeExpr(earg);
274: #endif
275: }
276: }
277: // Don't restore the value of 'this' upon function return
278: if (needThis() && istate)
279: {
280: VarDeclaration *thisvar = findParentVar(thisarg, istate->localThis);
281: if (!thisvar) // it's a reference. Find which variable it refers to.
282: thisvar = findParentVar(thisarg->interpret(istate), istate->localThis);
283: for (size_t i = 0; i < istate->vars.dim; i++)
284: { VarDeclaration *v = istate->vars.tdata()[i];
285: if (v == thisvar)
286: { istate->vars.tdata()[i] = NULL;
287: break;
288: }
289: }
290: }
291:
292: /* Save the values of the local variables used
293: */
294: Expressions valueSaves;
295: if (istate)
296: {
297: //printf("saving local variables...\n");
298: valueSaves.setDim(istate->vars.dim);
299: for (size_t i = 0; i < istate->vars.dim; i++)
300: { VarDeclaration *v = istate->vars.tdata()[i];
301: bool isParentVar = false;
302: /* Nested functions only restore their own local variables
303: * (not variables in the parent function)
304: */
305: if (v && (!isNested() || v->parent == this))
306: {
307: //printf("\tsaving [%d] %s = %s\n", i, v->toChars(), v->getValue() ? v->getValue()->toChars() : "");
308: valueSaves.tdata()[i] = v->getValue();
309: v->setValueNull();
310: }
311: }
312: }
313:
314: Expression *e = NULL;
315: while (1)
316: {
317: e = fbody->interpret(&istatex);
318: if (e == EXP_CANT_INTERPRET)
319: {
320: #if LOG
321: printf("function body failed to interpret\n");
322: #endif
323: e = NULL;
324: }
325:
326: /* This is how we deal with a recursive statement AST
327: * that has arbitrary goto statements in it.
328: * Bubble up a 'result' which is the target of the goto
329: * statement, then go recursively down the AST looking
330: * for that statement, then execute starting there.
331: */
332: if (e == EXP_GOTO_INTERPRET)
333: {
334: istatex.start = istatex.gotoTarget; // set starting statement
335: istatex.gotoTarget = NULL;
336: }
337: else
338: break;
339: }
340: assert(e != EXP_CONTINUE_INTERPRET && e != EXP_BREAK_INTERPRET);
341:
342: /* Restore the parameter values
343: */
344: for (size_t i = 0; i < dim; i++)
345: {
346: VarDeclaration *v = parameters->tdata()[i];
347: v->setValueWithoutChecking(vsave.tdata()[i]);
348: }
349: /* Clear __result. (Bug 6049).
350: */
351: if (vresult)
352: vresult->setValueNull();
353:
354: if (istate)
355: {
356: /* Restore the variable values
357: */
358: //printf("restoring local variables...\n");
359: for (size_t i = 0; i < istate->vars.dim; i++)
360: { VarDeclaration *v = istate->vars.tdata()[i];
361: /* Nested functions only restore their own local variables
362: * (not variables in the parent function)
363: */
364: if (v && (!isNested() || v->parent == this))
365: { v->setValueWithoutChecking(valueSaves.tdata()[i]);
366: //printf("\trestoring [%d] %s = %s\n", i, v->toChars(), v->getValue() ? v->getValue()->toChars() : "");
367: }
368: }
369: }
370: return e;
371: }
372:
373: /******************************** Statement ***************************/
374:
375: #define START() \
376: if (istate->start) \
377: { if (istate->start != this) \
378: return NULL; \
379: istate->start = NULL; \
380: }
381:
382: /***********************************
383: * Interpret the statement.
384: * Returns:
385: * NULL continue to next statement
386: * EXP_CANT_INTERPRET cannot interpret statement at compile time
387: * !NULL expression from return statement
388: */
389:
390: Expression *Statement::interpret(InterState *istate)
391: {
392: #if LOG
393: printf("Statement::interpret()\n");
394: #endif
395: START()
396: error("Statement %s cannot be interpreted at compile time", this->toChars());
397: return EXP_CANT_INTERPRET;
398: }
399:
400: Expression *ExpStatement::interpret(InterState *istate)
401: {
402: #if LOG
403: printf("ExpStatement::interpret(%s)\n", exp ? exp->toChars() : "");
404: #endif
405: START()
406: if (exp)
407: {
408: Expression *e = exp->interpret(istate, ctfeNeedNothing);
409: if (e == EXP_CANT_INTERPRET)
410: {
411: //printf("-ExpStatement::interpret(): %p\n", e);
412: return EXP_CANT_INTERPRET;
413: }
414: }
415: return NULL;
416: }
417:
418: Expression *CompoundStatement::interpret(InterState *istate)
419: { Expression *e = NULL;
420:
421: #if LOG
422: printf("CompoundStatement::interpret()\n");
423: #endif
424: if (istate->start == this)
425: istate->start = NULL;
426: if (statements)
427: {
428: for (size_t i = 0; i < statements->dim; i++)
429: { Statement *s = statements->tdata()[i];
430:
431: if (s)
432: {
433: e = s->interpret(istate);
434: if (e)
435: break;
436: }
437: }
438: }
439: #if LOG
440: printf("-CompoundStatement::interpret() %p\n", e);
441: #endif
442: return e;
443: }
444:
445: Expression *UnrolledLoopStatement::interpret(InterState *istate)
446: { Expression *e = NULL;
447:
448: #if LOG
449: printf("UnrolledLoopStatement::interpret()\n");
450: #endif
451: if (istate->start == this)
452: istate->start = NULL;
453: if (statements)
454: {
455: for (size_t i = 0; i < statements->dim; i++)
456: { Statement *s = statements->tdata()[i];
457:
458: e = s->interpret(istate);
459: if (e == EXP_CANT_INTERPRET)
460: break;
461: if (e == EXP_CONTINUE_INTERPRET)
462: {
463: if (istate->gotoTarget && istate->gotoTarget != this)
464: break; // continue at higher level
465: istate->gotoTarget = NULL;
466: e = NULL;
467: continue;
468: }
469: if (e == EXP_BREAK_INTERPRET)
470: {
471: if (!istate->gotoTarget || istate->gotoTarget == this)
472: {
473: istate->gotoTarget = NULL;
474: e = NULL;
475: } // else break at a higher level
476: break;
477: }
478: if (e)
479: break;
480: }
481: }
482: return e;
483: }
484:
485: // For CTFE only. Returns true if 'e' is TRUE or a non-null pointer.
486: int isTrueBool(Expression *e)
487: {
488: return e->isBool(TRUE) || (e->type->ty == Tpointer && e->op != TOKnull);
489: }
490:
491: Expression *IfStatement::interpret(InterState *istate)
492: {
493: #if LOG
494: printf("IfStatement::interpret(%s)\n", condition->toChars());
495: #endif
496:
497: if (istate->start == this)
498: istate->start = NULL;
499: if (istate->start)
500: {
501: Expression *e = NULL;
502: if (ifbody)
503: e = ifbody->interpret(istate);
504: if (istate->start && elsebody)
505: e = elsebody->interpret(istate);
506: return e;
507: }
508:
509: Expression *e = condition->interpret(istate);
510: assert(e);
511: //if (e == EXP_CANT_INTERPRET) printf("cannot interpret\n");
512: if (e != EXP_CANT_INTERPRET)
513: {
514: if (isTrueBool(e))
515: e = ifbody ? ifbody->interpret(istate) : NULL;
516: else if (e->isBool(FALSE))
517: e = elsebody ? elsebody->interpret(istate) : NULL;
518: else
519: {
520: e = EXP_CANT_INTERPRET;
521: }
522: }
523: return e;
524: }
525:
526: Expression *ScopeStatement::interpret(InterState *istate)
527: {
528: #if LOG
529: printf("ScopeStatement::interpret()\n");
530: #endif
531: if (istate->start == this)
532: istate->start = NULL;
533: return statement ? statement->interpret(istate) : NULL;
534: }
535:
536: Expression *resolveSlice(Expression *e)
537: {
538: if ( ((SliceExp *)e)->e1->op == TOKnull)
539: return ((SliceExp *)e)->e1;
540: return Slice(e->type, ((SliceExp *)e)->e1,
541: ((SliceExp *)e)->lwr, ((SliceExp *)e)->upr);
542: }
543:
544: /* Determine the array length, without interpreting it.
545: * e must be an array literal, or a slice
546: * It's very wasteful to resolve the slice when we only
547: * need the length.
548: */
549: uinteger_t resolveArrayLength(Expression *e)
550: {
551: if (e->op == TOKnull)
552: return 0;
553: if (e->op == TOKslice)
554: { uinteger_t ilo = ((SliceExp *)e)->lwr->toInteger();
555: uinteger_t iup = ((SliceExp *)e)->upr->toInteger();
556: return iup - ilo;
557: }
558: if (e->op == TOKstring)
559: { return ((StringExp *)e)->len;
560: }
561: if (e->op == TOKarrayliteral)
562: { ArrayLiteralExp *ale = (ArrayLiteralExp *)e;
563: return ale->elements ? ale->elements->dim : 0;
564: }
565: if (e->op == TOKassocarrayliteral)
566: { AssocArrayLiteralExp *ale = (AssocArrayLiteralExp *)e;
567: return ale->keys->dim;
568: }
569: assert(0);
570: return 0;
571: }
572:
573: // As Equal, but resolves slices before comparing
574: Expression *ctfeEqual(enum TOK op, Type *type, Expression *e1, Expression *e2)
575: {
576: if (e1->op == TOKslice)
577: e1 = resolveSlice(e1);
578: if (e2->op == TOKslice)
579: e2 = resolveSlice(e2);
580: return Equal(op, type, e1, e2);
581: }
582:
583:
584: void scrubArray(Expressions *elems);
585:
586: /* All results destined for use outside of CTFE need to have their CTFE-specific
587: * features removed.
588: * In particular, all slices must be resolved.
589: */
590: Expression *scrubReturnValue(Expression *e)
591: {
592: if (e->op == TOKslice)
593: {
594: e = resolveSlice(e);
595: }
596: if (e->op == TOKstructliteral)
597: {
598: StructLiteralExp *se = (StructLiteralExp *)e;
599: scrubArray(se->elements);
600: }
601: if (e->op == TOKarrayliteral)
602: {
603: scrubArray(((ArrayLiteralExp *)e)->elements);
604: }
605: if (e->op == TOKassocarrayliteral)
606: {
607: AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)e;
608: scrubArray(aae->keys);
609: scrubArray(aae->values);
610: }
611: return e;
612: }
613:
614: // Scrub all members of an array
615: void scrubArray(Expressions *elems)
616: {
617: for (size_t i = 0; i < elems->dim; i++)
618: {
619: Expression *m = elems->tdata()[i];
620: if (!m)
621: continue;
622: m = scrubReturnValue(m);
623: elems->tdata()[i] = m;
624: }
625: }
626:
627:
628: Expression *ReturnStatement::interpret(InterState *istate)
629: {
630: #if LOG
631: printf("ReturnStatement::interpret(%s)\n", exp ? exp->toChars() : "");
632: #endif
633: START()
634: if (!exp)
635: return EXP_VOID_INTERPRET;
636: assert(istate && istate->fd && istate->fd->type);
637: #if DMDV2
638: /* If the function returns a ref AND it's been called from an assignment,
639: * we need to return an lvalue. Otherwise, just do an (rvalue) interpret.
640: */
641: if (istate->fd->type && istate->fd->type->ty==Tfunction)
642: {
643: TypeFunction *tf = (TypeFunction *)istate->fd->type;
644: if (tf->isref && istate->caller && istate->caller->awaitingLvalueReturn)
645: { // We need to return an lvalue
646: Expression *e = exp->interpret(istate, ctfeNeedLvalue);
647: if (e == EXP_CANT_INTERPRET)
648: error("ref return %s is not yet supported in CTFE", exp->toChars());
649: return e;
650: }
651: if (tf->next && (tf->next->ty == Tdelegate) && istate->fd->closureVars.dim > 0)
652: {
653: // To support this, we need to copy all the closure vars
654: // into the delegate literal.
655: error("closures are not yet supported in CTFE");
656: return EXP_CANT_INTERPRET;
657: }
658: }
659: #endif
660: // We need to treat pointers specially, because TOKsymoff can be used to
661: // return a value OR a pointer
662: Expression *e;
663: if ((exp->type->ty == Tpointer && exp->type->nextOf()->ty != Tfunction))
664: e = exp->interpret(istate, ctfeNeedLvalue);
665: else
666: e = exp->interpret(istate);
667: if (e == EXP_CANT_INTERPRET)
668: return e;
669: if (!istate->caller)
670: {
671: e = scrubReturnValue(e);
672: if (e == EXP_CANT_INTERPRET)
673: return e;
674: }
675: else if (needToCopyLiteral(exp))
676: e = copyLiteral(e);
677: #if LOGASSIGN
678: printf("RETURN %s\n", loc.toChars());
679: showCtfeExpr(e);
680: #endif
681: return e;
682: }
683:
684: Expression *BreakStatement::interpret(InterState *istate)
685: {
686: #if LOG
687: printf("BreakStatement::interpret()\n");
688: #endif
689: START()
690: if (ident)
691: { LabelDsymbol *label = istate->fd->searchLabel(ident);
692: assert(label && label->statement);
693: Statement *s = label->statement;
694: if (s->isLabelStatement())
695: s = s->isLabelStatement()->statement;
696: if (s->isScopeStatement())
697: s = s->isScopeStatement()->statement;
698: istate->gotoTarget = s;
699: return EXP_BREAK_INTERPRET;
700: }
701: else
702: {
703: istate->gotoTarget = NULL;
704: return EXP_BREAK_INTERPRET;
705: }
706: }
707:
708: Expression *ContinueStatement::interpret(InterState *istate)
709: {
710: #if LOG
711: printf("ContinueStatement::interpret()\n");
712: #endif
713: START()
714: if (ident)
715: { LabelDsymbol *label = istate->fd->searchLabel(ident);
716: assert(label && label->statement);
717: Statement *s = label->statement;
718: if (s->isLabelStatement())
719: s = s->isLabelStatement()->statement;
720: if (s->isScopeStatement())
721: s = s->isScopeStatement()->statement;
722: istate->gotoTarget = s;
723: return EXP_CONTINUE_INTERPRET;
724: }
725: else
726: return EXP_CONTINUE_INTERPRET;
727: }
728:
729: Expression *WhileStatement::interpret(InterState *istate)
730: {
731: #if LOG
732: printf("WhileStatement::interpret()\n");
733: #endif
734: assert(0); // rewritten to ForStatement
735: return NULL;
736: }
737:
738: Expression *DoStatement::interpret(InterState *istate)
739: {
740: #if LOG
741: printf("DoStatement::interpret()\n");
742: #endif
743: if (istate->start == this)
744: istate->start = NULL;
745: Expression *e;
746:
747: if (istate->start)
748: {
749: e = body ? body->interpret(istate) : NULL;
750: if (istate->start)
751: return NULL;
752: if (e == EXP_CANT_INTERPRET)
753: return e;
754: if (e == EXP_BREAK_INTERPRET)
755: {
756: if (!istate->gotoTarget || istate->gotoTarget == this)
757: {
758: istate->gotoTarget = NULL;
759: e = NULL;
760: } // else break at a higher level
761: return e;
762: }
763: if (e == EXP_CONTINUE_INTERPRET)
764: if (!istate->gotoTarget || istate->gotoTarget == this)
765: {
766: goto Lcontinue;
767: }
768: else // else continue at a higher level
769: return e;
770: if (e)
771: return e;
772: }
773:
774: while (1)
775: {
776: e = body ? body->interpret(istate) : NULL;
777: if (e == EXP_CANT_INTERPRET)
778: break;
779: if (e == EXP_BREAK_INTERPRET)
780: {
781: if (!istate->gotoTarget || istate->gotoTarget == this)
782: {
783: istate->gotoTarget = NULL;
784: e = NULL;
785: } // else break at a higher level
786: break;
787: }
788: if (e && e != EXP_CONTINUE_INTERPRET)
789: break;
790: if (istate->gotoTarget && istate->gotoTarget != this)
791: break; // continue at a higher level
792:
793: Lcontinue:
794: istate->gotoTarget = NULL;
795: e = condition->interpret(istate);
796: if (e == EXP_CANT_INTERPRET)
797: break;
798: if (!e->isConst())
799: { e = EXP_CANT_INTERPRET;
800: break;
801: }
802: if (isTrueBool(e))
803: {
804: }
805: else if (e->isBool(FALSE))
806: { e = NULL;
807: break;
808: }
809: else
810: assert(0);
811: }
812: return e;
813: }
814:
815: Expression *ForStatement::interpret(InterState *istate)
816: {
817: #if LOG
818: printf("ForStatement::interpret()\n");
819: #endif
820: if (istate->start == this)
821: istate->start = NULL;
822: Expression *e;
823:
824: if (init)
825: {
826: e = init->interpret(istate);
827: if (e == EXP_CANT_INTERPRET)
828: return e;
829: assert(!e);
830: }
831:
832: if (istate->start)
833: {
834: e = body ? body->interpret(istate) : NULL;
835: if (istate->start)
836: return NULL;
837: if (e == EXP_CANT_INTERPRET)
838: return e;
839: if (e == EXP_BREAK_INTERPRET)
840: {
841: if (!istate->gotoTarget || istate->gotoTarget == this)
842: {
843: istate->gotoTarget = NULL;
844: return NULL;
845: } // else break at a higher level
846: }
847: if (e == EXP_CONTINUE_INTERPRET)
848: {
849: if (!istate->gotoTarget || istate->gotoTarget == this)
850: {
851: istate->gotoTarget = NULL;
852: goto Lcontinue;
853: } // else continue at a higher level
854: }
855: if (e)
856: return e;
857: }
858:
859: while (1)
860: {
861: if (!condition)
862: goto Lhead;
863: e = condition->interpret(istate);
864: if (e == EXP_CANT_INTERPRET)
865: break;
866: if (!e->isConst())
867: { e = EXP_CANT_INTERPRET;
868: break;
869: }
870: if (isTrueBool(e))
871: {
872: Lhead:
873: e = body ? body->interpret(istate) : NULL;
874: if (e == EXP_CANT_INTERPRET)
875: break;
876: if (e == EXP_BREAK_INTERPRET)
877: {
878: if (!istate->gotoTarget || istate->gotoTarget == this)
879: {
880: istate->gotoTarget = NULL;
881: e = NULL;
882: } // else break at a higher level
883: break;
884: }
885: if (e && e != EXP_CONTINUE_INTERPRET)
886: break;
887: if (istate->gotoTarget && istate->gotoTarget != this)
888: break; // continue at a higher level
889: Lcontinue:
890: istate->gotoTarget = NULL;
891: if (increment)
892: {
893: e = increment->interpret(istate);
894: if (e == EXP_CANT_INTERPRET)
895: break;
896: }
897: }
898: else if (e->isBool(FALSE))
899: { e = NULL;
900: break;
901: }
902: else
903: assert(0);
904: }
905: return e;
906: }
907:
908: Expression *ForeachStatement::interpret(InterState *istate)
909: {
910: #if 1
911: assert(0); // rewritten to ForStatement
912: return NULL;
913: #else
914: #if LOG
915: printf("ForeachStatement::interpret()\n");
916: #endif
917: if (istate->start == this)
918: istate->start = NULL;
919: if (istate->start)
920: return NULL;
921:
922: Expression *e = NULL;
923: Expression *eaggr;
924:
925: if (value->isOut() || value->isRef())
926: return EXP_CANT_INTERPRET;
927:
928: eaggr = aggr->interpret(istate);
929: if (eaggr == EXP_CANT_INTERPRET)
930: return EXP_CANT_INTERPRET;
931:
932: Expression *dim = ArrayLength(Type::tsize_t, eaggr);
933: if (dim == EXP_CANT_INTERPRET)
934: return EXP_CANT_INTERPRET;
935:
936: Expression *keysave = key ? key->value : NULL;
937: Expression *valuesave = value->value;
938:
939: uinteger_t d = dim->toUInteger();
940: uinteger_t index;
941:
942: if (op == TOKforeach)
943: {
944: for (index = 0; index < d; index++)
945: {
946: Expression *ekey = new IntegerExp(loc, index, Type::tsize_t);
947: if (key)
948: key->value = ekey;
949: e = Index(value->type, eaggr, ekey);
950: if (e == EXP_CANT_INTERPRET)
951: break;
952: value->value = e;
953:
954: e = body ? body->interpret(istate) : NULL;
955: if (e == EXP_CANT_INTERPRET)
956: break;
957: if (e == EXP_BREAK_INTERPRET)
958: {
959: if (!istate->gotoTarget || istate->gotoTarget == this)
960: {
961: istate->gotoTarget = NULL;
962: e = NULL;
963: } // else break at a higher level
964: break;
965: }
966: if (e == EXP_CONTINUE_INTERPRET)
967: {
968: if (istate->gotoTarget && istate->gotoTarget != this)
969: break; // continue at higher level
970: istate->gotoTarget = NULL;
971: e = NULL;
972: }
973: else if (e)
974: break;
975: }
976: }
977: else // TOKforeach_reverse
978: {
979: for (index = d; index-- != 0;)
980: {
981: Expression *ekey = new IntegerExp(loc, index, Type::tsize_t);
982: if (key)
983: key->value = ekey;
984: e = Index(value->type, eaggr, ekey);
985: if (e == EXP_CANT_INTERPRET)
986: break;
987: value->value = e;
988:
989: e = body ? body->interpret(istate) : NULL;
990: if (e == EXP_CANT_INTERPRET)
991: break;
992: if (e == EXP_BREAK_INTERPRET)
993: {
994: if (!istate->gotoTarget || istate->gotoTarget == this)
995: {
996: istate->gotoTarget = NULL;
997: e = NULL;
998: } // else break at a higher level
999: break;
1000: }
1001: if (e == EXP_CONTINUE_INTERPRET)
1002: {
1003: if (istate->gotoTarget && istate->gotoTarget != this)
1004: break; // continue at higher level
1005: istate->gotoTarget = NULL;
1006: e = NULL;
1007: }
1008: else if (e)
1009: break;
1010: }
1011: }
1012: value->value = valuesave;
1013: if (key)
1014: key->value = keysave;
1015: return e;
1016: #endif
1017: }
1018:
1019: #if DMDV2
1020: Expression *ForeachRangeStatement::interpret(InterState *istate)
1021: {
1022: #if 1
1023: assert(0); // rewritten to ForStatement
1024: return NULL;
1025: #else
1026: #if LOG
1027: printf("ForeachRangeStatement::interpret()\n");
1028: #endif
1029: if (istate->start == this)
1030: istate->start = NULL;
1031: if (istate->start)
1032: return NULL;
1033:
1034: Expression *e = NULL;
1035: Expression *elwr = lwr->interpret(istate);
1036: if (elwr == EXP_CANT_INTERPRET)
1037: return EXP_CANT_INTERPRET;
1038:
1039: Expression *eupr = upr->interpret(istate);
1040: if (eupr == EXP_CANT_INTERPRET)
1041: return EXP_CANT_INTERPRET;
1042:
1043: Expression *keysave = key->value;
1044:
1045: if (op == TOKforeach)
1046: {
1047: key->value = elwr;
1048:
1049: while (1)
1050: {
1051: e = Cmp(TOKlt, key->value->type, key->value, eupr);
1052: if (e == EXP_CANT_INTERPRET)
1053: break;
1054: if (e->isBool(TRUE) == FALSE)
1055: { e = NULL;
1056: break;
1057: }
1058:
1059: e = body ? body->interpret(istate) : NULL;
1060: if (e == EXP_CANT_INTERPRET)
1061: break;
1062: if (e == EXP_BREAK_INTERPRET)
1063: {
1064: if (!istate->gotoTarget || istate->gotoTarget == this)
1065: {
1066: istate->gotoTarget = NULL;
1067: e = NULL;
1068: } // else break at a higher level
1069: break;
1070: }
1071: if (e == EXP_CONTINUE_INTERPRET
1072: && istate->gotoTarget && istate->gotoTarget != this)
1073: break; // continue at higher level
1074: if (e == NULL || e == EXP_CONTINUE_INTERPRET)
1075: { e = Add(key->value->type, key->value, new IntegerExp(loc, 1, key->value->type));
1076: istate->gotoTarget = NULL;
1077: if (e == EXP_CANT_INTERPRET)
1078: break;
1079: key->value = e;
1080: }
1081: else
1082: break;
1083: }
1084: }
1085: else // TOKforeach_reverse
1086: {
1087: key->value = eupr;
1088:
1089: do
1090: {
1091: e = Cmp(TOKgt, key->value->type, key->value, elwr);
1092: if (e == EXP_CANT_INTERPRET)
1093: break;
1094: if (e->isBool(TRUE) == FALSE)
1095: { e = NULL;
1096: break;
1097: }
1098:
1099: e = Min(key->value->type, key->value, new IntegerExp(loc, 1, key->value->type));
1100: if (e == EXP_CANT_INTERPRET)
1101: break;
1102: key->value = e;
1103:
1104: e = body ? body->interpret(istate) : NULL;
1105: if (e == EXP_CANT_INTERPRET)
1106: break;
1107: if (e == EXP_BREAK_INTERPRET)
1108: {
1109: if (!istate->gotoTarget || istate->gotoTarget == this)
1110: {
1111: istate->gotoTarget = NULL;
1112: e = NULL;
1113: } // else break at a higher level
1114: break;
1115: }
1116: if (e == EXP_CONTINUE_INTERPRET)
1117: {
1118: if (istate->gotoTarget && istate->gotoTarget != this)
1119: break; // continue at higher level
1120: istate->gotoTarget = NULL;
1121: }
1122: } while (e == NULL || e == EXP_CONTINUE_INTERPRET);
1123: }
1124: key->value = keysave;
1125: return e;
1126: #endif
1127: }
1128: #endif
1129:
1130: Expression *SwitchStatement::interpret(InterState *istate)
1131: {
1132: #if LOG
1133: printf("SwitchStatement::interpret()\n");
1134: #endif
1135: if (istate->start == this)
1136: istate->start = NULL;
1137: Expression *e = NULL;
1138:
1139: if (istate->start)
1140: {
1141: e = body ? body->interpret(istate) : NULL;
1142: if (istate->start)
1143: return NULL;
1144: if (e == EXP_CANT_INTERPRET)
1145: return e;
1146: if (e == EXP_BREAK_INTERPRET)
1147: {
1148: if (!istate->gotoTarget || istate->gotoTarget == this)
1149: {
1150: istate->gotoTarget = NULL;
1151: return NULL;
1152: } // else break at a higher level
1153: }
1154: return e;
1155: }
1156:
1157:
1158: Expression *econdition = condition->interpret(istate);
1159: if (econdition == EXP_CANT_INTERPRET)
1160: return EXP_CANT_INTERPRET;
1161: if (econdition->op == TOKslice)
1162: econdition = resolveSlice(econdition);
1163:
1164: Statement *s = NULL;
1165: if (cases)
1166: {
1167: for (size_t i = 0; i < cases->dim; i++)
1168: {
1169: CaseStatement *cs = cases->tdata()[i];
1170: e = ctfeEqual(TOKequal, Type::tint32, econdition, cs->exp);
1171: if (e == EXP_CANT_INTERPRET)
1172: return EXP_CANT_INTERPRET;
1173: if (e->isBool(TRUE))
1174: { s = cs;
1175: break;
1176: }
1177: }
1178: }
1179: if (!s)
1180: { if (hasNoDefault)
1181: error("no default or case for %s in switch statement", econdition->toChars());
1182: s = sdefault;
1183: }
1184:
1185: assert(s);
1186: istate->start = s;
1187: e = body ? body->interpret(istate) : NULL;
1188: assert(!istate->start);
1189: if (e == EXP_BREAK_INTERPRET)
1190: {
1191: if (!istate->gotoTarget || istate->gotoTarget == this)
1192: {
1193: istate->gotoTarget = NULL;
1194: e = NULL;
1195: } // else break at a higher level
1196: }
1197: return e;
1198: }
1199:
1200: Expression *CaseStatement::interpret(InterState *istate)
1201: {
1202: #if LOG
1203: printf("CaseStatement::interpret(%s) this = %p\n", exp->toChars(), this);
1204: #endif
1205: if (istate->start == this)
1206: istate->start = NULL;
1207: if (statement)
1208: return statement->interpret(istate);
1209: else
1210: return NULL;
1211: }
1212:
1213: Expression *DefaultStatement::interpret(InterState *istate)
1214: {
1215: #if LOG
1216: printf("DefaultStatement::interpret()\n");
1217: #endif
1218: if (istate->start == this)
1219: istate->start = NULL;
1220: if (statement)
1221: return statement->interpret(istate);
1222: else
1223: return NULL;
1224: }
1225:
1226: Expression *GotoStatement::interpret(InterState *istate)
1227: {
1228: #if LOG
1229: printf("GotoStatement::interpret()\n");
1230: #endif
1231: START()
1232: assert(label && label->statement);
1233: istate->gotoTarget = label->statement;
1234: return EXP_GOTO_INTERPRET;
1235: }
1236:
1237: Expression *GotoCaseStatement::interpret(InterState *istate)
1238: {
1239: #if LOG
1240: printf("GotoCaseStatement::interpret()\n");
1241: #endif
1242: START()
1243: assert(cs);
1244: istate->gotoTarget = cs;
1245: return EXP_GOTO_INTERPRET;
1246: }
1247:
1248: Expression *GotoDefaultStatement::interpret(InterState *istate)
1249: {
1250: #if LOG
1251: printf("GotoDefaultStatement::interpret()\n");
1252: #endif
1253: START()
1254: assert(sw && sw->sdefault);
1255: istate->gotoTarget = sw->sdefault;
1256: return EXP_GOTO_INTERPRET;
1257: }
1258:
1259: Expression *LabelStatement::interpret(InterState *istate)
1260: {
1261: #if LOG
1262: printf("LabelStatement::interpret()\n");
1263: #endif
1264: if (istate->start == this)
1265: istate->start = NULL;
1266: return statement ? statement->interpret(istate) : NULL;
1267: }
1268:
1269:
1270: Expression *TryCatchStatement::interpret(InterState *istate)
1271: {
1272: #if LOG
1273: printf("TryCatchStatement::interpret()\n");
1274: #endif
1275: START()
1276: error("try-catch statements are not yet supported in CTFE");
1277: return EXP_CANT_INTERPRET;
1278: }
1279:
1280:
1281: Expression *TryFinallyStatement::interpret(InterState *istate)
1282: {
1283: #if LOG
1284: printf("TryFinallyStatement::interpret()\n");
1285: #endif
1286: START()
1287: error("try-finally statements are not yet supported in CTFE");
1288: return EXP_CANT_INTERPRET;
1289: }
1290:
1291: Expression *ThrowStatement::interpret(InterState *istate)
1292: {
1293: #if LOG
1294: printf("ThrowStatement::interpret()\n");
1295: #endif
1296: START()
1297: error("throw statements are not yet supported in CTFE");
1298: return EXP_CANT_INTERPRET;
1299: }
1300:
1301: Expression *OnScopeStatement::interpret(InterState *istate)
1302: {
1303: #if LOG
1304: printf("OnScopeStatement::interpret()\n");
1305: #endif
1306: START()
1307: error("scope guard statements are not yet supported in CTFE");
1308: return EXP_CANT_INTERPRET;
1309: }
1310:
1311: Expression *WithStatement::interpret(InterState *istate)
1312: {
1313: #if LOG
1314: printf("WithStatement::interpret()\n");
1315: #endif
1316: START()
1317: error("with statements are not yet supported in CTFE");
1318: return EXP_CANT_INTERPRET;
1319: }
1320:
1321: Expression *AsmStatement::interpret(InterState *istate)
1322: {
1323: #if LOG
1324: printf("AsmStatement::interpret()\n");
1325: #endif
1326: START()
1327: error("asm statements cannot be interpreted at compile time");
1328: return EXP_CANT_INTERPRET;
1329: }
1330:
1331: #if DMDV2
1332: Expression *ImportStatement::interpret(InterState *istate)
1333: {
1334: #if LOG
1335: printf("ImportStatement::interpret()\n");
1336: #endif
1337: START();
1338: return NULL;
1339: }
1340: #endif
1341:
1342: /******************************** Expression ***************************/
1343:
1344: Expression *Expression::interpret(InterState *istate, CtfeGoal goal)
1345: {
1346: #if LOG
1347: printf("Expression::interpret() %s\n", toChars());
1348: printf("type = %s\n", type->toChars());
1349: dump(0);
1350: #endif
1351: error("Cannot interpret %s at compile time", toChars());
1352: return EXP_CANT_INTERPRET;
1353: }
1354:
1355: Expression *ThisExp::interpret(InterState *istate, CtfeGoal goal)
1356: {
1357: if (istate && istate->localThis && istate->localThis->op == TOKstructliteral)
1358: return istate->localThis;
1359: if (istate && istate->localThis)
1360: return istate->localThis->interpret(istate, goal);
1361: error("value of 'this' is not known at compile time");
1362: return EXP_CANT_INTERPRET;
1363: }
1364:
1365: Expression *NullExp::interpret(InterState *istate, CtfeGoal goal)
1366: {
1367: return this;
1368: }
1369:
1370: Expression *IntegerExp::interpret(InterState *istate, CtfeGoal goal)
1371: {
1372: #if LOG
1373: printf("IntegerExp::interpret() %s\n", toChars());
1374: #endif
1375: return this;
1376: }
1377:
1378: Expression *RealExp::interpret(InterState *istate, CtfeGoal goal)
1379: {
1380: #if LOG
1381: printf("RealExp::interpret() %s\n", toChars());
1382: #endif
1383: return this;
1384: }
1385:
1386: Expression *ComplexExp::interpret(InterState *istate, CtfeGoal goal)
1387: {
1388: return this;
1389: }
1390:
1391: Expression *StringExp::interpret(InterState *istate, CtfeGoal goal)
1392: {
1393: #if LOG
1394: printf("StringExp::interpret() %s\n", toChars());
1395: #endif
1396: /* Since we are using StringExps as reference types for char[] arrays,
1397: * we need to dup them if there's any chance they'll be modified.
1398: * For efficiency, we try to only dup when necessary.
1399: */
1400: // Fixed-length char arrays always get duped later anyway.
1401: if (type->ty == Tsarray)
1402: return this;
1403: /* String literals are normally immutable, so we don't need to dup them
1404: * In D2, we can detect attempts to write to read-only literals.
1405: * For D1, we could be pessimistic, and always dup.
1406: * But since it fails only when there has been an explicit cast, and any
1407: * such function would give different results at runtime anyway (eg, it
1408: * may crash), it hardly seems worth the massive performance hit.
1409: */
1410: #if DMDV2
1411: if (!((TypeNext *)type)->next->mod & (MODconst | MODimmutable))
warning C4806: '&' : unsafe operation: no value of type 'bool' promoted to type 'int' can equal the given constant
warning C6290: Bitwise operation on logical result: ! has higher precedence than &. Use && or (!(x & y)) instead
1412: { // It seems this happens only when there has been an explicit cast
1413: error("cannot cast a read-only string literal to mutable in CTFE");
1414: return EXP_CANT_INTERPRET;
1415: }
1416: #endif
1417: return this;
1418: }
1419:
1420: Expression *FuncExp::interpret(InterState *istate, CtfeGoal goal)
1421: {
1422: #if LOG
1423: printf("FuncExp::interpret() %s\n", toChars());
1424: #endif
1425: return this;
1426: }
1427:
1428: Expression *SymOffExp::interpret(InterState *istate, CtfeGoal goal)
1429: {
1430: #if LOG
1431: printf("SymOffExp::interpret() %s\n", toChars());
1432: #endif
1433: if (var->isFuncDeclaration() && offset == 0)
1434: {
1435: return this;
1436: }
1437: if (type->ty != Tpointer)
1438: { // Probably impossible
1439: error("Cannot interpret %s at compile time", toChars());
1440: return EXP_CANT_INTERPRET;
1441: }
1442: Type *pointee = ((TypePointer *)type)->next;
1443: Expression *val = getVarExp(loc, istate, var, goal);
1444: if (val->type->ty == Tarray || val->type->ty == Tsarray)
1445: {
1446: TypeArray *tar = (TypeArray *)val->type;
1447: dinteger_t sz = pointee->size();
1448: dinteger_t indx = offset/sz;
1449: assert(sz * indx == offset);
1450: Expression *aggregate = NULL;
1451: if (val->op == TOKarrayliteral || val->op == TOKstring)
1452: aggregate = val;
1453: else if (val->op == TOKslice)
1454: {
1455: aggregate = ((SliceExp *)val)->e1;
1456: Expression *lwr = ((SliceExp *)val)->lwr->interpret(istate);
1457: indx += lwr->toInteger();
1458: }
1459: if (aggregate)
1460: {
1461: IntegerExp *ofs = new IntegerExp(loc, indx, Type::tsize_t);
1462: IndexExp *ie = new IndexExp(loc, aggregate, ofs);
1463: ie->type = type;
1464: return ie;
1465: }
1466: }
1467: else if (offset == 0 && pointee == var->type)
1468: {
1469: if (goal == ctfeNeedLvalue || goal == ctfeNeedLvalueRef)
1470: {
1471: VarExp *ve = new VarExp(loc, var);
1472: ve->type = type;
1473: return ve;
1474: }
1475: Expression *e = getVarExp(loc, istate, var, goal);
1476: e = new AddrExp(loc, e);
1477: e->type = type;
1478: return e;
1479: }
1480:
1481: error("Cannot interpret %s at compile time", toChars());
1482: return EXP_CANT_INTERPRET;
1483: }
1484:
1485: Expression *AddrExp::interpret(InterState *istate, CtfeGoal goal)
1486: {
1487: #if LOG
1488: printf("AddrExp::interpret() %s\n", toChars());
1489: #endif
1490: // For reference types, we need to return an lvalue ref.
1491: TY tb = e1->type->toBasetype()->ty;
1492: bool needRef = (tb == Tarray || tb == Taarray || tb == Tclass);
1493: Expression *e = e1->interpret(istate, needRef ? ctfeNeedLvalueRef : ctfeNeedLvalue);
1494: if (e == EXP_CANT_INTERPRET)
1495: return e;
1496: // Return a simplified address expression
1497: e = new AddrExp(loc, e);
1498: e->type = type;
1499: return e;
1500: }
1501:
1502: Expression *DelegateExp::interpret(InterState *istate, CtfeGoal goal)
1503: {
1504: #if LOG
1505: printf("DelegateExp::interpret() %s\n", toChars());
1506: #endif
1507: return this;
1508: }
1509:
1510:
1511: // -------------------------------------------------------------
1512: // Remove out, ref, and this
1513: // -------------------------------------------------------------
1514: // The variable used in a dotvar, index, or slice expression,
1515: // after 'out', 'ref', and 'this' have been removed.
1516: // *isReference will be set to true if a reference was removed.
1517: Expression * resolveReferences(Expression *e, Expression *thisval, bool *isReference /*=NULL */)
1518: {
1519: if (isReference)
1520: *isReference = false;
1521: for(;;)
1522: {
1523: if (e->op == TOKthis)
1524: {
1525: assert(thisval);
1526: assert(e != thisval);
1527: e = thisval;
1528: continue;
1529: }
1530: if (e->op == TOKvar) {
1531: // Chase down rebinding of out and ref.
1532: VarExp *ve = (VarExp *)e;
1533: VarDeclaration *v = ve->var->isVarDeclaration();
1534: if (v->type->ty == Tpointer)
1535: break;
1536: if (v && v->getValue() && v->getValue()->op == TOKvar) // it's probably a reference
1537: {
1538: // Make sure it's a real reference.
1539: // It's not a reference if v is a struct initialized to
1540: // 0 using an __initZ SymbolDeclaration from
1541: // TypeStruct::defaultInit()
1542: VarExp *ve2 = (VarExp *)v->getValue();
1543: if (!ve2->var->isSymbolDeclaration())
1544: {
1545: if (isReference)
1546: *isReference = true;
1547: e = v->getValue();
1548: continue;
1549: }
1550: }
1551: else if (v && v->getValue() && (v->getValue()->op == TOKslice))
1552: {
1553: SliceExp *se = (SliceExp *)v->getValue();
1554: if (se->e1->op == TOKarrayliteral || se->e1->op == TOKassocarrayliteral || se->e1->op == TOKstring)
1555: break;
1556: e = v->getValue();
1557: continue;
1558: }
1559: else if (v && v->getValue() && (v->getValue()->op==TOKindex || v->getValue()->op == TOKdotvar
1560: || v->getValue()->op == TOKthis ))
1561: {
1562: e = v->getValue();
1563: continue;
1564: }
1565: }
1566: break;
1567: }
1568: return e;
1569: }
1570:
1571: Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal)
1572: {
1573: Expression *e = EXP_CANT_INTERPRET;
1574: VarDeclaration *v = d->isVarDeclaration();
1575: SymbolDeclaration *s = d->isSymbolDeclaration();
1576: if (v)
1577: {
1578: #if DMDV2
1579: /* Magic variable __ctfe always returns true when interpreting
1580: */
1581: if (v->ident == Id::ctfe)
1582: return new IntegerExp(loc, 1, Type::tbool);
1583: if ((v->isConst() || v->isImmutable() || v->storage_class & STCmanifest) && v->init && !v->getValue())
1584: #else
1585: if (v->isConst() && v->init)
1586: #endif
1587: { e = v->init->toExpression();
1588: if (e && (e->op == TOKconstruct || e->op == TOKblit))
1589: { AssignExp *ae = (AssignExp *)e;
1590: e = ae->e2;
1591: v->inuse++;
1592: e = e->interpret(istate, ctfeNeedAnyValue);
1593: v->inuse--;
1594: if (e == EXP_CANT_INTERPRET)
1595: return e;
1596: e->type = v->type;
1597: }
1598: else
1599: {
1600: if (e && !e->type)
1601: e->type = v->type;
1602: if (e)
1603: e = e->interpret(istate, ctfeNeedAnyValue);
1604: }
1605: if (e && e != EXP_CANT_INTERPRET)
1606: v->setValueWithoutChecking(e);
1607: }
1608: else if (v->isCTFE() && !v->getValue())
1609: {
1610: if (v->init && v->type->size() != 0)
1611: {
1612: if (v->init->isVoidInitializer())
1613: {
1614: error(loc, "variable %s is used before initialization", v->toChars());
1615: return EXP_CANT_INTERPRET;
1616: }
1617: e = v->init->toExpression();
1618: e = e->interpret(istate);
1619: }
1620: else
1621: e = v->type->defaultInitLiteral(loc);
1622: }
1623: else if (!v->isDataseg() && !v->isCTFE() && !istate)
1624: { error(loc, "variable %s cannot be read at compile time", v->toChars());
1625: return EXP_CANT_INTERPRET;
1626: }
1627: else
1628: { e = v->getValue();
1629: if (!e && !v->isCTFE() && v->isDataseg())
1630: { error(loc, "static variable %s cannot be read at compile time", v->toChars());
1631: e = EXP_CANT_INTERPRET;
1632: }
1633: else if (!e)
1634: error(loc, "variable %s is used before initialization", v->toChars());
1635: else if (e == EXP_CANT_INTERPRET)
1636: return e;
1637: else if ((goal == ctfeNeedLvalue)
1638: || e->op == TOKstring || e->op == TOKstructliteral || e->op == TOKarrayliteral
1639: || e->op == TOKassocarrayliteral || e->op == TOKslice
1640: || e->type->toBasetype()->ty == Tpointer)
1641: return e; // it's already an Lvalue
1642: else
1643: e = e->interpret(istate, goal);
1644: }
1645: if (!e)
1646: e = EXP_CANT_INTERPRET;
1647: }
1648: else if (s)
1649: { // Struct static initializers, for example
1650: if (s->dsym->toInitializer() == s->sym)
1651: { Expressions *exps = new Expressions();
1652: e = new StructLiteralExp(loc, s->dsym, exps);
1653: e = e->semantic(NULL);
1654: if (e->op == TOKerror)
1655: e = EXP_CANT_INTERPRET;
1656: }
1657: else
1658: error(loc, "cannot interpret symbol %s at compile time", v->toChars());
1659: }
1660: else
1661: error(loc, "cannot interpret variable %s at compile time", v->toChars());
1662: return e;
1663: }
1664:
1665: Expression *VarExp::interpret(InterState *istate, CtfeGoal goal)
1666: {
1667: #if LOG
1668: printf("VarExp::interpret() %s\n", toChars());
1669: #endif
1670: if (goal == ctfeNeedLvalueRef)
1671: {
1672: // If it is a reference, return the thing it's pointing to.
1673: VarDeclaration *v = var->isVarDeclaration();
1674: if (v && v->getValue() && (v->storage_class & (STCref | STCout)))
1675: return v->getValue();
1676: if (v && !v->isDataseg() && !v->isCTFE() && !istate)
1677: { error("variable %s cannot be referenced at compile time", v->toChars());
1678: return EXP_CANT_INTERPRET;
1679: }
1680: else if (v && !v->getValue() && !v->isCTFE() && v->isDataseg())
1681: { error("static variable %s cannot be referenced at compile time", v->toChars());
1682: return EXP_CANT_INTERPRET;
1683: }
1684: return this;
1685: }
1686: Expression *e = getVarExp(loc, istate, var, goal);
1687: // A VarExp may include an implicit cast. It must be done explicitly.
1688: if (e != EXP_CANT_INTERPRET)
1689: e = paintTypeOntoLiteral(type, e);
1690: return e;
1691: }
1692:
1693: Expression *DeclarationExp::interpret(InterState *istate, CtfeGoal goal)
1694: {
1695: #if LOG
1696: printf("DeclarationExp::interpret() %s\n", toChars());
1697: #endif
1698: Expression *e;
1699: VarDeclaration *v = declaration->isVarDeclaration();
1700: if (v)
1701: {
1702: if (v->getValue())
1703: {
1704: addVarToInterstate(istate, v);
1705: v->setValueNull();
1706: }
1707: Dsymbol *s = v->toAlias();
1708: if (s == v && !v->isStatic() && v->init)
1709: {
1710: ExpInitializer *ie = v->init->isExpInitializer();
1711: if (ie)
1712: e = ie->exp->interpret(istate);
1713: else if (v->init->isVoidInitializer())
1714: e = NULL;
1715: else
1716: {
1717: error("Declaration %s is not yet implemented in CTFE", toChars());
1718: e = EXP_CANT_INTERPRET;
1719: }
1720: }
1721: else if (s == v && !v->init && v->type->size()==0)
1722: { // Zero-length arrays don't need an initializer
1723: e = v->type->defaultInitLiteral(loc);
1724: }
1725: #if DMDV2
1726: else if (s == v && (v->isConst() || v->isImmutable()) && v->init)
1727: #else
1728: else if (s == v && v->isConst() && v->init)
1729: #endif
1730: { e = v->init->toExpression();
1731: if (!e)
1732: e = EXP_CANT_INTERPRET;
1733: else if (!e->type)
1734: e->type = v->type;
1735: }
1736: else if (s->isTupleDeclaration() && !v->init)
1737: e = NULL;
1738: else
1739: {
1740: error("Declaration %s is not yet implemented in CTFE", toChars());
1741: e = EXP_CANT_INTERPRET;
1742: }
1743: }
1744: else if (declaration->isAttribDeclaration() ||
1745: declaration->isTemplateMixin() ||
1746: declaration->isTupleDeclaration())
1747: { // These can be made to work, too lazy now
1748: error("Declaration %s is not yet implemented in CTFE", toChars());
1749: e = EXP_CANT_INTERPRET;
1750: }
1751: else
1752: { // Others should not contain executable code, so are trivial to evaluate
1753: e = NULL;
1754: }
1755: #if LOG
1756: printf("-DeclarationExp::interpret(%s): %p\n", toChars(), e);
1757: #endif
1758: return e;
1759: }
1760:
1761: Expression *TupleExp::interpret(InterState *istate, CtfeGoal goal)
1762: {
1763: #if LOG
1764: printf("TupleExp::interpret() %s\n", toChars());
1765: #endif
1766: Expressions *expsx = NULL;
1767:
1768: for (size_t i = 0; i < exps->dim; i++)
1769: { Expression *e = exps->tdata()[i];
1770: Expression *ex;
1771:
1772: ex = e->interpret(istate);
1773: if (ex == EXP_CANT_INTERPRET)
1774: { delete expsx;
1775: return ex;
1776: }
1777:
1778: // A tuple of assignments can contain void (Bug 5676).
1779: if (goal == ctfeNeedNothing)
1780: continue;
1781: if (ex == EXP_VOID_INTERPRET)
1782: {
1783: error("ICE: void element %s in tuple", e->toChars());
1784: assert(0);
1785: }
1786:
1787: /* If any changes, do Copy On Write
1788: */
1789: if (ex != e)
1790: {
1791: if (!expsx)
1792: { expsx = new Expressions();
1793: expsx->setDim(exps->dim);
1794: for (size_t j = 0; j < i; j++)
1795: {
1796: expsx->tdata()[j] = exps->tdata()[j];
1797: }
1798: }
1799: expsx->tdata()[i] = ex;
1800: }
1801: }
1802: if (expsx)
1803: { TupleExp *te = new TupleExp(loc, expsx);
warning C6211: Leaking memory 'te' due to an exception. Consider using a local catch block to clean up memory: Lines: 1766, 1768, 1769, 1770, 1772, 1773, 1779, 1781, 1789, 1791, 1792, 1793, 1794, 1799, 1768, 1769, 1770, 1772, 1773, 1779, 1781, 1789, 1791, 1799, 1768, 1802, 1803, 1804, 1805
1804: expandTuples(te->exps);
1805: te->type = new TypeTuple(te->exps);
1806: return te;
1807: }
1808: return this;
1809: }
1810:
1811: Expression *ArrayLiteralExp::interpret(InterState *istate, CtfeGoal goal)
1812: { Expressions *expsx = NULL;
1813:
1814: #if LOG
1815: printf("ArrayLiteralExp::interpret() %s\n", toChars());
1816: #endif
1817: if (elements)
1818: {
1819: for (size_t i = 0; i < elements->dim; i++)
1820: { Expression *e = elements->tdata()[i];
1821: Expression *ex;
1822:
1823: if (e->op == TOKindex) // segfault bug 6250
1824: assert( ((IndexExp*)e)->e1 != this);
1825: ex = e->interpret(istate);
1826: if (ex == EXP_CANT_INTERPRET)
1827: goto Lerror;
1828:
1829: /* If any changes, do Copy On Write
1830: */
1831: if (ex != e)
1832: {
1833: if (!expsx)
1834: { expsx = new Expressions();
1835: expsx->setDim(elements->dim);
1836: for (size_t j = 0; j < elements->dim; j++)
1837: {
1838: expsx->tdata()[j] = elements->tdata()[j];
1839: }
1840: }
1841: expsx->tdata()[i] = ex;
1842: }
1843: }
1844: }
1845: if (elements && expsx)
1846: {
1847: expandTuples(expsx);
1848: if (expsx->dim != elements->dim)
1849: goto Lerror;
1850: ArrayLiteralExp *ae = new ArrayLiteralExp(loc, expsx);
1851: ae->type = type;
1852: return ae;
1853: }
1854: #if DMDV2
1855: if (((TypeNext *)type)->next->mod & (MODconst | MODimmutable))
1856: { // If it's immutable, we don't need to dup it
1857: return this;
1858: }
1859: #endif
1860: return copyLiteral(this);
1861:
1862: Lerror:
1863: if (expsx)
1864: delete expsx;
1865: error("cannot interpret array literal");
1866: return EXP_CANT_INTERPRET;
1867: }
1868:
1869: Expression *AssocArrayLiteralExp::interpret(InterState *istate, CtfeGoal goal)
1870: { Expressions *keysx = keys;
1871: Expressions *valuesx = values;
1872:
1873: #if LOG
1874: printf("AssocArrayLiteralExp::interpret() %s\n", toChars());
1875: #endif
1876: for (size_t i = 0; i < keys->dim; i++)
1877: { Expression *ekey = keys->tdata()[i];
1878: Expression *evalue = values->tdata()[i];
1879: Expression *ex;
1880:
1881: ex = ekey->interpret(istate);
1882: if (ex == EXP_CANT_INTERPRET)
1883: goto Lerr;
1884:
1885: /* If any changes, do Copy On Write
1886: */
1887: if (ex != ekey)
1888: {
1889: if (keysx == keys)
1890: keysx = (Expressions *)keys->copy();
1891: keysx->tdata()[i] = ex;
1892: }
1893:
1894: ex = evalue->interpret(istate);
1895: if (ex == EXP_CANT_INTERPRET)
1896: goto Lerr;
1897:
1898: /* If any changes, do Copy On Write
1899: */
1900: if (ex != evalue)
1901: {
1902: if (valuesx == values)
1903: valuesx = (Expressions *)values->copy();
1904: valuesx->tdata()[i] = ex;
1905: }
1906: }
1907: if (keysx != keys)
1908: expandTuples(keysx);
1909: if (valuesx != values)
1910: expandTuples(valuesx);
1911: if (keysx->dim != valuesx->dim)
1912: goto Lerr;
1913:
1914: /* Remove duplicate keys
1915: */
1916: for (size_t i = 1; i < keysx->dim; i++)
1917: { Expression *ekey = keysx->tdata()[i - 1];
1918: if (ekey->op == TOKslice)
1919: ekey = resolveSlice(ekey);
1920: for (size_t j = i; j < keysx->dim; j++)
1921: { Expression *ekey2 = keysx->tdata()[j];
1922: Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, ekey2);
1923: if (ex == EXP_CANT_INTERPRET)
1924: goto Lerr;
1925: if (ex->isBool(TRUE)) // if a match
1926: {
1927: // Remove ekey
1928: if (keysx == keys)
1929: keysx = (Expressions *)keys->copy();
1930: if (valuesx == values)
1931: valuesx = (Expressions *)values->copy();
1932: keysx->remove(i - 1);
1933: valuesx->remove(i - 1);
1934: i -= 1; // redo the i'th iteration
1935: break;
1936: }
1937: }
1938: }
1939:
1940: if (keysx != keys || valuesx != values)
1941: {
1942: AssocArrayLiteralExp *ae;
1943: ae = new AssocArrayLiteralExp(loc, keysx, valuesx);
1944: ae->type = type;
1945: return ae;
1946: }
1947: return this;
1948:
1949: Lerr:
1950: if (keysx != keys)
1951: delete keysx;
1952: if (valuesx != values)
1953: delete values;
1954: return EXP_CANT_INTERPRET;
1955: }
1956:
1957: Expression *StructLiteralExp::interpret(InterState *istate, CtfeGoal goal)
1958: { Expressions *expsx = NULL;
1959:
1960: #if LOG
1961: printf("StructLiteralExp::interpret() %s\n", toChars());
1962: #endif
1963: /* We don't know how to deal with overlapping fields
1964: */
1965: if (sd->hasUnions)
1966: { error("Unions with overlapping fields are not yet supported in CTFE");
1967: return EXP_CANT_INTERPRET;
1968: }
1969:
1970: if (elements)
1971: {
1972: for (size_t i = 0; i < elements->dim; i++)
1973: { Expression *e = elements->tdata()[i];
1974: if (!e)
1975: continue;
1976:
1977: Expression *ex = e->interpret(istate);
1978: if (ex == EXP_CANT_INTERPRET)
1979: { delete expsx;
1980: return EXP_CANT_INTERPRET;
1981: }
1982:
1983: /* If any changes, do Copy On Write
1984: */
1985: if (ex != e)
1986: {
1987: if (!expsx)
1988: { expsx = new Expressions();
1989: expsx->setDim(elements->dim);
1990: for (size_t j = 0; j < elements->dim; j++)
1991: {
1992: expsx->tdata()[j] = elements->tdata()[j];
1993: }
1994: }
1995: expsx->tdata()[i] = ex;
1996: }
1997: }
1998: }
1999: if (elements && expsx)
2000: {
2001: expandTuples(expsx);
2002: if (expsx->dim != elements->dim)
2003: { delete expsx;
2004: return EXP_CANT_INTERPRET;
2005: }
2006: StructLiteralExp *se = new StructLiteralExp(loc, sd, expsx);
2007: se->type = type;
2008: return se;
2009: }
2010: return copyLiteral(this);
2011: }
2012:
2013: /******************************
2014: * Helper for NewExp
2015: * Create an array literal consisting of 'elem' duplicated 'dim' times.
2016: */
2017: ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Type *type,
2018: Expression *elem, size_t dim)
2019: {
2020: Expressions *elements = new Expressions();
2021: elements->setDim(dim);
2022: for (size_t i = 0; i < dim; i++)
2023: elements->tdata()[i] = elem;
2024: ArrayLiteralExp *ae = new ArrayLiteralExp(0, elements);
2025: ae->type = type;
2026: return ae;
2027: }
2028:
2029: /******************************
2030: * Helper for NewExp
2031: * Create a string literal consisting of 'value' duplicated 'dim' times.
2032: */
2033: StringExp *createBlockDuplicatedStringLiteral(Type *type,
2034: unsigned value, size_t dim, int sz)
2035: {
2036: unsigned char *s;
2037: s = (unsigned char *)mem.calloc(dim + 1, sz);
2038: for (int elemi=0; elemi<dim; ++elemi)
warning C4018: '<' : signed/unsigned mismatch
2039: {
2040: switch (sz)
2041: {
2042: case 1: s[elemi] = value; break;
2043: case 2: ((unsigned short *)s)[elemi] = value; break;
2044: case 4: ((unsigned *)s)[elemi] = value; break;
2045: default: assert(0);
2046: }
2047: }
2048: StringExp *se = new StringExp(0, s, dim);
2049: se->type = type;
2050: return se;
2051: }
2052:
2053: Expression *NewExp::interpret(InterState *istate, CtfeGoal goal)
2054: {
2055: #if LOG
2056: printf("NewExp::interpret() %s\n", toChars());
2057: #endif
2058: if (newtype->ty == Tarray && arguments && arguments->dim == 1)
2059: {
2060: Expression *lenExpr = ((arguments->tdata()[0]))->interpret(istate);
2061: if (lenExpr == EXP_CANT_INTERPRET)
2062: return EXP_CANT_INTERPRET;
2063: return createBlockDuplicatedArrayLiteral(newtype,
2064: ((TypeArray *)newtype)->next->defaultInitLiteral(),
2065: lenExpr->toInteger());
warning C4244: 'argument' : conversion from 'dinteger_t' to 'size_t', possible loss of data
2066: }
2067: if (newtype->toBasetype()->ty == Tstruct)
2068: {
2069: Expression *se = newtype->defaultInitLiteral();
2070: #if DMDV2
2071: if (member)
2072: {
2073: int olderrors = global.errors;
2074: member->interpret(istate, arguments, se);
2075: if (olderrors != global.errors)
2076: {
2077: error("cannot evaluate %s at compile time", toChars());
2078: return EXP_CANT_INTERPRET;
2079: }
2080: }
2081: #else // The above code would fail on D1 because it doesn't use STRUCTTHISREF,
2082: // but that's OK because D1 doesn't have struct constructors anyway.
2083: assert(!member);
2084: #endif
2085: Expression *e = new AddrExp(loc, se);
2086: e->type = type;
2087: return e;
2088: }
2089: if (newtype->ty == Tclass)
2090: {
2091: error("classes are not yet supported in CTFE");
2092: return EXP_CANT_INTERPRET;
2093: }
2094: error("Cannot interpret %s at compile time", toChars());
2095: return EXP_CANT_INTERPRET;
2096: }
2097:
2098: Expression *UnaExp::interpretCommon(InterState *istate, CtfeGoal goal, Expression *(*fp)(Type *, Expression *))
2099: { Expression *e;
2100: Expression *e1;
2101:
2102: #if LOG
2103: printf("UnaExp::interpretCommon() %s\n", toChars());
2104: #endif
2105: e1 = this->e1->interpret(istate);
2106: if (e1 == EXP_CANT_INTERPRET)
2107: goto Lcant;
2108: e = (*fp)(type, e1);
2109: return e;
2110:
2111: Lcant:
2112: return EXP_CANT_INTERPRET;
2113: }
2114:
2115: #define UNA_INTERPRET(op) \
2116: Expression *op##Exp::interpret(InterState *istate, CtfeGoal goal) \
2117: { \
2118: return interpretCommon(istate, goal, &op); \
2119: }
2120:
2121: UNA_INTERPRET(Neg)
2122: UNA_INTERPRET(Com)
2123: UNA_INTERPRET(Not)
2124: UNA_INTERPRET(Bool)
2125:
2126: Expression *getAggregateFromPointer(Expression *e, dinteger_t *ofs)
2127: {
2128: *ofs = 0;
2129: if (e->op == TOKaddress)
2130: e = ((AddrExp *)e)->e1;
2131: if (e->op == TOKindex)
2132: {
2133: IndexExp *ie = (IndexExp *)e;
2134: // Note that each AA element is part of its own memory block
2135: if ((ie->e1->type->ty == Tarray || ie->e1->type->ty == Tsarray
2136: || ie->e1->op == TOKstring || ie->e1->op==TOKarrayliteral) &&
2137: ie->e2->op == TOKint64)
2138: {
2139: *ofs = ie->e2->toInteger();
2140: return ie->e1;
2141: }
2142: }
2143: return e;
2144: }
2145:
2146: // return e1 - e2 as an integer, or error if not possible
2147: Expression *pointerDifference(Loc loc, Type *type, Expression *e1, Expression *e2)
2148: {
2149: dinteger_t ofs1, ofs2;
2150: Expression *agg1 = getAggregateFromPointer(e1, &ofs1);
2151: Expression *agg2 = getAggregateFromPointer(e2, &ofs2);
2152: if (agg1 == agg2)
2153: {
2154: Type *pointee = ((TypePointer *)agg1->type)->next;
2155: dinteger_t sz = pointee->size();
2156: return new IntegerExp(loc, (ofs1-ofs2)*sz, type);
2157: }
2158: else if (agg1->op == TOKstring && agg2->op == TOKstring)
2159: {
2160: if (((StringExp *)agg1)->string == ((StringExp *)agg2)->string)
2161: {
2162: Type *pointee = ((TypePointer *)agg1->type)->next;
2163: dinteger_t sz = pointee->size();
2164: return new IntegerExp(loc, (ofs1-ofs2)*sz, type);
2165: }
2166: }
2167: #if LOGASSIGN
2168: printf("FAILED POINTER DIFF\n");
2169: showCtfeExpr(agg1);
2170: showCtfeExpr(agg2);
2171: #endif
2172: error(loc, "%s - %s cannot be interpreted at compile time: cannot subtract "
2173: "pointers to two different memory blocks",
2174: e1->toChars(), e2->toChars());
2175: return EXP_CANT_INTERPRET;
2176: }
2177:
2178: // Return eptr op e2, where eptr is a pointer, e2 is an integer,
2179: // and op is TOKadd or TOKmin
2180: Expression *pointerArithmetic(Loc loc, enum TOK op, Type *type,
2181: Expression *eptr, Expression *e2)
2182: {
2183: dinteger_t ofs1, ofs2;
2184: if (eptr->op == TOKaddress)
2185: eptr = ((AddrExp *)eptr)->e1;
2186: Expression *agg1 = getAggregateFromPointer(eptr, &ofs1);
2187: if (agg1->op != TOKstring && agg1->op != TOKarrayliteral)
2188: {
2189: error(loc, "cannot perform pointer arithmetic on non-arrays at compile time");
2190: return EXP_CANT_INTERPRET;
2191: }
2192: ofs2 = e2->toInteger();
2193: Type *pointee = ((TypePointer *)agg1->type)->next;
2194: dinteger_t sz = pointee->size();
2195: Expression *dollar = ArrayLength(Type::tsize_t, agg1);
2196: assert(dollar != EXP_CANT_INTERPRET);
2197: dinteger_t len = dollar->toInteger();
2198:
2199: Expression *val = agg1;
2200: TypeArray *tar = (TypeArray *)val->type;
2201: dinteger_t indx = ofs1;
2202: if (op == TOKadd || op == TOKaddass)
2203: indx = indx + ofs2/sz;
2204: else if (op == TOKmin || op == TOKminass)
2205: indx -= ofs2/sz;
2206: else
2207: error(loc, "CTFE Internal compiler error: bad pointer operation");
2208: if (val->op != TOKarrayliteral && val->op != TOKstring)
2209: {
2210: error(loc, "CTFE Internal compiler error: pointer arithmetic %s", val->toChars());
2211: return EXP_CANT_INTERPRET;
2212: }
2213: if (indx < 0 || indx > len)
2214: {
2215: error(loc, "cannot assign pointer to index %jd inside memory block [0..%jd]", indx, len);
2216: return EXP_CANT_INTERPRET;
2217: }
2218:
2219: IntegerExp *ofs = new IntegerExp(loc, indx, Type::tsize_t);
2220: IndexExp *ie = new IndexExp(loc, val, ofs);
2221: ie->type = type;
2222: return ie;
2223: }
2224:
2225: typedef Expression *(*fp_t)(Type *, Expression *, Expression *);
2226:
2227: Expression *BinExp::interpretCommon(InterState *istate, CtfeGoal goal, fp_t fp)
2228: { Expression *e;
2229: Expression *e1;
2230: Expression *e2;
2231:
2232: #if LOG
2233: printf("BinExp::interpretCommon() %s\n", toChars());
2234: #endif
2235: if (this->e1->type->ty == Tpointer && this->e2->type->ty == Tpointer && op == TOKmin)
2236: {
2237: e1 = this->e1->interpret(istate, ctfeNeedLvalue);
2238: e2 = this->e2->interpret(istate, ctfeNeedLvalue);
2239: return pointerDifference(loc, type, e1, e2);
2240: }
2241: if (this->e1->type->ty == Tpointer && this->e2->type->isintegral())
2242: {
2243: e1 = this->e1->interpret(istate, ctfeNeedLvalue);
2244: e2 = this->e2->interpret(istate);
2245: if (e1 == EXP_CANT_INTERPRET || e2 == EXP_CANT_INTERPRET)
2246: return EXP_CANT_INTERPRET;
2247: return pointerArithmetic(loc, op, type, e1, e2);
2248: }
2249: if (this->e2->type->ty == Tpointer && this->e1->type->ty == TOKint64 && op==TOKadd)
2250: {
2251: e2 = this->e2->interpret(istate, ctfeNeedLvalue);
2252: e1 = this->e1->interpret(istate);
2253: return pointerArithmetic(loc, op, type, e2, e1);
2254: }
2255: if (this->e1->type->ty == Tpointer || this->e2->type->ty == Tpointer)
2256: {
2257: error("pointer expression %s cannot be interpreted at compile time", toChars());
2258: return EXP_CANT_INTERPRET;
2259: }
2260: e1 = this->e1->interpret(istate);
2261: if (e1 == EXP_CANT_INTERPRET)
2262: goto Lcant;
2263: if (e1->isConst() != 1)
2264: goto Lcant;
2265:
2266: e2 = this->e2->interpret(istate);
2267: if (e2 == EXP_CANT_INTERPRET)
2268: goto Lcant;
2269: if (e2->isConst() != 1)
2270: goto Lcant;
2271:
2272: e = (*fp)(type, e1, e2);
2273: if (e == EXP_CANT_INTERPRET)
2274: error("%s cannot be interpreted at compile time", toChars());
2275: return e;
2276:
2277: Lcant:
2278: return EXP_CANT_INTERPRET;
2279: }
2280:
2281: #define BIN_INTERPRET(op) \
2282: Expression *op##Exp::interpret(InterState *istate, CtfeGoal goal) \
2283: { \
2284: return interpretCommon(istate, goal, &op); \
2285: }
2286:
2287: BIN_INTERPRET(Add)
2288: BIN_INTERPRET(Min)
2289: BIN_INTERPRET(Mul)
2290: BIN_INTERPRET(Div)
2291: BIN_INTERPRET(Mod)
2292: BIN_INTERPRET(Shl)
2293: BIN_INTERPRET(Shr)
2294: BIN_INTERPRET(Ushr)
2295: BIN_INTERPRET(And)
2296: BIN_INTERPRET(Or)
2297: BIN_INTERPRET(Xor)
2298:
2299:
2300: typedef Expression *(*fp2_t)(enum TOK, Type *, Expression *, Expression *);
2301:
2302: // Return EXP_CANT_INTERPRET if they point to independent memory blocks
2303: Expression *comparePointers(Loc loc, enum TOK op, Type *type, Expression *e1, Expression *e2)
2304: {
2305: dinteger_t ofs1, ofs2;
2306: Expression *agg1 = getAggregateFromPointer(e1, &ofs1);
2307: Expression *agg2 = getAggregateFromPointer(e2, &ofs2);
2308: if (agg1 == agg2 ||
2309: (agg1->op == TOKstring && agg2->op == TOKstring &&
2310: ((StringExp *)agg1)->string == ((StringExp *)agg2)->string))
2311:
2312: {
2313: dinteger_t cm = ofs1 - ofs2;
2314: dinteger_t n;
2315: dinteger_t zero = 0;
2316: switch(op)
2317: {
2318: case TOKlt: n = (ofs1 < ofs2); break;
2319: case TOKle: n = (ofs1 <= ofs2); break;
2320: case TOKgt: n = (ofs1 > ofs2); break;
2321: case TOKge: n = (ofs1 >= ofs2); break;
2322: case TOKidentity:
2323: case TOKequal: n = (ofs1 == ofs2); break;
2324: case TOKnotidentity:
2325: case TOKnotequal: n = (ofs1 != ofs2); break;
2326: default:
2327: assert(0);
2328: }
2329: return new IntegerExp(loc, n, type);
2330: }
2331: int cmp;
2332: if (e1->op == TOKnull)
2333: {
2334: cmp = (e2->op == TOKnull);
2335: }
2336: else if (e2->op == TOKnull)
2337: {
2338: cmp = 0;
2339: }
2340: else
2341: {
2342: switch(op)
2343: {
2344: case TOKidentity:
2345: case TOKequal:
2346: case TOKnotidentity: // 'cmp' gets inverted below
2347: case TOKnotequal:
2348: cmp = 0;
2349: break;
2350: default:
2351: return EXP_CANT_INTERPRET;
2352: }
2353: }
2354: if (op == TOKnotidentity || op == TOKnotequal)
2355: cmp ^= 1;
2356: return new IntegerExp(loc, cmp, type);
2357: }
2358:
2359: Expression *BinExp::interpretCommon2(InterState *istate, CtfeGoal goal, fp2_t fp)
2360: { Expression *e;
2361: Expression *e1;
2362: Expression *e2;
2363:
2364: #if LOG
2365: printf("BinExp::interpretCommon2() %s\n", toChars());
2366: #endif
2367: if (this->e1->type->ty == Tpointer && this->e2->type->ty == Tpointer)
2368: {
2369: e1 = this->e1->interpret(istate, ctfeNeedLvalue);
2370: e2 = this->e2->interpret(istate, ctfeNeedLvalue);
2371: e = comparePointers(loc, op, type, e1, e2);
2372: if (e == EXP_CANT_INTERPRET)
2373: {
2374: error("%s and %s point to independent memory blocks and "
2375: "cannot be compared at compile time", this->e1->toChars(),
2376: this->e2->toChars());
2377: }
2378: return e;
2379: }
2380: e1 = this->e1->interpret(istate);
2381: if (e1 == EXP_CANT_INTERPRET)
2382: goto Lcant;
2383: if (e1->op == TOKslice)
2384: e1 = resolveSlice(e1);
2385:
2386: if (e1->isConst() != 1 &&
2387: e1->op != TOKnull &&
2388: e1->op != TOKstring &&
2389: e1->op != TOKarrayliteral &&
2390: e1->op != TOKstructliteral)
2391: {
2392: error("cannot compare %s at compile time", e1->toChars());
2393: goto Lcant;
2394: }
2395:
2396: e2 = this->e2->interpret(istate);
2397: if (e2 == EXP_CANT_INTERPRET)
2398: goto Lcant;
2399: if (e2->op == TOKslice)
2400: e2 = resolveSlice(e2);
2401: if (e2->isConst() != 1 &&
2402: e2->op != TOKnull &&
2403: e2->op != TOKstring &&
2404: e2->op != TOKarrayliteral &&
2405: e2->op != TOKstructliteral)
2406: {
2407: error("cannot compare %s at compile time", e2->toChars());
2408: goto Lcant;
2409: }
2410: e = (*fp)(op, type, e1, e2);
2411: if (e == EXP_CANT_INTERPRET)
2412: error("%s cannot be interpreted at compile time", toChars());
2413: return e;
2414:
2415: Lcant:
2416: return EXP_CANT_INTERPRET;
2417: }
2418:
2419: #define BIN_INTERPRET2(op) \
2420: Expression *op##Exp::interpret(InterState *istate, CtfeGoal goal) \
2421: { \
2422: return interpretCommon2(istate, goal, &op); \
2423: }
2424:
2425: BIN_INTERPRET2(Equal)
2426: BIN_INTERPRET2(Identity)
2427: BIN_INTERPRET2(Cmp)
2428:
2429: /* Helper functions for BinExp::interpretAssignCommon
2430: */
2431:
2432: /***************************************
2433: * Duplicate the elements array, then set field 'indexToChange' = newelem.
2434: */
2435: Expressions *changeOneElement(Expressions *oldelems, size_t indexToChange, Expression *newelem)
2436: {
2437: Expressions *expsx = new Expressions();
2438: expsx->setDim(oldelems->dim);
2439: for (size_t j = 0; j < expsx->dim; j++)
2440: {
2441: if (j == indexToChange)
2442: expsx->tdata()[j] = newelem;
2443: else
2444: expsx->tdata()[j] = oldelems->tdata()[j];
2445: }
2446: return expsx;
2447: }
2448:
2449: /********************************
2450: * Add v to the istate list, unless it already exists there.
2451: */
2452: void addVarToInterstate(InterState *istate, VarDeclaration *v)
2453: {
2454: if (!v->isParameter())
2455: {
2456: for (size_t i = 0; 1; i++)
2457: {
2458: if (i == istate->vars.dim)
2459: { istate->vars.push(v);
2460: //printf("\tadding %s to istate\n", v->toChars());
2461: break;
2462: }
2463: if (v == istate->vars.tdata()[i])
2464: break;
2465: }
2466: }
2467: }
2468:
2469: // Create a new struct literal, which is the same as se except that se.field[offset] = elem
2470: Expression * modifyStructField(Type *type, StructLiteralExp *se, size_t offset, Expression *newval)
2471: {
2472: int fieldi = se->getFieldIndex(newval->type, offset);
2473: if (fieldi == -1)
2474: return EXP_CANT_INTERPRET;
2475: /* Create new struct literal reflecting updated fieldi
2476: */
2477: Expressions *expsx = changeOneElement(se->elements, fieldi, newval);
2478: Expression * ee = new StructLiteralExp(se->loc, se->sd, expsx);
2479: ee->type = se->type;
2480: return ee;
2481: }
2482:
2483: /********************************
2484: * Given an array literal arr (either arrayliteral, stringliteral, or assocArrayLiteral),
2485: * set arr[index] = newval and return the new array.
2486: *
2487: */
2488: Expression *assignAssocArrayElement(Loc loc, AssocArrayLiteralExp *aae, Expression *index, Expression *newval)
2489: {
2490: /* Create new associative array literal reflecting updated key/value
2491: */
2492: Expressions *keysx = aae->keys;
2493: Expressions *valuesx = aae->values;
2494: int updated = 0;
2495: for (size_t j = valuesx->dim; j; )
2496: { j--;
2497: Expression *ekey = aae->keys->tdata()[j];
2498: Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, index);
2499: if (ex == EXP_CANT_INTERPRET)
2500: return EXP_CANT_INTERPRET;
2501: if (ex->isBool(TRUE))
2502: { valuesx->tdata()[j] = newval;
2503: updated = 1;
2504: }
2505: }
2506: if (!updated)
2507: { // Append index/newval to keysx[]/valuesx[]
2508: valuesx->push(newval);
2509: keysx->push(index);
2510: }
2511: return newval;
2512: }
2513:
2514: // Return true if e is derived from UnaryExp.
2515: // Consider moving this function into Expression.
2516: UnaExp *isUnaExp(Expression *e)
2517: {
2518: switch (e->op)
2519: {
2520: case TOKdotvar:
2521: case TOKindex:
2522: case TOKslice:
2523: case TOKcall:
2524: case TOKdot:
2525: case TOKdotti:
2526: case TOKdottype:
2527: case TOKcast:
2528: return (UnaExp *)e;
2529: default:
2530: break;
2531: }
2532: return NULL;
2533: }
2534:
2535: // Returns the variable which is eventually modified, or NULL if an rvalue.
2536: // thisval is the current value of 'this'.
2537: VarDeclaration * findParentVar(Expression *e, Expression *thisval)
2538: {
2539: for (;;)
2540: {
2541: e = resolveReferences(e, thisval);
2542: if (e->op == TOKvar)
2543: break;
2544: if (e->op == TOKindex)
2545: e = ((IndexExp*)e)->e1;
2546: else if (e->op == TOKdotvar)
2547: e = ((DotVarExp *)e)->e1;
2548: else if (e->op == TOKdotti)
2549: e = ((DotTemplateInstanceExp *)e)->e1;
2550: else if (e->op == TOKslice)
2551: e = ((SliceExp*)e)->e1;
2552: else
2553: return NULL;
2554: }
2555: VarDeclaration *v = ((VarExp *)e)->var->isVarDeclaration();
2556: assert(v);
2557: return v;
2558: }
2559:
2560: // Given expr, which evaluates to an array/AA/string literal,
2561: // return true if it needs to be copied
2562: bool needToCopyLiteral(Expression *expr)
2563: {
2564: for (;;)
2565: {
2566: switch (expr->op)
2567: {
2568: case TOKarrayliteral:
2569: case TOKassocarrayliteral:
2570: case TOKstructliteral:
2571: return true;
2572: case TOKstring:
2573: case TOKthis:
2574: case TOKvar:
2575: return false;
2576: case TOKassign:
2577: return false;
2578: case TOKindex:
2579: case TOKdotvar:
2580: case TOKslice:
2581: case TOKcast:
2582: expr = ((UnaExp *)expr)->e1;
2583: continue;
2584: case TOKcat:
2585: return needToCopyLiteral(((BinExp *)expr)->e1) ||
2586: needToCopyLiteral(((BinExp *)expr)->e2);
2587: case TOKcatass:
2588: expr = ((BinExp *)expr)->e2;
2589: continue;
2590: default:
2591: return false;
2592: }
2593: }
2594: }
2595:
2596: Expressions *copyLiteralArray(Expressions *oldelems)
2597: {
2598: if (!oldelems)
2599: return oldelems;
2600: Expressions *newelems = new Expressions();
2601: newelems->setDim(oldelems->dim);
2602: for (size_t i = 0; i < oldelems->dim; i++)
2603: newelems->tdata()[i] = copyLiteral(oldelems->tdata()[i]);
2604: return newelems;
2605: }
2606:
2607:
2608:
2609: // Make a copy of the ArrayLiteral, AALiteral, String, or StructLiteral.
2610: // This value will be used for in-place modification.
2611: Expression *copyLiteral(Expression *e)
2612: {
2613: if (e->op == TOKstring) // syntaxCopy doesn't make a copy for StringExp!
2614: {
2615: StringExp *se = (StringExp *)e;
2616: unsigned char *s;
2617: s = (unsigned char *)mem.calloc(se->len + 1, se->sz);
2618: memcpy(s, se->string, se->len * se->sz);
2619: StringExp *se2 = new StringExp(se->loc, s, se->len);
2620: se2->committed = se->committed;
2621: se2->postfix = se->postfix;
2622: se2->type = se->type;
2623: se2->sz = se->sz;
2624: return se2;
2625: }
2626: else if (e->op == TOKarrayliteral)
2627: {
2628: ArrayLiteralExp *ae = (ArrayLiteralExp *)e;
2629: ArrayLiteralExp *r = new ArrayLiteralExp(e->loc,
2630: copyLiteralArray(ae->elements));
2631: r->type = e->type;
2632: return r;
2633: }
2634: else if (e->op == TOKassocarrayliteral)
2635: {
2636: AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)e;
2637: AssocArrayLiteralExp *r = new AssocArrayLiteralExp(e->loc,
2638: copyLiteralArray(aae->keys), copyLiteralArray(aae->values));
2639: r->type = e->type;
2640: return r;
2641: }
2642: /* syntaxCopy doesn't work for struct literals, because of a nasty special
2643: * case: block assignment is permitted inside struct literals, eg,
2644: * an int[4] array can be initialized with a single int.
2645: */
2646: else if (e->op == TOKstructliteral)
2647: {
2648: StructLiteralExp *se = (StructLiteralExp *)e;
2649: Expressions *oldelems = se->elements;
2650: Expressions * newelems = new Expressions();
2651: newelems->setDim(oldelems->dim);
2652: for (size_t i = 0; i < newelems->dim; i++)
2653: {
2654: Expression *m = oldelems->tdata()[i];
2655: // We need the struct definition to detect block assignment
2656: StructDeclaration *sd = se->sd;
2657: Dsymbol *s = sd->fields.tdata()[i];
2658: VarDeclaration *v = s->isVarDeclaration();
2659: assert(v);
2660: // If it is a void assignment, use the default initializer
2661: if (!m)
2662: m = v->type->defaultInitLiteral(e->loc);
2663: if (m->op == TOKslice)
2664: m = resolveSlice(m);
2665: if ((v->type->ty != m->type->ty) && v->type->ty == Tsarray)
2666: {
2667: // Block assignment from inside struct literals
2668: TypeSArray *tsa = (TypeSArray *)v->type;
2669: uinteger_t length = tsa->dim->toInteger();
2670: m = createBlockDuplicatedArrayLiteral(v->type, m, length);
warning C4244: 'argument' : conversion from 'uinteger_t' to 'size_t', possible loss of data
2671: }
2672: else if (v->type->ty != Tarray) // NOTE: do not copy array references
2673: m = copyLiteral(m);
2674: newelems->tdata()[i] = m;
2675: }
2676: #if DMDV2
2677: StructLiteralExp *r = new StructLiteralExp(e->loc, se->sd, newelems, se->stype);
2678: #else
2679: StructLiteralExp *r = new StructLiteralExp(e->loc, se->sd, newelems);
2680: #endif
2681: r->type = e->type;
2682: return r;
2683: }
2684: else if (e->op == TOKfunction || e->op == TOKdelegate
2685: || e->op == TOKsymoff || e->op == TOKnull
2686: || e->op == TOKvar
2687: || e->op == TOKint64 || e->op == TOKfloat64
2688: || e->op == TOKchar || e->op == TOKcomplex80)
2689: { // Simple value types
2690: Expression *r = e->syntaxCopy();
2691: r->type = e->type;
2692: return r;
2693: }
2694: else if (e->type->ty == Tpointer && e->type->nextOf()->ty != Tfunction)
2695: { // For pointers, we only do a shallow copy.
2696: Expression *r;
2697: if (e->op == TOKaddress)
2698: r = new AddrExp(e->loc, ((AddrExp *)e)->e1);
2699: else if (e->op == TOKindex)
2700: r = new IndexExp(e->loc, ((IndexExp *)e)->e1, ((IndexExp *)e)->e2);
2701: else if (e->op == TOKdotvar)
2702: r = new DotVarExp(e->loc, ((DotVarExp *)e)->e1,
2703: ((DotVarExp *)e)->var
2704: #if DMDV2
2705: , ((DotVarExp *)e)->hasOverloads
2706: #endif
2707: );
2708: else
2709: assert(0);
2710: r->type = e->type;
2711: return r;
2712: }
2713: else if (e->op == TOKslice)
2714: { // Array slices only do a shallow copy
2715: Expression *r = new SliceExp(e->loc, ((SliceExp *)e)->e1,
2716: ((SliceExp *)e)->lwr, ((SliceExp *)e)->upr);
2717: r->type = e->type;
2718: return r;
2719: }
2720: else
2721: {
2722: e->error("Internal Compiler Error: CTFE literal %s", e->toChars());
2723: assert(0);
2724: return e;
2725: }
2726: }
2727:
2728: /* Deal with type painting.
2729: * Type painting is a major nuisance: we can't just set
2730: * e->type = type, because that would change the original literal.
2731: * But, we can't simply copy the literal either, because that would change
2732: * the values of any pointers.
2733: */
2734: Expression *paintTypeOntoLiteral(Type *type, Expression *lit)
2735: {
2736: if (lit->type == type)
2737: return lit;
2738: Expression *e;
2739: if (lit->op == TOKslice)
2740: {
2741: SliceExp *se = (SliceExp *)lit;
2742: e = new SliceExp(lit->loc, se->e1, se->lwr, se->upr);
2743: }
2744: else if (lit->op == TOKindex)
2745: {
2746: IndexExp *ie = (IndexExp *)lit;
2747: e = new IndexExp(lit->loc, ie->e1, ie->e2);
2748: }
2749: else if (lit->op == TOKarrayliteral)
2750: {
2751: ArrayLiteralExp *ae = (ArrayLiteralExp *)lit;
2752: e = new ArrayLiteralExp(lit->loc, ae->elements);
2753: }
2754: else if (lit->op == TOKstring)
2755: {
2756: // For strings, we need to introduce another level of indirection
2757: e = new SliceExp(lit->loc, lit,
2758: new IntegerExp(0, 0, Type::tsize_t), ArrayLength(Type::tsize_t, lit));
2759: }
2760: else if (lit->op == TOKassocarrayliteral)
2761: {
2762: AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)lit;
2763: e = new AssocArrayLiteralExp(lit->loc, aae->keys, aae->values);
2764: }
2765: else
2766: e = copyLiteral(lit);
2767: e->type = type;
2768: return e;
2769: }
2770:
2771: /* Set a slice of char array literal 'existingAE' from a string 'newval'.
2772: * existingAE[firstIndex..firstIndex+newval.length] = newval.
2773: */
2774: void sliceAssignArrayLiteralFromString(ArrayLiteralExp *existingAE, StringExp *newval, int firstIndex)
2775: {
2776: size_t newlen = newval->len;
2777: size_t sz = newval->sz;
2778: unsigned char *s = (unsigned char *)newval->string;
2779: Type *elemType = existingAE->type->nextOf();
2780: for (size_t j = 0; j < newlen; j++)
2781: {
2782: dinteger_t val;
2783: switch (sz)
2784: {
2785: case 1: val = s[j]; break;
2786: case 2: val = ((unsigned short *)s)[j]; break;
2787: case 4: val = ((unsigned *)s)[j]; break;
2788: default:
2789: assert(0);
2790: break;
2791: }
2792: existingAE->elements->tdata()[j+firstIndex]
2793: = new IntegerExp(newval->loc, val, elemType);
2794: }
2795: }
2796:
2797: /* Set a slice of string 'existingSE' from a char array literal 'newae'.
2798: * existingSE[firstIndex..firstIndex+newae.length] = newae.
2799: */
2800: void sliceAssignStringFromArrayLiteral(StringExp *existingSE, ArrayLiteralExp *newae, int firstIndex)
2801: {
2802: unsigned char *s = (unsigned char *)existingSE->string;
2803: for (size_t j = 0; j < newae->elements->dim; j++)
2804: {
2805: unsigned value = newae->elements->tdata()[j]->toInteger();
warning C4244: 'initializing' : conversion from 'dinteger_t' to 'unsigned int', possible loss of data
2806: switch (existingSE->sz)
2807: {
2808: case 1: s[j+firstIndex] = value; break;
2809: case 2: ((unsigned short *)s)[j+firstIndex] = value; break;
2810: case 4: ((unsigned *)s)[j+firstIndex] = value; break;
2811: default:
2812: assert(0);
2813: break;
2814: }
2815: }
2816: }
2817:
2818: /* Set a slice of string 'existingSE' from a string 'newstr'.
2819: * existingSE[firstIndex..firstIndex+newstr.length] = newstr.
2820: */
2821: void sliceAssignStringFromString(StringExp *existingSE, StringExp *newstr, int firstIndex)
2822: {
2823: unsigned char *s = (unsigned char *)existingSE->string;
2824: size_t sz = existingSE->sz;
2825: assert(sz == newstr->sz);
2826: memcpy(s + firstIndex * sz, newstr->string, sz * newstr->len);
2827: }
2828:
2829:
2830: /* Set dest = src, where both dest and src are container value literals
2831: * (ie, struct literals, or static arrays (can be an array literal or a string)
2832: * Assignment is recursively in-place.
2833: * Purpose: any reference to a member of 'dest' will remain valid after the
2834: * assignment.
2835: */
2836: void assignInPlace(Expression *dest, Expression *src)
2837: {
2838: assert(dest->op == TOKstructliteral || dest->op == TOKarrayliteral ||
2839: dest->op == TOKstring);
2840: Expressions *oldelems;
2841: Expressions *newelems;
2842: if (dest->op == TOKstructliteral)
2843: {
2844: assert(dest->op == src->op);
2845: oldelems = ((StructLiteralExp *)dest)->elements;
2846: newelems = ((StructLiteralExp *)src)->elements;
2847: }
2848: else if (dest->op == TOKarrayliteral && src->op==TOKarrayliteral)
2849: {
2850: oldelems = ((ArrayLiteralExp *)dest)->elements;
2851: newelems = ((ArrayLiteralExp *)src)->elements;
2852: }
2853: else if (dest->op == TOKstring && src->op == TOKstring)
2854: {
2855: sliceAssignStringFromString((StringExp *)dest, (StringExp *)src, 0);
2856: return;
2857: }
2858: else if (dest->op == TOKarrayliteral && src->op == TOKstring)
2859: {
2860: sliceAssignArrayLiteralFromString((ArrayLiteralExp *)dest, (StringExp *)src, 0);
2861: return;
2862: }
2863: else if (src->op == TOKarrayliteral && dest->op == TOKstring)
2864: {
2865: sliceAssignStringFromArrayLiteral((StringExp *)dest, (ArrayLiteralExp *)src, 0);
2866: return;
2867: }
2868: else assert(0);
2869:
2870: assert(oldelems->dim == newelems->dim);
2871:
2872: for (size_t i= 0; i < oldelems->dim; ++i)
2873: {
2874: Expression *e = newelems->tdata()[i];
2875: Expression *o = oldelems->tdata()[i];
2876: if (e->op == TOKstructliteral)
2877: {
2878: assert(o->op == e->op);
2879: assignInPlace(o, e);
2880: }
2881: else if (e->type->ty == Tsarray && o->type->ty == Tsarray)
2882: {
2883: assignInPlace(o, e);
2884: }
2885: else
2886: {
2887: oldelems->tdata()[i] = newelems->tdata()[i];
2888: }
2889: }
2890: }
2891:
2892: void recursiveBlockAssign(ArrayLiteralExp *ae, Expression *val, bool wantRef)
2893: {
2894: assert( ae->type->ty == Tsarray || ae->type->ty == Tarray);
2895: #if DMDV2
2896: Type *desttype = ((TypeArray *)ae->type)->next->castMod(0);
2897: bool directblk = (val->type->toBasetype()->castMod(0)) == desttype;
2898: #else
2899: Type *desttype = ((TypeArray *)ae->type)->next;
2900: bool directblk = (val->type->toBasetype()) == desttype;
2901: #endif
2902:
2903: bool cow = !(val->op == TOKstructliteral || val->op == TOKarrayliteral
2904: || val->op == TOKstring);
2905:
2906: for (size_t k = 0; k < ae->elements->dim; k++)
2907: {
2908: if (!directblk && ae->elements->tdata()[k]->op == TOKarrayliteral)
2909: {
2910: recursiveBlockAssign((ArrayLiteralExp *)ae->elements->tdata()[k], val, wantRef);
2911: }
2912: else
2913: {
2914: if (wantRef || cow)
2915: ae->elements->tdata()[k] = val;
2916: else
2917: assignInPlace(ae->elements->tdata()[k], val);
2918: }
2919: }
2920: }
2921:
2922:
2923: Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_t fp, int post)
2924: {
2925: #if LOG
2926: printf("BinExp::interpretAssignCommon() %s\n", toChars());
2927: #endif
2928: Expression *returnValue = EXP_CANT_INTERPRET;
2929: Expression *e1 = this->e1;
2930: if (!istate)
2931: {
2932: error("value of %s is not known at compile time", e1->toChars());
2933: return returnValue;
2934: }
2935: /* Before we begin, we need to know if this is a reference assignment
2936: * (dynamic array, AA, or class) or a value assignment.
2937: * Determining this for slice assignments are tricky: we need to know
2938: * if it is a block assignment (a[] = e) rather than a direct slice
2939: * assignment (a[] = b[]). Note that initializers of multi-dimensional
2940: * static arrays can have 2D block assignments (eg, int[7][7] x = 6;).
2941: * So we need to recurse to determine if it is a block assignment.
2942: */
2943: bool isBlockAssignment = false;
2944: if (e1->op == TOKslice)
2945: {
2946: // a[] = e can have const e. So we compare the naked types.
2947: Type *desttype = e1->type->toBasetype();
2948: #if DMDV2
2949: Type *srctype = e2->type->toBasetype()->castMod(0);
2950: #else
2951: Type *srctype = e2->type->toBasetype();
2952: #endif
2953: while ( desttype->ty == Tsarray || desttype->ty == Tarray)
2954: {
2955: desttype = ((TypeArray *)desttype)->next;
2956: #if DMDV2
2957: if (srctype == desttype->castMod(0))
2958: #else
2959: if (srctype == desttype)
2960: #endif
2961: {
2962: isBlockAssignment = true;
2963: break;
2964: }
2965: }
2966: }
2967: bool wantRef = false;
2968: if (!fp && this->e1->type->toBasetype() == this->e2->type->toBasetype() &&
2969: (e1->type->toBasetype()->ty == Tarray || e1->type->toBasetype()->ty == Taarray ||
2970: e1->type->toBasetype()->ty == Tclass)
2971: // e = *x is never a reference, because *x is always a value
2972: && this->e2->op != TOKstar
2973: )
2974: {
2975: #if DMDV2
2976: wantRef = true;
2977: #else
2978: /* D1 doesn't have const in the type system. But there is still a
2979: * vestigal const in the form of static const variables.
2980: * Problematic code like:
2981: * const int [] x = [1,2,3];
2982: * int [] y = x;
2983: * can be dealt with by making this a non-ref assign (y = x.dup).
2984: * Otherwise it's a big mess.
2985: */
2986: VarDeclaration * targetVar = findParentVar(e2, istate->localThis);
2987: if (!(targetVar && targetVar->isConst()))
2988: wantRef = true;
2989: // slice assignment of static arrays is not reference assignment
2990: if ((e1->op==TOKslice) && ((SliceExp *)e1)->e1->type->ty == Tsarray)
2991: wantRef = false;
2992: #endif
2993: }
2994: if (isBlockAssignment && (e2->type->toBasetype()->ty == Tarray || e2->type->toBasetype()->ty == Tsarray))
2995: {
2996: wantRef = true;
2997: }
2998: /* This happens inside compiler-generated foreach statements.
2999: * It's another case where we need a reference
3000: * Note that a similar case, where e2 = 'this', occurs in
3001: * construction of a struct with an invariant().
3002: */
3003: if (op==TOKconstruct && this->e1->op==TOKvar && this->e2->op != TOKthis
3004: && this->e2->op != TOKcomma
3005: && ((VarExp*)this->e1)->var->storage_class & STCref)
3006: wantRef = true;
3007:
3008: if (fp)
3009: {
3010: if (e1->op == TOKcast)
3011: { CastExp *ce = (CastExp *)e1;
3012: e1 = ce->e1;
3013: }
3014: }
3015: if (e1 == EXP_CANT_INTERPRET)
3016: return e1;
3017:
3018: // First, deal with this = e; and call() = e;
3019: if (e1->op == TOKthis)
3020: {
3021: e1 = istate->localThis;
3022: }
3023: if (e1->op == TOKcall)
3024: {
3025: bool oldWaiting = istate->awaitingLvalueReturn;
3026: istate->awaitingLvalueReturn = true;
3027: e1 = e1->interpret(istate);
3028: istate->awaitingLvalueReturn = oldWaiting;
3029: if (e1 == EXP_CANT_INTERPRET)
3030: return e1;
3031: if (e1->op == TOKarrayliteral || e1->op == TOKstring)
3032: {
3033: // f() = e2, when f returns an array, is always a slice assignment.
3034: // Convert into arr[0..arr.length] = e2
3035: e1 = new SliceExp(loc, e1,
3036: new IntegerExp(0, 0, Type::tsize_t),
3037: ArrayLength(Type::tsize_t, e1));
3038: e1->type = type;
3039: }
3040: }
3041: if (e1->op == TOKstar)
3042: {
3043: e1 = e1->interpret(istate, ctfeNeedLvalue);
3044: if (e1 == EXP_CANT_INTERPRET)
3045: return EXP_CANT_INTERPRET;
3046: }
3047:
3048: if (!(e1->op == TOKarraylength || e1->op == TOKvar || e1->op == TOKdotvar
3049: || e1->op == TOKindex || e1->op == TOKslice))
3050: printf("CTFE internal error: unsupported assignment %s\n", toChars());
3051: assert(e1->op == TOKarraylength || e1->op == TOKvar || e1->op == TOKdotvar
3052: || e1->op == TOKindex || e1->op == TOKslice);
3053:
3054: Expression * newval = NULL;
3055:
3056: if (!wantRef)
3057: { // We need to treat pointers specially, because TOKsymoff can be used to
3058: // return a value OR a pointer
3059: assert(e1);
3060: assert(e1->type);
3061: if ((e1->type->ty == Tpointer && e1->type->nextOf()->ty != Tfunction) && (e2->op == TOKsymoff || e2->op==TOKaddress || e2->op==TOKvar)) // && (e1->op==TOKaddress)) //TOKsymoff || e1->op==TOKdotvar))
3062: newval = this->e2->interpret(istate, ctfeNeedLvalue);
3063: else
3064: newval = this->e2->interpret(istate);
3065: }
3066: if (newval == EXP_CANT_INTERPRET)
3067: return newval;
3068: // ----------------------------------------------------
3069: // Deal with read-modify-write assignments.
3070: // Set 'newval' to the final assignment value
3071: // Also determine the return value (except for slice
3072: // assignments, which are more complicated)
3073: // ----------------------------------------------------
3074:
3075: if (fp || e1->op == TOKarraylength)
3076: {
3077: // If it isn't a simple assignment, we need the existing value
3078: Expression * oldval = e1->interpret(istate);
3079: if (oldval == EXP_CANT_INTERPRET)
3080: return EXP_CANT_INTERPRET;
3081: while (oldval->op == TOKvar)
3082: {
3083: oldval = resolveReferences(oldval, istate->localThis);
3084: oldval = oldval->interpret(istate);
3085: if (oldval == EXP_CANT_INTERPRET)
3086: return oldval;
3087: }
3088:
3089: if (fp)
3090: {
3091: // ~= can create new values (see bug 6052)
3092: if (op == TOKcatass)
3093: {
3094: if (needToCopyLiteral(this->e2))
3095: newval = copyLiteral(newval);
3096: if (newval->op == TOKslice)
3097: newval = resolveSlice(newval);
3098: // It becomes a reference assignment
3099: wantRef = true;
3100: }
3101: if (oldval->op == TOKslice)
3102: oldval = resolveSlice(oldval);
3103: if (this->e1->type->ty == Tpointer && this->e2->type->isintegral()
3104: && (op==TOKaddass || op == TOKminass))
3105: {
3106: oldval = this->e1->interpret(istate, ctfeNeedLvalue);
3107: newval = this->e2->interpret(istate);
3108: if (oldval == EXP_CANT_INTERPRET || newval == EXP_CANT_INTERPRET)
3109: return EXP_CANT_INTERPRET;
3110: newval = pointerArithmetic(loc, op, type, oldval, newval);
3111: }
3112: else if (this->e1->type->ty == Tpointer)
3113: {
3114: error("pointer expression %s cannot be interpreted at compile time", toChars());
3115: return EXP_CANT_INTERPRET;
3116: }
3117: else
3118: {
3119: newval = (*fp)(type, oldval, newval);
3120: }
3121: if (newval == EXP_CANT_INTERPRET)
3122: {
3123: error("Cannot interpret %s at compile time", toChars());
3124: return EXP_CANT_INTERPRET;
3125: }
3126: // Determine the return value
3127: returnValue = Cast(type, type, post ? oldval : newval);
3128: if (returnValue == EXP_CANT_INTERPRET)
3129: return returnValue;
3130: }
3131: else
3132: returnValue = newval;
3133: if (e1->op == TOKarraylength)
3134: {
3135: size_t oldlen = oldval->toInteger();
warning C4244: 'initializing' : conversion from 'dinteger_t' to 'size_t', possible loss of data
3136: size_t newlen = newval->toInteger();
warning C4244: 'initializing' : conversion from 'dinteger_t' to 'size_t', possible loss of data
3137: if (oldlen == newlen) // no change required -- we're done!
3138: return returnValue;
3139: // Now change the assignment from arr.length = n into arr = newval
3140: e1 = ((ArrayLengthExp *)e1)->e1;
3141: if (oldlen != 0)
3142: { // Get the old array literal.
3143: oldval = e1->interpret(istate);
3144: while (oldval->op == TOKvar)
3145: { oldval = resolveReferences(oldval, istate->localThis);
3146: oldval = oldval->interpret(istate);
3147: }
3148: }
3149: if (oldval->op == TOKslice)
3150: oldval = resolveSlice(oldval);
3151: Type *t = e1->type->toBasetype();
3152: if (t->ty == Tarray)
3153: {
3154: Type *elemType= NULL;
3155: elemType = ((TypeArray *)t)->next;
3156: assert(elemType);
3157: Expression *defaultElem = elemType->defaultInitLiteral();
3158:
3159: Expressions *elements = new Expressions();
3160: elements->setDim(newlen);
3161: size_t copylen = oldlen < newlen ? oldlen : newlen;
3162: if (oldlen !=0)
3163: assert(oldval->op == TOKarrayliteral);
3164: ArrayLiteralExp *ae = (ArrayLiteralExp *)oldval;
3165: for (size_t i = 0; i < copylen; i++)
3166: elements->tdata()[i] = ae->elements->tdata()[i];
3167: if (elemType->ty == Tstruct || elemType->ty == Tsarray)
3168: { /* If it is an aggregate literal representing a value type,
3169: * we need to create a unique copy for each element
3170: */
3171: for (size_t i = copylen; i < newlen; i++)
3172: elements->tdata()[i] = copyLiteral(defaultElem);
3173: }
3174: else
3175: {
3176: for (size_t i = copylen; i < newlen; i++)
3177: elements->tdata()[i] = defaultElem;
3178: }
3179: ArrayLiteralExp *aae = new ArrayLiteralExp(0, elements);
3180: aae->type = t;
3181: newval = aae;
3182: // We have changed it into a reference assignment
3183: // Note that returnValue is still the new length.
3184: wantRef = true;
3185: if (e1->op == TOKstar)
3186: { // arr.length+=n becomes (t=&arr, *(t).length=*(t).length+n);
3187: e1 = e1->interpret(istate, ctfeNeedLvalue);
3188: if (e1 == EXP_CANT_INTERPRET)
3189: return EXP_CANT_INTERPRET;
3190: }
3191: }
3192: else
3193: {
3194: error("%s is not yet supported at compile time", toChars());
3195: return EXP_CANT_INTERPRET;
3196: }
3197:
3198: }
3199: }
3200: else if (!wantRef && e1->op != TOKslice)
3201: { /* Look for special case of struct being initialized with 0.
3202: */
3203: if (type->toBasetype()->ty == Tstruct && newval->op == TOKint64)
3204: {
3205: newval = type->defaultInitLiteral(loc);
3206: }
3207: newval = Cast(type, type, newval);
3208: if (newval == EXP_CANT_INTERPRET)
3209: {
3210: error("CTFE error: cannot cast %s to type %s", this->e2->toChars(), type->toChars());
3211: return EXP_CANT_INTERPRET;
3212: }
3213: returnValue = newval;
3214: }
3215: if (newval == EXP_CANT_INTERPRET)
3216: return newval;
3217:
3218: // -------------------------------------------------
3219: // Make sure destination can be modified
3220: // -------------------------------------------------
3221: // Make sure we're not trying to modify a global or static variable
3222: // We do this by locating the ultimate parent variable which gets modified.
3223: VarDeclaration * ultimateVar = findParentVar(e1, istate->localThis);
3224: if (ultimateVar && ultimateVar->isDataseg() && !ultimateVar->isCTFE())
3225: { // Can't modify global or static data
3226: error("%s cannot be modified at compile time", ultimateVar->toChars());
3227: return EXP_CANT_INTERPRET;
3228: }
3229:
3230: // This happens inside compiler-generated foreach statements.
3231: if (op==TOKconstruct && this->e1->op==TOKvar && this->e2->op != TOKthis
3232: && this->e2->op != TOKcomma
3233: && ((VarExp*)this->e1)->var->storage_class & STCref)
3234: {
3235: VarDeclaration *v = ((VarExp *)e1)->var->isVarDeclaration();
3236: v->setValueNull();
3237: v->createStackValue(e2);
3238: #if (LOGASSIGN)
3239: printf("FOREACH ASSIGN %s=%s\n", v->toChars(), e2->toChars());
3240: #endif
3241: return e2;
3242: }
3243:
3244: bool destinationIsReference = false;
3245: e1 = resolveReferences(e1, istate->localThis, &destinationIsReference);
3246:
3247: // Unless we have a simple var assignment, we're
3248: // only modifying part of the variable. So we need to make sure
3249: // that the parent variable exists.
3250: if (e1->op != TOKvar && ultimateVar && !ultimateVar->getValue())
3251: ultimateVar->createRefValue(copyLiteral(ultimateVar->type->defaultInitLiteral()));
3252:
3253: // ---------------------------------------
3254: // Deal with reference assignment
3255: // (We already have 'newval' for arraylength operations)
3256: // ---------------------------------------
3257: if (wantRef && !fp && this->e1->op != TOKarraylength)
3258: {
3259: newval = this->e2->interpret(istate, ctfeNeedLvalue);
3260: if (newval == EXP_CANT_INTERPRET)
3261: return newval;
3262: // If it is an assignment from a array function parameter passed by
3263: // reference, resolve the reference. (This should NOT happen for
3264: // non-reference types).
3265: if (newval->op == TOKvar && (newval->type->ty == Tarray ||
3266: newval->type->ty == Tclass))
3267: {
3268: newval = newval->interpret(istate);
3269: }
3270:
3271: if (newval->op == TOKassocarrayliteral || newval->op == TOKstring ||
3272: newval->op==TOKarrayliteral)
3273: {
3274: if (needToCopyLiteral(this->e2))
3275: newval = copyLiteral(newval);
3276: }
3277: returnValue = newval;
3278: }
3279:
3280: // ---------------------------------------
3281: // Deal with dotvar expressions
3282: // ---------------------------------------
3283: // Because structs are not reference types, dotvar expressions can be
3284: // collapsed into a single assignment.
3285: if (!wantRef && e1->op == TOKdotvar)
3286: {
3287: // Strip of all of the leading dotvars, unless we started with a call
3288: // (in which case, we already have the lvalue).
3289: if (this->e1->op != TOKcall)
3290: e1 = e1->interpret(istate, ctfeNeedLvalue);
3291: if (e1 == EXP_CANT_INTERPRET)
3292: return e1;
3293: if (e1->op == TOKstructliteral && newval->op == TOKstructliteral)
3294: {
3295: assignInPlace(e1, newval);
3296: return returnValue;
3297: }
3298: }
3299: #if LOGASSIGN
3300: if (wantRef)
3301: printf("REF ASSIGN: %s=%s\n", e1->toChars(), newval->toChars());
3302: else
3303: printf("ASSIGN: %s=%s\n", e1->toChars(), newval->toChars());
3304: showCtfeExpr(newval);
3305: #endif
3306:
3307: /* Assignment to variable of the form:
3308: * v = newval
3309: */
3310: if (e1->op == TOKvar)
3311: {
3312: VarExp *ve = (VarExp *)e1;
3313: VarDeclaration *v = ve->var->isVarDeclaration();
3314: if (!destinationIsReference)
3315: addVarToInterstate(istate, v);
3316: if (wantRef)
3317: {
3318: v->setValueNull();
3319: v->createRefValue(newval);
3320: }
3321: else if (e1->type->toBasetype()->ty == Tstruct)
3322: {
3323: // In-place modification
3324: if (newval->op != TOKstructliteral)
3325: {
3326: error("CTFE internal error assigning struct");
3327: return EXP_CANT_INTERPRET;
3328: }
3329: newval = copyLiteral(newval);
3330: if (v->getValue())
3331: assignInPlace(v->getValue(), newval);
3332: else
3333: v->createRefValue(newval);
3334: }
3335: else
3336: {
3337: if (e1->type->toBasetype()->ty == Tarray || e1->type->toBasetype()->ty == Taarray)
3338: { // arr op= arr
3339: if (!v->getValue())
3340: v->createRefValue(newval);
3341: else v->setRefValue(newval);
3342: }
3343: else
3344: {
3345: if (!v->getValue()) // creating a new value
3346: v->createStackValue(newval);
3347: else
3348: v->setStackValue(newval);
3349: }
3350: }
3351: }
3352: else if (e1->op == TOKdotvar)
3353: {
3354: /* Assignment to member variable of the form:
3355: * e.v = newval
3356: */
3357: Expression *exx = ((DotVarExp *)e1)->e1;
3358: if (wantRef && exx->op != TOKstructliteral)
3359: {
3360: exx = exx->interpret(istate);
3361: if (exx == EXP_CANT_INTERPRET)
3362: return exx;
3363: }
3364: if (exx->op != TOKstructliteral)
3365: {
3366: error("CTFE internal error: Dotvar assignment");
3367: return EXP_CANT_INTERPRET;
3368: }
3369: StructLiteralExp *se = (StructLiteralExp *)exx;
3370: VarDeclaration *member = ((DotVarExp *)e1)->var->isVarDeclaration();
3371: if (!member)
3372: {
3373: error("CTFE internal error: Dotvar assignment");
3374: return EXP_CANT_INTERPRET;
3375: }
3376: int fieldi = se->getFieldIndex(member->type, member->offset);
3377: if (fieldi == -1)
3378: return EXP_CANT_INTERPRET;
3379: assert(fieldi>=0 && fieldi < se->elements->dim);
warning C4018: '<' : signed/unsigned mismatch
3380: if (newval->op == TOKstructliteral)
3381: assignInPlace(se->elements->tdata()[fieldi], newval);
3382: else
3383: se->elements->tdata()[fieldi] = newval;
3384: if (ultimateVar && !destinationIsReference)
3385: addVarToInterstate(istate, ultimateVar);
3386: return returnValue;
3387: }
3388: else if (e1->op == TOKindex)
3389: {
3390: /* Assignment to array element of the form:
3391: * aggregate[i] = newval
3392: */
3393: IndexExp *ie = (IndexExp *)e1;
3394: uinteger_t destarraylen = 0; // not for AAs
3395:
3396: // Set the $ variable, and find the array literal to modify
3397: if (ie->e1->type->toBasetype()->ty != Taarray && ie->e1->type->toBasetype()->ty != Tpointer)
3398: {
3399: Expression *oldval = ie->e1->interpret(istate);
3400: if (oldval->op == TOKnull)
3401: {
3402: error("cannot index null array %s", ie->e1->toChars());
3403: return EXP_CANT_INTERPRET;
3404: }
3405: if (oldval->op != TOKarrayliteral && oldval->op != TOKstring
3406: && oldval->op != TOKslice)
3407: {
3408: error("cannot determine length of %s at compile time",
3409: ie->e1->toChars());
3410: return EXP_CANT_INTERPRET;
3411: }
3412: destarraylen = resolveArrayLength(oldval);
3413: if (ie->lengthVar)
3414: {
3415: IntegerExp *dollarExp = new IntegerExp(loc, destarraylen, Type::tsize_t);
3416: ie->lengthVar->createStackValue(dollarExp);
3417: }
3418: }
3419: Expression *index = ie->e2->interpret(istate);
3420: if (ie->lengthVar)
3421: ie->lengthVar->setValueNull(); // $ is defined only inside []
3422: if (index == EXP_CANT_INTERPRET)
3423: return EXP_CANT_INTERPRET;
3424:
3425: if (index->op == TOKslice) // only happens with AA assignment
3426: index = resolveSlice(index);
3427:
3428: ArrayLiteralExp *existingAE = NULL;
3429: StringExp *existingSE = NULL;
3430: AssocArrayLiteralExp *existingAA = NULL;
3431:
3432: Expression *aggregate = resolveReferences(ie->e1, istate->localThis);
3433:
3434: // Set the index to modify (for non-AAs), and check that it is in range
3435: int indexToModify = 0;
3436: if (ie->e1->type->toBasetype()->ty != Taarray)
3437: {
3438: indexToModify = index->toInteger();
warning C4244: '=' : conversion from 'dinteger_t' to 'int', possible loss of data
3439: if (ie->e1->type->toBasetype()->ty == Tpointer)
3440: {
3441: dinteger_t ofs;
3442: aggregate = aggregate->interpret(istate, ctfeNeedLvalue);
3443: if (aggregate == EXP_CANT_INTERPRET)
3444: return EXP_CANT_INTERPRET;
3445: if (aggregate->op == TOKnull)
3446: {
3447: error("cannot index through null pointer %s", ie->e1->toChars());
3448: return EXP_CANT_INTERPRET;
3449: }
3450: aggregate = getAggregateFromPointer(aggregate, &ofs);
3451: indexToModify += ofs;
warning C4244: '+=' : conversion from 'dinteger_t' to 'int', possible loss of data
3452: destarraylen = resolveArrayLength(aggregate);
3453: }
3454: if (indexToModify >= destarraylen)
3455: {
3456: error("array index %d is out of bounds [0..%d]", indexToModify,
3457: destarraylen);
3458: return EXP_CANT_INTERPRET;
3459: }
3460: }
3461:
3462: /* The only possible indexable LValue aggregates are array literals,
3463: * slices of array literals, and AA literals.
3464: */
3465: if (aggregate->op == TOKindex || aggregate->op == TOKdotvar ||
3466: aggregate->op == TOKslice || aggregate->op == TOKcall ||
3467: aggregate->op == TOKstar)
3468: {
3469: aggregate = aggregate->interpret(istate, ctfeNeedLvalue);
3470: if (aggregate == EXP_CANT_INTERPRET)
3471: return EXP_CANT_INTERPRET;
3472: // The array could be an index of an AA. Resolve it if so.
3473: if (aggregate->op == TOKindex)
3474: {
3475: IndexExp *ie = (IndexExp *)aggregate;
warning C6246: Local declaration of 'ie' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '3393' of 'c:\projects\extern\d\dmd\src\interpret.c': Lines: 3393
3476: aggregate = Index(ie->type, ie->e1, ie->e2);
3477: }
3478: }
3479: if (aggregate->op == TOKvar)
3480: {
3481: VarExp *ve = (VarExp *)aggregate;
3482: VarDeclaration *v = ve->var->isVarDeclaration();
3483: aggregate = v->getValue();
3484: if (aggregate->op == TOKnull)
3485: {
3486: if (v->type->ty == Taarray)
3487: { // Assign to empty associative array
3488: Expressions *valuesx = new Expressions();
3489: Expressions *keysx = new Expressions();
3490: Expression *index = ie->e2->interpret(istate);
warning C6246: Local declaration of 'index' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '3419' of 'c:\projects\extern\d\dmd\src\interpret.c': Lines: 3419
3491: if (index == EXP_CANT_INTERPRET)
3492: return EXP_CANT_INTERPRET;
3493: valuesx->push(newval);
3494: keysx->push(index);
3495: Expression *aae2 = new AssocArrayLiteralExp(loc, keysx, valuesx);
3496: aae2->type = v->type;
3497: newval = aae2;
3498: v->setRefValue(newval);
3499: return returnValue;
3500: }
3501: // This would be a runtime segfault
3502: error("cannot index null array %s", v->toChars());
3503: return EXP_CANT_INTERPRET;
3504: }
3505: }
3506: if (aggregate->op == TOKslice)
3507: {
3508: SliceExp *sexp = (SliceExp *)aggregate;
3509: aggregate = sexp->e1;
3510: Expression *lwr = sexp->lwr->interpret(istate);
3511: indexToModify += lwr->toInteger();
warning C4244: '+=' : conversion from 'dinteger_t' to 'int', possible loss of data
3512: }
3513: if (aggregate->op == TOKarrayliteral)
3514: existingAE = (ArrayLiteralExp *)aggregate;
3515: else if (aggregate->op == TOKstring)
3516: existingSE = (StringExp *)aggregate;
3517: else if (aggregate->op == TOKassocarrayliteral)
3518: existingAA = (AssocArrayLiteralExp *)aggregate;
3519: else
3520: {
3521: error("CTFE internal compiler error %s", aggregate->toChars());
3522: return EXP_CANT_INTERPRET;
3523: }
3524: if (!wantRef && newval->op == TOKslice)
3525: {
3526: newval = resolveSlice(newval);
3527: if (newval == EXP_CANT_INTERPRET)
3528: {
3529: error("Compiler error: CTFE index assign %s", toChars());
3530: assert(0);
3531: }
3532: }
3533:
3534: if (existingAE)
3535: {
3536: if (newval->op == TOKstructliteral)
3537: assignInPlace((Expression *)(existingAE->elements->tdata()[indexToModify]), newval);
3538: else
3539: existingAE->elements->tdata()[indexToModify] = newval;
3540: return returnValue;
3541: }
3542: if (existingSE)
3543: {
3544: unsigned char *s = (unsigned char *)existingSE->string;
3545: unsigned value = newval->toInteger();
warning C4244: 'initializing' : conversion from 'dinteger_t' to 'unsigned int', possible loss of data
3546: switch (existingSE->sz)
3547: {
3548: case 1: s[indexToModify] = value; break;
3549: case 2: ((unsigned short *)s)[indexToModify] = value; break;
3550: case 4: ((unsigned *)s)[indexToModify] = value; break;
3551: default:
3552: assert(0);
3553: break;
3554: }
3555: return returnValue;
3556: }
3557: else if (existingAA)
3558: {
3559: if (assignAssocArrayElement(loc, existingAA, index, newval) == EXP_CANT_INTERPRET)
3560: return EXP_CANT_INTERPRET;
3561: return returnValue;
3562: }
3563: else
3564: {
3565: error("Index assignment %s is not yet supported in CTFE ", toChars());
3566: return EXP_CANT_INTERPRET;
3567: }
3568: return returnValue;
3569: }
3570: else if (e1->op == TOKslice)
3571: {
3572: // ------------------------------
3573: // aggregate[] = newval
3574: // aggregate[low..upp] = newval
3575: // ------------------------------
3576: SliceExp * sexp = (SliceExp *)e1;
3577: // Set the $ variable
3578: Expression *oldval = sexp->e1;
3579: bool assignmentToSlicedPointer = false;
3580: if (oldval->type->toBasetype()->ty == Tpointer && oldval->type->toBasetype()->nextOf()->ty != Tfunction)
3581: { // Slicing a pointer
3582: oldval = oldval->interpret(istate, ctfeNeedLvalue);
3583: dinteger_t ofs;
3584: oldval = getAggregateFromPointer(oldval, &ofs);
3585: assignmentToSlicedPointer = true;
3586: } else
3587: oldval = oldval->interpret(istate);
3588:
3589: if (oldval->op != TOKarrayliteral && oldval->op != TOKstring
3590: && oldval->op != TOKslice && oldval->op != TOKnull)
3591: {
3592: error("CTFE ICE: cannot resolve array length");
3593: return EXP_CANT_INTERPRET;
3594: }
3595: uinteger_t dollar = resolveArrayLength(oldval);
3596: if (sexp->lengthVar)
3597: {
3598: Expression *arraylen = new IntegerExp(loc, dollar, Type::tsize_t);
3599: sexp->lengthVar->createStackValue(arraylen);
3600: }
3601:
3602: Expression *upper = NULL;
3603: Expression *lower = NULL;
3604: if (sexp->upr)
3605: upper = sexp->upr->interpret(istate);
3606: if (sexp->lwr)
3607: lower = sexp->lwr->interpret(istate);
3608: if (sexp->lengthVar)
3609: sexp->lengthVar->setValueNull(); // $ is defined only in [L..U]
3610: if (upper == EXP_CANT_INTERPRET || lower == EXP_CANT_INTERPRET)
3611: return EXP_CANT_INTERPRET;
3612:
3613: int dim = dollar;
warning C4244: 'initializing' : conversion from 'uinteger_t' to 'int', possible loss of data
3614: int upperbound = upper ? upper->toInteger() : dim;
warning C4244: 'initializing' : conversion from 'dinteger_t' to 'int', possible loss of data
3615: int lowerbound = lower ? lower->toInteger() : 0;
warning C4244: 'initializing' : conversion from 'dinteger_t' to 'int', possible loss of data
3616:
3617: if (!assignmentToSlicedPointer && (((int)lowerbound < 0) || (upperbound > dim)))
3618: {
3619: error("Array bounds [0..%d] exceeded in slice [%d..%d]",
3620: dim, lowerbound, upperbound);
3621: return EXP_CANT_INTERPRET;
3622: }
3623: if (upperbound == lowerbound)
3624: return newval;
3625:
3626: Expression *aggregate = resolveReferences(((SliceExp *)e1)->e1, istate->localThis);
3627: int firstIndex = lowerbound;
3628:
3629: ArrayLiteralExp *existingAE = NULL;
3630: StringExp *existingSE = NULL;
3631:
3632: /* The only possible slicable LValue aggregates are array literals,
3633: * and slices of array literals.
3634: */
3635:
3636: if (aggregate->op == TOKindex || aggregate->op == TOKdotvar ||
3637: aggregate->op == TOKslice ||
3638: aggregate->op == TOKstar || aggregate->op == TOKcall)
3639: {
3640: aggregate = aggregate->interpret(istate, ctfeNeedLvalue);
3641: if (aggregate == EXP_CANT_INTERPRET)
3642: return EXP_CANT_INTERPRET;
3643: // The array could be an index of an AA. Resolve it if so.
3644: if (aggregate->op == TOKindex)
3645: {
3646: IndexExp *ie = (IndexExp *)aggregate;
3647: aggregate = Index(ie->type, ie->e1, ie->e2);
3648: }
3649: }
3650: if (aggregate->op == TOKvar)
3651: {
3652: VarExp *ve = (VarExp *)(aggregate);
3653: VarDeclaration *v = ve->var->isVarDeclaration();
3654: aggregate = v->getValue();
3655: }
3656: if (aggregate->op == TOKslice)
3657: { // Slice of a slice --> change the bounds
3658: SliceExp *sexpold = (SliceExp *)aggregate;
3659: dinteger_t hi = upperbound + sexpold->lwr->toInteger();
3660: firstIndex = lowerbound + sexpold->lwr->toInteger();
warning C4244: '=' : conversion from 'dinteger_t' to 'int', possible loss of data
3661: if (hi > sexpold->upr->toInteger())
3662: {
3663: error("slice [%d..%d] exceeds array bounds [0..%jd]",
3664: lowerbound, upperbound,
3665: sexpold->upr->toInteger() - sexpold->lwr->toInteger());
3666: return EXP_CANT_INTERPRET;
3667: }
3668: aggregate = sexpold->e1;
3669: }
3670: if (aggregate->type->toBasetype()->ty == Tpointer && aggregate->type->toBasetype()->nextOf()->ty != Tfunction)
3671: { // Slicing a pointer --> change the bounds
3672: aggregate = sexp->e1->interpret(istate, ctfeNeedLvalue);
3673: dinteger_t ofs;
3674: aggregate = getAggregateFromPointer(aggregate, &ofs);
3675: dinteger_t hi = upperbound + ofs;
3676: firstIndex = lowerbound + ofs;
warning C4244: '=' : conversion from 'dinteger_t' to 'int', possible loss of data
3677: if (firstIndex < 0 || hi > dim)
3678: {
3679: error("slice [%d..%jd] exceeds memory block bounds [0..%jd]",
3680: firstIndex, hi, dim);
3681: return EXP_CANT_INTERPRET;
3682: }
3683: }
3684: if (aggregate->op==TOKarrayliteral)
3685: existingAE = (ArrayLiteralExp *)aggregate;
3686: else if (aggregate->op==TOKstring)
3687: existingSE = (StringExp *)aggregate;
3688:
3689: if (!wantRef && newval->op == TOKslice)
3690: {
3691: newval = resolveSlice(newval);
3692: if (newval == EXP_CANT_INTERPRET)
3693: {
3694: error("Compiler error: CTFE slice %s", toChars());
3695: assert(0);
3696: }
3697: }
3698:
3699: // For slice assignment, we check that the lengths match.
3700: size_t srclen = 0;
3701: if (newval->op == TOKarrayliteral)
3702: srclen = ((ArrayLiteralExp *)newval)->elements->dim;
3703: else if (newval->op == TOKstring)
3704: srclen = ((StringExp *)newval)->len;
3705: if (!isBlockAssignment && srclen != (upperbound - lowerbound))
3706: {
3707: error("Array length mismatch assigning [0..%d] to [%d..%d]", srclen, lowerbound, upperbound);
3708: return EXP_CANT_INTERPRET;
3709: }
3710:
3711: if (!isBlockAssignment && newval->op == TOKarrayliteral && existingAE)
3712: {
3713: Expressions *oldelems = existingAE->elements;
3714: Expressions *newelems = ((ArrayLiteralExp *)newval)->elements;
3715: for (size_t j = 0; j < newelems->dim; j++)
3716: {
3717: oldelems->tdata()[j + firstIndex] = newelems->tdata()[j];
3718: }
3719: return newval;
3720: }
3721: else if (newval->op == TOKstring && existingSE)
3722: {
3723: sliceAssignStringFromString((StringExp *)existingSE, (StringExp *)newval, firstIndex);
3724: return newval;
3725: }
3726: else if (newval->op == TOKstring && existingAE)
3727: { /* Mixed slice: it was initialized as an array literal of chars.
3728: * Now a slice of it is being set with a string.
3729: */
3730: sliceAssignArrayLiteralFromString(existingAE, (StringExp *)newval, firstIndex);
3731: return newval;
3732: }
3733: else if (newval->op == TOKarrayliteral && existingSE)
3734: { /* Mixed slice: it was initialized as a string literal.
3735: * Now a slice of it is being set with an array literal.
3736: */
3737: sliceAssignStringFromArrayLiteral(existingSE, (ArrayLiteralExp *)newval, firstIndex);
3738: return newval;
3739: }
3740: else if (existingSE)
3741: { // String literal block slice assign
3742: unsigned value = newval->toInteger();
warning C4244: 'initializing' : conversion from 'dinteger_t' to 'unsigned int', possible loss of data
3743: unsigned char *s = (unsigned char *)existingSE->string;
3744: for (size_t j = 0; j < upperbound-lowerbound; j++)
warning C4018: '<' : signed/unsigned mismatch
3745: {
3746: switch (existingSE->sz)
3747: {
3748: case 1: s[j+firstIndex] = value; break;
3749: case 2: ((unsigned short *)s)[j+firstIndex] = value; break;
3750: case 4: ((unsigned *)s)[j+firstIndex] = value; break;
3751: default:
3752: assert(0);
3753: break;
3754: }
3755: }
3756: if (goal == ctfeNeedNothing)
3757: return NULL; // avoid creating an unused literal
3758: SliceExp *retslice = new SliceExp(loc, existingSE,
3759: new IntegerExp(loc, firstIndex, Type::tsize_t),
3760: new IntegerExp(loc, firstIndex + upperbound-lowerbound, Type::tsize_t));
3761: retslice->type = this->type;
3762: return retslice->interpret(istate);
3763: }
3764: else if (existingAE)
3765: {
3766: /* Block assignment, initialization of static arrays
3767: * x[] = e
3768: * x may be a multidimensional static array. (Note that this
3769: * only happens with array literals, never with strings).
3770: */
3771: Expressions * w = existingAE->elements;
3772: assert( existingAE->type->ty == Tsarray ||
3773: existingAE->type->ty == Tarray);
3774: #if DMDV2
3775: Type *desttype = ((TypeArray *)existingAE->type)->next->castMod(0);
3776: bool directblk = (e2->type->toBasetype()->castMod(0)) == desttype;
3777: #else
3778: Type *desttype = ((TypeArray *)existingAE->type)->next;
3779: bool directblk = (e2->type->toBasetype()) == desttype;
3780: #endif
3781: bool cow = !(newval->op == TOKstructliteral || newval->op == TOKarrayliteral
3782: || newval->op == TOKstring);
3783: for (size_t j = 0; j < upperbound-lowerbound; j++)
warning C4018: '<' : signed/unsigned mismatch
3784: {
3785: if (!directblk)
3786: // Multidimensional array block assign
3787: recursiveBlockAssign((ArrayLiteralExp *)w->tdata()[j+firstIndex], newval, wantRef);
3788: else
3789: {
3790: if (wantRef || cow)
3791: existingAE->elements->tdata()[j+firstIndex] = newval;
3792: else
3793: assignInPlace(existingAE->elements->tdata()[j+firstIndex], newval);
3794: }
3795: }
3796: if (goal == ctfeNeedNothing)
3797: return NULL; // avoid creating an unused literal
3798: SliceExp *retslice = new SliceExp(loc, existingAE,
3799: new IntegerExp(loc, firstIndex, Type::tsize_t),
3800: new IntegerExp(loc, firstIndex + upperbound-lowerbound, Type::tsize_t));
3801: retslice->type = this->type;
3802: return retslice->interpret(istate);
3803: }
3804: else
3805: error("Slice operation %s cannot be evaluated at compile time", toChars());
3806: }
3807: else
3808: {
3809: error("%s cannot be evaluated at compile time", toChars());
3810: #ifdef DEBUG
3811: dump(0);
3812: #endif
3813: }
3814: return returnValue;
3815: }
3816:
3817: Expression *AssignExp::interpret(InterState *istate, CtfeGoal goal)
3818: {
3819: return interpretAssignCommon(istate, goal, NULL);
3820: }
3821:
3822: #define BIN_ASSIGN_INTERPRET(op) \
3823: Expression *op##AssignExp::interpret(InterState *istate, CtfeGoal goal) \
3824: { \
3825: return interpretAssignCommon(istate, goal, &op); \
3826: }
3827:
3828: BIN_ASSIGN_INTERPRET(Add)
3829: BIN_ASSIGN_INTERPRET(Min)
3830: BIN_ASSIGN_INTERPRET(Cat)
3831: BIN_ASSIGN_INTERPRET(Mul)
3832: BIN_ASSIGN_INTERPRET(Div)
3833: BIN_ASSIGN_INTERPRET(Mod)
3834: BIN_ASSIGN_INTERPRET(Shl)
3835: BIN_ASSIGN_INTERPRET(Shr)
3836: BIN_ASSIGN_INTERPRET(Ushr)
3837: BIN_ASSIGN_INTERPRET(And)
3838: BIN_ASSIGN_INTERPRET(Or)
3839: BIN_ASSIGN_INTERPRET(Xor)
3840:
3841: Expression *PostExp::interpret(InterState *istate, CtfeGoal goal)
3842: {
3843: #if LOG
3844: printf("PostExp::interpret() %s\n", toChars());
3845: #endif
3846: Expression *e;
3847: if (op == TOKplusplus)
3848: e = interpretAssignCommon(istate, goal, &Add, 1);
3849: else
3850: e = interpretAssignCommon(istate, goal, &Min, 1);
3851: #if LOG
3852: if (e == EXP_CANT_INTERPRET)
3853: printf("PostExp::interpret() CANT\n");
3854: #endif
3855: return e;
3856: }
3857:
3858: Expression *AndAndExp::interpret(InterState *istate, CtfeGoal goal)
3859: {
3860: #if LOG
3861: printf("AndAndExp::interpret() %s\n", toChars());
3862: #endif
3863: Expression *e = e1->interpret(istate);
3864: if (e != EXP_CANT_INTERPRET)
3865: {
3866: if (e->isBool(FALSE))
3867: e = new IntegerExp(e1->loc, 0, type);
3868: else if (isTrueBool(e))
3869: {
3870: e = e2->interpret(istate);
3871: if (e != EXP_CANT_INTERPRET)
3872: {
3873: if (e->isBool(FALSE))
3874: e = new IntegerExp(e1->loc, 0, type);
3875: else if (isTrueBool(e))
3876: e = new IntegerExp(e1->loc, 1, type);
3877: else
3878: e = EXP_CANT_INTERPRET;
3879: }
3880: }
3881: else
3882: e = EXP_CANT_INTERPRET;
3883: }
3884: return e;
3885: }
3886:
3887: Expression *OrOrExp::interpret(InterState *istate, CtfeGoal goal)
3888: {
3889: #if LOG
3890: printf("OrOrExp::interpret() %s\n", toChars());
3891: #endif
3892: Expression *e = e1->interpret(istate);
3893: if (e != EXP_CANT_INTERPRET)
3894: {
3895: if (isTrueBool(e))
3896: e = new IntegerExp(e1->loc, 1, type);
3897: else if (e->isBool(FALSE))
3898: {
3899: e = e2->interpret(istate);
3900: if (e != EXP_CANT_INTERPRET)
3901: {
3902: if (e->isBool(FALSE))
3903: e = new IntegerExp(e1->loc, 0, type);
3904: else if (isTrueBool(e))
3905: e = new IntegerExp(e1->loc, 1, type);
3906: else
3907: e = EXP_CANT_INTERPRET;
3908: }
3909: }
3910: else
3911: e = EXP_CANT_INTERPRET;
3912: }
3913: return e;
3914: }
3915:
3916: Expression *CallExp::interpret(InterState *istate, CtfeGoal goal)
3917: { Expression *e = EXP_CANT_INTERPRET;
3918:
3919: #if LOG
3920: printf("CallExp::interpret() %s\n", toChars());
3921: #endif
3922:
3923: Expression * pthis = NULL;
3924: FuncDeclaration *fd = NULL;
3925: Expression *ecall = e1;
3926: if (ecall->op == TOKcall)
3927: {
3928: ecall = e1->interpret(istate);
3929: if (ecall == EXP_CANT_INTERPRET)
3930: return ecall;
3931: }
3932: if (ecall->op == TOKstar)
3933: { // Calling a function pointer
3934: Expression * pe = ((PtrExp*)ecall)->e1;
3935: if (pe->op == TOKvar) {
3936: VarDeclaration *vd = ((VarExp *)((PtrExp*)ecall)->e1)->var->isVarDeclaration();
3937: if (vd && vd->getValue() && vd->getValue()->op == TOKsymoff)
3938: fd = ((SymOffExp *)vd->getValue())->var->isFuncDeclaration();
3939: else
3940: {
3941: ecall = getVarExp(loc, istate, vd, goal);
3942: if (ecall == EXP_CANT_INTERPRET)
3943: return ecall;
3944:
3945: if (ecall->op == TOKsymoff)
3946: fd = ((SymOffExp *)ecall)->var->isFuncDeclaration();
3947: }
3948: }
3949: else
3950: ecall = ((PtrExp*)ecall)->e1->interpret(istate);
3951:
3952: }
3953: if (ecall == EXP_CANT_INTERPRET)
3954: return ecall;
3955:
3956: if (ecall->op == TOKindex)
3957: { ecall = e1->interpret(istate);
3958: if (ecall == EXP_CANT_INTERPRET)
3959: return ecall;
3960: }
3961:
3962: if (ecall->op == TOKdotvar && !((DotVarExp*)ecall)->var->isFuncDeclaration())
3963: { ecall = e1->interpret(istate);
3964: if (ecall == EXP_CANT_INTERPRET)
3965: return ecall;
3966: }
3967:
3968: if (ecall->op == TOKdotvar)
3969: { // Calling a member function
3970: pthis = ((DotVarExp*)e1)->e1;
3971: fd = ((DotVarExp*)e1)->var->isFuncDeclaration();
3972: }
3973: else if (ecall->op == TOKvar)
3974: {
3975: VarDeclaration *vd = ((VarExp *)ecall)->var->isVarDeclaration();
3976: if (vd && vd->getValue())
3977: ecall = vd->getValue();
3978: else // Calling a function
3979: fd = ((VarExp *)e1)->var->isFuncDeclaration();
3980: }
3981: if (ecall->op == TOKdelegate)
3982: { // Calling a delegate
3983: fd = ((DelegateExp *)ecall)->func;
3984: pthis = ((DelegateExp *)ecall)->e1;
3985: }
3986: else if (ecall->op == TOKfunction)
3987: { // Calling a delegate literal
3988: fd = ((FuncExp*)ecall)->fd;
3989: }
3990: else if (ecall->op == TOKstar && ((PtrExp*)ecall)->e1->op==TOKfunction)
3991: { // Calling a function literal
3992: fd = ((FuncExp*)((PtrExp*)ecall)->e1)->fd;
3993: }
3994:
3995: TypeFunction *tf = fd ? (TypeFunction *)(fd->type) : NULL;
3996: if (!tf)
3997: { // DAC: I'm not sure if this ever happens
3998: //printf("ecall=%s %d %d\n", ecall->toChars(), ecall->op, TOKcall);
3999: error("cannot evaluate %s at compile time", toChars());
4000: return EXP_CANT_INTERPRET;
4001: }
4002: if (!fd)
4003: {
4004: error("cannot evaluate %s at compile time", toChars());
4005: return EXP_CANT_INTERPRET;
4006: }
4007: if (pthis)
4008: { // Member function call
4009: if (pthis->op == TOKthis)
4010: pthis = istate ? istate->localThis : NULL;
4011: else
4012: {
4013: if (pthis->op == TOKcomma)
4014: pthis = pthis->interpret(istate);
4015: if (pthis == EXP_CANT_INTERPRET)
4016: return EXP_CANT_INTERPRET;
4017: // Evaluate 'this'
4018: if (pthis->op != TOKvar)
4019: pthis = pthis->interpret(istate, ctfeNeedLvalue);
4020: if (pthis == EXP_CANT_INTERPRET)
4021: return EXP_CANT_INTERPRET;
4022: }
4023: }
4024: // Check for built-in functions
4025: Expression *eresult;
4026: if (evaluateIfBuiltin(&eresult, istate, fd, arguments, pthis))
4027: return eresult;
4028:
4029: // Inline .dup. Special case because it needs the return type.
4030: if (!pthis && fd->ident == Id::adDup && arguments && arguments->dim == 2)
4031: {
4032: e = arguments->tdata()[1];
4033: e = e->interpret(istate);
4034: if (e != EXP_CANT_INTERPRET)
4035: {
4036: if (e->op == TOKslice)
4037: e= resolveSlice(e);
4038: e = expType(type, e);
4039: e = copyLiteral(e);
4040: }
4041: return e;
4042: }
4043: if (!fd->fbody)
4044: {
4045: error("%s cannot be interpreted at compile time,"
4046: " because it has no available source code", fd->toChars());
4047: return EXP_CANT_INTERPRET;
4048: }
4049: eresult = fd->interpret(istate, arguments, pthis);
4050: if (eresult)
4051: e = eresult;
4052: else if (fd->type->toBasetype()->nextOf()->ty == Tvoid && !global.errors)
4053: e = EXP_VOID_INTERPRET;
4054: else
4055: error("cannot evaluate %s at compile time", toChars());
4056: return e;
4057: }
4058:
4059: Expression *CommaExp::interpret(InterState *istate, CtfeGoal goal)
4060: {
4061: #if LOG
4062: printf("CommaExp::interpret() %s\n", toChars());
4063: #endif
4064:
4065: CommaExp * firstComma = this;
4066: while (firstComma->e1->op == TOKcomma)
4067: firstComma = (CommaExp *)firstComma->e1;
4068:
4069: // If it creates a variable, and there's no context for
4070: // the variable to be created in, we need to create one now.
4071: InterState istateComma;
4072: if (!istate && firstComma->e1->op == TOKdeclaration)
4073: istate = &istateComma;
4074:
4075: // If the comma returns a temporary variable, it needs to be an lvalue
4076: // (this is particularly important for struct constructors)
4077: if (e1->op == TOKdeclaration && e2->op == TOKvar
4078: && ((DeclarationExp *)e1)->declaration == ((VarExp*)e2)->var
4079: && ((VarExp*)e2)->var->storage_class & STCctfe) // same as Expression::isTemp
4080: {
4081: VarExp* ve = (VarExp *)e2;
4082: VarDeclaration *v = ve->var->isVarDeclaration();
4083: if (!v->init && !v->getValue())
4084: {
4085: v->createRefValue(copyLiteral(v->type->defaultInitLiteral()));
4086: }
4087: if (!v->getValue()) {
4088: Expression *newval = v->init->toExpression();
4089: // v->setRefValue(v->init->toExpression());
4090: // Bug 4027. Copy constructors are a weird case where the
4091: // initializer is a void function (the variable is modified
4092: // through a reference parameter instead).
4093: newval = newval->interpret(istate);
4094: if (newval == EXP_CANT_INTERPRET)
4095: return EXP_CANT_INTERPRET;
4096: if (newval != EXP_VOID_INTERPRET)
4097: {
4098: // v isn't necessarily null.
4099: v->setValueWithoutChecking(copyLiteral(newval));
4100: }
4101: }
4102: if (goal == ctfeNeedLvalue || goal == ctfeNeedLvalueRef)
4103: return e2;
4104: return e2->interpret(istate, goal);
4105: }
4106: Expression *e = e1->interpret(istate, ctfeNeedNothing);
4107: if (e != EXP_CANT_INTERPRET)
4108: e = e2->interpret(istate, goal);
4109: return e;
4110: }
4111:
4112: Expression *CondExp::interpret(InterState *istate, CtfeGoal goal)
4113: {
4114: #if LOG
4115: printf("CondExp::interpret() %s\n", toChars());
4116: #endif
4117: Expression *e;
4118: if (econd->type->ty == Tpointer && econd->type->nextOf()->ty != Tfunction)
4119: {
4120: e = econd->interpret(istate, ctfeNeedLvalue);
4121: if (e == EXP_CANT_INTERPRET)
4122: return e;
4123: if (e->op != TOKnull)
4124: e = new IntegerExp(loc, 1, Type::tbool);
4125: }
4126: else
4127: e = econd->interpret(istate);
4128: if (e != EXP_CANT_INTERPRET)
4129: {
4130: if (isTrueBool(e))
4131: e = e1->interpret(istate, goal);
4132: else if (e->isBool(FALSE))
4133: e = e2->interpret(istate, goal);
4134: else
4135: {
4136: error("%s does not evaluate to boolean result at compile time",
4137: econd->toChars());
4138: e = EXP_CANT_INTERPRET;
4139: }
4140: }
4141: return e;
4142: }
4143:
4144: Expression *ArrayLengthExp::interpret(InterState *istate, CtfeGoal goal)
4145: { Expression *e;
4146: Expression *e1;
4147:
4148: #if LOG
4149: printf("ArrayLengthExp::interpret() %s\n", toChars());
4150: #endif
4151: e1 = this->e1->interpret(istate);
4152: assert(e1);
4153: if (e1 == EXP_CANT_INTERPRET)
4154: return EXP_CANT_INTERPRET;
4155: if (e1->op == TOKstring || e1->op == TOKarrayliteral || e1->op == TOKslice
4156: || e1->op == TOKassocarrayliteral || e1->op == TOKnull)
4157: {
4158: e = new IntegerExp(loc, resolveArrayLength(e1), type);
4159: }
4160: else
4161: {
4162: error("%s cannot be evaluated at compile time", toChars());
4163: return EXP_CANT_INTERPRET;
4164: }
4165: return e;
4166: }
4167:
4168: /* Given an AA literal 'ae', and a key 'e2':
4169: * Return ae[e2] if present, or NULL if not found.
4170: * Return EXP_CANT_INTERPRET on error.
4171: */
4172: Expression *findKeyInAA(AssocArrayLiteralExp *ae, Expression *e2)
4173: {
4174: /* Search the keys backwards, in case there are duplicate keys
4175: */
4176: for (size_t i = ae->keys->dim; i;)
4177: {
4178: i--;
4179: Expression *ekey = ae->keys->tdata()[i];
4180: Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, e2);
4181: if (ex == EXP_CANT_INTERPRET)
4182: {
4183: error("cannot evaluate %s==%s at compile time",
4184: ekey->toChars(), e2->toChars());
4185: return ex;
4186: }
4187: if (ex->isBool(TRUE))
4188: {
4189: return ae->values->tdata()[i];
4190: }
4191: }
4192: return NULL;
4193: }
4194:
4195: Expression *IndexExp::interpret(InterState *istate, CtfeGoal goal)
4196: {
4197: Expression *e1 = NULL;
4198: Expression *e2;
4199:
4200: #if LOG
4201: printf("IndexExp::interpret() %s\n", toChars());
4202: #endif
4203: if (this->e1->type->toBasetype()->ty == Tpointer)
4204: {
4205: // Indexing a pointer. Note that there is no $ in this case.
4206: e1 = this->e1->interpret(istate);
4207: if (e1 == EXP_CANT_INTERPRET)
4208: return EXP_CANT_INTERPRET;
4209:
4210: e2 = this->e2->interpret(istate);
4211: if (e2 == EXP_CANT_INTERPRET)
4212: return EXP_CANT_INTERPRET;
4213: dinteger_t indx = e2->toInteger();
4214: Expression *e;
warning C4101: 'e' : unreferenced local variable
4215: dinteger_t ofs;
4216: Expression *agg = getAggregateFromPointer(e1, &ofs);
4217: if (agg->op == TOKnull)
4218: {
4219: error("cannot index null pointer %s", this->e1->toChars());
4220: return EXP_CANT_INTERPRET;
4221: }
4222: assert(agg->op == TOKarrayliteral || agg->op == TOKstring);
4223: dinteger_t len = ArrayLength(Type::tsize_t, agg)->toInteger();
4224: Type *pointee = ((TypePointer *)agg->type)->next;
4225: if ((indx + ofs) < 0 || (indx+ofs) > len)
4226: {
4227: error("pointer index [%jd] exceeds allocated memory block [0..%jd]",
4228: indx+ofs, len);
4229: return EXP_CANT_INTERPRET;
4230: }
4231: return Index(type, agg, new IntegerExp(loc, indx+ofs, Type::tsize_t));
4232: }
4233: e1 = this->e1->interpret(istate);
4234: if (e1 == EXP_CANT_INTERPRET)
4235: return EXP_CANT_INTERPRET;
4236:
4237: if (e1->op == TOKnull)
4238: {
4239: error("cannot index null array %s", this->e1->toChars());
4240: return EXP_CANT_INTERPRET;
4241: }
4242: /* Set the $ variable.
4243: * Note that foreach uses indexing but doesn't need $
4244: */
4245: if (lengthVar && (e1->op == TOKstring || e1->op == TOKarrayliteral
4246: || e1->op == TOKslice))
4247: {
4248: uinteger_t dollar = resolveArrayLength(e1);
4249: Expression *dollarExp = new IntegerExp(loc, dollar, Type::tsize_t);
4250: lengthVar->createStackValue(dollarExp);
4251: }
4252:
4253: e2 = this->e2->interpret(istate);
4254: if (lengthVar)
4255: lengthVar->setValueNull(); // $ is defined only inside []
4256: if (e2 == EXP_CANT_INTERPRET)
4257: return EXP_CANT_INTERPRET;
4258: if (e1->op == TOKslice && e2->op == TOKint64)
4259: {
4260: // Simplify index of slice: agg[lwr..upr][indx] --> agg[indx']
4261: uinteger_t indx = e2->toInteger();
4262: uinteger_t ilo = ((SliceExp *)e1)->lwr->toInteger();
4263: uinteger_t iup = ((SliceExp *)e1)->upr->toInteger();
4264:
4265: if (indx > iup - ilo)
4266: {
4267: error("index %ju exceeds array length %ju", indx, iup - ilo);
4268: return EXP_CANT_INTERPRET;
4269: }
4270: indx += ilo;
4271: e1 = ((SliceExp *)e1)->e1;
4272: e2 = new IntegerExp(e2->loc, indx, e2->type);
4273: }
4274: Expression *e = NULL;
4275: if ((goal == ctfeNeedLvalue && type->ty != Taarray && type->ty != Tarray
4276: && type->ty != Tsarray && type->ty != Tstruct && type->ty != Tclass)
4277: || (goal == ctfeNeedLvalueRef && type->ty != Tsarray && type->ty != Tstruct)
4278: )
4279: { // Pointer or reference of a scalar type
4280: e = new IndexExp(loc, e1, e2);
4281: e->type = type;
4282: return e;
4283: }
4284: if (e1->op == TOKassocarrayliteral)
4285: {
4286: if (e2->op == TOKslice)
4287: e2 = resolveSlice(e2);
4288: e = findKeyInAA((AssocArrayLiteralExp *)e1, e2);
4289: if (!e)
4290: {
4291: error("key %s not found in associative array %s",
4292: e2->toChars(), this->e1->toChars());
4293: return EXP_CANT_INTERPRET;
4294: }
4295: if (e == EXP_CANT_INTERPRET)
4296: return e;
4297: assert(!e->checkSideEffect(2));
4298: e = paintTypeOntoLiteral(type, e);
4299: }
4300: else
4301: {
4302: e = Index(type, e1, e2);
4303: }
4304: if (e == EXP_CANT_INTERPRET)
4305: {
4306: error("%s cannot be interpreted at compile time", toChars());
4307: return e;
4308: }
4309: if (goal == ctfeNeedRvalue && (e->op == TOKslice || e->op == TOKdotvar))
4310: e = e->interpret(istate);
4311: return e;
4312: }
4313:
4314:
4315: Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal)
4316: {
4317: Expression *e1;
4318: Expression *lwr;
4319: Expression *upr;
4320:
4321: #if LOG
4322: printf("SliceExp::interpret() %s\n", toChars());
4323: #endif
4324:
4325: if (this->e1->type->toBasetype()->ty == Tpointer)
4326: {
4327: // Slicing a pointer. Note that there is no $ in this case.
4328: e1 = this->e1->interpret(istate);
4329: if (e1 == EXP_CANT_INTERPRET)
4330: return EXP_CANT_INTERPRET;
4331:
4332: /* Evaluate lower and upper bounds of slice
4333: */
4334: lwr = this->lwr->interpret(istate);
4335: if (lwr == EXP_CANT_INTERPRET)
4336: return EXP_CANT_INTERPRET;
4337: upr = this->upr->interpret(istate);
4338: if (upr == EXP_CANT_INTERPRET)
4339: return EXP_CANT_INTERPRET;
4340: uinteger_t ilwr;
4341: uinteger_t iupr;
4342: ilwr = lwr->toInteger();
4343: iupr = upr->toInteger();
4344: Expression *e;
4345: dinteger_t ofs;
4346: Expression *agg = getAggregateFromPointer(e1, &ofs);
4347: if (agg->op == TOKnull)
4348: {
4349: if (iupr == ilwr)
4350: {
4351: e = new NullExp(loc);
4352: e->type = type;
4353: return e;
4354: }
4355: error("cannot slice null pointer %s", this->e1->toChars());
4356: return EXP_CANT_INTERPRET;
4357: }
4358: assert(agg->op == TOKarrayliteral || agg->op == TOKstring);
4359: dinteger_t len = ArrayLength(Type::tsize_t, agg)->toInteger();
4360: Type *pointee = ((TypePointer *)agg->type)->next;
4361: if ((ilwr + ofs) < 0 || (iupr+ofs) > (len + 1) || iupr < ilwr)
4362: {
4363: error("pointer slice [%jd..%jd] exceeds allocated memory block [0..%jd]",
4364: ilwr+ofs, iupr+ofs, len);
4365: return EXP_CANT_INTERPRET;
4366: }
4367: e = new SliceExp(loc, agg, lwr, upr);
4368: e->type = type;
4369: return e;
4370: }
4371: if (goal == ctfeNeedRvalue && this->e1->op == TOKstring)
4372: e1 = this->e1; // Will get duplicated anyway
4373: else
4374: e1 = this->e1->interpret(istate, goal);
4375: if (e1 == EXP_CANT_INTERPRET)
4376: return EXP_CANT_INTERPRET;
4377: if (e1->op == TOKvar)
4378: e1 = e1->interpret(istate);
4379:
4380: if (!this->lwr)
4381: {
4382: if (goal == ctfeNeedLvalue || goal == ctfeNeedLvalueRef)
4383: return e1;
4384: Expression *e = e1->castTo(NULL, type);
4385: return e->interpret(istate);
4386: }
4387:
4388: /* Set the $ variable
4389: */
4390: if (e1->op != TOKarrayliteral && e1->op != TOKstring &&
4391: e1->op != TOKnull && e1->op != TOKslice)
4392: {
4393: error("Cannot determine length of %s at compile time\n", e1->toChars());
4394: return EXP_CANT_INTERPRET;
4395: }
4396: uinteger_t dollar = resolveArrayLength(e1);
4397: if (lengthVar)
4398: {
4399: IntegerExp *dollarExp = new IntegerExp(loc, dollar, Type::tsize_t);
4400: lengthVar->createStackValue(dollarExp);
4401: }
4402:
4403: /* Evaluate lower and upper bounds of slice
4404: */
4405: lwr = this->lwr->interpret(istate);
4406: if (lwr != EXP_CANT_INTERPRET)
4407: upr = this->upr->interpret(istate);
4408: if (lengthVar)
4409: lengthVar->setValueNull(); // $ is defined only inside [L..U]
4410: if (lwr == EXP_CANT_INTERPRET || upr == EXP_CANT_INTERPRET)
4411: {
4412: return EXP_CANT_INTERPRET;
4413: }
4414:
4415: Expression *e;
4416: uinteger_t ilwr;
4417: uinteger_t iupr;
4418: ilwr = lwr->toInteger();
4419: iupr = upr->toInteger();
4420: if (e1->op == TOKnull)
4421: {
4422: if (ilwr== 0 && iupr == 0)
4423: return e1;
4424: e1->error("slice [%ju..%ju] is out of bounds", ilwr, iupr);
4425: return EXP_CANT_INTERPRET;
4426: }
4427: if (e1->op == TOKslice)
4428: {
4429: SliceExp *se = (SliceExp *)e1;
4430: // Simplify slice of slice:
4431: // aggregate[lo1..up1][lwr..upr] ---> aggregate[lwr'..upr']
4432: uinteger_t lo1 = se->lwr->toInteger();
4433: uinteger_t up1 = se->upr->toInteger();
4434: if (ilwr > iupr || iupr > up1 - lo1)
4435: {
4436: error("slice[%ju..%ju] exceeds array bounds[%ju..%ju]",
4437: ilwr, iupr, lo1, up1);
4438: return EXP_CANT_INTERPRET;
4439: }
4440: ilwr += lo1;
4441: iupr += lo1;
4442: e = new SliceExp(loc, se->e1,
4443: new IntegerExp(loc, ilwr, lwr->type),
4444: new IntegerExp(loc, iupr, upr->type));
4445: e->type = type;
4446: return e;
4447: }
4448: if (e1->op == TOKarrayliteral
4449: || e1->op == TOKstring)
4450: {
4451: if (iupr < ilwr || ilwr < 0 || iupr > dollar)
4452: {
4453: error("slice [%jd..%jd] exceeds array bounds [0..%jd]",
4454: ilwr, iupr, dollar);
4455: return EXP_CANT_INTERPRET;
4456: }
4457: }
4458: e = new SliceExp(loc, e1, lwr, upr);
4459: e->type = type;
4460: return e;
4461: }
4462:
4463: Expression *InExp::interpret(InterState *istate, CtfeGoal goal)
4464: { Expression *e = EXP_CANT_INTERPRET;
4465:
4466: #if LOG
4467: printf("InExp::interpret() %s\n", toChars());
4468: #endif
4469: Expression *e1 = this->e1->interpret(istate);
4470: if (e1 == EXP_CANT_INTERPRET)
4471: return e1;
4472: Expression *e2 = this->e2->interpret(istate);
4473: if (e2 == EXP_CANT_INTERPRET)
4474: return e2;
4475: if (e2->op == TOKnull)
4476: return new NullExp(loc, type);
4477: if (e2->op != TOKassocarrayliteral)
4478: {
4479: error(" %s cannot be interpreted at compile time", toChars());
4480: return EXP_CANT_INTERPRET;
4481: }
4482: if (e1->op == TOKslice)
4483: e1 = resolveSlice(e1);
4484: e = findKeyInAA((AssocArrayLiteralExp *)e2, e1);
4485: if (e == EXP_CANT_INTERPRET)
4486: return e;
4487: if (!e)
4488: return new NullExp(loc, type);
4489: e = new IndexExp(loc, e2, e1);
4490: e->type = type;
4491: return e;
4492: }
4493:
4494: Expression *CatExp::interpret(InterState *istate, CtfeGoal goal)
4495: { Expression *e;
4496: Expression *e1;
4497: Expression *e2;
4498:
4499: #if LOG
4500: printf("CatExp::interpret() %s\n", toChars());
4501: #endif
4502: e1 = this->e1->interpret(istate);
4503: if (e1 == EXP_CANT_INTERPRET)
4504: {
4505: goto Lcant;
4506: }
4507: if (e1->op == TOKslice)
4508: {
4509: e1 = resolveSlice(e1);
4510: }
4511: e2 = this->e2->interpret(istate);
4512: if (e2 == EXP_CANT_INTERPRET)
4513: goto Lcant;
4514: if (e2->op == TOKslice)
4515: e2 = resolveSlice(e2);
4516: e = Cat(type, e1, e2);
4517: if (e == EXP_CANT_INTERPRET)
4518: error("%s cannot be interpreted at compile time", toChars());
4519: return e;
4520:
4521: Lcant:
4522: #if LOG
4523: printf("CatExp::interpret() %s CANT\n", toChars());
4524: #endif
4525: return EXP_CANT_INTERPRET;
4526: }
4527:
4528:
4529: Expression *CastExp::interpret(InterState *istate, CtfeGoal goal)
4530: { Expression *e;
4531: Expression *e1;
4532:
4533: #if LOG
4534: printf("CastExp::interpret() %s\n", toChars());
4535: #endif
4536: e1 = this->e1->interpret(istate, goal);
4537: if (e1 == EXP_CANT_INTERPRET)
4538: goto Lcant;
4539: if (to->ty == Tpointer && e1->op != TOKnull)
4540: { // Deal with casts from char[] to char *
4541: if (e1->op == TOKslice)
4542: {
4543: if ( ((SliceExp *)e1)->e1->op == TOKnull)
4544: {
4545: return paintTypeOntoLiteral(type, ((SliceExp *)e1)->e1);
4546: }
4547: e = new IndexExp(loc, ((SliceExp *)e1)->e1, ((SliceExp *)e1)->lwr);
4548: e->type = type;
4549: return e;
4550: }
4551: if (e1->op == TOKarrayliteral)
4552: {
4553: e = new IndexExp(loc, e1, new IntegerExp(loc, 0, Type::tsize_t));
4554: e->type = type;
4555: return e;
4556: }
4557: if (e1->op == TOKstring)
4558: {
4559: return e1;
4560: }
4561: if (e1->op == TOKindex && ((IndexExp *)e1)->e1->type != e1->type)
4562: { // type painting operation
4563: IndexExp *ie = (IndexExp *)e1;
4564: e = new IndexExp(e1->loc, ie->e1, ie->e2);
4565: e->type = type;
4566: return e;
4567: }
4568: error("pointer cast from %s to %s is not supported at compile time",
4569: e1->type->toChars(), to->toChars());
4570: return EXP_CANT_INTERPRET;
4571: }
4572: if (to->ty == Tarray && e1->op == TOKslice)
4573: {
4574: e1 = new SliceExp(e1->loc, ((SliceExp *)e1)->e1, ((SliceExp *)e1)->lwr,
4575: ((SliceExp *)e1)->upr);
4576: e1->type = to;
4577: return e1;
4578: }
4579: // Disallow array type painting, except for conversions between built-in
4580: // types of identical size.
4581: if ((to->ty == Tsarray || to->ty == Tarray) &&
4582: (e1->type->ty == Tsarray || e1->type->ty == Tarray) &&
4583: #if DMDV2
4584: e1->type->nextOf()->castMod(0) != to->nextOf()->castMod(0)
4585: #else
4586: e1->type->nextOf() != to->nextOf()
4587: #endif
4588: && !(to->nextOf()->isTypeBasic() && e1->type->nextOf()->isTypeBasic()
4589: && to->nextOf()->size() == e1->type->nextOf()->size()) )
4590: {
4591: error("array cast from %s to %s is not supported at compile time", e1->type->toChars(), to->toChars());
4592: return EXP_CANT_INTERPRET;
4593: }
4594: if (to->ty == Tsarray && e1->op == TOKslice)
4595: e1 = resolveSlice(e1);
4596: if (to->toBasetype()->ty == Tbool && e1->type->ty==Tpointer)
4597: {
4598: return new IntegerExp(loc, e1->op != TOKnull, to);
4599: }
4600: if (e1->op == TOKnull)
4601: return paintTypeOntoLiteral(to, e1);
4602:
4603: e = Cast(type, to, e1);
4604: if (e == EXP_CANT_INTERPRET)
4605: error("%s cannot be interpreted at compile time", toChars());
4606: return e;
4607:
4608: Lcant:
4609: #if LOG
4610: printf("CastExp::interpret() %s CANT\n", toChars());
4611: #endif
4612: return EXP_CANT_INTERPRET;
4613: }
4614:
4615:
4616: Expression *AssertExp::interpret(InterState *istate, CtfeGoal goal)
4617: { Expression *e;
4618: Expression *e1;
4619:
4620: #if LOG
4621: printf("AssertExp::interpret() %s\n", toChars());
4622: #endif
4623: if (this->e1->op == TOKthis)
4624: {
4625: if (istate->localThis)
4626: {
4627: if (istate->localThis->op == TOKdotvar
4628: && ((DotVarExp *)(istate->localThis))->e1->op == TOKthis)
4629: return getVarExp(loc, istate, ((DotVarExp*)(istate->localThis))->var, ctfeNeedRvalue);
4630: else
4631: return istate->localThis->interpret(istate);
4632: }
4633: }
4634: // Deal with pointers (including compiler-inserted assert(&this, "null this"))
4635: if (this->e1->type->ty == Tpointer && this->e1->type->nextOf()->ty != Tfunction)
4636: {
4637: e1 = this->e1->interpret(istate, ctfeNeedLvalue);
4638: if (e1 == EXP_CANT_INTERPRET)
4639: goto Lcant;
4640: if (e1->op != TOKnull)
4641: return new IntegerExp(loc, 1, Type::tbool);
4642: }
4643: else
4644: e1 = this->e1->interpret(istate);
4645: if (e1 == EXP_CANT_INTERPRET)
4646: goto Lcant;
4647: if (isTrueBool(e1))
4648: {
4649: }
4650: else if (e1->isBool(FALSE))
4651: {
4652: if (msg)
4653: {
4654: e = msg->interpret(istate);
4655: if (e == EXP_CANT_INTERPRET)
4656: goto Lcant;
4657: error("%s", e->toChars());
4658: }
4659: else
4660: error("%s failed", toChars());
4661: goto Lcant;
4662: }
4663: else
4664: {
4665: error("%s is not a compile-time boolean expression", e1->toChars());
4666: goto Lcant;
4667: }
4668: return e1;
4669:
4670: Lcant:
4671: return EXP_CANT_INTERPRET;
4672: }
4673:
4674: Expression *PtrExp::interpret(InterState *istate, CtfeGoal goal)
4675: { Expression *e = EXP_CANT_INTERPRET;
4676:
4677: #if LOG
4678: printf("PtrExp::interpret() %s\n", toChars());
4679: #endif
4680: // Constant fold *(&structliteral + offset)
4681: if (e1->op == TOKadd)
4682: { AddExp *ae = (AddExp *)e1;
4683: if (ae->e1->op == TOKaddress && ae->e2->op == TOKint64)
4684: { AddrExp *ade = (AddrExp *)ae->e1;
4685: Expression *ex = ade->e1;
4686: ex = ex->interpret(istate);
4687: if (ex != EXP_CANT_INTERPRET)
4688: {
4689: if (ex->op == TOKstructliteral)
4690: { StructLiteralExp *se = (StructLiteralExp *)ex;
4691: unsigned offset = ae->e2->toInteger();
warning C4244: 'initializing' : conversion from 'dinteger_t' to 'unsigned int', possible loss of data
4692: e = se->getField(type, offset);
4693: if (!e)
4694: e = EXP_CANT_INTERPRET;
4695: return e;
4696: }
4697: }
4698: }
4699: e = Ptr(type, e1);
4700: }
4701: #if DMDV2
4702: #else // this is required for D1, where structs return *this instead of 'this'.
4703: else if (e1->op == TOKthis)
4704: {
4705: if(istate->localThis)
4706: return istate->localThis->interpret(istate);
4707: }
4708: #endif
4709: else
4710: { // It's possible we have an array bounds error. We need to make sure it
4711: // errors with this line number, not the one where the pointer was set.
4712: e = e1->interpret(istate, ctfeNeedLvalue);
4713: if (e == EXP_CANT_INTERPRET)
4714: return e;
4715: if (goal != ctfeNeedLvalue)
4716: {
4717: if (e->op == TOKindex && e->type->ty == Tpointer)
4718: {
4719: IndexExp *ie = (IndexExp *)e;
4720: if ((ie->e1->op == TOKarrayliteral || ie->e1->op == TOKstring)
4721: && ie->e2->op == TOKint64)
4722: {
4723: Expression *dollar = ArrayLength(Type::tsize_t, ie->e1);
4724: dinteger_t len = dollar->toInteger();
4725: dinteger_t indx = ie->e2->toInteger();
4726: assert(indx >=0 && indx <= len); // invalid pointer
4727: if (indx == len)
4728: {
4729: error("dereference of pointer %s one past end of memory block limits [0..%jd]",
4730: toChars(), len);
4731: return EXP_CANT_INTERPRET;
4732: }
4733: return Index(type, ie->e1, ie->e2);
4734: }
4735: if (ie->e1->op == TOKassocarrayliteral)
4736: return Index(type, ie->e1, ie->e2);
4737: }
4738: if (e->op == TOKstructliteral)
4739: return e;
4740: e = e1->interpret(istate, goal);
4741: if (e->op == TOKaddress)
4742: {
4743: e = ((AddrExp*)e)->e1;
4744: if (e->op == TOKdotvar || e->op == TOKindex)
4745: e = e->interpret(istate, goal);
4746: }
4747: if (e == EXP_CANT_INTERPRET)
4748: return e;
4749: }
4750: else if (e->op == TOKaddress)
4751: e = ((AddrExp*)e)->e1; // *(&x) ==> x
4752: if (e->op == TOKnull)
4753: {
4754: error("dereference of null pointer '%s'", e1->toChars());
4755: return EXP_CANT_INTERPRET;
4756: }
4757: e->type = type;
4758: }
4759:
4760: #if LOG
4761: if (e == EXP_CANT_INTERPRET)
4762: printf("PtrExp::interpret() %s = EXP_CANT_INTERPRET\n", toChars());
4763: #endif
4764: return e;
4765: }
4766:
4767: Expression *DotVarExp::interpret(InterState *istate, CtfeGoal goal)
4768: { Expression *e = EXP_CANT_INTERPRET;
4769:
4770: #if LOG
4771: printf("DotVarExp::interpret() %s\n", toChars());
4772: #endif
4773:
4774: Expression *ex = e1->interpret(istate);
4775: if (ex != EXP_CANT_INTERPRET)
4776: {
4777: if (ex->op == TOKaddress)
4778: ex = ((AddrExp *)ex)->e1;
4779: if (ex->op == TOKstructliteral)
4780: { StructLiteralExp *se = (StructLiteralExp *)ex;
4781: VarDeclaration *v = var->isVarDeclaration();
4782: if (v)
4783: {
4784: if (goal == ctfeNeedLvalue || goal == ctfeNeedLvalueRef)
4785: {
4786: // We can't use getField, because it makes a copy
4787: int i = se->getFieldIndex(type, v->offset);
4788: if (i == -1)
4789: {
4790: error("couldn't find field %s in %s", v->toChars(), type->toChars());
4791: return EXP_CANT_INTERPRET;
4792: }
4793: e = se->elements->tdata()[i];
4794: // If it is an lvalue literal, return it...
4795: if (e->op == TOKstructliteral)
4796: return e;
4797: if ((type->ty == Tsarray || goal == ctfeNeedLvalue) && (
4798: e->op == TOKarrayliteral ||
4799: e->op == TOKassocarrayliteral || e->op == TOKstring ||
4800: e->op == TOKslice))
4801: return e;
4802: /* Element is an allocated pointer, which was created in
4803: * CastExp.
4804: */
4805: if (goal == ctfeNeedLvalue && e->op == TOKindex &&
4806: e->type == type &&
4807: (type->ty == Tpointer && type->nextOf()->ty != Tfunction))
4808: return e;
4809: // ...Otherwise, just return the (simplified) dotvar expression
4810: e = new DotVarExp(loc, ex, v);
4811: e->type = type;
4812: return e;
4813: }
4814: e = se->getField(type, v->offset);
4815: if (!e)
4816: {
4817: error("couldn't find field %s in %s", v->toChars(), type->toChars());
4818: e = EXP_CANT_INTERPRET;
4819: }
4820: // If it is an rvalue literal, return it...
4821: if (e->op == TOKstructliteral || e->op == TOKarrayliteral ||
4822: e->op == TOKassocarrayliteral || e->op == TOKstring)
4823: return e;
4824: if (type->ty == Tpointer && type->nextOf()->ty != Tfunction)
4825: {
4826: assert(e->type == type);
4827: return e;
4828: }
4829: return e->interpret(istate, goal);
4830: }
4831: }
4832: else
4833: error("%s.%s is not yet implemented at compile time", e1->toChars(), var->toChars());
4834: }
4835:
4836: #if LOG
4837: if (e == EXP_CANT_INTERPRET)
4838: printf("DotVarExp::interpret() %s = EXP_CANT_INTERPRET\n", toChars());
4839: #endif
4840: return e;
4841: }
4842:
4843: /******************************* Special Functions ***************************/
4844:
4845: #if DMDV1
4846:
4847: Expression *interpret_aaLen(InterState *istate, Expressions *arguments)
4848: {
4849: if (!arguments || arguments->dim != 1)
4850: return NULL;
4851: Expression *earg = arguments->tdata()[0];
4852: earg = earg->interpret(istate);
4853: if (earg == EXP_CANT_INTERPRET)
4854: return NULL;
4855: if (earg->op != TOKassocarrayliteral)
4856: return NULL;
4857: AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg;
4858: Expression *e = new IntegerExp(aae->loc, aae->keys->dim, Type::tsize_t);
4859: return e;
4860: }
4861:
4862: Expression *interpret_aaKeys(InterState *istate, Expressions *arguments)
4863: {
4864: #if LOG
4865: printf("interpret_aaKeys()\n");
4866: #endif
4867: if (!arguments || arguments->dim != 2)
4868: return NULL;
4869: Expression *earg = arguments->tdata()[0];
4870: earg = earg->interpret(istate);
4871: if (earg == EXP_CANT_INTERPRET)
4872: return NULL;
4873: if (earg->op == TOKnull)
4874: return new NullExp(earg->loc);
4875: if (earg->op != TOKassocarrayliteral && earg->type->toBasetype()->ty != Taarray)
4876: return NULL;
4877: AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg;
4878: Expression *e = new ArrayLiteralExp(aae->loc, aae->keys);
4879: Type *elemType = ((TypeAArray *)aae->type)->index;
4880: e->type = new TypeSArray(elemType, new IntegerExp(arguments ? arguments->dim : 0));
4881: return copyLiteral(e);
4882: }
4883:
4884: Expression *interpret_aaValues(InterState *istate, Expressions *arguments)
4885: {
4886: #if LOG
4887: printf("interpret_aaValues()\n");
4888: #endif
4889: if (!arguments || arguments->dim != 3)
4890: return NULL;
4891: Expression *earg = arguments->tdata()[0];
4892: earg = earg->interpret(istate);
4893: if (earg == EXP_CANT_INTERPRET)
4894: return NULL;
4895: if (earg->op == TOKnull)
4896: return new NullExp(earg->loc);
4897: if (earg->op != TOKassocarrayliteral && earg->type->toBasetype()->ty != Taarray)
4898: return NULL;
4899: AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg;
4900: Expression *e = new ArrayLiteralExp(aae->loc, aae->values);
4901: Type *elemType = ((TypeAArray *)aae->type)->next;
4902: e->type = new TypeSArray(elemType, new IntegerExp(arguments ? arguments->dim : 0));
4903: //printf("result is %s\n", e->toChars());
4904: return copyLiteral(e);
4905: }
4906:
4907: #endif
4908:
4909: #if DMDV2
4910:
4911: Expression *interpret_length(InterState *istate, Expression *earg)
4912: {
4913: //printf("interpret_length()\n");
4914: earg = earg->interpret(istate);
4915: if (earg == EXP_CANT_INTERPRET)
4916: return NULL;
4917: if (earg->op != TOKassocarrayliteral)
4918: return NULL;
4919: AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg;
4920: Expression *e = new IntegerExp(aae->loc, aae->keys->dim, Type::tsize_t);
4921: return e;
4922: }
4923:
4924: Expression *interpret_keys(InterState *istate, Expression *earg, FuncDeclaration *fd)
4925: {
4926: #if LOG
4927: printf("interpret_keys()\n");
4928: #endif
4929: earg = earg->interpret(istate);
4930: if (earg == EXP_CANT_INTERPRET)
4931: return NULL;
4932: if (earg->op == TOKnull)
4933: return new NullExp(earg->loc);
4934: if (earg->op != TOKassocarrayliteral && earg->type->toBasetype()->ty != Taarray)
4935: return NULL;
4936: assert(earg->op == TOKassocarrayliteral);
4937: AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg;
4938: Expression *e = new ArrayLiteralExp(aae->loc, aae->keys);
4939: assert(fd->type->ty == Tfunction);
4940: assert(fd->type->nextOf()->ty == Tarray);
4941: Type *elemType = ((TypeFunction *)fd->type)->nextOf()->nextOf();
4942: e->type = new TypeSArray(elemType, new IntegerExp(aae->keys->dim));
4943: return copyLiteral(e);
4944: }
4945:
4946: Expression *interpret_values(InterState *istate, Expression *earg, FuncDeclaration *fd)
4947: {
4948: #if LOG
4949: printf("interpret_values()\n");
4950: #endif
4951: earg = earg->interpret(istate);
4952: if (earg == EXP_CANT_INTERPRET)
4953: return NULL;
4954: if (earg->op == TOKnull)
4955: return new NullExp(earg->loc);
4956: if (earg->op != TOKassocarrayliteral && earg->type->toBasetype()->ty != Taarray)
4957: return NULL;
4958: assert(earg->op == TOKassocarrayliteral);
4959: AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg;
4960: Expression *e = new ArrayLiteralExp(aae->loc, aae->values);
4961: assert(fd->type->ty == Tfunction);
4962: assert(fd->type->nextOf()->ty == Tarray);
4963: Type *elemType = ((TypeFunction *)fd->type)->nextOf()->nextOf();
4964: e->type = new TypeSArray(elemType, new IntegerExp(aae->values->dim));
4965: //printf("result is %s\n", e->toChars());
4966: return copyLiteral(e);
4967: }
4968:
4969: #endif
4970:
4971: #if DMDV2
4972: // Return true if t is an AA, or AssociativeArray!(key, value)
4973: bool isAssocArray(Type *t)
4974: {
4975: t = t->toBasetype();
4976: if (t->ty == Taarray)
4977: return true;
4978: if (t->ty != Tstruct)
4979: return false;
4980: StructDeclaration *sym = ((TypeStruct *)t)->sym;
4981: if (sym->ident == Id::AssociativeArray)
4982: return true;
4983: return false;
4984: }
4985: #endif
4986:
4987: /* Decoding UTF strings for foreach loops. Duplicates the functionality of
4988: * the twelve _aApplyXXn functions in aApply.d in the runtime.
4989: */
4990: Expression *foreachApplyUtf(InterState *istate, Expression *str, Expression *deleg, bool rvs)
4991: {
4992: #if LOG
4993: printf("foreachApplyUtf(%s, %s)\n", str->toChars(), deleg->toChars());
4994: #endif
4995: FuncDeclaration *fd;
4996: Expression *pthis = NULL;
4997: if (deleg->op == TOKdelegate)
4998: {
4999: fd = ((DelegateExp *)deleg)->func;
5000: pthis = ((DelegateExp *)deleg)->e1;
5001: }
5002: else if (deleg->op == TOKfunction)
5003: fd = ((FuncExp*)deleg)->fd;
5004:
5005: assert(fd && fd->fbody);
warning C6001: Using uninitialized memory 'fd': Lines: 4995, 4996, 4997, 5002, 5005
5006: assert(fd->parameters);
5007: int numParams = fd->parameters->dim;
5008: assert(numParams == 1 || numParams==2);
5009: Type *charType = fd->parameters->tdata()[numParams-1]->type;
5010: Type *indexType = numParams == 2 ? fd->parameters->tdata()[0]->type
5011: : Type::tsize_t;
5012: uinteger_t len = resolveArrayLength(str);
5013: if (len == 0)
5014: return new IntegerExp(deleg->loc, 0, indexType);
5015:
5016: if (str->op == TOKslice)
5017: str = resolveSlice(str);
5018:
5019: StringExp *se = NULL;
5020: ArrayLiteralExp *ale = NULL;
5021: if (str->op == TOKstring)
5022: se = (StringExp *) str;
5023: else if (str->op == TOKarrayliteral)
5024: ale = (ArrayLiteralExp *)str;
5025: else
5026: { error("CTFE internal error: cannot foreach %s", str->toChars());
5027: return EXP_CANT_INTERPRET;
5028: }
5029: Expressions args;
5030: args.setDim(numParams);
5031:
5032: Expression *eresult;
5033:
5034: // Buffers for encoding; also used for decoding array literals
5035: unsigned char utf8buf[4];
5036: unsigned short utf16buf[2];
5037:
5038: size_t start = rvs ? len : 0;
warning C4244: 'initializing' : conversion from 'uinteger_t' to 'size_t', possible loss of data
5039: size_t end = rvs ? 0: len;
warning C4244: 'initializing' : conversion from 'uinteger_t' to 'size_t', possible loss of data
5040: for (size_t indx = start; indx != end;)
5041: {
5042: // Step 1: Decode the next dchar from the string.
5043:
5044: const char *errmsg = NULL; // Used for reporting decoding errors
5045: dchar_t rawvalue; // Holds the decoded dchar
5046:
5047: if (ale)
5048: { // If it is an array literal, copy the code points into the buffer
5049: int buflen = 1; // #code points in the buffer
5050: size_t n = 1; // #code points in this char
5051: int sz = ale->type->nextOf()->size();
warning C4244: 'initializing' : conversion from 'd_uns64' to 'int', possible loss of data
5052:
5053: switch(sz)
5054: {
5055: case 1:
5056: if (rvs)
5057: { // find the start of the string
5058: --indx;
5059: buflen = 1;
5060: while (indx > 0 && buflen < 4)
5061: { Expression * r = ale->elements->tdata()[indx];
5062: assert(r->op == TOKint64);
5063: unsigned char x = ((IntegerExp *)r)->value;
warning C4244: 'initializing' : conversion from 'dinteger_t' to 'unsigned char', possible loss of data
5064: if ( (x & 0xC0) != 0x80)
5065: break;
5066: ++buflen;
5067: }
5068: }
5069: else
5070: buflen = (indx + 4 > len) ? len - indx : 4;
warning C4244: '=' : conversion from 'uinteger_t' to 'int', possible loss of data
5071: for (int i=0; i < buflen; ++i)
5072: {
5073: Expression * r = ale->elements->tdata()[indx + i];
5074: assert(r->op == TOKint64);
5075: utf8buf[i] = ((IntegerExp *)r)->value;
warning C4244: '=' : conversion from 'dinteger_t' to 'unsigned char', possible loss of data
5076: }
5077: n = 0;
5078: errmsg = utf_decodeChar(&utf8buf[0], buflen, &n, &rawvalue);
5079: break;
5080: case 2:
5081: if (rvs)
5082: { // find the start of the string
5083: --indx;
5084: buflen = 1;
5085: Expression * r = ale->elements->tdata()[indx];
5086: assert(r->op == TOKint64);
5087: unsigned short x = ((IntegerExp *)r)->value;
warning C4244: 'initializing' : conversion from 'dinteger_t' to 'unsigned short', possible loss of data
5088: if (indx > 0 && x >= 0xDC00 && x <= 0xDFFF)
5089: {
5090: --indx;
5091: ++buflen;
5092: }
5093: }
5094: else
5095: buflen = (indx + 2 > len) ? len - indx : 2;
warning C4244: '=' : conversion from 'uinteger_t' to 'int', possible loss of data
5096: for (int i=0; i < buflen; ++i)
5097: {
5098: Expression * r = ale->elements->tdata()[indx + i];
5099: assert(r->op == TOKint64);
5100: utf16buf[i] = ((IntegerExp *)r)->value;
warning C4244: '=' : conversion from 'dinteger_t' to 'unsigned short', possible loss of data
5101: }
5102: n = 0;
5103: errmsg = utf_decodeWchar(&utf16buf[0], buflen, &n, &rawvalue);
5104: break;
5105: case 4:
5106: {
5107: if (rvs)
5108: --indx;
5109:
5110: Expression * r = ale->elements->tdata()[indx];
5111: assert(r->op == TOKint64);
5112: rawvalue = ((IntegerExp *)r)->value;
warning C4244: '=' : conversion from 'dinteger_t' to 'dchar_t', possible loss of data
5113: n = 1;
5114: }
5115: break;
5116: default:
5117: assert(0);
5118: }
5119: if (!rvs)
5120: indx += n;
5121: }
5122: else
5123: { // String literals
5124: size_t saveindx; // used for reverse iteration
5125:
5126: switch (se->sz)
5127: {
5128: case 1:
5129: if (rvs)
5130: { // find the start of the string
5131: unsigned char *s = (unsigned char *)se->string;
5132: --indx;
5133: while (indx > 0 && ((s[indx]&0xC0)==0x80))
5134: --indx;
5135: saveindx = indx;
5136: }
5137: errmsg = utf_decodeChar((unsigned char *)se->string, se->len, &indx, &rawvalue);
5138: if (rvs)
5139: indx = saveindx;
5140: break;
5141: case 2:
5142: if (rvs)
5143: { // find the start
5144: unsigned short *s = (unsigned short *)se->string;
5145: --indx;
5146: if (s[indx] >= 0xDC00 && s[indx]<= 0xDFFF)
5147: --indx;
5148: saveindx = indx;
5149: }
5150: errmsg = utf_decodeWchar((unsigned short *)se->string, se->len, &indx, &rawvalue);
5151: if (rvs)
5152: indx = saveindx;
5153: break;
5154: case 4:
5155: if (rvs)
5156: --indx;
5157: rawvalue = ((unsigned *)(se->string))[indx];
5158: if (!rvs)
5159: ++indx;
5160: break;
5161: default:
5162: assert(0);
5163: }
5164: }
5165: if (errmsg)
5166: { deleg->error("%s", errmsg);
5167: return EXP_CANT_INTERPRET;
5168: }
5169:
5170: // Step 2: encode the dchar in the target encoding
5171:
5172: int charlen = 1; // How many codepoints are involved?
5173: switch(charType->size())
5174: {
5175: case 1:
5176: charlen = utf_codeLengthChar(rawvalue);
5177: utf_encodeChar(&utf8buf[0], rawvalue);
5178: break;
5179: case 2:
5180: charlen = utf_codeLengthWchar(rawvalue);
5181: utf_encodeWchar(&utf16buf[0], rawvalue);
5182: break;
5183: case 4:
5184: break;
5185: default:
5186: assert(0);
5187: }
5188:
5189:
5190: // Step 3: call the delegate once for each code point
5191:
5192: // The index only needs to be set once
5193: if (numParams == 2)
5194: args.tdata()[0] = new IntegerExp(deleg->loc, indx, indexType);
5195:
5196: Expression *val = NULL;
5197:
5198: for (int k= 0; k < charlen; ++k)
5199: {
5200: dchar_t codepoint;
5201: switch(charType->size())
5202: {
5203: case 1:
5204: codepoint = utf8buf[k];
5205: break;
5206: case 2:
5207: codepoint = utf16buf[k];
5208: break;
5209: case 4:
5210: codepoint = rawvalue;
5211: break;
5212: default:
5213: assert(0);
5214: }
5215: val = new IntegerExp(str->loc, codepoint, charType);
5216:
5217: args.tdata()[numParams - 1] = val;
5218:
5219: eresult = fd->interpret(istate, &args, pthis);
5220: if (eresult == EXP_CANT_INTERPRET)
5221: return EXP_CANT_INTERPRET;
5222:
5223: assert(eresult->op == TOKint64);
5224: if (((IntegerExp *)eresult)->value != 0)
5225: return eresult;
5226: }
5227: }
5228: return eresult;
5229: }
5230:
5231: /* If this is a built-in function, set 'result' to the interpreted result,
5232: * and return true.
5233: * Otherwise, return false
5234: */
5235: bool evaluateIfBuiltin(Expression **result, InterState *istate,
5236: FuncDeclaration *fd, Expressions *arguments, Expression *pthis)
5237: {
5238: Expression *e = NULL;
5239: int nargs = arguments ? arguments->dim : 0;
5240: #if DMDV2
5241: if (pthis && isAssocArray(pthis->type) && nargs==0)
5242: {
5243: if (fd->ident == Id::length)
5244: e = interpret_length(istate, pthis);
5245: else if (fd->ident == Id::keys)
5246: e = interpret_keys(istate, pthis, fd);
5247: else if (fd->ident == Id::values)
5248: e = interpret_values(istate, pthis, fd);
5249: else if (fd->ident == Id::rehash)
5250: e = pthis; // rehash is a no-op
5251: }
5252: if (!pthis)
5253: {
5254: enum BUILTIN b = fd->isBuiltin();
5255: if (b)
5256: { Expressions args;
5257: args.setDim(arguments->dim);
warning C6011: Dereferencing NULL pointer 'arguments': Lines: 5238, 5239, 5241, 5252, 5254, 5255, 5256, 5257
5258: for (size_t i = 0; i < args.dim; i++)
5259: {
5260: Expression *earg = arguments->tdata()[i];
5261: earg = earg->interpret(istate);
5262: if (earg == EXP_CANT_INTERPRET)
5263: return earg;
warning C4800: 'Expression *' : forcing value to bool 'true' or 'false' (performance warning)
5264: args.tdata()[i] = earg;
5265: }
5266: e = eval_builtin(b, &args);
5267: if (!e)
5268: e = EXP_CANT_INTERPRET;
5269: }
5270: }
5271: #endif
5272: #if DMDV1
5273: if (!pthis)
5274: {
5275: if (fd->ident == Id::aaLen)
5276: e = interpret_aaLen(istate, arguments);
5277: else if (fd->ident == Id::aaKeys)
5278: e = interpret_aaKeys(istate, arguments);
5279: else if (fd->ident == Id::aaValues)
5280: e = interpret_aaValues(istate, arguments);
5281: else if (fd->ident == Id::aaRehash && nargs == 2)
5282: { // rehash is a no-op
5283: Expression *earg = (Expression *)(arguments->data[0]);
5284: return earg->interpret(istate, ctfeNeedLvalue);
5285: }
5286: }
5287: #endif
5288: if (!pthis)
5289: {
5290: size_t idlen = strlen(fd->ident->string);
5291: if (nargs == 2 && (idlen == 10 || idlen == 11)
5292: && !strncmp(fd->ident->string, "_aApply", 7))
5293: { // Functions from aApply.d and aApplyR.d in the runtime
5294: bool rvs = (idlen == 11); // true if foreach_reverse
5295: char c = fd->ident->string[idlen-3]; // char width: 'c', 'w', or 'd'
5296: char s = fd->ident->string[idlen-2]; // string width: 'c', 'w', or 'd'
5297: char n = fd->ident->string[idlen-1]; // numParams: 1 or 2.
5298: // There are 12 combinations
5299: if ( (n == '1' || n == '2') &&
5300: (c == 'c' || c == 'w' || c == 'd') &&
5301: (s == 'c' || s == 'w' || s == 'd') && c != s)
5302: { Expression *str = arguments->tdata()[0];
5303: str = str->interpret(istate);
5304: if (str == EXP_CANT_INTERPRET)
5305: {
5306: *result = EXP_CANT_INTERPRET;
5307: return true;
5308: }
5309: *result = foreachApplyUtf(istate, str, arguments->tdata()[1], rvs);
5310: return true;
5311: }
5312: }
5313: }
5314: if (!e)
5315: return false;
5316: *result = e;
5317: return true;
5318: }
5319:
5320: /*************************** CTFE Sanity Checks ***************************/
5321:
5322: /* Setter functions for CTFE variable values.
5323: * These functions exist to check for compiler CTFE bugs.
5324: */
5325:
5326: bool isStackValueValid(Expression *newval)
5327: {
5328: if (newval->type->ty == Tpointer && newval->type->nextOf()->ty != Tfunction)
5329: {
5330: if (newval->op == TOKaddress || newval->op == TOKnull ||
5331: newval->op == TOKstring)
5332: return true;
5333: if (newval->op == TOKindex)
5334: {
5335: Expression *g = ((IndexExp *)newval)->e1;
5336: if (g->op == TOKarrayliteral || g->op == TOKstring ||
5337: g->op == TOKassocarrayliteral)
5338: return true;
5339: }
5340: if (newval->op == TOKvar)
5341: return true;
5342: if (newval->type->nextOf()->ty == Tarray && newval->op == TOKslice)
5343: return true;
5344: newval->error("CTFE internal error: illegal pointer value %s\n", newval->toChars());
5345: return false;
5346: }
5347: if ((newval->op ==TOKarrayliteral) || ( newval->op==TOKstructliteral) ||
5348: (newval->op==TOKstring) || (newval->op == TOKassocarrayliteral) ||
5349: (newval->op == TOKnull) || (newval->op == TOKslice))
5350: { return false;
5351: }
5352: if (newval->op == TOKvar)
5353: {
5354: VarExp *ve = (VarExp *)newval;
5355: VarDeclaration *vv = ve->var->isVarDeclaration();
5356: // Must not be a reference to a reference
5357: if (!(vv && vv->getValue() && vv->getValue()->op == TOKvar))
5358: return true;
5359: }
5360: if (newval->op == TOKdotvar)
5361: {
5362: if (((DotVarExp *)newval)->e1->op == TOKstructliteral)
5363: return true;
5364: }
5365: if (newval->op == TOKindex)
5366: {
5367: IndexExp *ie = (IndexExp *)newval;
5368: if (ie->e2->op == TOKint64)
5369: {
5370: if (ie->e1->op == TOKarrayliteral || ie->e1->op == TOKstring)
5371: return true;
5372: }
5373: if (ie->e1->op == TOKassocarrayliteral)
5374: return true;
5375: // BUG: Happens ONLY in ref foreach. Should tighten this.
5376: if (ie->e2->op == TOKvar)
5377: return true;
5378: }
5379: if (newval->op == TOKfunction) return true; // function/delegate literal
5380: if (newval->op == TOKdelegate) return true;
5381: if (newval->op == TOKsymoff) // function pointer
5382: {
5383: if (((SymOffExp *)newval)->var->isFuncDeclaration())
5384: return true;
5385: }
5386: if (newval->op == TOKint64 || newval->op == TOKfloat64 ||
5387: newval->op == TOKchar || newval->op == TOKcomplex80)
5388: return true;
5389: newval->error("CTFE internal error: illegal stack value %s\n", newval->toChars());
5390: return false;
5391: }
5392:
5393: bool isRefValueValid(Expression *newval)
5394: {
5395: assert(newval);
5396: if ((newval->op ==TOKarrayliteral) || ( newval->op==TOKstructliteral) ||
5397: (newval->op==TOKstring) || (newval->op == TOKassocarrayliteral) ||
5398: (newval->op == TOKnull))
5399: { return true;
5400: }
5401: // Dynamic arrays passed by ref may be null. When this happens
5402: // they may originate from an index or dotvar expression.
5403: if (newval->type->ty == Tarray || newval->type->ty == Taarray
5404: || newval->type->ty == Tclass)
5405: if (newval->op == TOKdotvar || newval->op == TOKindex)
5406: return isStackValueValid(newval); // actually must be null
5407: if (newval->op == TOKslice)
5408: {
5409: SliceExp *se = (SliceExp *)newval;
5410: assert(se->lwr && se->lwr != EXP_CANT_INTERPRET && se->lwr->op == TOKint64);
5411: assert(se->upr && se->upr != EXP_CANT_INTERPRET && se->upr->op == TOKint64);
5412: assert(se->e1->op == TOKarrayliteral || se->e1->op == TOKstring);
5413: return true;
5414: }
5415: newval->error("CTFE internal error: illegal reference value %s\n", newval->toChars());
5416: return false;
5417: }
5418:
5419: void VarDeclaration::setValueNull()
5420: {
5421: literalvalue = NULL;
5422: }
5423:
5424: // Don't check for validity
5425: void VarDeclaration::setValueWithoutChecking(Expression *newval)
5426: {
5427: assert(!newval || isStackValueValid(newval) || isRefValueValid(newval));
5428: literalvalue = newval;
5429: }
5430: void VarDeclaration::createRefValue(Expression *newval)
5431: {
5432: assert(!literalvalue);
5433: assert(isRefValueValid(newval));
5434: literalvalue = newval;
5435: }
5436:
5437: void VarDeclaration::setRefValue(Expression *newval)
5438: {
5439: assert(literalvalue);
5440: assert(isRefValueValid(newval));
5441: literalvalue = newval;
5442: }
5443:
5444: void VarDeclaration::setStackValue(Expression *newval)
5445: {
5446: assert(literalvalue);
5447: assert(isStackValueValid(newval));
5448: literalvalue = newval;
5449: }
5450: void VarDeclaration::createStackValue(Expression *newval)
5451: {
5452: assert(!literalvalue);
5453: assert(isStackValueValid(newval));
5454: literalvalue = newval;
5455: }
5456: