* allow generic parameters as iterator variable in for in loops, resolves #38050

git-svn-id: trunk@47425 -
This commit is contained in:
florian 2020-11-15 19:10:34 +00:00
parent 3d2ee097b5
commit 878f6d9ce4
3 changed files with 80 additions and 3 deletions

1
.gitattributes vendored
View File

@ -18529,6 +18529,7 @@ tests/webtbs/tw38022.pp svneol=native#text/pascal
tests/webtbs/tw3805.pp svneol=native#text/plain
tests/webtbs/tw38051.pp svneol=native#text/pascal
tests/webtbs/tw38054.pp svneol=native#text/plain
tests/webtbs/tw38058.pp svneol=native#text/pascal
tests/webtbs/tw38069.pp svneol=native#text/pascal
tests/webtbs/tw38074.pp svneol=native#text/pascal
tests/webtbs/tw38083.pp svneol=native#text/pascal

View File

@ -985,9 +985,14 @@ implementation
typecheckpass(expr);
end;
case expr.resultdef.typ of
stringdef: result:=create_string_for_in_loop(hloopvar, hloopbody, expr);
arraydef: result:=create_array_for_in_loop(hloopvar, hloopbody, expr);
setdef: result:=create_set_for_in_loop(hloopvar, hloopbody, expr);
stringdef:
result:=create_string_for_in_loop(hloopvar, hloopbody, expr);
arraydef:
result:=create_array_for_in_loop(hloopvar, hloopbody, expr);
setdef:
result:=create_set_for_in_loop(hloopvar, hloopbody, expr);
undefineddef:
result:=cnothingnode.create;
else
begin
result:=cerrornode.create;

71
tests/webtbs/tw38058.pp Normal file
View File

@ -0,0 +1,71 @@
{$mode objfpc}
program Project1;
type
TElem=(a,b,c,d,e,f);
TmyElem=(my_a,my_c,my_e);
TElems=set of TElem;//Output set, need convert my_a->a, my_c->c, my_e->e остальное скипаем
TmyElems=set of TmyElem;//Input set
generic TSetConverter<TGEnumIn,TGSetIn,TGEnumOut,TGSetOut,TGEnumConverter>=class
class function Convert(value:TGSetIn):TGSetOut;
end;
TmyElem2TElem_Converter=class
class function Convert(valueIn:TmyElem;out valueOut:TElem):boolean;
end;
TConverter=specialize TSetConverter<TmyElem,TmyElems,TElem,TElems,TmyElem2TElem_Converter>;
class function TmyElem2TElem_Converter.Convert(valueIn:TmyElem;out valueOut:TElem):boolean;
begin
result:=true;
case valueIn of
my_a:valueOut:=a;
my_c:valueOut:=c;
my_e:valueOut:=e;
else result:=false;
end;
end;
{//Variant 1
class function TSetConverter.Convert(value:TGSetIn):TGSetOut;
var
CurrentEnumIn:TGEnumIn;
CurrentEnumOut:TGEnumOut;
tvalue:TGSetIn;
begin
result:=[];
for CurrentEnumIn:=low(TGEnumIn) to high(TGEnumIn) do begin
tvalue:=value-[CurrentEnumIn];
if tvalue<>value then begin
if TGEnumConverter.convert(CurrentEnumIn,CurrentEnumOut) then
result:=result+[CurrentEnumOut];
if tvalue=[] then exit;
value:=tvalue;
end;
end;
end;
}
//Variant 2
class function TSetConverter.Convert(value:TGSetIn):TGSetOut;
var
CurrentEnumIn:TGEnumIn;
CurrentEnumOut:TGEnumOut;
begin
result:=[];
for CurrentEnumIn in value do
if TGEnumConverter.convert(CurrentEnumIn,CurrentEnumOut) then
result:=result+[CurrentEnumOut];
end;
var
Elems:TElems;
Elem:TElem;
begin
Elems:=TConverter.Convert([my_a,my_c,my_e]);
for Elem in Elems do
write(Elem);
readln;
end.