mirror of
https://github.com/dlang/dmd.git
synced 2025-04-26 13:10:12 +03:00
Move dmd files into compiler/
This commit is contained in:
parent
20bd0cacbd
commit
6374bb87b7
4579 changed files with 4 additions and 4 deletions
880
compiler/test/compilable/staticforeach.d
Normal file
880
compiler/test/compilable/staticforeach.d
Normal file
|
@ -0,0 +1,880 @@
|
|||
// REQUIRED_ARGS: -o-
|
||||
// EXTRA_FILES: imports/imp12242a1.d imports/imp12242a2.d
|
||||
// PERMUTE_ARGS:
|
||||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
9
|
||||
8
|
||||
7
|
||||
6
|
||||
5
|
||||
4
|
||||
3
|
||||
2
|
||||
1
|
||||
0
|
||||
S(1, 2, 3, [0, 1, 2])
|
||||
x0: 1
|
||||
x1: 2
|
||||
x2: 3
|
||||
a: [0, 1, 2]
|
||||
(int[], char[], bool[], Object[])
|
||||
[0, 0]
|
||||
x0: int
|
||||
x1: double
|
||||
x2: char
|
||||
test(0)→ 0
|
||||
test(1)→ 1
|
||||
test(2)→ 2
|
||||
test(3)→ 3
|
||||
test(4)→ 4
|
||||
test(5)→ 5
|
||||
test(6)→ 6
|
||||
test(7)→ 7
|
||||
test(8)→ 8
|
||||
test(9)→ 9
|
||||
test(10)→ -1
|
||||
test(11)→ -1
|
||||
test(12)→ -1
|
||||
test(13)→ -1
|
||||
test(14)→ -1
|
||||
1
|
||||
[1, 2, 3]
|
||||
2
|
||||
[1, 2, 3]
|
||||
3
|
||||
[1, 2, 3]
|
||||
0 1
|
||||
1 2
|
||||
2 3
|
||||
1
|
||||
3
|
||||
4
|
||||
object
|
||||
Tuple
|
||||
tuple
|
||||
main
|
||||
front
|
||||
popFront
|
||||
empty
|
||||
back
|
||||
popBack
|
||||
Iota
|
||||
iota
|
||||
map
|
||||
to
|
||||
text
|
||||
all
|
||||
any
|
||||
join
|
||||
S
|
||||
s
|
||||
Seq
|
||||
Overloads
|
||||
Parameters
|
||||
forward
|
||||
foo
|
||||
A
|
||||
B
|
||||
C
|
||||
D
|
||||
E
|
||||
Types
|
||||
Visitor
|
||||
testVisitor
|
||||
staticMap
|
||||
arrayOf
|
||||
StaticForeachLoopVariable
|
||||
StaticForeachScopeExit
|
||||
StaticForeachReverseHiding
|
||||
UnrolledForeachReverse
|
||||
StaticForeachReverse
|
||||
StaticForeachByAliasDefault
|
||||
NestedStaticForeach
|
||||
TestAliasOutsideFunctionScope
|
||||
OpApplyMultipleStaticForeach
|
||||
OpApplyMultipleStaticForeachLowered
|
||||
RangeStaticForeach
|
||||
OpApplySingleStaticForeach
|
||||
TypeStaticForeach
|
||||
AliasForeach
|
||||
EnumForeach
|
||||
TestUninterpretable
|
||||
SeqForeachConstant
|
||||
SeqForeachBreakContinue
|
||||
TestStaticForeach
|
||||
testtest
|
||||
fun
|
||||
testEmpty
|
||||
bug17660
|
||||
breakContinueBan
|
||||
MixinTemplate
|
||||
testToStatement
|
||||
bug17688
|
||||
T
|
||||
foo2
|
||||
T2
|
||||
TestStaticForeach2
|
||||
issue22007
|
||||
1 2 '3'
|
||||
2 3 '4'
|
||||
0 1
|
||||
1 2
|
||||
2 3
|
||||
---
|
||||
*/
|
||||
|
||||
module staticforeach;
|
||||
|
||||
struct Tuple(T...){
|
||||
T expand;
|
||||
alias expand this;
|
||||
}
|
||||
auto tuple(T...)(T t){ return Tuple!T(t); }
|
||||
|
||||
/+struct TupleStaticForeach{ // should work, but is not the fault of the static foreach implementation.
|
||||
//pragma(msg, [tuple(1,"2",'3'),tuple(2,"3",'4')].map!((x)=>x));
|
||||
static foreach(a,b,c;[tuple(1,"2",'3'),tuple(2,"3",'4')].map!((x)=>x)){
|
||||
pragma(msg,a," ",b," ",c);
|
||||
}
|
||||
}+/
|
||||
|
||||
void main(){
|
||||
static foreach(a,b,c;[tuple(1,"2",'3'),tuple(2,"3",'4')].map!((x)=>x)){
|
||||
pragma(msg, a," ",b," ",c);
|
||||
}
|
||||
static struct S{
|
||||
// (aggregate scope, forward referencing possible)
|
||||
static assert(stripA("123")==1);
|
||||
static assert(stripA([1],2)==2);
|
||||
static foreach(i;0..2){
|
||||
mixin(`import imports.imp12242a`~text(i+1)~`;`);
|
||||
static assert(stripA("123")==1);
|
||||
static assert(stripA([1],2)==2);
|
||||
}
|
||||
static assert(stripA("123")==1);
|
||||
static assert(stripA([1],2)==2);
|
||||
}
|
||||
static foreach(i;0..2){
|
||||
// (function scope, no forward referencing)
|
||||
mixin(`import imports.imp12242a`~text(i+1)~`;`);
|
||||
static assert(stripA("123")==1);
|
||||
static if(i) static assert(stripA([1],2)==2);
|
||||
}
|
||||
static assert(stripA("123")==1);
|
||||
static assert(stripA([1],2)==2);
|
||||
}
|
||||
|
||||
auto front(T)(T[] a){ return a[0]; }
|
||||
auto popFront(T)(ref T[] a){ a=a[1..$]; }
|
||||
auto empty(T)(T[] a){ return !a.length; }
|
||||
auto back(T)(T[] a){ return a[$-1]; }
|
||||
auto popBack(T)(ref T[] a){ a=a[0..$-1]; }
|
||||
|
||||
struct Iota(T){
|
||||
T s,e;
|
||||
@property bool empty(){ return s>=e; }
|
||||
@property T front(){ return s; }
|
||||
@property T back(){ return cast(T)(e-1); }
|
||||
void popFront(){ s++; }
|
||||
void popBack(){ e--; }
|
||||
}
|
||||
auto iota(T)(T s, T e){ return Iota!T(s,e); }
|
||||
|
||||
template map(alias a){
|
||||
struct Map(R){
|
||||
R r;
|
||||
@property front(){ return a(r.front); }
|
||||
@property back(){ return a(r.back); }
|
||||
@property bool empty(){ return r.empty; }
|
||||
void popFront(){ r.popFront(); }
|
||||
void popBack(){ r.popBack(); }
|
||||
}
|
||||
auto map(R)(R r){ return Map!R(r); }
|
||||
}
|
||||
|
||||
template to(T:string){
|
||||
string to(S)(S x)if(is(S:int)||is(S:size_t)||is(S:char)){
|
||||
static if(is(S==char)) return cast(string)[x];
|
||||
if(x<0) return "-"~to(-1 * x);
|
||||
if(x==0) return "0";
|
||||
return (x>=10?to(x/10):"")~cast(char)(x%10+'0');
|
||||
}
|
||||
}
|
||||
auto text(T)(T arg){ return to!string(arg); };
|
||||
|
||||
template all(alias a){
|
||||
bool all(R)(R r){
|
||||
foreach(x;r) if(!a(x)) return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
template any(alias a){
|
||||
bool any(R)(R r){
|
||||
foreach(x;r) if(a(x)) return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
auto join(R)(R r,string sep=""){
|
||||
string a;
|
||||
int first=0;
|
||||
foreach(x;r){
|
||||
if(first++) a~=sep;
|
||||
a~=x;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
static foreach_reverse(x;iota(0,10).map!(to!string)){
|
||||
pragma(msg, x);
|
||||
}
|
||||
|
||||
// create struct members iteratively
|
||||
struct S{
|
||||
static foreach(i;a){
|
||||
mixin("int x"~to!string(i)~";");
|
||||
}
|
||||
immutable int[] a = [0,1,2];
|
||||
}
|
||||
enum s=S(1,2,3);
|
||||
pragma(msg, s);
|
||||
|
||||
// loop over struct members
|
||||
static foreach(member;__traits(allMembers,S)){
|
||||
pragma(msg, member,": ",mixin("s."~member));
|
||||
}
|
||||
|
||||
// print prime numbers using overload sets as state variables.
|
||||
/+
|
||||
static assert(is(typeof(bad57)));
|
||||
static assert(!is(typeof(bad53)));
|
||||
|
||||
static foreach(x;iota(2,100)){
|
||||
static foreach(y;iota(2,x)){
|
||||
static if(!(x%y)){
|
||||
mixin("void bad"~to!string(x)~"();");
|
||||
}
|
||||
}
|
||||
static if(!is(typeof(mixin("bad"~to!string(x))))){
|
||||
static assert(iota(2,x).all!(y=>!!(x%y)));
|
||||
pragma(msg, x);
|
||||
}else{
|
||||
static assert(iota(2,x).any!(y=>!(x%y)));
|
||||
}
|
||||
}
|
||||
+/
|
||||
|
||||
|
||||
alias Seq(T...)=T;
|
||||
|
||||
alias Overloads(alias a) = Seq!(__traits(getOverloads, __traits(parent, a), __traits(identifier, a)));
|
||||
|
||||
template Parameters(alias f){
|
||||
static if(is(typeof(f) P == function)) alias Parameters=P;
|
||||
}
|
||||
|
||||
template forward(alias a){
|
||||
enum x=2;
|
||||
static foreach(f;Overloads!a){
|
||||
auto ref forward(Parameters!f args){
|
||||
return f(args);
|
||||
}
|
||||
}
|
||||
enum y=3;
|
||||
}
|
||||
|
||||
int foo(int x){ return x; }
|
||||
string foo(string x){ return x; }
|
||||
|
||||
static assert(forward!foo(2)==2 && forward!foo("hi") == "hi");
|
||||
|
||||
|
||||
// simple boilerplate-free visitor pattern
|
||||
static foreach(char T;'A'..'F'){
|
||||
mixin("class "~T~q{{
|
||||
void accept(Visitor v){
|
||||
return v.visit(this);
|
||||
}
|
||||
}});
|
||||
}
|
||||
alias Types = Seq!(mixin("Seq!("~iota('A','F').map!(to!string).join(", ")~")"));
|
||||
abstract class Visitor{
|
||||
static foreach(T;Types){
|
||||
abstract void visit(T);
|
||||
}
|
||||
}
|
||||
|
||||
string testVisitor(){
|
||||
string r;
|
||||
void writeln(T...)(T args){
|
||||
static foreach(x;args) r~=x;
|
||||
r~='\n';
|
||||
}
|
||||
class Visitor: .Visitor{
|
||||
static foreach(T;Types){
|
||||
override void visit(T){
|
||||
writeln("visited: ",T.stringof);
|
||||
}
|
||||
}
|
||||
}
|
||||
void main(){
|
||||
auto v=new Visitor;
|
||||
static foreach(T;Types){
|
||||
v.visit(new T);
|
||||
}
|
||||
}
|
||||
main();
|
||||
return r;
|
||||
}
|
||||
static assert(testVisitor()=="visited: A
|
||||
visited: B
|
||||
visited: C
|
||||
visited: D
|
||||
visited: E
|
||||
");
|
||||
|
||||
// iterative computation over AliasSeq:
|
||||
template staticMap(alias F,T...){
|
||||
alias state0=Seq!();
|
||||
static foreach(i,A;T){
|
||||
mixin("alias state"~to!string(i+1)~" = Seq!(state"~to!string(i)~",F!A);");
|
||||
}
|
||||
alias staticMap = Seq!(mixin("state"~to!string(T.length)));
|
||||
}
|
||||
|
||||
alias arrayOf(T)=T[];
|
||||
static assert(is(staticMap!(arrayOf,int,char,bool,Object)==Seq!(int[], char[], bool[], Object[])));
|
||||
pragma(msg, staticMap!(arrayOf,int,char,bool,Object));
|
||||
|
||||
|
||||
struct StaticForeachLoopVariable{
|
||||
int x;
|
||||
static foreach(i;0..1){
|
||||
mixin("enum x"~text(i)~" = i;");
|
||||
}
|
||||
int y;
|
||||
static assert(__traits(allMembers, StaticForeachLoopVariable).length==3);
|
||||
static assert(!is(typeof(StaticForeachLoopVariable.i)));
|
||||
static assert(!is(typeof(__traits(getMember, StaticForeachLoopVariable, "i"))));
|
||||
}
|
||||
|
||||
struct StaticForeachScopeExit{
|
||||
static:
|
||||
int[] test(){
|
||||
int[] r;
|
||||
scope(exit) r ~= 1234;
|
||||
{
|
||||
static foreach(i;0..5){
|
||||
scope(exit) r ~= i;
|
||||
}
|
||||
r ~= 5;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
static assert(test()==[5,4,3,2,1,0]);
|
||||
}
|
||||
|
||||
struct StaticForeachReverseHiding{
|
||||
static foreach(i;[0]){
|
||||
enum i = 1; // TODO: disallow?
|
||||
static assert(i==0);
|
||||
}
|
||||
}
|
||||
|
||||
struct UnrolledForeachReverse{
|
||||
static:
|
||||
alias Seq(T...)=T;
|
||||
int[] test(){
|
||||
int[] r;
|
||||
foreach_reverse(i;Seq!(0,1,2,3)){
|
||||
r~=i;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
static assert(test()==[3,2,1,0]);
|
||||
}
|
||||
|
||||
struct StaticForeachReverse{
|
||||
static:
|
||||
alias Seq(T...)=T;
|
||||
int[] test(){
|
||||
int[] r;
|
||||
static foreach_reverse(i;0..4){
|
||||
r~=i;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
static assert(test()==[3,2,1,0]);
|
||||
|
||||
int[] test2(){
|
||||
int[] r;
|
||||
static foreach_reverse(i;[0,1,2,3]){
|
||||
r~=i;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
static assert(test2()==[3,2,1,0]);
|
||||
|
||||
int[] test3(){
|
||||
static struct S{
|
||||
int opApplyReverse(scope int delegate(int) dg){
|
||||
foreach_reverse(i;0..4) if(auto r=dg(i)) return r;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
int[] r;
|
||||
static foreach_reverse(i;S()){
|
||||
r~=i;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
static assert(test3()==[3,2,1,0]);
|
||||
|
||||
int[] test4(){
|
||||
int[] r;
|
||||
static foreach_reverse(i;Seq!(0,1,2,3)){
|
||||
r~=i;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
static assert(test()==[3,2,1,0]);
|
||||
}
|
||||
|
||||
struct StaticForeachByAliasDefault{
|
||||
static:
|
||||
alias Seq(T...)=T;
|
||||
|
||||
int[] test(){
|
||||
int a,b,c;
|
||||
static foreach(i,x;Seq!(a,b,c)) x=i;
|
||||
return [a,b,c];
|
||||
}
|
||||
static assert(test()==[0,1,2]);
|
||||
|
||||
int[] test2(){
|
||||
int x=0;
|
||||
int foo(){ return ++x; }
|
||||
static foreach(y;Seq!foo)
|
||||
return [y,y,y];
|
||||
}
|
||||
static assert(test2()==[1,2,3]);
|
||||
|
||||
void test3(){
|
||||
int x=0;
|
||||
int foo(){ return ++x; }
|
||||
static assert(!is(typeof({
|
||||
static foreach(enum y;Seq!foo)
|
||||
return [y,y,y];
|
||||
})));
|
||||
}
|
||||
}
|
||||
|
||||
struct NestedStaticForeach{
|
||||
static:
|
||||
static foreach(i,name;["a"]){
|
||||
static foreach(j,name2;["d"]){
|
||||
mixin("enum int[] "~name~name2~"=[i, j];");
|
||||
}
|
||||
}
|
||||
pragma(msg, ad);
|
||||
}
|
||||
|
||||
struct TestAliasOutsideFunctionScope{
|
||||
static:
|
||||
alias Seq(T...)=T;
|
||||
int a;
|
||||
static foreach(alias x;Seq!(a)){
|
||||
}
|
||||
}
|
||||
|
||||
struct OpApplyMultipleStaticForeach{
|
||||
static:
|
||||
struct OpApply{
|
||||
int opApply(scope int delegate(int,int) dg){
|
||||
foreach(i;0..10) if(auto r=dg(i,i*i)) return r;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
static foreach(a,b;OpApply()){
|
||||
mixin(`enum x`~cast(char)('0'+a)~"=b;");
|
||||
}
|
||||
static foreach(i;0..10){
|
||||
static assert(mixin(`x`~cast(char)('0'+i))==i*i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct OpApplyMultipleStaticForeachLowered{
|
||||
static:
|
||||
struct OpApply{
|
||||
int opApply(scope int delegate(int,int) dg){
|
||||
foreach(i;0..10) if(auto r=dg(i,i*i)) return r;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
static foreach(x;{
|
||||
static struct S(T...){ this(T k){ this.x=k; } T x; }
|
||||
static s(T...)(T a){ return S!T(a); }
|
||||
typeof({ foreach(a,b;OpApply()){ return s(a,b); } assert(0);}())[] r;
|
||||
foreach(a,b;OpApply()) r~=s(a,b);
|
||||
return r;
|
||||
}()){
|
||||
mixin(`enum x`~cast(char)('0'+x.x[0])~"=x.x[1];");
|
||||
}
|
||||
static foreach(i;0..10){
|
||||
static assert(mixin(`x`~cast(char)('0'+i))==i*i);
|
||||
}
|
||||
}
|
||||
|
||||
struct RangeStaticForeach{
|
||||
static:
|
||||
struct Range{
|
||||
int x=0;
|
||||
this(int x){ this.x=x; }
|
||||
@property int front(){ return x; }
|
||||
void popFront(){ x += 2; }
|
||||
@property bool empty(){ return x>=10; }
|
||||
}
|
||||
static foreach(i;Range()){
|
||||
mixin(`enum x`~cast(char)('0'+i)~"=i;");
|
||||
}
|
||||
static foreach(i;0..5){
|
||||
static assert(mixin(`x`~cast(char)('0'+2*i))==2*i);
|
||||
}
|
||||
static assert(!is(typeof({
|
||||
struct S{
|
||||
static foreach(i,k;Range()){}
|
||||
}
|
||||
})));
|
||||
static foreach(k;Range()){} // ok
|
||||
}
|
||||
|
||||
struct OpApplySingleStaticForeach{
|
||||
static:
|
||||
struct OpApply{
|
||||
int opApply(scope int delegate(int) dg){
|
||||
foreach(i;0..10) if(auto r=dg(i)) return r;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
static foreach(b;OpApply()){
|
||||
mixin(`enum x`~cast(char)('0'+b)~"=b;");
|
||||
}
|
||||
static foreach(i;0..10){
|
||||
static assert(mixin(`x`~cast(char)('0'+i))==i);
|
||||
}
|
||||
}
|
||||
|
||||
struct TypeStaticForeach{
|
||||
static:
|
||||
alias Seq(T...)=T;
|
||||
static foreach(i,alias T;Seq!(int,double,char)){
|
||||
mixin(`T x`~cast(char)('0'+i)~";");
|
||||
}
|
||||
pragma(msg, "x0: ",typeof(x0));
|
||||
pragma(msg, "x1: ",typeof(x1));
|
||||
pragma(msg, "x2: ",typeof(x2));
|
||||
static assert(is(typeof(x0)==int));
|
||||
static assert(is(typeof(x1)==double));
|
||||
static assert(is(typeof(x2)==char));
|
||||
}
|
||||
|
||||
struct AliasForeach{
|
||||
static:
|
||||
alias Seq(T...)=T;
|
||||
int[] test(){
|
||||
int a,b,c;
|
||||
static foreach(x;Seq!(a,b,c,2)){
|
||||
static if(is(typeof({x=2;}))) x=2;
|
||||
}
|
||||
int x,y,z;
|
||||
static foreach(alias k;Seq!(x,y,z,2)){
|
||||
static if(is(typeof({k=2;}))) k=2;
|
||||
}
|
||||
int j,k,l;
|
||||
static assert(!is(typeof({
|
||||
static foreach(ref x;Seq!(j,k,l,2)){
|
||||
static if(is(typeof({x=2;}))) x=2;
|
||||
}
|
||||
})));
|
||||
return [x,y,z];
|
||||
}
|
||||
static assert(test()==[2,2,2]);
|
||||
}
|
||||
|
||||
struct EnumForeach{
|
||||
static:
|
||||
alias Seq(T...)=T;
|
||||
int a=1;
|
||||
int fun(){ return 1; }
|
||||
int gun(){ return 2; }
|
||||
int hun(){ return 3;}
|
||||
auto test(){
|
||||
static foreach(i,enum x;Seq!(fun,gun,hun)){
|
||||
static assert(i+1==x);
|
||||
}
|
||||
foreach(i,enum x;Seq!(fun,gun,hun)){
|
||||
static assert(i+1==x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct TestUninterpretable{
|
||||
static:
|
||||
alias Seq(T...)=T;
|
||||
auto test(){
|
||||
int k;
|
||||
static assert(!is(typeof({
|
||||
static foreach(x;[k]){}
|
||||
})));
|
||||
static assert(!is(typeof({
|
||||
foreach(enum x;[1,2,3]){}
|
||||
})));
|
||||
static assert(!is(typeof({
|
||||
foreach(alias x;[1,2,3]){}
|
||||
})));
|
||||
foreach(enum x;Seq!(1,2,3)){} // ok
|
||||
foreach(alias x;Seq!(1,2,3)){} // ok
|
||||
static foreach(enum x;[1,2,3]){} // ok
|
||||
static foreach(alias x;[1,2,3]){} // ok
|
||||
static assert(!is(typeof({
|
||||
static foreach(enum alias x;[1,2,3]){}
|
||||
})));
|
||||
int x;
|
||||
static foreach(i;Seq!x){ } // ok
|
||||
static foreach(i,j;Seq!(1,2,x)){ } // ok
|
||||
static assert(!is(typeof({
|
||||
static foreach(ref x;[1,2,3]){}
|
||||
})));
|
||||
}
|
||||
}
|
||||
|
||||
struct SeqForeachConstant{
|
||||
static:
|
||||
alias Seq(T...)=T;
|
||||
static assert(!is(typeof({
|
||||
foreach(x;Seq!1) x=2;
|
||||
})));
|
||||
int test2(){
|
||||
int r=0;
|
||||
foreach(x;Seq!(1,2,3)){
|
||||
enum k=x;
|
||||
r+=k;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
static assert(test2()==6);
|
||||
}
|
||||
|
||||
struct SeqForeachBreakContinue{
|
||||
static:
|
||||
alias Seq(T...)=T;
|
||||
int[] test(){
|
||||
int[] r;
|
||||
foreach(i;Seq!(0,1,2,3,4,5)){
|
||||
if(i==2) continue;
|
||||
if(i==4) break;
|
||||
r~=i;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
static assert(test()==[0,1,3]);
|
||||
}
|
||||
|
||||
struct TestStaticForeach{
|
||||
static:
|
||||
int test(int x){
|
||||
int r=0;
|
||||
label: switch(x){
|
||||
static foreach(i;0..10){
|
||||
case i: r=i; break label; // TODO: remove label when restriction is lifted
|
||||
}
|
||||
default: r=-1; break label;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
static foreach(i;0..15){
|
||||
pragma(msg, "test(",i,")→ ",test(i));
|
||||
static assert(test(i)==(i<10?i:-1));
|
||||
}
|
||||
|
||||
enum x=[1,2,3];
|
||||
|
||||
static foreach(i;x){
|
||||
mixin("enum x"~cast(char)('0'+i)~"="~cast(char)('0'+i)~";");
|
||||
}
|
||||
|
||||
static foreach(i;x){
|
||||
pragma(msg, mixin("x"~cast(char)('0'+i)));
|
||||
pragma(msg,x);
|
||||
}
|
||||
|
||||
int[] noBreakNoContinue(){
|
||||
int[] r;
|
||||
static foreach(i;0..1){
|
||||
// if(i==3) continue; // TODO: error?
|
||||
// if(i==7) break; // TODO: error?
|
||||
r~=i;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
mixin("enum k=3;");
|
||||
}
|
||||
|
||||
static foreach(i,j;[1,2,3]){
|
||||
pragma(msg, int(i)," ",j);
|
||||
}
|
||||
|
||||
void testtest(){
|
||||
static foreach(i,v;[1,2,3]){
|
||||
pragma(msg, int(i)," ",v);
|
||||
static assert(i+1 == v);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static foreach(i;Seq!(1,2,3,4,int)){
|
||||
static if(!is(i) && i!=2){
|
||||
pragma(msg, i);
|
||||
}
|
||||
}
|
||||
|
||||
int fun(int x){
|
||||
int r=0;
|
||||
label: switch(x){
|
||||
static foreach(i;Seq!(0,1,2,3,4,5,6)){
|
||||
static if (i < 5)
|
||||
case i: r=i; break label; // TODO: remove label when restriction is lifted
|
||||
}
|
||||
default: r=-1; break label;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static foreach(i;0..10) static assert(fun(i)==(i<5?i:-1));
|
||||
|
||||
static foreach(i;0..0) { }
|
||||
void testEmpty(){
|
||||
static foreach(i;0..0) { }
|
||||
}
|
||||
|
||||
auto bug17660(){
|
||||
int x;
|
||||
static foreach (i; 0 .. 1) { return 3; }
|
||||
return x;
|
||||
}
|
||||
static assert(bug17660()==3);
|
||||
|
||||
int breakContinueBan(){
|
||||
static assert(!is(typeof({
|
||||
for(;;){
|
||||
static foreach(i;0..1){
|
||||
break;
|
||||
}
|
||||
}
|
||||
})));
|
||||
static assert(!is(typeof({
|
||||
for(;;){
|
||||
static foreach(i;0..1){
|
||||
continue;
|
||||
}
|
||||
}
|
||||
})));
|
||||
Louter1: for(;;){
|
||||
static foreach(i;0..1){
|
||||
break Louter1;
|
||||
}
|
||||
}
|
||||
Louter2: foreach(i;0..10){
|
||||
static foreach(j;0..1){
|
||||
continue Louter2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static foreach(i;0..1){
|
||||
for(;;){ break; } // ok
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
static assert(breakContinueBan()==1);
|
||||
|
||||
mixin template MixinTemplate(){
|
||||
static foreach(i;0..2){
|
||||
mixin(`enum x`~cast(char)('0'+i)~"=i;");
|
||||
}
|
||||
static foreach(i;[0,1]){
|
||||
mixin(`enum y`~cast(char)('0'+i)~"=i;");
|
||||
}
|
||||
}
|
||||
void testToStatement(){
|
||||
mixin MixinTemplate;
|
||||
static assert(x0==0 && x1==1);
|
||||
static assert(y0==0 && y1==1);
|
||||
}
|
||||
|
||||
void bug17688(){
|
||||
final switch(1) static foreach(x;0..1){ int y=3; case 1: return; }
|
||||
static assert(!is(typeof(y)));
|
||||
}
|
||||
|
||||
struct T{ enum n = 1; }
|
||||
T foo(T v)@nogc{
|
||||
static foreach(x;0..v.n){ }
|
||||
return T.init;
|
||||
}
|
||||
T foo2(T v)@nogc{
|
||||
static foreach(_;0..typeof(return).n){ }
|
||||
return T.init;
|
||||
}
|
||||
|
||||
//https://issues.dlang.org/show_bug.cgi?id=18698
|
||||
|
||||
static foreach(m; __traits(allMembers, staticforeach))
|
||||
{
|
||||
pragma(msg, m);
|
||||
}
|
||||
|
||||
//https://issues.dlang.org/show_bug.cgi?id=20072
|
||||
struct T2{
|
||||
static foreach(i;0..1)
|
||||
struct S{}
|
||||
}
|
||||
static assert(is(__traits(parent,T2.S)==T2));
|
||||
|
||||
struct TestStaticForeach2
|
||||
{
|
||||
static:
|
||||
// StringExp
|
||||
char[] test(string str)()
|
||||
{
|
||||
char[] s;
|
||||
static foreach (c; str)
|
||||
{
|
||||
s ~= c;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
static assert(test!"tёstñ" == ['t', '\xd1', '\x91', 's', 't', '\xc3', '\xb1']);
|
||||
|
||||
static foreach (c; "")
|
||||
{
|
||||
static assert(0);
|
||||
}
|
||||
|
||||
// NullExp
|
||||
enum int[] a = null;
|
||||
static foreach (c; a)
|
||||
{
|
||||
static assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
//https://issues.dlang.org/show_bug.cgi?id=22007
|
||||
void issue22007()
|
||||
{
|
||||
immutable int[32] array = 1;
|
||||
foreach (size_t a, int b; array) {}
|
||||
static foreach (size_t a, int b; array) { }
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue