annotate dmd/interpret.c @ 884:a166ba5bdf2d

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