comparison dmd/ForeachStatement.d @ 135:af1bebfd96a4 dmd2037

dmd 2.038
author Eldar Insafutdinov <e.insafutdinov@gmail.com>
date Mon, 13 Sep 2010 22:19:42 +0100
parents 60bb0fe4563e
children 94b6033c07f3
comparison
equal deleted inserted replaced
134:4251f96733f4 135:af1bebfd96a4
113 //printf("ForeachStatement.semantic() %p\n", this); 113 //printf("ForeachStatement.semantic() %p\n", this);
114 ScopeDsymbol sym; 114 ScopeDsymbol sym;
115 Statement s = this; 115 Statement s = this;
116 size_t dim = arguments.dim; 116 size_t dim = arguments.dim;
117 TypeAArray taa = null; 117 TypeAArray taa = null;
118 Dsymbol sapply = null;
118 119
119 Type tn = null; 120 Type tn = null;
120 Type tnv = null; 121 Type tnv = null;
121 122
122 func = sc.func; 123 func = sc.func;
253 sc = sc.push(sym); 254 sc = sc.push(sym);
254 255
255 sc.noctor++; 256 sc.noctor++;
256 257
257 Lagain: 258 Lagain:
259 Identifier idapply = (op == TOK.TOKforeach_reverse)
260 ? Id.applyReverse : Id.apply;
261 sapply = null;
258 switch (tab.ty) 262 switch (tab.ty)
259 { 263 {
260 case TY.Tarray: 264 case TY.Tarray:
261 case TY.Tsarray: 265 case TY.Tsarray:
262 if (!checkForArgTypes()) 266 if (!checkForArgTypes())
443 goto Lapply; 447 goto Lapply;
444 } 448 }
445 case TY.Tclass: 449 case TY.Tclass:
446 case TY.Tstruct: 450 case TY.Tstruct:
447 version (DMDV2) { 451 version (DMDV2) {
452 /* Prefer using opApply, if it exists
453 */
454 if (dim != 1) // only one argument allowed with ranges
455 goto Lapply;
456
457 sapply = search_function(cast(AggregateDeclaration)tab.toDsymbol(sc), idapply);
458 if (sapply)
459 goto Lapply;
460
448 { /* Look for range iteration, i.e. the properties 461 { /* Look for range iteration, i.e. the properties
449 * .empty, .next, .retreat, .head and .rear 462 * .empty, .next, .retreat, .head and .rear
450 * foreach (e; aggr) { ... } 463 * foreach (e; aggr) { ... }
451 * translates to: 464 * translates to:
452 * for (auto __r = aggr[]; !__r.empty; __r.next) 465 * for (auto __r = aggr[]; !__r.empty; __r.next)
453 * { auto e = __r.head; 466 * { auto e = __r.head;
454 * ... 467 * ...
455 * } 468 * }
456 */ 469 */
457 if (dim != 1) // only one argument allowed with ranges
458 goto Lapply;
459
460 AggregateDeclaration ad = (tab.ty == TY.Tclass) 470 AggregateDeclaration ad = (tab.ty == TY.Tclass)
461 ? cast(AggregateDeclaration)(cast(TypeClass)tab).sym 471 ? cast(AggregateDeclaration)(cast(TypeClass)tab).sym
462 : cast(AggregateDeclaration)(cast(TypeStruct)tab).sym; 472 : cast(AggregateDeclaration)(cast(TypeStruct)tab).sym;
463 473
464 Identifier idhead; 474 Identifier idhead;
529 } 539 }
530 } 540 }
531 case TY.Tdelegate: 541 case TY.Tdelegate:
532 Lapply: 542 Lapply:
533 { 543 {
534 FuncDeclaration fdapply;
535 Parameters args;
536 Expression ec; 544 Expression ec;
537 Expression e; 545 Expression e;
538 FuncLiteralDeclaration fld;
539 Parameter a; 546 Parameter a;
540 Type t;
541 Expression flde;
542 Identifier id;
543 Type tret;
544 547
545 if (!checkForArgTypes()) 548 if (!checkForArgTypes())
546 { 549 {
547 body_ = body_.semantic(sc); 550 body_ = body_.semantic(sc);
548 return this; 551 return this;
549 } 552 }
550 553
551 tret = func.type.nextOf(); 554 Type tret = func.type.nextOf();
552 555
553 // Need a variable to hold value from any return statements in body. 556 // Need a variable to hold value from any return statements in body.
554 if (!sc.func.vresult && tret && tret != Type.tvoid) 557 if (!sc.func.vresult && tret && tret != Type.tvoid)
555 { 558 {
556 auto v = new VarDeclaration(loc, tret, Id.result, null); 559 auto v = new VarDeclaration(loc, tret, Id.result, null);
564 } 567 }
565 568
566 /* Turn body into the function literal: 569 /* Turn body into the function literal:
567 * int delegate(ref T arg) { body } 570 * int delegate(ref T arg) { body }
568 */ 571 */
569 args = new Parameters(); 572 auto args = new Parameters();
570 for (size_t i = 0; i < dim; i++) 573 for (size_t i = 0; i < dim; i++)
571 { 574 {
572 auto arg = arguments[i]; 575 auto arg = arguments[i];
576 Identifier id;
573 577
574 arg.type = arg.type.semantic(loc, sc); 578 arg.type = arg.type.semantic(loc, sc);
575 if (arg.storageClass & STC.STCref) 579 if (arg.storageClass & STC.STCref)
576 id = arg.ident; 580 id = arg.ident;
577 else 581 else
578 { // Make a copy of the ref argument so it isn't 582 { // Make a copy of the ref argument so it isn't
579 // a reference. 583 // a reference.
580 VarDeclaration v;
581 Initializer ie;
582
583 id = Lexer.uniqueId("__applyArg", i); 584 id = Lexer.uniqueId("__applyArg", i);
584 585
585 ie = new ExpInitializer(Loc(0), new IdentifierExp(Loc(0), id)); 586 Initializer ie = new ExpInitializer(Loc(0), new IdentifierExp(Loc(0), id));
586 v = new VarDeclaration(Loc(0), arg.type, arg.ident, ie); 587 auto v = new VarDeclaration(Loc(0), arg.type, arg.ident, ie);
587 s = new DeclarationStatement(Loc(0), v); 588 s = new DeclarationStatement(Loc(0), v);
588 body_ = new CompoundStatement(loc, s, body_); 589 body_ = new CompoundStatement(loc, s, body_);
589 } 590 }
590 a = new Parameter(STC.STCref, arg.type, id, null); 591 a = new Parameter(STC.STCref, arg.type, id, null);
591 args.push(a); 592 args.push(a);
592 } 593 }
593 t = new TypeFunction(args, Type.tint32, 0, LINK.LINKd); 594 Type t = new TypeFunction(args, Type.tint32, 0, LINK.LINKd);
594 fld = new FuncLiteralDeclaration(loc, Loc(0), t, TOK.TOKdelegate, this); 595 FuncLiteralDeclaration fld = new FuncLiteralDeclaration(loc, Loc(0), t, TOK.TOKdelegate, this);
595 fld.fbody = body_; 596 fld.fbody = body_;
596 flde = new FuncExp(loc, fld); 597 Expression flde = new FuncExp(loc, fld);
597 flde = flde.semantic(sc); 598 flde = flde.semantic(sc);
598 fld.tookAddressOf = 0; 599 fld.tookAddressOf = 0;
599 600
600 // Resolve any forward referenced goto's 601 // Resolve any forward referenced goto's
601 for (int i = 0; i < gotos.dim; i++) 602 for (size_t i = 0; i < gotos.dim; i++)
602 { 603 {
603 auto cs = cast(CompoundStatement)gotos.data[i]; 604 auto cs = cast(CompoundStatement)gotos.data[i];
604 auto gs = cast(GotoStatement)cs.statements[0]; 605 auto gs = cast(GotoStatement)cs.statements[0];
605 606
606 if (!gs.label.statement) 607 if (!gs.label.statement)
629 error("foreach: value must be type %s, not %s", taa.nextOf().toChars(), arg.type.toChars()); 630 error("foreach: value must be type %s, not %s", taa.nextOf().toChars(), arg.type.toChars());
630 631
631 /* Call: 632 /* Call:
632 * _aaApply(aggr, keysize, flde) 633 * _aaApply(aggr, keysize, flde)
633 */ 634 */
635 FuncDeclaration fdapply;
634 if (dim == 2) 636 if (dim == 2)
635 fdapply = FuncDeclaration.genCfunc(Type.tindex, "_aaApply2"); 637 fdapply = FuncDeclaration.genCfunc(Type.tindex, "_aaApply2");
636 else 638 else
637 fdapply = FuncDeclaration.genCfunc(Type.tindex, "_aaApply"); 639 fdapply = FuncDeclaration.genCfunc(Type.tindex, "_aaApply");
638 640
672 case TY.Tdchar: flag += 2; break; 674 case TY.Tdchar: flag += 2; break;
673 } 675 }
674 string r = (op == TOK.TOKforeach_reverse) ? "R" : ""; 676 string r = (op == TOK.TOKforeach_reverse) ? "R" : "";
675 int j = sprintf(fdname.ptr, "_aApply%.*s%.*s%zd".ptr, r, 2, fntab[flag].ptr, dim); 677 int j = sprintf(fdname.ptr, "_aApply%.*s%.*s%zd".ptr, r, 2, fntab[flag].ptr, dim);
676 assert(j < fdname.sizeof); 678 assert(j < fdname.sizeof);
677 fdapply = FuncDeclaration.genCfunc(Type.tindex, fdname[0..j].idup); 679 FuncDeclaration fdapply = FuncDeclaration.genCfunc(Type.tindex, fdname[0..j].idup);
678 680
679 ec = new VarExp(Loc(0), fdapply); 681 ec = new VarExp(Loc(0), fdapply);
680 auto exps = new Expressions(); 682 auto exps = new Expressions();
681 if (tab.ty == TY.Tsarray) 683 if (tab.ty == TY.Tsarray)
682 aggr = aggr.castTo(sc, tn.arrayOf()); 684 aggr = aggr.castTo(sc, tn.arrayOf());
698 error("opApply() function for %s must return an int", tab.toChars()); 700 error("opApply() function for %s must return an int", tab.toChars());
699 } 701 }
700 else 702 else
701 { 703 {
702 assert(tab.ty == TY.Tstruct || tab.ty == TY.Tclass); 704 assert(tab.ty == TY.Tstruct || tab.ty == TY.Tclass);
703 Identifier idapply = (op == TOK.TOKforeach_reverse) 705 auto exps = new Expressions();
704 ? Id.applyReverse : Id.apply; 706 if (!sapply)
705 Dsymbol sapply = search_function(cast(AggregateDeclaration)tab.toDsymbol(sc), idapply); 707 sapply = search_function(cast(AggregateDeclaration)tab.toDsymbol(sc), idapply);
706 Expressions exps = new Expressions();
707 static if (false) { 708 static if (false) {
708 TemplateDeclaration td; 709 TemplateDeclaration td;
709 if (sapply && (td = sapply.isTemplateDeclaration()) !is null) 710 if (sapply && (td = sapply.isTemplateDeclaration()) !is null)
710 { 711 {
711 /* Call: 712 /* Call: