Mercurial > projects > ddmd
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: |