Changeset 295
- Timestamp:
- 12/15/09 23:46:13 (15 years ago)
- Files:
-
- trunk/src/opover.c (modified) (1 diff)
- trunk/src/statement.c (modified) (5 diffs)
- trunk/src/template.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/src/opover.c
r269 r295 578 578 if (arguments->dim == 2) 579 579 { 580 580 if (!arg->type) 581 581 arg->type = taa->index; // key type 582 582 arg = (Parameter *)arguments->data[1]; 583 583 } 584 584 if (!arg->type) 585 585 arg->type = taa->next; // value type 586 586 break; 587 587 } 588 588 589 589 case Tclass: 590 590 ad = ((TypeClass *)tab)->sym; 591 591 goto Laggr; 592 592 593 593 case Tstruct: 594 594 ad = ((TypeStruct *)tab)->sym; 595 595 goto Laggr; 596 596 597 597 Laggr: 598 Dsymbol *s = search_function(ad, 599 (op == TOKforeach_reverse) ? Id::applyReverse 600 : Id::apply); 601 if (s) 602 goto Lapply; // prefer opApply 603 598 604 if (arguments->dim == 1) 599 605 { 600 606 if (!arg->type) 601 607 { 602 608 /* Look for a head() or rear() overload 603 609 */ 604 610 Identifier *id = (op == TOKforeach) ? Id::Fhead : Id::Ftoe; 605 611 Dsymbol *s = search_function(ad, id); 606 612 FuncDeclaration *fd = s ? s->isFuncDeclaration() : NULL; 607 613 if (!fd) 608 614 { if (s && s->isTemplateDeclaration()) 609 615 break; 610 616 goto Lapply; 611 617 } 612 618 arg->type = fd->type->nextOf(); 613 619 } 614 620 break; 615 621 } 616 622 617 623 Lapply: 618 624 { /* Look for an 619 625 * int opApply(int delegate(ref Type [, ...]) dg); 620 626 * overload 621 627 */ 622 Dsymbol *s = search_function(ad,623 (op == TOKforeach_reverse) ? Id::applyReverse624 : Id::apply);625 628 if (s) 626 629 { 627 630 FuncDeclaration *fd = s->isFuncDeclaration(); 628 631 if (fd) 629 632 { inferApplyArgTypesX(fd, arguments); 630 633 break; 631 634 } 632 635 #if 0 633 636 TemplateDeclaration *td = s->isTemplateDeclaration(); 634 637 if (td) 635 638 { inferApplyArgTypesZ(td, arguments); 636 639 break; 637 640 } 638 641 #endif 639 642 } 640 643 break; 641 644 } 642 645 643 646 case Tdelegate: 644 647 { trunk/src/statement.c
r273 r295 1290 1290 1291 1291 this->func = NULL; 1292 1292 } 1293 1293 1294 1294 Statement *ForeachStatement::syntaxCopy() 1295 1295 { 1296 1296 Parameters *args = Parameter::arraySyntaxCopy(arguments); 1297 1297 Expression *exp = aggr->syntaxCopy(); 1298 1298 ForeachStatement *s = new ForeachStatement(loc, op, args, exp, 1299 1299 body ? body->syntaxCopy() : NULL); 1300 1300 return s; 1301 1301 } 1302 1302 1303 1303 Statement *ForeachStatement::semantic(Scope *sc) 1304 1304 { 1305 1305 //printf("ForeachStatement::semantic() %p\n", this); 1306 1306 ScopeDsymbol *sym; 1307 1307 Statement *s = this; 1308 1308 size_t dim = arguments->dim; 1309 1309 TypeAArray *taa = NULL; 1310 Dsymbol *sapply = NULL; 1310 1311 1311 1312 Type *tn = NULL; 1312 1313 Type *tnv = NULL; 1313 1314 1314 1315 func = sc->func; 1315 1316 if (func->fes) 1316 1317 func = func->fes->func; 1317 1318 1318 1319 aggr = aggr->semantic(sc); 1319 1320 aggr = resolveProperties(sc, aggr); 1320 1321 aggr = aggr->optimize(WANTvalue); 1321 1322 if (!aggr->type) 1322 1323 { 1323 1324 error("invalid foreach aggregate %s", aggr->toChars()); 1324 1325 return this; 1325 1326 } 1326 1327 1327 1328 inferApplyArgTypes(op, arguments, aggr); 1328 1329 1329 1330 /* Check for inference errors … … 1421 1422 st->push(new ExpStatement(loc, de)); 1422 1423 1423 1424 st->push(body->syntaxCopy()); 1424 1425 s = new CompoundStatement(loc, st); 1425 1426 s = new ScopeStatement(loc, s); 1426 1427 statements->push(s); 1427 1428 } 1428 1429 1429 1430 s = new UnrolledLoopStatement(loc, statements); 1430 1431 s = s->semantic(sc); 1431 1432 return s; 1432 1433 } 1433 1434 1434 1435 sym = new ScopeDsymbol(); 1435 1436 sym->parent = sc->scopesym; 1436 1437 sc = sc->push(sym); 1437 1438 1438 1439 sc->noctor++; 1439 1440 1440 1441 Lagain: 1442 Identifier *idapply = (op == TOKforeach_reverse) 1443 ? Id::applyReverse : Id::apply; 1444 sapply = NULL; 1441 1445 switch (tab->ty) 1442 1446 { 1443 1447 case Tarray: 1444 1448 case Tsarray: 1445 1449 if (!checkForArgTypes()) 1446 1450 return this; 1447 1451 1448 1452 if (dim < 1 || dim > 2) 1449 1453 { 1450 1454 error("only one or two arguments for array foreach"); 1451 1455 break; 1452 1456 } 1453 1457 1454 1458 /* Look for special case of parsing char types out of char type 1455 1459 * array. 1456 1460 */ 1457 1461 tn = tab->nextOf()->toBasetype(); 1458 1462 if (tn->ty == Tchar || tn->ty == Twchar || tn->ty == Tdchar) 1459 1463 { Parameter *arg; 1460 1464 … … 1603 1607 if (dim < 1 || dim > 2) 1604 1608 { 1605 1609 error("only one or two arguments for associative array foreach"); 1606 1610 break; 1607 1611 } 1608 1612 #if SARRAYVALUE 1609 1613 /* This only works if Key or Value is a static array. 1610 1614 */ 1611 1615 tab = taa->getImpl()->type; 1612 1616 goto Lagain; 1613 1617 #else 1614 1618 if (op == TOKforeach_reverse) 1615 1619 { 1616 1620 error("no reverse iteration on associative arrays"); 1617 1621 } 1618 1622 goto Lapply; 1619 1623 #endif 1620 1624 case Tclass: 1621 1625 case Tstruct: 1622 1626 #if DMDV2 1627 /* Prefer using opApply, if it exists 1628 */ 1629 if (dim != 1) // only one argument allowed with ranges 1630 goto Lapply; 1631 1632 sapply = search_function((AggregateDeclaration *)tab->toDsymbol(sc), idapply); 1633 if (sapply) 1634 goto Lapply; 1635 1623 1636 { /* Look for range iteration, i.e. the properties 1624 1637 * .empty, .next, .retreat, .head and .rear 1625 1638 * foreach (e; aggr) { ... } 1626 1639 * translates to: 1627 1640 * for (auto __r = aggr[]; !__r.empty; __r.next) 1628 1641 * { auto e = __r.head; 1629 1642 * ... 1630 1643 * } 1631 1644 */ 1632 if (dim != 1) // only one argument allowed with ranges1633 goto Lapply;1634 1645 AggregateDeclaration *ad = (tab->ty == Tclass) 1635 1646 ? (AggregateDeclaration *)((TypeClass *)tab)->sym 1636 1647 : (AggregateDeclaration *)((TypeStruct *)tab)->sym; 1637 1648 Identifier *idhead; 1638 1649 Identifier *idnext; 1639 1650 if (op == TOKforeach) 1640 1651 { idhead = Id::Fhead; 1641 1652 idnext = Id::Fnext; 1642 1653 } 1643 1654 else 1644 1655 { idhead = Id::Ftoe; 1645 1656 idnext = Id::Fretreat; 1646 1657 } 1647 1658 Dsymbol *shead = search_function(ad, idhead); 1648 1659 if (!shead) 1649 1660 goto Lapply; 1650 1661 1651 1662 /* Generate a temporary __r and initialize it with the aggregate. 1652 1663 */ 1653 1664 Identifier *id = Identifier::generateId("__r"); … … 1682 1693 ve->storage_class |= arg->storageClass & (STCin | STCout | STCref | STC_TYPECTOR); 1683 1694 1684 1695 DeclarationExp *de = new DeclarationExp(loc, ve); 1685 1696 1686 1697 Statement *body = new CompoundStatement(loc, 1687 1698 new DeclarationStatement(loc, de), this->body); 1688 1699 1689 1700 s = new ForStatement(loc, init, condition, increment, body); 1690 1701 #if 0 1691 1702 printf("init: %s\n", init->toChars()); 1692 1703 printf("condition: %s\n", condition->toChars()); 1693 1704 printf("increment: %s\n", increment->toChars()); 1694 1705 printf("body: %s\n", body->toChars()); 1695 1706 #endif 1696 1707 s = s->semantic(sc); 1697 1708 break; 1698 1709 } 1699 1710 #endif 1700 1711 case Tdelegate: 1701 1712 Lapply: 1702 { FuncDeclaration *fdapply; 1703 Parameters *args; 1713 { 1704 1714 Expression *ec; 1705 1715 Expression *e; 1706 FuncLiteralDeclaration *fld;1707 1716 Parameter *a; 1708 Type *t;1709 Expression *flde;1710 Identifier *id;1711 Type *tret;1712 1717 1713 1718 if (!checkForArgTypes()) 1714 1719 { body = body->semantic(sc); 1715 1720 return this; 1716 1721 } 1717 1722 1718 tret = func->type->nextOf();1723 Type *tret = func->type->nextOf(); 1719 1724 1720 1725 // Need a variable to hold value from any return statements in body. 1721 1726 if (!sc->func->vresult && tret && tret != Type::tvoid) 1722 { VarDeclaration *v; 1723 1724 v = new VarDeclaration(loc, tret, Id::result, NULL); 1727 { 1728 VarDeclaration *v = new VarDeclaration(loc, tret, Id::result, NULL); 1725 1729 v->noauto = 1; 1726 1730 v->semantic(sc); 1727 1731 if (!sc->insert(v)) 1728 1732 assert(0); 1729 1733 v->parent = sc->func; 1730 1734 sc->func->vresult = v; 1731 1735 } 1732 1736 1733 1737 /* Turn body into the function literal: 1734 1738 * int delegate(ref T arg) { body } 1735 1739 */ 1736 args = new Parameters();1740 Parameters *args = new Parameters(); 1737 1741 for (size_t i = 0; i < dim; i++) 1738 1742 { Parameter *arg = (Parameter *)arguments->data[i]; 1743 Identifier *id; 1739 1744 1740 1745 arg->type = arg->type->semantic(loc, sc); 1741 1746 if (arg->storageClass & STCref) 1742 1747 id = arg->ident; 1743 1748 else 1744 1749 { // Make a copy of the ref argument so it isn't 1745 1750 // a reference. 1746 VarDeclaration *v;1747 Initializer *ie;1748 1751 1749 1752 id = Lexer::uniqueId("__applyArg", i); 1750 1751 ie = new ExpInitializer(0, new IdentifierExp(0, id)); 1752 v = new VarDeclaration(0, arg->type, arg->ident, ie); 1753 Initializer *ie = new ExpInitializer(0, new IdentifierExp(0, id)); 1754 VarDeclaration *v = new VarDeclaration(0, arg->type, arg->ident, ie); 1753 1755 s = new DeclarationStatement(0, v); 1754 1756 body = new CompoundStatement(loc, s, body); 1755 1757 } 1756 1758 a = new Parameter(STCref, arg->type, id, NULL); 1757 1759 args->push(a); 1758 1760 } 1759 t = new TypeFunction(args, Type::tint32, 0, LINKd);1760 fld = new FuncLiteralDeclaration(loc, 0, t, TOKdelegate, this);1761 Type *t = new TypeFunction(args, Type::tint32, 0, LINKd); 1762 FuncLiteralDeclaration *fld = new FuncLiteralDeclaration(loc, 0, t, TOKdelegate, this); 1761 1763 fld->fbody = body; 1762 flde = new FuncExp(loc, fld);1764 Expression *flde = new FuncExp(loc, fld); 1763 1765 flde = flde->semantic(sc); 1764 1766 fld->tookAddressOf = 0; 1765 1767 1766 1768 // Resolve any forward referenced goto's 1767 for ( int i = 0; i < gotos.dim; i++)1769 for (size_t i = 0; i < gotos.dim; i++) 1768 1770 { CompoundStatement *cs = (CompoundStatement *)gotos.data[i]; 1769 1771 GotoStatement *gs = (GotoStatement *)cs->statements->data[0]; 1770 1772 1771 1773 if (!gs->label->statement) 1772 1774 { // 'Promote' it to this scope, and replace with a return 1773 1775 cases.push(gs); 1774 1776 s = new ReturnStatement(0, new IntegerExp(cases.dim + 1)); 1775 1777 cs->statements->data[0] = (void *)s; 1776 1778 } 1777 1779 } 1778 1780 1779 1781 if (tab->ty == Taarray) 1780 1782 { 1781 1783 // Check types 1782 1784 Parameter *arg = (Parameter *)arguments->data[0]; 1783 1785 if (dim == 2) 1784 1786 { 1785 1787 if (arg->storageClass & STCref) 1786 1788 error("foreach: index cannot be ref"); 1787 1789 if (!arg->type->equals(taa->index)) 1788 1790 error("foreach: index must be type %s, not %s", taa->index->toChars(), arg->type->toChars()); 1789 1791 arg = (Parameter *)arguments->data[1]; 1790 1792 } 1791 1793 if (!arg->type->equals(taa->nextOf())) 1792 1794 error("foreach: value must be type %s, not %s", taa->nextOf()->toChars(), arg->type->toChars()); 1793 1795 1794 1796 /* Call: 1795 1797 * _aaApply(aggr, keysize, flde) 1796 1798 */ 1799 FuncDeclaration *fdapply; 1797 1800 if (dim == 2) 1798 1801 fdapply = FuncDeclaration::genCfunc(Type::tindex, "_aaApply2"); 1799 1802 else 1800 1803 fdapply = FuncDeclaration::genCfunc(Type::tindex, "_aaApply"); 1801 1804 ec = new VarExp(0, fdapply); 1802 1805 Expressions *exps = new Expressions(); 1803 1806 exps->push(aggr); 1804 1807 size_t keysize = taa->index->size(); 1805 1808 keysize = (keysize + (PTRSIZE-1)) & ~(PTRSIZE-1); 1806 1809 exps->push(new IntegerExp(0, keysize, Type::tsize_t)); 1807 1810 exps->push(flde); 1808 1811 e = new CallExp(loc, ec, exps); 1809 1812 e->type = Type::tindex; // don't run semantic() on e 1810 1813 } 1811 1814 else if (tab->ty == Tarray || tab->ty == Tsarray) 1812 1815 { 1813 1816 /* Call: 1814 1817 * _aApply(aggr, flde) 1815 1818 */ 1816 1819 static char fntab[9][3] = … … 1821 1824 char fdname[7+1+2+ sizeof(dim)*3 + 1]; 1822 1825 int flag; 1823 1826 1824 1827 switch (tn->ty) 1825 1828 { 1826 1829 case Tchar: flag = 0; break; 1827 1830 case Twchar: flag = 3; break; 1828 1831 case Tdchar: flag = 6; break; 1829 1832 default: assert(0); 1830 1833 } 1831 1834 switch (tnv->ty) 1832 1835 { 1833 1836 case Tchar: flag += 0; break; 1834 1837 case Twchar: flag += 1; break; 1835 1838 case Tdchar: flag += 2; break; 1836 1839 default: assert(0); 1837 1840 } 1838 1841 const char *r = (op == TOKforeach_reverse) ? "R" : ""; 1839 1842 int j = sprintf(fdname, "_aApply%s%.*s%zd", r, 2, fntab[flag], dim); 1840 1843 assert(j < sizeof(fdname)); 1841 fdapply = FuncDeclaration::genCfunc(Type::tindex, fdname);1844 FuncDeclaration *fdapply = FuncDeclaration::genCfunc(Type::tindex, fdname); 1842 1845 1843 1846 ec = new VarExp(0, fdapply); 1844 1847 Expressions *exps = new Expressions(); 1845 1848 if (tab->ty == Tsarray) 1846 1849 aggr = aggr->castTo(sc, tn->arrayOf()); 1847 1850 exps->push(aggr); 1848 1851 exps->push(flde); 1849 1852 e = new CallExp(loc, ec, exps); 1850 1853 e->type = Type::tindex; // don't run semantic() on e 1851 1854 } 1852 1855 else if (tab->ty == Tdelegate) 1853 1856 { 1854 1857 /* Call: 1855 1858 * aggr(flde) 1856 1859 */ 1857 1860 Expressions *exps = new Expressions(); 1858 1861 exps->push(flde); 1859 1862 e = new CallExp(loc, aggr, exps); 1860 1863 e = e->semantic(sc); 1861 1864 if (e->type != Type::tint32) 1862 1865 error("opApply() function for %s must return an int", tab->toChars()); 1863 1866 } 1864 1867 else 1865 1868 { 1866 1869 assert(tab->ty == Tstruct || tab->ty == Tclass); 1867 Identifier *idapply = (op == TOKforeach_reverse)1868 ? Id::applyReverse : Id::apply;1869 Dsymbol *sapply = search_function((AggregateDeclaration *)tab->toDsymbol(sc), idapply);1870 1870 Expressions *exps = new Expressions(); 1871 if (!sapply) 1872 sapply = search_function((AggregateDeclaration *)tab->toDsymbol(sc), idapply); 1871 1873 #if 0 1872 1874 TemplateDeclaration *td; 1873 1875 if (sapply && 1874 1876 (td = sapply->isTemplateDeclaration()) != NULL) 1875 1877 { /* Call: 1876 1878 * aggr.apply!(fld)() 1877 1879 */ 1878 1880 Objects *tiargs = new Objects(); 1879 1881 tiargs->push(fld); 1880 1882 ec = new DotTemplateInstanceExp(loc, aggr, idapply, tiargs); 1881 1883 } 1882 1884 else 1883 1885 #endif 1884 1886 { 1885 1887 /* Call: 1886 1888 * aggr.apply(flde) 1887 1889 */ 1888 1890 ec = new DotIdExp(loc, aggr, idapply); 1889 1891 exps->push(flde); 1890 1892 } trunk/src/template.c
r294 r295 3736 3736 __except (__ehfilter(GetExceptionInformation())) 3737 3737 { 3738 3738 global.gag = 0; // ensure error message gets printed 3739 3739 error("recursive expansion"); 3740 3740 fatal(); 3741 3741 } 3742 3742 #endif 3743 3743 } 3744 3744 3745 3745 Laftersemantic: 3746 3746 sc2->pop(); 3747 3747 3748 3748 scope->pop(); 3749 3749 3750 3750 // Give additional context info if error occurred during instantiation 3751 3751 if (global.errors != errorsave) 3752 3752 { 3753 3753 error("error instantiating"); 3754 3754 if (tinst) 3755 3755 { tinst->printInstantiationTrace(); 3756 fatal();3757 3756 } 3758 3757 errors = 1; 3759 3758 if (global.gag) 3760 3759 tempdecl->instances.remove(tempdecl_instance_idx); 3761 3760 } 3762 3761 3763 3762 #if LOG 3764 3763 printf("-TemplateInstance::semantic('%s', this=%p)\n", toChars(), this); 3765 3764 #endif 3766 3765 } 3767 3766 3768 3767 3769 3768 void TemplateInstance::semanticTiargs(Scope *sc) 3770 3769 { 3771 3770 //printf("+TemplateInstance::semanticTiargs() %s\n", toChars()); 3772 3771 if (semantictiargsdone) 3773 3772 return; 3774 3773 semantictiargsdone = 1; 3775 3774 semanticTiargs(loc, sc, tiargs, 0); 3776 3775 }
