PageRenderTime 56ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/d/dmd/statement.c

https://bitbucket.org/goshawk/gdc/
C | 4560 lines | 3578 code | 633 blank | 349 comment | 668 complexity | 8cffde6f3962fa6c60ceb278ef036e82 MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0

Large files files are truncated, but you can click here to view the full file

  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. /* NOTE: This file has been patched from the original DMD distribution to
  10. work with the GDC compiler.
  11. Modified by Michael Parrott, September 2009
  12. Using David Friedman's code
  13. */
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <assert.h>
  17. #include "rmem.h"
  18. #include "statement.h"
  19. #include "expression.h"
  20. #include "cond.h"
  21. #include "init.h"
  22. #include "staticassert.h"
  23. #include "mtype.h"
  24. #include "scope.h"
  25. #include "declaration.h"
  26. #include "aggregate.h"
  27. #include "id.h"
  28. #include "hdrgen.h"
  29. #include "parse.h"
  30. #include "template.h"
  31. #include "attrib.h"
  32. #if _WIN32
  33. #include <windows.h>
  34. #define CRITSECSIZE sizeof(CRITICAL_SECTION)
  35. #elif linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4
  36. #include <pthread.h>
  37. #define CRITSECSIZE sizeof(pthread_mutex_t)
  38. #else
  39. #define CRITSECSIZE 64
  40. #endif
  41. /******************************** Statement ***************************/
  42. Statement::Statement(Loc loc)
  43. : loc(loc)
  44. {
  45. // If this is an in{} contract scope statement (skip for determining
  46. // inlineStatus of a function body for header content)
  47. incontract = 0;
  48. }
  49. Statement *Statement::syntaxCopy()
  50. {
  51. assert(0);
  52. return NULL;
  53. }
  54. void Statement::print()
  55. {
  56. fprintf(stdmsg, "%s\n", toChars());
  57. fflush(stdmsg);
  58. }
  59. char *Statement::toChars()
  60. { OutBuffer *buf;
  61. HdrGenState hgs;
  62. buf = new OutBuffer();
  63. toCBuffer(buf, &hgs);
  64. return buf->toChars();
  65. }
  66. void Statement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  67. {
  68. buf->printf("Statement::toCBuffer()");
  69. buf->writenl();
  70. }
  71. Statement *Statement::semantic(Scope *sc)
  72. {
  73. return this;
  74. }
  75. Statement *Statement::semanticNoScope(Scope *sc)
  76. {
  77. //printf("Statement::semanticNoScope() %s\n", toChars());
  78. Statement *s = this;
  79. if (!s->isCompoundStatement() && !s->isScopeStatement())
  80. {
  81. s = new CompoundStatement(loc, this); // so scopeCode() gets called
  82. }
  83. s = s->semantic(sc);
  84. return s;
  85. }
  86. // Same as semanticNoScope(), but do create a new scope
  87. Statement *Statement::semanticScope(Scope *sc, Statement *sbreak, Statement *scontinue)
  88. {
  89. Scope *scd = sc->push();
  90. if (sbreak)
  91. scd->sbreak = sbreak;
  92. if (scontinue)
  93. scd->scontinue = scontinue;
  94. Statement *s = semanticNoScope(scd);
  95. scd->pop();
  96. return s;
  97. }
  98. void Statement::error(const char *format, ...)
  99. {
  100. va_list ap;
  101. va_start(ap, format);
  102. ::verror(loc, format, ap);
  103. va_end( ap );
  104. }
  105. void Statement::warning(const char *format, ...)
  106. {
  107. va_list ap;
  108. va_start(ap, format);
  109. ::vwarning(loc, format, ap);
  110. va_end( ap );
  111. }
  112. int Statement::hasBreak()
  113. {
  114. //printf("Statement::hasBreak()\n");
  115. return FALSE;
  116. }
  117. int Statement::hasContinue()
  118. {
  119. return FALSE;
  120. }
  121. // TRUE if statement uses exception handling
  122. int Statement::usesEH()
  123. {
  124. return FALSE;
  125. }
  126. /* Only valid after semantic analysis
  127. */
  128. int Statement::blockExit(bool mustNotThrow)
  129. {
  130. printf("Statement::blockExit(%p)\n", this);
  131. printf("%s\n", toChars());
  132. assert(0);
  133. return BEany;
  134. }
  135. // TRUE if statement 'comes from' somewhere else, like a goto
  136. int Statement::comeFrom()
  137. {
  138. //printf("Statement::comeFrom()\n");
  139. return FALSE;
  140. }
  141. // Return TRUE if statement has no code in it
  142. int Statement::isEmpty()
  143. {
  144. //printf("Statement::isEmpty()\n");
  145. return FALSE;
  146. }
  147. /****************************************
  148. * If this statement has code that needs to run in a finally clause
  149. * at the end of the current scope, return that code in the form of
  150. * a Statement.
  151. * Output:
  152. * *sentry code executed upon entry to the scope
  153. * *sexception code executed upon exit from the scope via exception
  154. * *sfinally code executed in finally block
  155. */
  156. void Statement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
  157. {
  158. //printf("Statement::scopeCode()\n");
  159. //print();
  160. *sentry = NULL;
  161. *sexception = NULL;
  162. *sfinally = NULL;
  163. }
  164. /*********************************
  165. * Flatten out the scope by presenting the statement
  166. * as an array of statements.
  167. * Returns NULL if no flattening necessary.
  168. */
  169. Statements *Statement::flatten(Scope *sc)
  170. {
  171. return NULL;
  172. }
  173. /******************************** PeelStatement ***************************/
  174. PeelStatement::PeelStatement(Statement *s)
  175. : Statement(s->loc)
  176. {
  177. this->s = s;
  178. }
  179. Statement *PeelStatement::semantic(Scope *sc)
  180. {
  181. /* "peel" off this wrapper, and don't run semantic()
  182. * on the result.
  183. */
  184. return s;
  185. }
  186. /******************************** ExpStatement ***************************/
  187. ExpStatement::ExpStatement(Loc loc, Expression *exp)
  188. : Statement(loc)
  189. {
  190. this->exp = exp;
  191. }
  192. ExpStatement::ExpStatement(Loc loc, Dsymbol *declaration)
  193. : Statement(loc)
  194. {
  195. this->exp = new DeclarationExp(loc, declaration);
  196. }
  197. Statement *ExpStatement::syntaxCopy()
  198. {
  199. Expression *e = exp ? exp->syntaxCopy() : NULL;
  200. ExpStatement *es = new ExpStatement(loc, e);
  201. return es;
  202. }
  203. void ExpStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  204. {
  205. if (exp)
  206. { exp->toCBuffer(buf, hgs);
  207. if (exp->op != TOKdeclaration)
  208. { buf->writeByte(';');
  209. if (!hgs->FLinit.init)
  210. buf->writenl();
  211. }
  212. }
  213. else
  214. {
  215. buf->writeByte(';');
  216. if (!hgs->FLinit.init)
  217. buf->writenl();
  218. }
  219. }
  220. Statement *ExpStatement::semantic(Scope *sc)
  221. {
  222. if (exp)
  223. {
  224. //printf("ExpStatement::semantic() %s\n", exp->toChars());
  225. exp = exp->semantic(sc);
  226. exp = resolveProperties(sc, exp);
  227. exp->checkSideEffect(0);
  228. exp = exp->optimize(0);
  229. }
  230. return this;
  231. }
  232. int ExpStatement::blockExit(bool mustNotThrow)
  233. { int result = BEfallthru;
  234. if (exp)
  235. {
  236. if (exp->op == TOKhalt)
  237. return BEhalt;
  238. if (exp->op == TOKassert)
  239. { AssertExp *a = (AssertExp *)exp;
  240. if (a->e1->isBool(FALSE)) // if it's an assert(0)
  241. return BEhalt;
  242. }
  243. if (exp->canThrow())
  244. result |= BEthrow;
  245. }
  246. return result;
  247. }
  248. int ExpStatement::isEmpty()
  249. {
  250. return exp == NULL;
  251. }
  252. void ExpStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
  253. {
  254. //printf("ExpStatement::scopeCode()\n");
  255. //print();
  256. *sentry = NULL;
  257. *sexception = NULL;
  258. *sfinally = NULL;
  259. if (exp)
  260. {
  261. if (exp->op == TOKdeclaration)
  262. {
  263. DeclarationExp *de = (DeclarationExp *)(exp);
  264. VarDeclaration *v = de->declaration->isVarDeclaration();
  265. if (v)
  266. { Expression *e;
  267. e = v->callScopeDtor(sc);
  268. if (e)
  269. {
  270. //printf("dtor is: "); e->print();
  271. #if 0
  272. if (v->type->toBasetype()->ty == Tstruct)
  273. { /* Need a 'gate' to turn on/off destruction,
  274. * in case v gets moved elsewhere.
  275. */
  276. Identifier *id = Lexer::uniqueId("__runDtor");
  277. ExpInitializer *ie = new ExpInitializer(loc, new IntegerExp(1));
  278. VarDeclaration *rd = new VarDeclaration(loc, Type::tint32, id, ie);
  279. *sentry = new ExpStatement(loc, rd);
  280. v->rundtor = rd;
  281. /* Rewrite e as:
  282. * rundtor && e
  283. */
  284. Expression *ve = new VarExp(loc, v->rundtor);
  285. e = new AndAndExp(loc, ve, e);
  286. e->type = Type::tbool;
  287. }
  288. #endif
  289. *sfinally = new ExpStatement(loc, e);
  290. }
  291. }
  292. }
  293. }
  294. }
  295. /******************************** CompileStatement ***************************/
  296. CompileStatement::CompileStatement(Loc loc, Expression *exp)
  297. : Statement(loc)
  298. {
  299. this->exp = exp;
  300. }
  301. Statement *CompileStatement::syntaxCopy()
  302. {
  303. Expression *e = exp->syntaxCopy();
  304. CompileStatement *es = new CompileStatement(loc, e);
  305. return es;
  306. }
  307. void CompileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  308. {
  309. buf->writestring("mixin(");
  310. exp->toCBuffer(buf, hgs);
  311. buf->writestring(");");
  312. if (!hgs->FLinit.init)
  313. buf->writenl();
  314. }
  315. Statements *CompileStatement::flatten(Scope *sc)
  316. {
  317. //printf("CompileStatement::flatten() %s\n", exp->toChars());
  318. exp = exp->semantic(sc);
  319. exp = resolveProperties(sc, exp);
  320. exp = exp->optimize(WANTvalue | WANTinterpret);
  321. if (exp->op == TOKerror)
  322. return NULL;
  323. StringExp *se = exp->toString();
  324. if (!se)
  325. { error("argument to mixin must be a string, not (%s)", exp->toChars());
  326. return NULL;
  327. }
  328. se = se->toUTF8(sc);
  329. Parser p(sc->module, (unsigned char *)se->string, se->len, 0);
  330. p.loc = loc;
  331. p.nextToken();
  332. Statements *a = new Statements();
  333. while (p.token.value != TOKeof)
  334. {
  335. Statement *s = p.parseStatement(PSsemi | PScurlyscope);
  336. if (s) // if no parsing errors
  337. a->push(s);
  338. }
  339. return a;
  340. }
  341. Statement *CompileStatement::semantic(Scope *sc)
  342. {
  343. //printf("CompileStatement::semantic() %s\n", exp->toChars());
  344. Statements *a = flatten(sc);
  345. if (!a)
  346. return NULL;
  347. Statement *s = new CompoundStatement(loc, a);
  348. return s->semantic(sc);
  349. }
  350. /******************************** CompoundStatement ***************************/
  351. CompoundStatement::CompoundStatement(Loc loc, Statements *s)
  352. : Statement(loc)
  353. {
  354. statements = s;
  355. }
  356. CompoundStatement::CompoundStatement(Loc loc, Statement *s1, Statement *s2)
  357. : Statement(loc)
  358. {
  359. statements = new Statements();
  360. statements->reserve(2);
  361. statements->push(s1);
  362. statements->push(s2);
  363. }
  364. CompoundStatement::CompoundStatement(Loc loc, Statement *s1)
  365. : Statement(loc)
  366. {
  367. statements = new Statements();
  368. statements->push(s1);
  369. }
  370. Statement *CompoundStatement::syntaxCopy()
  371. {
  372. Statements *a = new Statements();
  373. a->setDim(statements->dim);
  374. for (size_t i = 0; i < statements->dim; i++)
  375. { Statement *s = (Statement *)statements->data[i];
  376. if (s)
  377. s = s->syntaxCopy();
  378. a->data[i] = s;
  379. }
  380. CompoundStatement *cs = new CompoundStatement(loc, a);
  381. return cs;
  382. }
  383. Statement *CompoundStatement::semantic(Scope *sc)
  384. { Statement *s;
  385. //printf("CompoundStatement::semantic(this = %p, sc = %p)\n", this, sc);
  386. for (size_t i = 0; i < statements->dim; )
  387. {
  388. s = (Statement *) statements->data[i];
  389. if (s)
  390. { Statements *a = s->flatten(sc);
  391. if (a)
  392. {
  393. statements->remove(i);
  394. statements->insert(i, a);
  395. continue;
  396. }
  397. s = s->semantic(sc);
  398. statements->data[i] = s;
  399. if (s)
  400. {
  401. Statement *sentry;
  402. Statement *sexception;
  403. Statement *sfinally;
  404. s->scopeCode(sc, &sentry, &sexception, &sfinally);
  405. if (sentry)
  406. {
  407. sentry = sentry->semantic(sc);
  408. statements->data[i] = sentry;
  409. }
  410. if (sexception)
  411. {
  412. if (i + 1 == statements->dim && !sfinally)
  413. {
  414. #if 1
  415. sexception = sexception->semantic(sc);
  416. #else
  417. statements->push(sexception);
  418. if (sfinally)
  419. // Assume sexception does not throw
  420. statements->push(sfinally);
  421. #endif
  422. }
  423. else
  424. {
  425. /* Rewrite:
  426. * s; s1; s2;
  427. * As:
  428. * s;
  429. * try { s1; s2; }
  430. * catch (Object __o)
  431. * { sexception; throw __o; }
  432. */
  433. Statement *body;
  434. Statements *a = new Statements();
  435. for (size_t j = i + 1; j < statements->dim; j++)
  436. {
  437. a->push((*statements)[j]);
  438. }
  439. body = new CompoundStatement(0, a);
  440. body = new ScopeStatement(0, body);
  441. Identifier *id = Lexer::uniqueId("__o");
  442. Statement *handler = new ThrowStatement(0, new IdentifierExp(0, id));
  443. handler = new CompoundStatement(0, sexception, handler);
  444. Array *catches = new Array();
  445. Catch *ctch = new Catch(0, NULL, id, handler);
  446. catches->push(ctch);
  447. s = new TryCatchStatement(0, body, catches);
  448. if (sfinally)
  449. s = new TryFinallyStatement(0, s, sfinally);
  450. s = s->semantic(sc);
  451. statements->setDim(i + 1);
  452. statements->push(s);
  453. break;
  454. }
  455. }
  456. else if (sfinally)
  457. {
  458. if (0 && i + 1 == statements->dim)
  459. {
  460. statements->push(sfinally);
  461. }
  462. else
  463. {
  464. /* Rewrite:
  465. * s; s1; s2;
  466. * As:
  467. * s; try { s1; s2; } finally { sfinally; }
  468. */
  469. Statement *body;
  470. Statements *a = new Statements();
  471. for (size_t j = i + 1; j < statements->dim; j++)
  472. {
  473. a->push((*statements)[j]);
  474. }
  475. body = new CompoundStatement(0, a);
  476. s = new TryFinallyStatement(0, body, sfinally);
  477. s = s->semantic(sc);
  478. statements->setDim(i + 1);
  479. statements->push(s);
  480. break;
  481. }
  482. }
  483. }
  484. }
  485. i++;
  486. }
  487. if (statements->dim == 1)
  488. {
  489. return (*statements)[0];
  490. }
  491. return this;
  492. }
  493. Statements *CompoundStatement::flatten(Scope *sc)
  494. {
  495. return statements;
  496. }
  497. ReturnStatement *CompoundStatement::isReturnStatement()
  498. {
  499. ReturnStatement *rs = NULL;
  500. for (size_t i = 0; i < statements->dim; i++)
  501. { Statement *s = (*statements)[i];
  502. if (s)
  503. {
  504. rs = s->isReturnStatement();
  505. if (rs)
  506. break;
  507. }
  508. }
  509. return rs;
  510. }
  511. void CompoundStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  512. {
  513. for (size_t i = 0; i < statements->dim; i++)
  514. { Statement *s = (Statement *) statements->data[i];
  515. if (s)
  516. s->toCBuffer(buf, hgs);
  517. }
  518. }
  519. int CompoundStatement::usesEH()
  520. {
  521. for (size_t i = 0; i < statements->dim; i++)
  522. { Statement *s = (Statement *) statements->data[i];
  523. if (s && s->usesEH())
  524. return TRUE;
  525. }
  526. return FALSE;
  527. }
  528. int CompoundStatement::blockExit(bool mustNotThrow)
  529. {
  530. //printf("CompoundStatement::blockExit(%p) %d\n", this, statements->dim);
  531. int result = BEfallthru;
  532. for (size_t i = 0; i < statements->dim; i++)
  533. { Statement *s = (Statement *) statements->data[i];
  534. if (s)
  535. {
  536. //printf("result = x%x\n", result);
  537. //printf("%s\n", s->toChars());
  538. if (!(result & BEfallthru) && !s->comeFrom())
  539. {
  540. if (s->blockExit(mustNotThrow) != BEhalt && !s->isEmpty())
  541. s->warning("statement is not reachable");
  542. }
  543. else
  544. {
  545. result &= ~BEfallthru;
  546. result |= s->blockExit(mustNotThrow);
  547. }
  548. }
  549. }
  550. return result;
  551. }
  552. int CompoundStatement::comeFrom()
  553. { int comefrom = FALSE;
  554. //printf("CompoundStatement::comeFrom()\n");
  555. for (size_t i = 0; i < statements->dim; i++)
  556. { Statement *s = (Statement *)statements->data[i];
  557. if (!s)
  558. continue;
  559. comefrom |= s->comeFrom();
  560. }
  561. return comefrom;
  562. }
  563. int CompoundStatement::isEmpty()
  564. {
  565. for (size_t i = 0; i < statements->dim; i++)
  566. { Statement *s = (Statement *) statements->data[i];
  567. if (s && !s->isEmpty())
  568. return FALSE;
  569. }
  570. return TRUE;
  571. }
  572. /******************************** CompoundDeclarationStatement ***************************/
  573. CompoundDeclarationStatement::CompoundDeclarationStatement(Loc loc, Statements *s)
  574. : CompoundStatement(loc, s)
  575. {
  576. statements = s;
  577. }
  578. Statement *CompoundDeclarationStatement::syntaxCopy()
  579. {
  580. Statements *a = new Statements();
  581. a->setDim(statements->dim);
  582. for (size_t i = 0; i < statements->dim; i++)
  583. { Statement *s = (Statement *)statements->data[i];
  584. if (s)
  585. s = s->syntaxCopy();
  586. a->data[i] = s;
  587. }
  588. CompoundDeclarationStatement *cs = new CompoundDeclarationStatement(loc, a);
  589. return cs;
  590. }
  591. void CompoundDeclarationStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  592. {
  593. int nwritten = 0;
  594. for (size_t i = 0; i < statements->dim; i++)
  595. { Statement *s = (Statement *) statements->data[i];
  596. ExpStatement *ds;
  597. if (s &&
  598. (ds = s->isExpStatement()) != NULL &&
  599. ds->exp->op == TOKdeclaration)
  600. {
  601. DeclarationExp *de = (DeclarationExp *)ds->exp;
  602. assert(de->op == TOKdeclaration);
  603. Declaration *d = de->declaration->isDeclaration();
  604. assert(d);
  605. VarDeclaration *v = d->isVarDeclaration();
  606. if (v)
  607. {
  608. /* This essentially copies the part of VarDeclaration::toCBuffer()
  609. * that does not print the type.
  610. * Should refactor this.
  611. */
  612. if (nwritten)
  613. {
  614. buf->writeByte(',');
  615. buf->writestring(v->ident->toChars());
  616. }
  617. else
  618. {
  619. StorageClassDeclaration::stcToCBuffer(buf, v->storage_class);
  620. if (v->type)
  621. v->type->toCBuffer(buf, v->ident, hgs);
  622. else
  623. buf->writestring(v->ident->toChars());
  624. }
  625. if (v->init)
  626. { buf->writestring(" = ");
  627. #if DMDV2
  628. ExpInitializer *ie = v->init->isExpInitializer();
  629. if (ie && (ie->exp->op == TOKconstruct || ie->exp->op == TOKblit))
  630. ((AssignExp *)ie->exp)->e2->toCBuffer(buf, hgs);
  631. else
  632. #endif
  633. v->init->toCBuffer(buf, hgs);
  634. }
  635. }
  636. else
  637. d->toCBuffer(buf, hgs);
  638. nwritten++;
  639. }
  640. }
  641. buf->writeByte(';');
  642. if (!hgs->FLinit.init)
  643. buf->writenl();
  644. }
  645. /**************************** UnrolledLoopStatement ***************************/
  646. UnrolledLoopStatement::UnrolledLoopStatement(Loc loc, Statements *s)
  647. : Statement(loc)
  648. {
  649. statements = s;
  650. }
  651. Statement *UnrolledLoopStatement::syntaxCopy()
  652. {
  653. Statements *a = new Statements();
  654. a->setDim(statements->dim);
  655. for (size_t i = 0; i < statements->dim; i++)
  656. { Statement *s = (Statement *)statements->data[i];
  657. if (s)
  658. s = s->syntaxCopy();
  659. a->data[i] = s;
  660. }
  661. UnrolledLoopStatement *cs = new UnrolledLoopStatement(loc, a);
  662. return cs;
  663. }
  664. Statement *UnrolledLoopStatement::semantic(Scope *sc)
  665. {
  666. //printf("UnrolledLoopStatement::semantic(this = %p, sc = %p)\n", this, sc);
  667. sc->noctor++;
  668. Scope *scd = sc->push();
  669. scd->sbreak = this;
  670. scd->scontinue = this;
  671. for (size_t i = 0; i < statements->dim; i++)
  672. {
  673. Statement *s = (Statement *) statements->data[i];
  674. if (s)
  675. {
  676. //printf("[%d]: %s\n", i, s->toChars());
  677. s = s->semantic(scd);
  678. statements->data[i] = s;
  679. }
  680. }
  681. scd->pop();
  682. sc->noctor--;
  683. return this;
  684. }
  685. void UnrolledLoopStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  686. {
  687. buf->writestring("unrolled {");
  688. buf->writenl();
  689. for (size_t i = 0; i < statements->dim; i++)
  690. { Statement *s;
  691. s = (Statement *) statements->data[i];
  692. if (s)
  693. s->toCBuffer(buf, hgs);
  694. }
  695. buf->writeByte('}');
  696. buf->writenl();
  697. }
  698. int UnrolledLoopStatement::hasBreak()
  699. {
  700. return TRUE;
  701. }
  702. int UnrolledLoopStatement::hasContinue()
  703. {
  704. return TRUE;
  705. }
  706. int UnrolledLoopStatement::usesEH()
  707. {
  708. for (size_t i = 0; i < statements->dim; i++)
  709. { Statement *s = (Statement *) statements->data[i];
  710. if (s && s->usesEH())
  711. return TRUE;
  712. }
  713. return FALSE;
  714. }
  715. int UnrolledLoopStatement::blockExit(bool mustNotThrow)
  716. {
  717. int result = BEfallthru;
  718. for (size_t i = 0; i < statements->dim; i++)
  719. { Statement *s = (Statement *) statements->data[i];
  720. if (s)
  721. {
  722. int r = s->blockExit(mustNotThrow);
  723. result |= r & ~(BEbreak | BEcontinue);
  724. }
  725. }
  726. return result;
  727. }
  728. int UnrolledLoopStatement::comeFrom()
  729. { int comefrom = FALSE;
  730. //printf("UnrolledLoopStatement::comeFrom()\n");
  731. for (size_t i = 0; i < statements->dim; i++)
  732. { Statement *s = (Statement *)statements->data[i];
  733. if (!s)
  734. continue;
  735. comefrom |= s->comeFrom();
  736. }
  737. return comefrom;
  738. }
  739. /******************************** ScopeStatement ***************************/
  740. ScopeStatement::ScopeStatement(Loc loc, Statement *s)
  741. : Statement(loc)
  742. {
  743. this->statement = s;
  744. }
  745. Statement *ScopeStatement::syntaxCopy()
  746. {
  747. Statement *s;
  748. s = statement ? statement->syntaxCopy() : NULL;
  749. s = new ScopeStatement(loc, s);
  750. return s;
  751. }
  752. Statement *ScopeStatement::semantic(Scope *sc)
  753. { ScopeDsymbol *sym;
  754. //printf("ScopeStatement::semantic(sc = %p)\n", sc);
  755. if (statement)
  756. { Statements *a;
  757. sym = new ScopeDsymbol();
  758. sym->parent = sc->scopesym;
  759. sc = sc->push(sym);
  760. a = statement->flatten(sc);
  761. if (a)
  762. {
  763. statement = new CompoundStatement(loc, a);
  764. }
  765. statement = statement->semantic(sc);
  766. if (statement)
  767. {
  768. Statement *sentry;
  769. Statement *sexception;
  770. Statement *sfinally;
  771. statement->scopeCode(sc, &sentry, &sexception, &sfinally);
  772. if (sfinally)
  773. {
  774. //printf("adding sfinally\n");
  775. sfinally = sfinally->semantic(sc);
  776. statement = new CompoundStatement(loc, statement, sfinally);
  777. }
  778. }
  779. sc->pop();
  780. }
  781. return this;
  782. }
  783. int ScopeStatement::hasBreak()
  784. {
  785. //printf("ScopeStatement::hasBreak() %s\n", toChars());
  786. return statement ? statement->hasBreak() : FALSE;
  787. }
  788. int ScopeStatement::hasContinue()
  789. {
  790. return statement ? statement->hasContinue() : FALSE;
  791. }
  792. int ScopeStatement::usesEH()
  793. {
  794. return statement ? statement->usesEH() : FALSE;
  795. }
  796. int ScopeStatement::blockExit(bool mustNotThrow)
  797. {
  798. //printf("ScopeStatement::blockExit(%p)\n", statement);
  799. return statement ? statement->blockExit(mustNotThrow) : BEfallthru;
  800. }
  801. int ScopeStatement::comeFrom()
  802. {
  803. //printf("ScopeStatement::comeFrom()\n");
  804. return statement ? statement->comeFrom() : FALSE;
  805. }
  806. int ScopeStatement::isEmpty()
  807. {
  808. //printf("ScopeStatement::isEmpty() %d\n", statement ? statement->isEmpty() : TRUE);
  809. return statement ? statement->isEmpty() : TRUE;
  810. }
  811. void ScopeStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  812. {
  813. buf->writeByte('{');
  814. buf->writenl();
  815. if (statement)
  816. statement->toCBuffer(buf, hgs);
  817. buf->writeByte('}');
  818. buf->writenl();
  819. }
  820. /******************************** WhileStatement ***************************/
  821. WhileStatement::WhileStatement(Loc loc, Expression *c, Statement *b)
  822. : Statement(loc)
  823. {
  824. condition = c;
  825. body = b;
  826. }
  827. Statement *WhileStatement::syntaxCopy()
  828. {
  829. WhileStatement *s = new WhileStatement(loc, condition->syntaxCopy(), body ? body->syntaxCopy() : NULL);
  830. return s;
  831. }
  832. Statement *WhileStatement::semantic(Scope *sc)
  833. {
  834. /* Rewrite as a for(;condition;) loop
  835. */
  836. Statement *s = new ForStatement(loc, NULL, condition, NULL, body);
  837. s = s->semantic(sc);
  838. return s;
  839. }
  840. int WhileStatement::hasBreak()
  841. {
  842. return TRUE;
  843. }
  844. int WhileStatement::hasContinue()
  845. {
  846. return TRUE;
  847. }
  848. int WhileStatement::usesEH()
  849. {
  850. assert(0);
  851. return body ? body->usesEH() : 0;
  852. }
  853. int WhileStatement::blockExit(bool mustNotThrow)
  854. {
  855. assert(0);
  856. //printf("WhileStatement::blockExit(%p)\n", this);
  857. int result = BEnone;
  858. if (condition->canThrow())
  859. result |= BEthrow;
  860. if (condition->isBool(TRUE))
  861. {
  862. if (body)
  863. { result |= body->blockExit(mustNotThrow);
  864. if (result & BEbreak)
  865. result |= BEfallthru;
  866. }
  867. }
  868. else if (condition->isBool(FALSE))
  869. {
  870. result |= BEfallthru;
  871. }
  872. else
  873. {
  874. if (body)
  875. result |= body->blockExit(mustNotThrow);
  876. result |= BEfallthru;
  877. }
  878. result &= ~(BEbreak | BEcontinue);
  879. return result;
  880. }
  881. int WhileStatement::comeFrom()
  882. {
  883. assert(0);
  884. if (body)
  885. return body->comeFrom();
  886. return FALSE;
  887. }
  888. void WhileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  889. {
  890. buf->writestring("while (");
  891. condition->toCBuffer(buf, hgs);
  892. buf->writebyte(')');
  893. buf->writenl();
  894. if (body)
  895. body->toCBuffer(buf, hgs);
  896. }
  897. /******************************** DoStatement ***************************/
  898. DoStatement::DoStatement(Loc loc, Statement *b, Expression *c)
  899. : Statement(loc)
  900. {
  901. body = b;
  902. condition = c;
  903. }
  904. Statement *DoStatement::syntaxCopy()
  905. {
  906. DoStatement *s = new DoStatement(loc, body ? body->syntaxCopy() : NULL, condition->syntaxCopy());
  907. return s;
  908. }
  909. Statement *DoStatement::semantic(Scope *sc)
  910. {
  911. sc->noctor++;
  912. if (body)
  913. body = body->semanticScope(sc, this, this);
  914. sc->noctor--;
  915. condition = condition->semantic(sc);
  916. condition = resolveProperties(sc, condition);
  917. condition = condition->optimize(WANTvalue);
  918. condition = condition->checkToBoolean();
  919. return this;
  920. }
  921. int DoStatement::hasBreak()
  922. {
  923. return TRUE;
  924. }
  925. int DoStatement::hasContinue()
  926. {
  927. return TRUE;
  928. }
  929. int DoStatement::usesEH()
  930. {
  931. return body ? body->usesEH() : 0;
  932. }
  933. int DoStatement::blockExit(bool mustNotThrow)
  934. { int result;
  935. if (body)
  936. { result = body->blockExit(mustNotThrow);
  937. if (result == BEbreak)
  938. return BEfallthru;
  939. if (result & BEcontinue)
  940. result |= BEfallthru;
  941. }
  942. else
  943. result = BEfallthru;
  944. if (result & BEfallthru)
  945. {
  946. if (condition->canThrow())
  947. result |= BEthrow;
  948. if (!(result & BEbreak) && condition->isBool(TRUE))
  949. result &= ~BEfallthru;
  950. }
  951. result &= ~(BEbreak | BEcontinue);
  952. return result;
  953. }
  954. int DoStatement::comeFrom()
  955. {
  956. if (body)
  957. return body->comeFrom();
  958. return FALSE;
  959. }
  960. void DoStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  961. {
  962. buf->writestring("do");
  963. buf->writenl();
  964. if (body)
  965. body->toCBuffer(buf, hgs);
  966. buf->writestring("while (");
  967. condition->toCBuffer(buf, hgs);
  968. buf->writebyte(')');
  969. }
  970. /******************************** ForStatement ***************************/
  971. ForStatement::ForStatement(Loc loc, Statement *init, Expression *condition, Expression *increment, Statement *body)
  972. : Statement(loc)
  973. {
  974. this->init = init;
  975. this->condition = condition;
  976. this->increment = increment;
  977. this->body = body;
  978. }
  979. Statement *ForStatement::syntaxCopy()
  980. {
  981. Statement *i = NULL;
  982. if (init)
  983. i = init->syntaxCopy();
  984. Expression *c = NULL;
  985. if (condition)
  986. c = condition->syntaxCopy();
  987. Expression *inc = NULL;
  988. if (increment)
  989. inc = increment->syntaxCopy();
  990. ForStatement *s = new ForStatement(loc, i, c, inc, body->syntaxCopy());
  991. return s;
  992. }
  993. Statement *ForStatement::semantic(Scope *sc)
  994. {
  995. ScopeDsymbol *sym = new ScopeDsymbol();
  996. sym->parent = sc->scopesym;
  997. sc = sc->push(sym);
  998. if (init)
  999. init = init->semantic(sc);
  1000. #if 0
  1001. if (!condition)
  1002. // Use a default value
  1003. condition = new IntegerExp(loc, 1, Type::tboolean);
  1004. #endif
  1005. sc->noctor++;
  1006. if (condition)
  1007. {
  1008. condition = condition->semantic(sc);
  1009. condition = resolveProperties(sc, condition);
  1010. condition = condition->optimize(WANTvalue);
  1011. condition = condition->checkToBoolean();
  1012. }
  1013. if (increment)
  1014. { increment = increment->semantic(sc);
  1015. increment = resolveProperties(sc, increment);
  1016. increment = increment->optimize(0);
  1017. }
  1018. sc->sbreak = this;
  1019. sc->scontinue = this;
  1020. if (body)
  1021. body = body->semanticNoScope(sc);
  1022. sc->noctor--;
  1023. sc->pop();
  1024. return this;
  1025. }
  1026. void ForStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
  1027. {
  1028. //printf("ForStatement::scopeCode()\n");
  1029. //print();
  1030. if (init)
  1031. init->scopeCode(sc, sentry, sexception, sfinally);
  1032. else
  1033. Statement::scopeCode(sc, sentry, sexception, sfinally);
  1034. }
  1035. int ForStatement::hasBreak()
  1036. {
  1037. //printf("ForStatement::hasBreak()\n");
  1038. return TRUE;
  1039. }
  1040. int ForStatement::hasContinue()
  1041. {
  1042. return TRUE;
  1043. }
  1044. int ForStatement::usesEH()
  1045. {
  1046. return (init && init->usesEH()) || body->usesEH();
  1047. }
  1048. int ForStatement::blockExit(bool mustNotThrow)
  1049. { int result = BEfallthru;
  1050. if (init)
  1051. { result = init->blockExit(mustNotThrow);
  1052. if (!(result & BEfallthru))
  1053. return result;
  1054. }
  1055. if (condition)
  1056. { if (condition->canThrow())
  1057. result |= BEthrow;
  1058. if (condition->isBool(TRUE))
  1059. result &= ~BEfallthru;
  1060. else if (condition->isBool(FALSE))
  1061. return result;
  1062. }
  1063. else
  1064. result &= ~BEfallthru; // the body must do the exiting
  1065. if (body)
  1066. { int r = body->blockExit(mustNotThrow);
  1067. if (r & (BEbreak | BEgoto))
  1068. result |= BEfallthru;
  1069. result |= r & ~(BEfallthru | BEbreak | BEcontinue);
  1070. }
  1071. if (increment && increment->canThrow())
  1072. result |= BEthrow;
  1073. return result;
  1074. }
  1075. int ForStatement::comeFrom()
  1076. {
  1077. //printf("ForStatement::comeFrom()\n");
  1078. if (body)
  1079. { int result = body->comeFrom();
  1080. //printf("result = %d\n", result);
  1081. return result;
  1082. }
  1083. return FALSE;
  1084. }
  1085. void ForStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
  1086. {
  1087. buf->writestring("for (");
  1088. if (init)
  1089. {
  1090. hgs->FLinit.init++;
  1091. init->toCBuffer(buf, hgs);
  1092. hgs->FLinit.init--;
  1093. }
  1094. else
  1095. buf->writebyte(';');
  1096. if (condition)
  1097. { buf->writebyte(' ');
  1098. condition->toCBuffer(buf, hgs);
  1099. }
  1100. buf->writebyte(';');
  1101. if (increment)
  1102. { buf->writebyte(' ');
  1103. increment->toCBuffer(buf, hgs);
  1104. }
  1105. buf->writebyte(')');
  1106. buf->writenl();
  1107. buf->writebyte('{');
  1108. buf->writenl();
  1109. body->toCBuffer(buf, hgs);
  1110. buf->writebyte('}');
  1111. buf->writenl();
  1112. }
  1113. /******************************** ForeachStatement ***************************/
  1114. ForeachStatement::ForeachStatement(Loc loc, enum TOK op, Parameters *arguments,
  1115. Expression *aggr, Statement *body)
  1116. : Statement(loc)
  1117. {
  1118. this->op = op;
  1119. this->arguments = arguments;
  1120. this->aggr = aggr;
  1121. this->body = body;
  1122. this->key = NULL;
  1123. this->value = NULL;
  1124. this->func = NULL;
  1125. this->cases = NULL;
  1126. this->gotos = NULL;
  1127. }
  1128. Statement *ForeachStatement::syntaxCopy()
  1129. {
  1130. //printf("ForeachStatement::syntaxCopy()\n");
  1131. Parameters *args = Parameter::arraySyntaxCopy(arguments);
  1132. Expression *exp = aggr->syntaxCopy();
  1133. ForeachStatement *s = new ForeachStatement(loc, op, args, exp,
  1134. body ? body->syntaxCopy() : NULL);
  1135. return s;
  1136. }
  1137. Statement *ForeachStatement::semantic(Scope *sc)
  1138. {
  1139. //printf("ForeachStatement::semantic() %p\n", this);
  1140. ScopeDsymbol *sym;
  1141. Statement *s = this;
  1142. size_t dim = arguments->dim;
  1143. TypeAArray *taa = NULL;
  1144. Type *tn = NULL;
  1145. Type *tnv = NULL;
  1146. func = sc->func;
  1147. if (func->fes)
  1148. func = func->fes->func;
  1149. aggr = aggr->semantic(sc);
  1150. aggr = resolveProperties(sc, aggr);
  1151. aggr = aggr->optimize(WANTvalue);
  1152. if (!aggr->type)
  1153. {
  1154. error("invalid foreach aggregate %s", aggr->toChars());
  1155. return this;
  1156. }
  1157. inferApplyArgTypes(op, arguments, aggr);
  1158. /* Check for inference errors
  1159. */
  1160. if (dim != arguments->dim)
  1161. {
  1162. //printf("dim = %d, arguments->dim = %d\n", dim, arguments->dim);
  1163. error("cannot uniquely infer foreach argument types");
  1164. return this;
  1165. }
  1166. Type *tab = aggr->type->toBasetype();
  1167. if (tab->ty == Ttuple) // don't generate new scope for tuple loops
  1168. {
  1169. if (dim < 1 || dim > 2)
  1170. {
  1171. error("only one (value) or two (key,value) arguments for tuple foreach");
  1172. return s;
  1173. }
  1174. TypeTuple *tuple = (TypeTuple *)tab;
  1175. Statements *statements = new Statements();
  1176. //printf("aggr: op = %d, %s\n", aggr->op, aggr->toChars());
  1177. size_t n;
  1178. TupleExp *te = NULL;
  1179. if (aggr->op == TOKtuple) // expression tuple
  1180. { te = (TupleExp *)aggr;
  1181. n = te->exps->dim;
  1182. }
  1183. else if (aggr->op == TOKtype) // type tuple
  1184. {
  1185. n = Parameter::dim(tuple->arguments);
  1186. }
  1187. else
  1188. assert(0);
  1189. for (size_t j = 0; j < n; j++)
  1190. { size_t k = (op == TOKforeach) ? j : n - 1 - j;
  1191. Expression *e;
  1192. Type *t;
  1193. if (te)
  1194. e = te->exps->tdata()[k];
  1195. else
  1196. t = Parameter::getNth(tuple->arguments, k)->type;
  1197. Parameter *arg = arguments->tdata()[0];
  1198. Statements *st = new Statements();
  1199. if (dim == 2)
  1200. { // Declare key
  1201. if (arg->storageClass & (STCout | STCref | STClazy))
  1202. error("no storage class for key %s", arg->ident->toChars());
  1203. arg->type = arg->type->semantic(loc, sc);
  1204. TY keyty = arg->type->ty;
  1205. if (keyty != Tint32 && keyty != Tuns32)
  1206. {
  1207. if (global.params.is64bit)
  1208. {
  1209. if (keyty != Tint64 && keyty != Tuns64)
  1210. error("foreach: key type must be int or uint, long or ulong, not %s", arg->type->toChars());
  1211. }
  1212. else
  1213. error("foreach: key type must be int or uint, not %s", arg->type->toChars());
  1214. }
  1215. Initializer *ie = new ExpInitializer(0, new IntegerExp(k));
  1216. VarDeclaration *var = new VarDeclaration(loc, arg->type, arg->ident, ie);
  1217. var->storage_class |= STCconst;
  1218. DeclarationExp *de = new DeclarationExp(loc, var);
  1219. st->push(new ExpStatement(loc, de));
  1220. arg = (*arguments)[1]; // value
  1221. }
  1222. // Declare value
  1223. if (arg->storageClass & (STCout | STCref | STClazy))
  1224. error("no storage class for value %s", arg->ident->toChars());
  1225. Dsymbol *var;
  1226. if (te)
  1227. { Type *tb = e->type->toBasetype();
  1228. Dsymbol *s = NULL;
  1229. if ((tb->ty == Tfunction || tb->ty == Tsarray) && e->op == TOKvar)
  1230. s = ((VarExp *)e)->var;
  1231. else if (e->op == TOKtemplate)
  1232. s =((TemplateExp *)e)->td;
  1233. else if (e->op == TOKimport)
  1234. s =((ScopeExp *)e)->sds;
  1235. if (s)
  1236. var = new AliasDeclaration(loc, arg->ident, s);
  1237. else
  1238. {
  1239. arg->type = e->type;
  1240. Initializer *ie = new ExpInitializer(0, e);
  1241. VarDeclaration *v = new VarDeclaration(loc, arg->type, arg->ident, ie);
  1242. if (e->isConst() || e->op == TOKstring)
  1243. v->storage_class |= STCconst;
  1244. var = v;
  1245. }
  1246. }
  1247. else
  1248. {
  1249. var = new AliasDeclaration(loc, arg->ident, t);
  1250. }
  1251. DeclarationExp *de = new DeclarationExp(loc, var);
  1252. st->push(new ExpStatement(loc, de));
  1253. st->push(body->syntaxCopy());
  1254. s = new CompoundStatement(loc, st);
  1255. s = new ScopeStatement(loc, s);
  1256. statements->push(s);
  1257. }
  1258. s = new UnrolledLoopStatement(loc, statements);
  1259. s = s->semantic(sc);
  1260. return s;
  1261. }
  1262. for (size_t i = 0; i < dim; i++)
  1263. { Parameter *arg = (Parameter *)arguments->data[i];
  1264. if (!arg->type)
  1265. {
  1266. error("cannot infer type for %s", arg->ident->toChars());
  1267. return this;
  1268. }
  1269. }
  1270. sym = new ScopeDsymbol();
  1271. sym->parent = sc->scopesym;
  1272. sc = sc->push(sym);
  1273. sc->noctor++;
  1274. switch (tab->ty)
  1275. {
  1276. case Tarray:
  1277. case Tsarray:
  1278. if (dim < 1 || dim > 2)
  1279. {
  1280. error("only one or two arguments for array foreach");
  1281. break;
  1282. }
  1283. /* Look for special case of parsing char types out of char type
  1284. * array.
  1285. */
  1286. tn = tab->nextOf()->toBasetype();
  1287. if (tn->ty == Tchar || tn->ty == Twchar || tn->ty == Tdchar)
  1288. { Parameter *arg;
  1289. int i = (dim == 1) ? 0 : 1; // index of value
  1290. arg = (Parameter *)arguments->data[i];
  1291. arg->type = arg->type->semantic(loc, sc);
  1292. tnv = arg->type->toBasetype();
  1293. if (tnv->ty != tn->ty &&
  1294. (tnv->ty == Tchar || tnv->ty == Twchar || tnv->ty == Tdchar))
  1295. {
  1296. if (arg->storageClass & STCref)
  1297. error("foreach: value of UTF conversion cannot be ref");
  1298. if (dim == 2)
  1299. { arg = (Parameter *)arguments->data[0];
  1300. if (arg->storageClass & STCref)
  1301. error("foreach: key cannot be ref");
  1302. }
  1303. goto Lapply;
  1304. }
  1305. }
  1306. for (size_t i = 0; i < dim; i++)
  1307. { // Declare args
  1308. Parameter *arg = (Parameter *)arguments->data[i];
  1309. Type *argtype = arg->type->semantic(loc, sc);
  1310. VarDeclaration *var;
  1311. var = new VarDeclaration(loc, argtype, arg->ident, NULL);
  1312. var->storage_class |= STCforeach;
  1313. var->storage_class |= arg->storageClass & (STCin | STCout | STCref);
  1314. if (dim == 2 && i == 0)
  1315. key = var;
  1316. else
  1317. value = var;
  1318. #if 0
  1319. DeclarationExp *de = new DeclarationExp(loc, var);
  1320. de->semantic(sc);
  1321. #endif
  1322. }
  1323. #if 1
  1324. {
  1325. /* Convert to a ForStatement
  1326. * foreach (key, value; a) body =>
  1327. * for (T[] tmp = a[], size_t key; key < tmp.length; ++key)
  1328. * { T value = tmp[k]; body }
  1329. *
  1330. * foreach_reverse (key, value; a) body =>
  1331. * for (T[] tmp = a[], size_t key = tmp.length; key--; )
  1332. * { T value = tmp[k]; body }
  1333. */
  1334. Identifier *id = Lexer::uniqueId("__aggr");
  1335. ExpInitializer *ie = new ExpInitializer(loc, new SliceExp(loc, aggr, NULL, NULL));
  1336. VarDeclaration *tmp = new VarDeclaration(loc, tab->nextOf()->arrayOf(), id, ie);
  1337. Expression *tmp_length = new DotIdExp(loc, new VarExp(loc, tmp), Id::length);
  1338. if (!key)
  1339. {
  1340. Identifier *idkey = Lexer::uniqueId("__key");
  1341. key = new VarDeclaration(loc, Type::tsize_t, idkey, NULL);
  1342. }
  1343. if (op == TOKforeach_reverse)
  1344. key->init = new ExpInitializer(loc, tmp_length);
  1345. else
  1346. key->init = new ExpInitializer(loc, new IntegerExp(0));
  1347. Statements *cs = new Statements();
  1348. cs->push(new ExpStatement(loc, tmp));
  1349. cs->push(new ExpStatement(loc, key));
  1350. Statement *forinit = new CompoundDeclarationStatement(loc, cs);
  1351. Expression *cond;
  1352. if (op == TOKforeach_reverse)
  1353. // key--
  1354. cond = new PostExp(TOKminusminus, loc, new VarExp(loc, key));
  1355. else
  1356. // key < tmp.length
  1357. cond = new CmpExp(TOKlt, loc, new VarExp(loc, key), tmp_length);
  1358. Expression *increment = NULL;
  1359. if (op == TOKforeach)
  1360. // key += 1
  1361. increment = new AddAssignExp(loc, new VarExp(loc, key), new IntegerExp(1));
  1362. // T value = tmp[key];
  1363. value->init = new ExpInitializer(loc, new IndexExp(loc, new VarExp(loc, tmp), new VarExp(loc, key)));
  1364. Statement *ds = new ExpStatement(loc, value);
  1365. body = new CompoundStatement(loc, ds, body);
  1366. ForStatement *fs = new ForStatement(loc, forinit, cond, increment, body);
  1367. s = fs->semantic(sc);
  1368. break;
  1369. }
  1370. #else
  1371. if (!value->type->equals(tab->next))
  1372. {
  1373. if (aggr->op == TOKstring)
  1374. aggr = aggr->implicitCastTo(sc, value->type->arrayOf());
  1375. else
  1376. error("foreach: %s is not an array of %s",
  1377. tab->toChars(), value->type->toChars());
  1378. }
  1379. if (key)
  1380. {
  1381. if (key->type->ty != Tint32 && key->type->ty != Tuns32)
  1382. {
  1383. if (global.params.is64bit)
  1384. {
  1385. if (key->type->ty != Tint64 && key->type->ty != Tuns64)
  1386. error("foreach: key type must be int or uint, long or ulong, not %s", key->type->toChars());
  1387. }
  1388. else
  1389. error("foreach: key type must be int or uint, not %s", key->type->toChars());
  1390. }
  1391. if (key->storage_class & (STCout | STCref))
  1392. error("foreach: key cannot be out or ref");
  1393. }
  1394. sc->sbreak = this;
  1395. sc->scontinue = this;
  1396. body = body->semantic(sc);
  1397. break;
  1398. #endif
  1399. case Taarray:
  1400. taa = (TypeAArray *)tab;
  1401. if (dim < 1 || dim > 2)
  1402. {
  1403. error("only one or two arguments for associative array foreach");
  1404. break;
  1405. }
  1406. if (op == TOKforeach_reverse)
  1407. {
  1408. error("no reverse iteration on associative arrays");
  1409. }
  1410. goto Lapply;
  1411. case Tclass:
  1412. case Tstruct:
  1413. #if DMDV2
  1414. { /* Look for range iteration, i.e. the properties
  1415. * .empty, .next, .retreat, .head and .rear
  1416. * foreach (e; aggr) { ... }
  1417. * translates to:
  1418. * for (auto __r = aggr[]; !__r.empty; __r.next)
  1419. * { auto e = __r.head;
  1420. * ...
  1421. * }
  1422. */
  1423. if (dim != 1) // only one argument allowed with ranges
  1424. goto Lapply;
  1425. AggregateDeclaration *ad = (tab->ty == Tclass)
  1426. ? (AggregateDeclaration *)((TypeClass *)tab)->sym
  1427. : (AggregateDeclaration *)((TypeStruct *)tab)->sym;
  1428. Identifier *idhead;
  1429. Identifier *idnext;
  1430. if (op == TOKforeach)
  1431. { idhead = Id::Fhead;
  1432. idnext = Id::Fnext;
  1433. }
  1434. else
  1435. { idhead = Id::Ftoe;
  1436. idnext = Id::Fretreat;
  1437. }
  1438. Dsymbol *shead = search_function(ad, idhead);
  1439. if (!shead)
  1440. goto Lapply;
  1441. /* Generate a temporary __r and initialize it with the aggregate.
  1442. */
  1443. Identifier *id = Identifier::generateId("__r");
  1444. Expression *rinit = new SliceExp(loc, aggr, NULL, NULL);
  1445. rinit = rinit->trySemantic(sc);
  1446. if (!rinit) // if application of [] failed
  1447. rinit = aggr;
  1448. VarDeclaration *r = new VarDeclaration(loc, NULL, id, new ExpInitializer(loc, rinit));
  1449. // r->semantic(sc);
  1450. //printf("r: %s, init: %s\n", r->toChars(), r->init->toChars());
  1451. Statement *init = new ExpStatement(loc, r);
  1452. //printf("init: %s\n", init->toChars());
  1453. // !__r.empty
  1454. Expression *e = new VarExp(loc, r);
  1455. e = new DotIdExp(loc, e, Id::Fempty);
  1456. Expression *condition = new NotExp(loc, e);
  1457. // __r.next
  1458. e = new VarExp(loc, r);
  1459. Expression *increment = new DotIdExp(loc, e, idnext);
  1460. /* Declaration statement for e:
  1461. * auto e = __r.idhead;
  1462. */
  1463. e = new VarExp(loc, r);
  1464. Expression *einit = new DotIdExp(loc, e, idhead);
  1465. // einit = einit->semantic(sc);
  1466. Parameter *arg = (Parameter *)arguments->data[0];
  1467. VarDeclaration *ve = new VarDeclaration(loc, arg->type, arg->ident, new ExpInitializer(loc, einit));
  1468. ve->storage_class |= STCforeach;
  1469. ve->storage_class |= arg->storageClass & (STCin | STCout | STCref | STC_TYPECTOR);
  1470. DeclarationExp *de = new DeclarationExp(loc, ve);
  1471. Statement *body = new CompoundStatement(loc,
  1472. new ExpStatement(loc, de), this->body);
  1473. s = new ForStatement(loc, init, condition, increment, body);
  1474. #if 0
  1475. printf("init: %s\n", init->toChars());
  1476. printf("condition: %s\n", condition->toChars());
  1477. printf("increment: %s\n", increment->toChars());
  1478. printf("body: %s\n", body->toChars());
  1479. #endif
  1480. s = s->semantic(sc);
  1481. break;
  1482. }
  1483. #endif
  1484. case Tdelegate:
  1485. Lapply:
  1486. {
  1487. Expression *ec;
  1488. Expression *e;
  1489. Parameter *a;
  1490. Type *tret = func->type->nextOf();
  1491. // Need a variable to hold value from any return statements in body.
  1492. if (!sc->func->vresult && tret && tret != Type::tvoid)
  1493. {
  1494. VarDeclaration *v = new VarDeclaration(loc, tret, Id::result, NULL);
  1495. v->noscope = 1;
  1496. v->semantic(sc);
  1497. if (!sc->insert(v))
  1498. assert(0);
  1499. v->parent = sc->func;
  1500. sc->func->vresult = v;
  1501. }
  1502. /* Turn body into the function literal:
  1503. * int delegate(ref T arg) { body }
  1504. */
  1505. Parameters *args = new Parameters();
  1506. for (size_t i = 0; i < dim; i++)
  1507. { Parameter *arg = (Parameter *)arguments->data[i];
  1508. Identifier *id;
  1509. arg->type = arg->type->semantic(loc, sc);
  1510. if (arg->storageClass & STCref)
  1511. id = arg->ident;
  1512. else
  1513. { // Make a copy of the ref argument so it isn't
  1514. // a reference.
  1515. id = Lexer::uniqueId("__applyArg", i);
  1516. Initializer *ie = new ExpInitializer(0, new IdentifierExp(0, id));
  1517. VarDeclaration *v = new VarDeclaration(0, arg->type, arg->ident, ie);
  1518. s = new ExpStatement(0, v);
  1519. body = new CompoundStatement(loc, s, body);
  1520. }
  1521. a = new Parameter(STCref, arg->type, id, NULL);
  1522. args->push(a);
  1523. }
  1524. Type *t = new TypeFunction(args, Type::tint32, 0, LINKd);
  1525. cases = new Statements();
  1526. gotos = new Array();
  1527. FuncLiteralDeclaration *fld = new FuncLiteralDeclaration(loc, 0, t, TOKdelegate, this);
  1528. fld->fbody = body;
  1529. Expression *flde = new FuncExp(loc, fld);
  1530. flde = flde->semantic(sc);
  1531. // Resolve any forward referenced goto's
  1532. for (size_t i = 0; i < gotos->dim; i++)
  1533. { CompoundStatement *cs = (CompoundStatement *)gotos->data[i];
  1534. GotoStatement *gs = (GotoStatement *)cs->statements->data[0];
  1535. if (!gs->label->statement)
  1536. { // 'Promote' it to this scope, and replace with a return
  1537. cases->push(gs);
  1538. s = new ReturnStatement(0, new IntegerExp(cases->dim + 1));
  1539. cs->statements->data[0] = (void *)s;
  1540. }
  1541. }
  1542. if (taa)
  1543. {
  1544. // Check types
  1545. Parameter *arg = (Parameter *)arguments->data[0];
  1546. if (dim == 2)
  1547. {
  1548. if (arg->storageClass & STCref)
  1549. error("foreach: index cannot be ref");
  1550. if (!arg->type->equals(taa->index))
  1551. error("foreach: ind…

Large files files are truncated, but you can click here to view the full file