Browse Source

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

git-svn-id: trunk@47425 -
florian 4 years ago
parent
commit
878f6d9ce4
3 changed files with 80 additions and 3 deletions
  1. 1 0
      .gitattributes
  2. 8 3
      compiler/nflw.pas
  3. 71 0
      tests/webtbs/tw38058.pp

+ 1 - 0
.gitattributes

@@ -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

+ 8 - 3
compiler/nflw.pas

@@ -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 - 0
tests/webtbs/tw38058.pp

@@ -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.