152
|
1 // REQUIRED_ARGS: -o-
|
|
2 // PERMUTE_ARGS:
|
|
3 // EXTRA_FILES: imports/imp12242a1.d imports/imp12242a2.d
|
|
4 /*
|
|
5 TEST_OUTPUT:
|
|
6 ---
|
|
7 9
|
|
8 8
|
|
9 7
|
|
10 6
|
|
11 5
|
|
12 4
|
|
13 3
|
|
14 2
|
|
15 1
|
|
16 0
|
|
17 S(1, 2, 3, [0, 1, 2])
|
|
18 x0: 1
|
|
19 x1: 2
|
|
20 x2: 3
|
|
21 a: [0, 1, 2]
|
|
22 (int[], char[], bool[], Object[])
|
|
23 [0, 0]
|
|
24 x0: int
|
|
25 x1: double
|
|
26 x2: char
|
|
27 test(0)→ 0
|
|
28 test(1)→ 1
|
|
29 test(2)→ 2
|
|
30 test(3)→ 3
|
|
31 test(4)→ 4
|
|
32 test(5)→ 5
|
|
33 test(6)→ 6
|
|
34 test(7)→ 7
|
|
35 test(8)→ 8
|
|
36 test(9)→ 9
|
|
37 test(10)→ -1
|
|
38 test(11)→ -1
|
|
39 test(12)→ -1
|
|
40 test(13)→ -1
|
|
41 test(14)→ -1
|
|
42 1
|
|
43 [1, 2, 3]
|
|
44 2
|
|
45 [1, 2, 3]
|
|
46 3
|
|
47 [1, 2, 3]
|
|
48 0 1
|
|
49 1 2
|
|
50 2 3
|
|
51 1
|
|
52 3
|
|
53 4
|
|
54 object
|
|
55 Tuple
|
|
56 tuple
|
|
57 main
|
|
58 front
|
|
59 popFront
|
|
60 empty
|
|
61 back
|
|
62 popBack
|
|
63 Iota
|
|
64 iota
|
|
65 map
|
|
66 to
|
|
67 text
|
|
68 all
|
|
69 any
|
|
70 join
|
|
71 S
|
|
72 s
|
|
73 Seq
|
|
74 Overloads
|
|
75 Parameters
|
|
76 forward
|
|
77 foo
|
|
78 A
|
|
79 B
|
|
80 C
|
|
81 D
|
|
82 E
|
|
83 Types
|
|
84 Visitor
|
|
85 testVisitor
|
|
86 staticMap
|
|
87 arrayOf
|
|
88 StaticForeachLoopVariable
|
|
89 StaticForeachScopeExit
|
|
90 StaticForeachReverseHiding
|
|
91 UnrolledForeachReverse
|
|
92 StaticForeachReverse
|
|
93 StaticForeachByAliasDefault
|
|
94 NestedStaticForeach
|
|
95 TestAliasOutsideFunctionScope
|
|
96 OpApplyMultipleStaticForeach
|
|
97 OpApplyMultipleStaticForeachLowered
|
|
98 RangeStaticForeach
|
|
99 OpApplySingleStaticForeach
|
|
100 TypeStaticForeach
|
|
101 AliasForeach
|
|
102 EnumForeach
|
|
103 TestUninterpretable
|
|
104 SeqForeachConstant
|
|
105 SeqForeachBreakContinue
|
|
106 TestStaticForeach
|
|
107 testtest
|
|
108 fun
|
|
109 testEmpty
|
|
110 bug17660
|
|
111 breakContinueBan
|
|
112 MixinTemplate
|
|
113 testToStatement
|
|
114 bug17688
|
|
115 T
|
|
116 foo2
|
|
117 T2
|
|
118 1 2 '3'
|
|
119 2 3 '4'
|
|
120 0 1
|
|
121 1 2
|
|
122 2 3
|
|
123 ---
|
|
124 */
|
|
125
|
|
126 module staticforeach;
|
|
127
|
|
128 struct Tuple(T...){
|
|
129 T expand;
|
|
130 alias expand this;
|
|
131 }
|
|
132 auto tuple(T...)(T t){ return Tuple!T(t); }
|
|
133
|
|
134 /+struct TupleStaticForeach{ // should work, but is not the fault of the static foreach implementation.
|
|
135 //pragma(msg, [tuple(1,"2",'3'),tuple(2,"3",'4')].map!((x)=>x));
|
|
136 static foreach(a,b,c;[tuple(1,"2",'3'),tuple(2,"3",'4')].map!((x)=>x)){
|
|
137 pragma(msg,a," ",b," ",c);
|
|
138 }
|
|
139 }+/
|
|
140
|
|
141 void main(){
|
|
142 static foreach(a,b,c;[tuple(1,"2",'3'),tuple(2,"3",'4')].map!((x)=>x)){
|
|
143 pragma(msg, a," ",b," ",c);
|
|
144 }
|
|
145 static struct S{
|
|
146 // (aggregate scope, forward referencing possible)
|
|
147 static assert(stripA("123")==1);
|
|
148 static assert(stripA([1],2)==2);
|
|
149 static foreach(i;0..2){
|
|
150 mixin(`import imports.imp12242a`~text(i+1)~`;`);
|
|
151 static assert(stripA("123")==1);
|
|
152 static assert(stripA([1],2)==2);
|
|
153 }
|
|
154 static assert(stripA("123")==1);
|
|
155 static assert(stripA([1],2)==2);
|
|
156 }
|
|
157 static foreach(i;0..2){
|
|
158 // (function scope, no forward referencing)
|
|
159 mixin(`import imports.imp12242a`~text(i+1)~`;`);
|
|
160 static assert(stripA("123")==1);
|
|
161 static if(i) static assert(stripA([1],2)==2);
|
|
162 }
|
|
163 static assert(stripA("123")==1);
|
|
164 static assert(stripA([1],2)==2);
|
|
165 }
|
|
166
|
|
167 auto front(T)(T[] a){ return a[0]; }
|
|
168 auto popFront(T)(ref T[] a){ a=a[1..$]; }
|
|
169 auto empty(T)(T[] a){ return !a.length; }
|
|
170 auto back(T)(T[] a){ return a[$-1]; }
|
|
171 auto popBack(T)(ref T[] a){ a=a[0..$-1]; }
|
|
172
|
|
173 struct Iota(T){
|
|
174 T s,e;
|
|
175 @property bool empty(){ return s>=e; }
|
|
176 @property T front(){ return s; }
|
|
177 @property T back(){ return cast(T)(e-1); }
|
|
178 void popFront(){ s++; }
|
|
179 void popBack(){ e--; }
|
|
180 }
|
|
181 auto iota(T)(T s, T e){ return Iota!T(s,e); }
|
|
182
|
|
183 template map(alias a){
|
|
184 struct Map(R){
|
|
185 R r;
|
|
186 @property front(){ return a(r.front); }
|
|
187 @property back(){ return a(r.back); }
|
|
188 @property bool empty(){ return r.empty; }
|
|
189 void popFront(){ r.popFront(); }
|
|
190 void popBack(){ r.popBack(); }
|
|
191 }
|
|
192 auto map(R)(R r){ return Map!R(r); }
|
|
193 }
|
|
194
|
|
195 template to(T:string){
|
|
196 string to(S)(S x)if(is(S:int)||is(S:size_t)||is(S:char)){
|
|
197 static if(is(S==char)) return cast(string)[x];
|
|
198 if(x<0) return "-"~to(-1 * x);
|
|
199 if(x==0) return "0";
|
|
200 return (x>=10?to(x/10):"")~cast(char)(x%10+'0');
|
|
201 }
|
|
202 }
|
|
203 auto text(T)(T arg){ return to!string(arg); };
|
|
204
|
|
205 template all(alias a){
|
|
206 bool all(R)(R r){
|
|
207 foreach(x;r) if(!a(x)) return false;
|
|
208 return true;
|
|
209 }
|
|
210 }
|
|
211 template any(alias a){
|
|
212 bool any(R)(R r){
|
|
213 foreach(x;r) if(a(x)) return true;
|
|
214 return false;
|
|
215 }
|
|
216 }
|
|
217 auto join(R)(R r,string sep=""){
|
|
218 string a;
|
|
219 int first=0;
|
|
220 foreach(x;r){
|
|
221 if(first++) a~=sep;
|
|
222 a~=x;
|
|
223 }
|
|
224 return a;
|
|
225 }
|
|
226
|
|
227 static foreach_reverse(x;iota(0,10).map!(to!string)){
|
|
228 pragma(msg, x);
|
|
229 }
|
|
230
|
|
231 // create struct members iteratively
|
|
232 struct S{
|
|
233 static foreach(i;a){
|
|
234 mixin("int x"~to!string(i)~";");
|
|
235 }
|
|
236 immutable int[] a = [0,1,2];
|
|
237 }
|
|
238 enum s=S(1,2,3);
|
|
239 pragma(msg, s);
|
|
240
|
|
241 // loop over struct members
|
|
242 static foreach(member;__traits(allMembers,S)){
|
|
243 pragma(msg, member,": ",mixin("s."~member));
|
|
244 }
|
|
245
|
|
246 // print prime numbers using overload sets as state variables.
|
|
247 /+
|
|
248 static assert(is(typeof(bad57)));
|
|
249 static assert(!is(typeof(bad53)));
|
|
250
|
|
251 static foreach(x;iota(2,100)){
|
|
252 static foreach(y;iota(2,x)){
|
|
253 static if(!(x%y)){
|
|
254 mixin("void bad"~to!string(x)~"();");
|
|
255 }
|
|
256 }
|
|
257 static if(!is(typeof(mixin("bad"~to!string(x))))){
|
|
258 static assert(iota(2,x).all!(y=>!!(x%y)));
|
|
259 pragma(msg, x);
|
|
260 }else{
|
|
261 static assert(iota(2,x).any!(y=>!(x%y)));
|
|
262 }
|
|
263 }
|
|
264 +/
|
|
265
|
|
266
|
|
267 alias Seq(T...)=T;
|
|
268
|
|
269 alias Overloads(alias a) = Seq!(__traits(getOverloads, __traits(parent, a), __traits(identifier, a)));
|
|
270
|
|
271 template Parameters(alias f){
|
|
272 static if(is(typeof(f) P == function)) alias Parameters=P;
|
|
273 }
|
|
274
|
|
275 template forward(alias a){
|
|
276 enum x=2;
|
|
277 static foreach(f;Overloads!a){
|
|
278 auto ref forward(Parameters!f args){
|
|
279 return f(args);
|
|
280 }
|
|
281 }
|
|
282 enum y=3;
|
|
283 }
|
|
284
|
|
285 int foo(int x){ return x; }
|
|
286 string foo(string x){ return x; }
|
|
287
|
|
288 static assert(forward!foo(2)==2 && forward!foo("hi") == "hi");
|
|
289
|
|
290
|
|
291 // simple boilerplate-free visitor pattern
|
|
292 static foreach(char T;'A'..'F'){
|
|
293 mixin("class "~T~q{{
|
|
294 void accept(Visitor v){
|
|
295 return v.visit(this);
|
|
296 }
|
|
297 }});
|
|
298 }
|
|
299 alias Types = Seq!(mixin("Seq!("~iota('A','F').map!(to!string).join(", ")~")"));
|
|
300 abstract class Visitor{
|
|
301 static foreach(T;Types){
|
|
302 abstract void visit(T);
|
|
303 }
|
|
304 }
|
|
305
|
|
306 string testVisitor(){
|
|
307 string r;
|
|
308 void writeln(T...)(T args){
|
|
309 static foreach(x;args) r~=x;
|
|
310 r~='\n';
|
|
311 }
|
|
312 class Visitor: .Visitor{
|
|
313 static foreach(T;Types){
|
|
314 override void visit(T){
|
|
315 writeln("visited: ",T.stringof);
|
|
316 }
|
|
317 }
|
|
318 }
|
|
319 void main(){
|
|
320 auto v=new Visitor;
|
|
321 static foreach(T;Types){
|
|
322 v.visit(new T);
|
|
323 }
|
|
324 }
|
|
325 main();
|
|
326 return r;
|
|
327 }
|
|
328 static assert(testVisitor()=="visited: A
|
|
329 visited: B
|
|
330 visited: C
|
|
331 visited: D
|
|
332 visited: E
|
|
333 ");
|
|
334
|
|
335 // iterative computation over AliasSeq:
|
|
336 template staticMap(alias F,T...){
|
|
337 alias state0=Seq!();
|
|
338 static foreach(i,A;T){
|
|
339 mixin("alias state"~to!string(i+1)~" = Seq!(state"~to!string(i)~",F!A);");
|
|
340 }
|
|
341 alias staticMap = Seq!(mixin("state"~to!string(T.length)));
|
|
342 }
|
|
343
|
|
344 alias arrayOf(T)=T[];
|
|
345 static assert(is(staticMap!(arrayOf,int,char,bool,Object)==Seq!(int[], char[], bool[], Object[])));
|
|
346 pragma(msg, staticMap!(arrayOf,int,char,bool,Object));
|
|
347
|
|
348
|
|
349 struct StaticForeachLoopVariable{
|
|
350 int x;
|
|
351 static foreach(i;0..1){
|
|
352 mixin("enum x"~text(i)~" = i;");
|
|
353 }
|
|
354 int y;
|
|
355 static assert(__traits(allMembers, StaticForeachLoopVariable).length==3);
|
|
356 static assert(!is(typeof(StaticForeachLoopVariable.i)));
|
|
357 static assert(!is(typeof(__traits(getMember, StaticForeachLoopVariable, "i"))));
|
|
358 }
|
|
359
|
|
360 struct StaticForeachScopeExit{
|
|
361 static:
|
|
362 int[] test(){
|
|
363 int[] r;
|
|
364 scope(exit) r ~= 1234;
|
|
365 {
|
|
366 static foreach(i;0..5){
|
|
367 scope(exit) r ~= i;
|
|
368 }
|
|
369 r ~= 5;
|
|
370 }
|
|
371 return r;
|
|
372 }
|
|
373 static assert(test()==[5,4,3,2,1,0]);
|
|
374 }
|
|
375
|
|
376 struct StaticForeachReverseHiding{
|
|
377 static foreach(i;[0]){
|
|
378 enum i = 1; // TODO: disallow?
|
|
379 static assert(i==0);
|
|
380 }
|
|
381 }
|
|
382
|
|
383 struct UnrolledForeachReverse{
|
|
384 static:
|
|
385 alias Seq(T...)=T;
|
|
386 int[] test(){
|
|
387 int[] r;
|
|
388 foreach_reverse(i;Seq!(0,1,2,3)){
|
|
389 r~=i;
|
|
390 }
|
|
391 return r;
|
|
392 }
|
|
393 static assert(test()==[3,2,1,0]);
|
|
394 }
|
|
395
|
|
396 struct StaticForeachReverse{
|
|
397 static:
|
|
398 alias Seq(T...)=T;
|
|
399 int[] test(){
|
|
400 int[] r;
|
|
401 static foreach_reverse(i;0..4){
|
|
402 r~=i;
|
|
403 }
|
|
404 return r;
|
|
405 }
|
|
406 static assert(test()==[3,2,1,0]);
|
|
407
|
|
408 int[] test2(){
|
|
409 int[] r;
|
|
410 static foreach_reverse(i;[0,1,2,3]){
|
|
411 r~=i;
|
|
412 }
|
|
413 return r;
|
|
414 }
|
|
415 static assert(test2()==[3,2,1,0]);
|
|
416
|
|
417 int[] test3(){
|
|
418 static struct S{
|
|
419 int opApplyReverse(scope int delegate(int) dg){
|
|
420 foreach_reverse(i;0..4) if(auto r=dg(i)) return r;
|
|
421 return 0;
|
|
422 }
|
|
423 }
|
|
424 int[] r;
|
|
425 static foreach_reverse(i;S()){
|
|
426 r~=i;
|
|
427 }
|
|
428 return r;
|
|
429 }
|
|
430 static assert(test3()==[3,2,1,0]);
|
|
431
|
|
432 int[] test4(){
|
|
433 int[] r;
|
|
434 static foreach_reverse(i;Seq!(0,1,2,3)){
|
|
435 r~=i;
|
|
436 }
|
|
437 return r;
|
|
438 }
|
|
439 static assert(test()==[3,2,1,0]);
|
|
440 }
|
|
441
|
|
442 struct StaticForeachByAliasDefault{
|
|
443 static:
|
|
444 alias Seq(T...)=T;
|
|
445
|
|
446 int[] test(){
|
|
447 int a,b,c;
|
|
448 static foreach(i,x;Seq!(a,b,c)) x=i;
|
|
449 return [a,b,c];
|
|
450 }
|
|
451 static assert(test()==[0,1,2]);
|
|
452
|
|
453 int[] test2(){
|
|
454 int x=0;
|
|
455 int foo(){ return ++x; }
|
|
456 static foreach(y;Seq!foo)
|
|
457 return [y,y,y];
|
|
458 }
|
|
459 static assert(test2()==[1,2,3]);
|
|
460
|
|
461 void test3(){
|
|
462 int x=0;
|
|
463 int foo(){ return ++x; }
|
|
464 static assert(!is(typeof({
|
|
465 static foreach(enum y;Seq!foo)
|
|
466 return [y,y,y];
|
|
467 })));
|
|
468 }
|
|
469 }
|
|
470
|
|
471 struct NestedStaticForeach{
|
|
472 static:
|
|
473 static foreach(i,name;["a"]){
|
|
474 static foreach(j,name2;["d"]){
|
|
475 mixin("enum int[] "~name~name2~"=[i, j];");
|
|
476 }
|
|
477 }
|
|
478 pragma(msg, ad);
|
|
479 }
|
|
480
|
|
481 struct TestAliasOutsideFunctionScope{
|
|
482 static:
|
|
483 alias Seq(T...)=T;
|
|
484 int a;
|
|
485 static foreach(alias x;Seq!(a)){
|
|
486 }
|
|
487 }
|
|
488
|
|
489 struct OpApplyMultipleStaticForeach{
|
|
490 static:
|
|
491 struct OpApply{
|
|
492 int opApply(scope int delegate(int,int) dg){
|
|
493 foreach(i;0..10) if(auto r=dg(i,i*i)) return r;
|
|
494 return 0;
|
|
495 }
|
|
496 }
|
|
497 static foreach(a,b;OpApply()){
|
|
498 mixin(`enum x`~cast(char)('0'+a)~"=b;");
|
|
499 }
|
|
500 static foreach(i;0..10){
|
|
501 static assert(mixin(`x`~cast(char)('0'+i))==i*i);
|
|
502 }
|
|
503 }
|
|
504
|
|
505
|
|
506 struct OpApplyMultipleStaticForeachLowered{
|
|
507 static:
|
|
508 struct OpApply{
|
|
509 int opApply(scope int delegate(int,int) dg){
|
|
510 foreach(i;0..10) if(auto r=dg(i,i*i)) return r;
|
|
511 return 0;
|
|
512 }
|
|
513 }
|
|
514 static foreach(x;{
|
|
515 static struct S(T...){ this(T k){ this.x=k; } T x; }
|
|
516 static s(T...)(T a){ return S!T(a); }
|
|
517 typeof({ foreach(a,b;OpApply()){ return s(a,b); } assert(0);}())[] r;
|
|
518 foreach(a,b;OpApply()) r~=s(a,b);
|
|
519 return r;
|
|
520 }()){
|
|
521 mixin(`enum x`~cast(char)('0'+x.x[0])~"=x.x[1];");
|
|
522 }
|
|
523 static foreach(i;0..10){
|
|
524 static assert(mixin(`x`~cast(char)('0'+i))==i*i);
|
|
525 }
|
|
526 }
|
|
527
|
|
528 struct RangeStaticForeach{
|
|
529 static:
|
|
530 struct Range{
|
|
531 int x=0;
|
|
532 this(int x){ this.x=x; }
|
|
533 @property int front(){ return x; }
|
|
534 void popFront(){ x += 2; }
|
|
535 @property bool empty(){ return x>=10; }
|
|
536 }
|
|
537 static foreach(i;Range()){
|
|
538 mixin(`enum x`~cast(char)('0'+i)~"=i;");
|
|
539 }
|
|
540 static foreach(i;0..5){
|
|
541 static assert(mixin(`x`~cast(char)('0'+2*i))==2*i);
|
|
542 }
|
|
543 static assert(!is(typeof({
|
|
544 struct S{
|
|
545 static foreach(i,k;Range()){}
|
|
546 }
|
|
547 })));
|
|
548 static foreach(k;Range()){} // ok
|
|
549 }
|
|
550
|
|
551 struct OpApplySingleStaticForeach{
|
|
552 static:
|
|
553 struct OpApply{
|
|
554 int opApply(scope int delegate(int) dg){
|
|
555 foreach(i;0..10) if(auto r=dg(i)) return r;
|
|
556 return 0;
|
|
557 }
|
|
558 }
|
|
559 static foreach(b;OpApply()){
|
|
560 mixin(`enum x`~cast(char)('0'+b)~"=b;");
|
|
561 }
|
|
562 static foreach(i;0..10){
|
|
563 static assert(mixin(`x`~cast(char)('0'+i))==i);
|
|
564 }
|
|
565 }
|
|
566
|
|
567 struct TypeStaticForeach{
|
|
568 static:
|
|
569 alias Seq(T...)=T;
|
|
570 static foreach(i,alias T;Seq!(int,double,char)){
|
|
571 mixin(`T x`~cast(char)('0'+i)~";");
|
|
572 }
|
|
573 pragma(msg, "x0: ",typeof(x0));
|
|
574 pragma(msg, "x1: ",typeof(x1));
|
|
575 pragma(msg, "x2: ",typeof(x2));
|
|
576 static assert(is(typeof(x0)==int));
|
|
577 static assert(is(typeof(x1)==double));
|
|
578 static assert(is(typeof(x2)==char));
|
|
579 }
|
|
580
|
|
581 struct AliasForeach{
|
|
582 static:
|
|
583 alias Seq(T...)=T;
|
|
584 int[] test(){
|
|
585 int a,b,c;
|
|
586 static foreach(x;Seq!(a,b,c,2)){
|
|
587 static if(is(typeof({x=2;}))) x=2;
|
|
588 }
|
|
589 int x,y,z;
|
|
590 static foreach(alias k;Seq!(x,y,z,2)){
|
|
591 static if(is(typeof({k=2;}))) k=2;
|
|
592 }
|
|
593 int j,k,l;
|
|
594 static assert(!is(typeof({
|
|
595 static foreach(ref x;Seq!(j,k,l,2)){
|
|
596 static if(is(typeof({x=2;}))) x=2;
|
|
597 }
|
|
598 })));
|
|
599 return [x,y,z];
|
|
600 }
|
|
601 static assert(test()==[2,2,2]);
|
|
602 }
|
|
603
|
|
604 struct EnumForeach{
|
|
605 static:
|
|
606 alias Seq(T...)=T;
|
|
607 int a=1;
|
|
608 int fun(){ return 1; }
|
|
609 int gun(){ return 2; }
|
|
610 int hun(){ return 3;}
|
|
611 auto test(){
|
|
612 static foreach(i,enum x;Seq!(fun,gun,hun)){
|
|
613 static assert(i+1==x);
|
|
614 }
|
|
615 foreach(i,enum x;Seq!(fun,gun,hun)){
|
|
616 static assert(i+1==x);
|
|
617 }
|
|
618 }
|
|
619 }
|
|
620
|
|
621 struct TestUninterpretable{
|
|
622 static:
|
|
623 alias Seq(T...)=T;
|
|
624 auto test(){
|
|
625 int k;
|
|
626 static assert(!is(typeof({
|
|
627 static foreach(x;[k]){}
|
|
628 })));
|
|
629 static assert(!is(typeof({
|
|
630 foreach(enum x;[1,2,3]){}
|
|
631 })));
|
|
632 static assert(!is(typeof({
|
|
633 foreach(alias x;[1,2,3]){}
|
|
634 })));
|
|
635 foreach(enum x;Seq!(1,2,3)){} // ok
|
|
636 foreach(alias x;Seq!(1,2,3)){} // ok
|
|
637 static foreach(enum x;[1,2,3]){} // ok
|
|
638 static foreach(alias x;[1,2,3]){} // ok
|
|
639 static assert(!is(typeof({
|
|
640 static foreach(enum alias x;[1,2,3]){}
|
|
641 })));
|
|
642 int x;
|
|
643 static foreach(i;Seq!x){ } // ok
|
|
644 static foreach(i,j;Seq!(1,2,x)){ } // ok
|
|
645 static assert(!is(typeof({
|
|
646 static foreach(ref x;[1,2,3]){}
|
|
647 })));
|
|
648 }
|
|
649 }
|
|
650
|
|
651 struct SeqForeachConstant{
|
|
652 static:
|
|
653 alias Seq(T...)=T;
|
|
654 static assert(!is(typeof({
|
|
655 foreach(x;Seq!1) x=2;
|
|
656 })));
|
|
657 int test2(){
|
|
658 int r=0;
|
|
659 foreach(x;Seq!(1,2,3)){
|
|
660 enum k=x;
|
|
661 r+=k;
|
|
662 }
|
|
663 return r;
|
|
664 }
|
|
665 static assert(test2()==6);
|
|
666 }
|
|
667
|
|
668 struct SeqForeachBreakContinue{
|
|
669 static:
|
|
670 alias Seq(T...)=T;
|
|
671 int[] test(){
|
|
672 int[] r;
|
|
673 foreach(i;Seq!(0,1,2,3,4,5)){
|
|
674 if(i==2) continue;
|
|
675 if(i==4) break;
|
|
676 r~=i;
|
|
677 }
|
|
678 return r;
|
|
679 }
|
|
680 static assert(test()==[0,1,3]);
|
|
681 }
|
|
682
|
|
683 struct TestStaticForeach{
|
|
684 static:
|
|
685 int test(int x){
|
|
686 int r=0;
|
|
687 label: switch(x){
|
|
688 static foreach(i;0..10){
|
|
689 case i: r=i; break label; // TODO: remove label when restriction is lifted
|
|
690 }
|
|
691 default: r=-1; break label;
|
|
692 }
|
|
693 return r;
|
|
694 }
|
|
695 static foreach(i;0..15){
|
|
696 pragma(msg, "test(",i,")→ ",test(i));
|
|
697 static assert(test(i)==(i<10?i:-1));
|
|
698 }
|
|
699
|
|
700 enum x=[1,2,3];
|
|
701
|
|
702 static foreach(i;x){
|
|
703 mixin("enum x"~cast(char)('0'+i)~"="~cast(char)('0'+i)~";");
|
|
704 }
|
|
705
|
|
706 static foreach(i;x){
|
|
707 pragma(msg, mixin("x"~cast(char)('0'+i)));
|
|
708 pragma(msg,x);
|
|
709 }
|
|
710
|
|
711 int[] noBreakNoContinue(){
|
|
712 int[] r;
|
|
713 static foreach(i;0..1){
|
|
714 // if(i==3) continue; // TODO: error?
|
|
715 // if(i==7) break; // TODO: error?
|
|
716 r~=i;
|
|
717 }
|
|
718 return r;
|
|
719 }
|
|
720
|
|
721 mixin("enum k=3;");
|
|
722 }
|
|
723
|
|
724 static foreach(i,j;[1,2,3]){
|
|
725 pragma(msg, int(i)," ",j);
|
|
726 }
|
|
727
|
|
728 void testtest(){
|
|
729 static foreach(i,v;[1,2,3]){
|
|
730 pragma(msg, int(i)," ",v);
|
|
731 static assert(i+1 == v);
|
|
732 }
|
|
733 }
|
|
734
|
|
735
|
|
736 static foreach(i;Seq!(1,2,3,4,int)){
|
|
737 static if(!is(i) && i!=2){
|
|
738 pragma(msg, i);
|
|
739 }
|
|
740 }
|
|
741
|
|
742 int fun(int x){
|
|
743 int r=0;
|
|
744 label: switch(x){
|
|
745 static foreach(i;Seq!(0,1,2,3,4,5,6)){
|
|
746 static if (i < 5)
|
|
747 case i: r=i; break label; // TODO: remove label when restriction is lifted
|
|
748 }
|
|
749 default: r=-1; break label;
|
|
750 }
|
|
751 return r;
|
|
752 }
|
|
753
|
|
754 static foreach(i;0..10) static assert(fun(i)==(i<5?i:-1));
|
|
755
|
|
756 static foreach(i;0..0) { }
|
|
757 void testEmpty(){
|
|
758 static foreach(i;0..0) { }
|
|
759 }
|
|
760
|
|
761 auto bug17660(){
|
|
762 int x;
|
|
763 static foreach (i; 0 .. 1) { return 3; }
|
|
764 return x;
|
|
765 }
|
|
766 static assert(bug17660()==3);
|
|
767
|
|
768 int breakContinueBan(){
|
|
769 static assert(!is(typeof({
|
|
770 for(;;){
|
|
771 static foreach(i;0..1){
|
|
772 break;
|
|
773 }
|
|
774 }
|
|
775 })));
|
|
776 static assert(!is(typeof({
|
|
777 for(;;){
|
|
778 static foreach(i;0..1){
|
|
779 continue;
|
|
780 }
|
|
781 }
|
|
782 })));
|
|
783 Louter1: for(;;){
|
|
784 static foreach(i;0..1){
|
|
785 break Louter1;
|
|
786 }
|
|
787 }
|
|
788 Louter2: foreach(i;0..10){
|
|
789 static foreach(j;0..1){
|
|
790 continue Louter2;
|
|
791 }
|
|
792 return 0;
|
|
793 }
|
|
794 static foreach(i;0..1){
|
|
795 for(;;){ break; } // ok
|
|
796 }
|
|
797 return 1;
|
|
798 }
|
|
799 static assert(breakContinueBan()==1);
|
|
800
|
|
801 mixin template MixinTemplate(){
|
|
802 static foreach(i;0..2){
|
|
803 mixin(`enum x`~cast(char)('0'+i)~"=i;");
|
|
804 }
|
|
805 static foreach(i;[0,1]){
|
|
806 mixin(`enum y`~cast(char)('0'+i)~"=i;");
|
|
807 }
|
|
808 }
|
|
809 void testToStatement(){
|
|
810 mixin MixinTemplate;
|
|
811 static assert(x0==0 && x1==1);
|
|
812 static assert(y0==0 && y1==1);
|
|
813 }
|
|
814
|
|
815 void bug17688(){
|
|
816 final switch(1) static foreach(x;0..1){ int y=3; case 1: return; }
|
|
817 static assert(!is(typeof(y)));
|
|
818 }
|
|
819
|
|
820 struct T{ enum n = 1; }
|
|
821 T foo(T v)@nogc{
|
|
822 static foreach(x;0..v.n){ }
|
|
823 return T.init;
|
|
824 }
|
|
825 T foo2(T v)@nogc{
|
|
826 static foreach(_;0..typeof(return).n){ }
|
|
827 return T.init;
|
|
828 }
|
|
829
|
|
830 //https://issues.dlang.org/show_bug.cgi?id=18698
|
|
831
|
|
832 static foreach(m; __traits(allMembers, staticforeach))
|
|
833 {
|
|
834 pragma(msg, m);
|
|
835 }
|
|
836
|
|
837 //https://issues.dlang.org/show_bug.cgi?id=20072
|
|
838 struct T2{
|
|
839 static foreach(i;0..1)
|
|
840 struct S{}
|
|
841 }
|
|
842 static assert(is(__traits(parent,T2.S)==T2));
|