ソースを参照

compiler: move all for-in loop helpers to the nflw unit

git-svn-id: branches/paul/features@13983 -
paul 15 年 前
コミット
731c4dfe66
2 ファイル変更359 行追加348 行削除
  1. 357 5
      compiler/nflw.pas
  2. 2 343
      compiler/pstatmnt.pas

+ 357 - 5
compiler/nflw.pas

@@ -216,17 +216,22 @@ interface
        ctryfinallynode : ttryfinallynodeclass;
        connode : tonnodeclass;
 
+// for-in loop helpers
+function create_type_for_in_loop(hloopvar, hloopbody, expr: tnode): tnode;
+function create_string_for_in_loop(hloopvar, hloopbody, expr: tnode): tnode;
+function create_array_for_in_loop(hloopvar, hloopbody, expr: tnode): tnode;
+function create_set_for_in_loop(hloopvar, hloopbody, expr: tnode): tnode;
+function create_enumerator_for_in_loop(hloopvar, hloopbody, expr: tnode;
+   enumerator_get, enumerator_move: tprocdef; enumerator_current: tpropertysym): tnode;
+function create_for_in_loop(hloopvar, hloopbody, expr: tnode): tnode;
 
 implementation
 
     uses
       globtype,systems,constexp,
       cutils,verbose,globals,
-      symconst,paramgr,defcmp,defutil,htypechk,pass_1,
-      ncal,nadd,ncon,nmem,nld,ncnv,nbas,cgobj,nutils,
-    {$ifdef prefetchnext}
-      ninl,
-    {$endif prefetchnext}
+      symconst,symtable,paramgr,defcmp,defutil,htypechk,pass_1,
+      ncal,nadd,ncon,nmem,nld,ncnv,nbas,cgobj,nutils,ninl,nset,
     {$ifdef state_tracking}
       nstate,
     {$endif}
@@ -234,6 +239,353 @@ implementation
       ;
 
 
+// for-in loop helpers
+
+function create_type_for_in_loop(hloopvar, hloopbody, expr: tnode): tnode;
+begin
+  result:=cfornode.create(hloopvar,
+       cinlinenode.create(in_low_x,false,expr.getcopy),
+       cinlinenode.create(in_high_x,false,expr.getcopy),
+       hloopbody,
+       false);
+end;
+
+function create_string_for_in_loop(hloopvar, hloopbody, expr: tnode): tnode;
+var
+  loopstatement, loopbodystatement: tstatementnode;
+  loopvar, stringvar: ttempcreatenode;
+  stringindex, loopbody, forloopnode: tnode;
+begin
+  { result is a block of statements }
+  result:=internalstatements(loopstatement);
+
+  { create a temp variable for expression }
+  stringvar := ctempcreatenode.create(
+    expr.resultdef,
+    expr.resultdef.size,
+    tt_persistent,true);
+
+  addstatement(loopstatement,stringvar);
+  addstatement(loopstatement,cassignmentnode.create(ctemprefnode.create(stringvar),expr.getcopy));
+
+  { create a loop counter: signed integer with size of string length }
+  loopvar := ctempcreatenode.create(
+    sinttype,
+    sinttype.size,
+    tt_persistent,true);
+
+  addstatement(loopstatement,loopvar);
+
+  stringindex:=ctemprefnode.create(loopvar);
+
+  loopbody:=internalstatements(loopbodystatement);
+  // for-in loop variable := string_expression[index]
+  addstatement(loopbodystatement,
+      cassignmentnode.create(hloopvar, cvecnode.create(ctemprefnode.create(stringvar),stringindex)));
+
+  { add the actual statement to the loop }
+  addstatement(loopbodystatement,hloopbody);
+
+  forloopnode:=cfornode.create(ctemprefnode.create(loopvar),
+     genintconstnode(1),
+     cinlinenode.create(in_length_x,false,ctemprefnode.create(stringvar)),
+     loopbody,
+     false);
+
+  addstatement(loopstatement,forloopnode);
+  { free the loop counter }
+  addstatement(loopstatement,ctempdeletenode.create(loopvar));
+  { free the temp variable for expression }
+  addstatement(loopstatement,ctempdeletenode.create(stringvar));
+end;
+
+function create_array_for_in_loop(hloopvar, hloopbody, expr: tnode): tnode;
+var
+  loopstatement, loopbodystatement: tstatementnode;
+  loopvar, arrayvar: ttempcreatenode;
+  arrayindex, lowbound, highbound, loopbody, forloopnode: tnode;
+begin
+  { result is a block of statements }
+  result:=internalstatements(loopstatement);
+
+  if (node_complexity(expr) > 1) and not is_open_array(expr.resultdef) then
+  begin
+    { create a temp variable for expression }
+    arrayvar := ctempcreatenode.create(
+      expr.resultdef,
+      expr.resultdef.size,
+      tt_persistent,true);
+
+    lowbound:=cinlinenode.create(in_low_x,false,ctemprefnode.create(arrayvar));
+    highbound:=cinlinenode.create(in_high_x,false,ctemprefnode.create(arrayvar));
+
+    addstatement(loopstatement,arrayvar);
+    addstatement(loopstatement,cassignmentnode.create(ctemprefnode.create(arrayvar),expr.getcopy));
+  end
+  else
+  begin
+    arrayvar:=nil;
+    lowbound:=cinlinenode.create(in_low_x,false,expr.getcopy);
+    highbound:=cinlinenode.create(in_high_x,false,expr.getcopy);
+  end;
+
+  { create a loop counter }
+  loopvar := ctempcreatenode.create(
+    tarraydef(expr.resultdef).rangedef,
+    tarraydef(expr.resultdef).rangedef.size,
+    tt_persistent,true);
+
+  addstatement(loopstatement,loopvar);
+
+  arrayindex:=ctemprefnode.create(loopvar);
+
+  loopbody:=internalstatements(loopbodystatement);
+  // for-in loop variable := array_expression[index]
+  if assigned(arrayvar) then
+    addstatement(loopbodystatement,
+        cassignmentnode.create(hloopvar,cvecnode.create(ctemprefnode.create(arrayvar),arrayindex)))
+  else
+    addstatement(loopbodystatement,
+        cassignmentnode.create(hloopvar,cvecnode.create(expr.getcopy,arrayindex)));
+
+  { add the actual statement to the loop }
+  addstatement(loopbodystatement,hloopbody);
+
+  forloopnode:=cfornode.create(ctemprefnode.create(loopvar),
+     lowbound,
+     highbound,
+     loopbody,
+     false);
+
+  addstatement(loopstatement,forloopnode);
+  { free the loop counter }
+  addstatement(loopstatement,ctempdeletenode.create(loopvar));
+  { free the temp variable for expression if needed }
+  if arrayvar<>nil then
+    addstatement(loopstatement,ctempdeletenode.create(arrayvar));
+end;
+
+function create_set_for_in_loop(hloopvar, hloopbody, expr: tnode): tnode;
+var
+  loopstatement, loopbodystatement: tstatementnode;
+  loopvar, setvar: ttempcreatenode;
+  loopbody, forloopnode: tnode;
+begin
+  { result is a block of statements }
+  result:=internalstatements(loopstatement);
+
+  { create a temp variable for expression }
+  setvar := ctempcreatenode.create(
+    expr.resultdef,
+    expr.resultdef.size,
+    tt_persistent,true);
+
+  addstatement(loopstatement,setvar);
+  addstatement(loopstatement,cassignmentnode.create(ctemprefnode.create(setvar),expr.getcopy));
+
+  { create a loop counter }
+  loopvar := ctempcreatenode.create(
+    tsetdef(expr.resultdef).elementdef,
+    tsetdef(expr.resultdef).elementdef.size,
+    tt_persistent,true);
+
+  addstatement(loopstatement,loopvar);
+
+  // if loopvar in set then
+  // begin
+  //   hloopvar := loopvar
+  //   for-in loop body
+  // end
+
+  loopbody:=cifnode.create(
+        cinnode.create(ctemprefnode.create(loopvar),ctemprefnode.create(setvar)),
+        internalstatements(loopbodystatement),
+        nil
+  );
+
+  addstatement(loopbodystatement,cassignmentnode.create(hloopvar,ctemprefnode.create(loopvar)));
+  { add the actual statement to the loop }
+  addstatement(loopbodystatement,hloopbody);
+
+  forloopnode:=cfornode.create(ctemprefnode.create(loopvar),
+     cinlinenode.create(in_low_x,false,ctemprefnode.create(setvar)),
+     cinlinenode.create(in_high_x,false,ctemprefnode.create(setvar)),
+     loopbody,
+     false);
+
+  addstatement(loopstatement,forloopnode);
+  { free the loop counter }
+  addstatement(loopstatement,ctempdeletenode.create(loopvar));
+  { free the temp variable for expression }
+  addstatement(loopstatement,ctempdeletenode.create(setvar));
+end;
+
+function create_enumerator_for_in_loop(hloopvar, hloopbody, expr: tnode;
+   enumerator_get, enumerator_move: tprocdef; enumerator_current: tpropertysym): tnode;
+var
+  loopstatement, loopbodystatement: tstatementnode;
+  enumvar: ttempcreatenode;
+  loopbody, whileloopnode,
+  enum_get, enum_move, enum_current, enum_get_params: tnode;
+  propaccesslist: tpropaccesslist;
+  enumerator_is_class: boolean;
+  enumerator_destructor: tprocdef;
+begin
+  { result is a block of statements }
+  result:=internalstatements(loopstatement);
+
+  enumerator_is_class := is_class(enumerator_get.returndef);
+
+  { create a temp variable for enumerator }
+  enumvar := ctempcreatenode.create(
+    enumerator_get.returndef,
+    enumerator_get.returndef.size,
+    tt_persistent,true);
+
+  addstatement(loopstatement,enumvar);
+
+  if enumerator_get.proctypeoption=potype_operator then
+  begin
+    enum_get_params:=ccallparanode.create(expr.getcopy,nil);
+    enum_get:=ccallnode.create(enum_get_params, tprocsym(enumerator_get.procsym), nil, nil, []);
+    tcallnode(enum_get).procdefinition:=enumerator_get;
+    addsymref(enumerator_get.procsym);
+  end
+  else
+    enum_get:=ccallnode.create(nil, tprocsym(enumerator_get.procsym), enumerator_get.owner, expr.getcopy, []);
+
+  addstatement(loopstatement,
+    cassignmentnode.create(
+      ctemprefnode.create(enumvar),
+      enum_get
+    ));
+
+  loopbody:=internalstatements(loopbodystatement);
+  { for-in loop variable := enumerator.current }
+  if getpropaccesslist(enumerator_current,palt_read,propaccesslist) then
+  begin
+     case propaccesslist.firstsym^.sym.typ of
+       fieldvarsym :
+         begin
+            { generate access code }
+            enum_current:=ctemprefnode.create(enumvar);
+            propaccesslist_to_node(enum_current,enumerator_current.owner,propaccesslist);
+            include(enum_current.flags,nf_isproperty);
+         end;
+       procsym :
+         begin
+            { generate the method call }
+            enum_current:=ccallnode.create(nil,tprocsym(propaccesslist.firstsym^.sym),enumerator_current.owner,ctemprefnode.create(enumvar),[]);
+            include(enum_current.flags,nf_isproperty);
+         end
+       else
+         begin
+            enum_current:=cerrornode.create;
+            Message(type_e_mismatch);
+         end;
+    end;
+  end
+  else
+    enum_current:=cerrornode.create;
+
+  addstatement(loopbodystatement,
+      cassignmentnode.create(hloopvar, enum_current));
+
+  { add the actual statement to the loop }
+  addstatement(loopbodystatement,hloopbody);
+
+  enum_move:=ccallnode.create(nil, tprocsym(enumerator_move.procsym), enumerator_move.owner, ctemprefnode.create(enumvar), []);
+  whileloopnode:=cwhilerepeatnode.create(enum_move,loopbody,true,false);
+
+  if enumerator_is_class then
+  begin
+    { insert a try-finally and call the destructor for the enumerator in the finally section }
+    enumerator_destructor:=tobjectdef(enumerator_get.returndef).Finddestructor;
+    if assigned(enumerator_destructor) then
+    begin
+      whileloopnode:=ctryfinallynode.create(
+        whileloopnode, // try node
+        ccallnode.create(nil,tprocsym(enumerator_destructor.procsym), // finally node
+          enumerator_destructor.procsym.owner,ctemprefnode.create(enumvar),[]));
+    end;
+    { if getenumerator <> nil then do the loop }
+    whileloopnode:=cifnode.create(
+      caddnode.create(unequaln, ctemprefnode.create(enumvar), cnilnode.create),
+      whileloopnode,
+      nil
+      );
+  end;
+
+  addstatement(loopstatement, whileloopnode);
+
+  if is_object(enumerator_get.returndef) then
+  begin
+    // call the object destructor too
+    enumerator_destructor:=tobjectdef(enumerator_get.returndef).Finddestructor;
+    if assigned(enumerator_destructor) then
+    begin
+      addstatement(loopstatement,
+        ccallnode.create(nil,tprocsym(enumerator_destructor.procsym),
+            enumerator_destructor.procsym.owner,ctemprefnode.create(enumvar),[]));
+    end;
+  end;
+
+  { free the temp variable for enumerator }
+  addstatement(loopstatement,ctempdeletenode.create(enumvar));
+end;
+
+function create_for_in_loop(hloopvar, hloopbody, expr: tnode): tnode;
+var
+  pd, movenext: tprocdef;
+  current: tpropertysym;
+begin
+  if expr.nodetype=typen then
+    result:=create_type_for_in_loop(hloopvar, hloopbody, expr)
+  else
+  begin
+    { loop is made for an expression }
+    // search for operator first
+    pd:=search_enumerator_operator(expr.resultdef);
+    // if there is no operator then search for class/object enumerator method
+    if (pd=nil) and (expr.resultdef.typ=objectdef) then
+      pd:=tobjectdef(expr.resultdef).search_enumerator_get;
+    if pd<>nil then
+    begin
+      // seach movenext and current symbols
+      movenext:=tobjectdef(pd.returndef).search_enumerator_move;
+      if movenext = nil then
+      begin
+        result:=cerrornode.create;
+        Message1(sym_e_no_enumerator_move,pd.returndef.GetTypeName);
+      end
+      else
+      begin
+        current:=tpropertysym(tobjectdef(pd.returndef).search_enumerator_current);
+        if current = nil then
+        begin
+          result:=cerrornode.create;
+          Message1(sym_e_no_enumerator_current,pd.returndef.GetTypeName);
+        end
+        else
+          result:=create_enumerator_for_in_loop(hloopvar, hloopbody, expr, pd, movenext, current);
+      end;
+    end
+    else
+    begin
+      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);
+      else
+        begin
+          result:=cerrornode.create;
+          Message1(sym_e_no_enumerator,expr.resultdef.GetTypeName);
+        end;
+      end;
+    end;
+  end;
+end;
+
 {****************************************************************************
                                  TLOOPNODE
 *****************************************************************************}

+ 2 - 343
compiler/pstatmnt.pas

@@ -501,305 +501,9 @@ implementation
            result:=cfornode.create(hloopvar,hfrom,hto,hblock,backward);
         end;
          
-        function create_type_loop(hloopvar, hloopbody, expr: tnode): tnode;
-        begin
-          result:=cfornode.create(hloopvar,
-               cinlinenode.create(in_low_x,false,expr.getcopy),
-               cinlinenode.create(in_high_x,false,expr.getcopy),
-               hloopbody,
-               false);
-        end; 
-
-        function create_string_loop(hloopvar, hloopbody, expr: tnode): tnode;
-        var
-          loopstatement, loopbodystatement: tstatementnode;
-          loopvar, stringvar: ttempcreatenode;
-          stringindex, loopbody, forloopnode: tnode;
-        begin
-          { result is a block of statements }
-          result:=internalstatements(loopstatement);
-
-          { create a temp variable for expression }
-          stringvar := ctempcreatenode.create(
-            expr.resultdef,
-            expr.resultdef.size,
-            tt_persistent,true);
-
-          addstatement(loopstatement,stringvar);
-          addstatement(loopstatement,cassignmentnode.create(ctemprefnode.create(stringvar),expr.getcopy));
-
-          { create a loop counter: signed integer with size of string length }
-          loopvar := ctempcreatenode.create(
-            sinttype,
-            sinttype.size,
-            tt_persistent,true);
-
-          addstatement(loopstatement,loopvar);
-
-          stringindex:=ctemprefnode.create(loopvar);
-
-          loopbody:=internalstatements(loopbodystatement);
-          // for-in loop variable := string_expression[index]
-          addstatement(loopbodystatement,
-              cassignmentnode.create(hloopvar, cvecnode.create(ctemprefnode.create(stringvar),stringindex)));
-
-          { add the actual statement to the loop }
-          addstatement(loopbodystatement,hloopbody);
-         
-          forloopnode:=cfornode.create(ctemprefnode.create(loopvar),
-             genintconstnode(1),
-             cinlinenode.create(in_length_x,false,ctemprefnode.create(stringvar)),
-             loopbody,
-             false);
-
-          addstatement(loopstatement,forloopnode);
-          { free the loop counter }
-          addstatement(loopstatement,ctempdeletenode.create(loopvar));
-          { free the temp variable for expression }
-          addstatement(loopstatement,ctempdeletenode.create(stringvar));
-        end;
-
-
-        function create_array_loop(hloopvar, hloopbody, expr: tnode): tnode;
-        var
-          loopstatement, loopbodystatement: tstatementnode;
-          loopvar, arrayvar: ttempcreatenode;
-          arrayindex, lowbound, highbound, loopbody, forloopnode: tnode;
-        begin
-          { result is a block of statements }
-          result:=internalstatements(loopstatement);
-
-          if (node_complexity(expr) > 1) and not is_open_array(expr.resultdef) then
-          begin
-            { create a temp variable for expression }
-            arrayvar := ctempcreatenode.create(
-              expr.resultdef,
-              expr.resultdef.size,
-              tt_persistent,true);
-
-            lowbound:=cinlinenode.create(in_low_x,false,ctemprefnode.create(arrayvar));
-            highbound:=cinlinenode.create(in_high_x,false,ctemprefnode.create(arrayvar));
-
-            addstatement(loopstatement,arrayvar);
-            addstatement(loopstatement,cassignmentnode.create(ctemprefnode.create(arrayvar),expr.getcopy));
-          end
-          else
-          begin
-            arrayvar:=nil;
-            lowbound:=cinlinenode.create(in_low_x,false,expr.getcopy);
-            highbound:=cinlinenode.create(in_high_x,false,expr.getcopy);
-          end;
-
-          { create a loop counter }
-          loopvar := ctempcreatenode.create(
-            tarraydef(expr.resultdef).rangedef,
-            tarraydef(expr.resultdef).rangedef.size,
-            tt_persistent,true);
-
-          addstatement(loopstatement,loopvar);
-
-          arrayindex:=ctemprefnode.create(loopvar);
-
-          loopbody:=internalstatements(loopbodystatement);
-          // for-in loop variable := array_expression[index]
-          if assigned(arrayvar) then
-            addstatement(loopbodystatement,
-                cassignmentnode.create(hloopvar,cvecnode.create(ctemprefnode.create(arrayvar),arrayindex)))
-          else
-            addstatement(loopbodystatement,
-                cassignmentnode.create(hloopvar,cvecnode.create(expr.getcopy,arrayindex)));
-
-          { add the actual statement to the loop }
-          addstatement(loopbodystatement,hloopbody);
-          
-          forloopnode:=cfornode.create(ctemprefnode.create(loopvar),
-             lowbound,
-             highbound,
-             loopbody,
-             false);
-
-          addstatement(loopstatement,forloopnode);
-          { free the loop counter }
-          addstatement(loopstatement,ctempdeletenode.create(loopvar));
-          { free the temp variable for expression if needed }
-          if arrayvar<>nil then
-            addstatement(loopstatement,ctempdeletenode.create(arrayvar));
-        end;
-
-        function create_set_loop(hloopvar, hloopbody, expr: tnode): tnode;
-        var
-          loopstatement, loopbodystatement: tstatementnode;
-          loopvar, setvar: ttempcreatenode;
-          loopbody, forloopnode: tnode;
-        begin
-          { result is a block of statements }
-          result:=internalstatements(loopstatement);
-
-          { create a temp variable for expression }
-          setvar := ctempcreatenode.create(
-            expr.resultdef,
-            expr.resultdef.size,
-            tt_persistent,true);
-
-          addstatement(loopstatement,setvar);
-          addstatement(loopstatement,cassignmentnode.create(ctemprefnode.create(setvar),expr.getcopy));
-
-          { create a loop counter }
-          loopvar := ctempcreatenode.create(
-            tsetdef(expr.resultdef).elementdef,
-            tsetdef(expr.resultdef).elementdef.size,
-            tt_persistent,true);
-
-          addstatement(loopstatement,loopvar);
-
-          // if loopvar in set then
-          // begin
-          //   hloopvar := loopvar
-          //   for-in loop body
-          // end
-
-          loopbody:=cifnode.create(
-                cinnode.create(ctemprefnode.create(loopvar),ctemprefnode.create(setvar)),
-                internalstatements(loopbodystatement),
-                nil
-          );
-
-          addstatement(loopbodystatement,cassignmentnode.create(hloopvar,ctemprefnode.create(loopvar)));
-          { add the actual statement to the loop }
-          addstatement(loopbodystatement,hloopbody);
-          
-          forloopnode:=cfornode.create(ctemprefnode.create(loopvar),
-             cinlinenode.create(in_low_x,false,ctemprefnode.create(setvar)),
-             cinlinenode.create(in_high_x,false,ctemprefnode.create(setvar)),
-             loopbody,
-             false);
-
-          addstatement(loopstatement,forloopnode);
-          { free the loop counter }
-          addstatement(loopstatement,ctempdeletenode.create(loopvar));
-          { free the temp variable for expression }
-          addstatement(loopstatement,ctempdeletenode.create(setvar));
-        end;
-
-        function create_enumerator_loop(hloopvar, hloopbody, expr: tnode;
-           enumerator_get, enumerator_move: tprocdef; enumerator_current: tpropertysym): tnode;
-        var
-          loopstatement, loopbodystatement: tstatementnode;
-          enumvar: ttempcreatenode;
-          loopbody, whileloopnode,
-          enum_get, enum_move, enum_current, enum_get_params: tnode;
-          propaccesslist: tpropaccesslist;
-          enumerator_is_class: boolean;
-          enumerator_destructor: tprocdef;
-        begin
-          { result is a block of statements }
-          result:=internalstatements(loopstatement);
-
-          enumerator_is_class := is_class(enumerator_get.returndef);
-
-          { create a temp variable for enumerator }
-          enumvar := ctempcreatenode.create(
-            enumerator_get.returndef,
-            enumerator_get.returndef.size,
-            tt_persistent,true);
-
-          addstatement(loopstatement,enumvar);
-
-          if enumerator_get.proctypeoption=potype_operator then
-          begin
-            enum_get_params:=ccallparanode.create(expr.getcopy,nil);
-            enum_get:=ccallnode.create(enum_get_params, tprocsym(enumerator_get.procsym), nil, nil, []);
-            tcallnode(enum_get).procdefinition:=enumerator_get;
-            addsymref(enumerator_get.procsym);
-          end
-          else
-            enum_get:=ccallnode.create(nil, tprocsym(enumerator_get.procsym), enumerator_get.owner, expr.getcopy, []);
-
-          addstatement(loopstatement,
-            cassignmentnode.create(
-              ctemprefnode.create(enumvar),
-              enum_get
-            ));
-
-          loopbody:=internalstatements(loopbodystatement);
-          { for-in loop variable := enumerator.current }
-          if getpropaccesslist(enumerator_current,palt_read,propaccesslist) then
-          begin
-             case propaccesslist.firstsym^.sym.typ of
-               fieldvarsym :
-                 begin
-                    { generate access code }
-                    enum_current:=ctemprefnode.create(enumvar);
-                    propaccesslist_to_node(enum_current,enumerator_current.owner,propaccesslist);
-                    include(enum_current.flags,nf_isproperty);
-                 end;
-               procsym :
-                 begin
-                    { generate the method call }
-                    enum_current:=ccallnode.create(nil,tprocsym(propaccesslist.firstsym^.sym),enumerator_current.owner,ctemprefnode.create(enumvar),[]);
-                    include(enum_current.flags,nf_isproperty);
-                 end
-               else
-                 begin
-                    enum_current:=cerrornode.create;
-                    Message(type_e_mismatch);
-                 end;
-            end;
-          end
-          else
-            enum_current:=cerrornode.create;
-
-          addstatement(loopbodystatement,
-              cassignmentnode.create(hloopvar, enum_current));
-
-          { add the actual statement to the loop }
-          addstatement(loopbodystatement,hloopbody);
-
-          enum_move:=ccallnode.create(nil, tprocsym(enumerator_move.procsym), enumerator_move.owner, ctemprefnode.create(enumvar), []);
-          whileloopnode:=cwhilerepeatnode.create(enum_move,loopbody,true,false);
-
-          if enumerator_is_class then
-          begin
-            { insert a try-finally and call the destructor for the enumerator in the finally section }
-            enumerator_destructor:=tobjectdef(enumerator_get.returndef).Finddestructor;
-            if assigned(enumerator_destructor) then
-            begin
-              whileloopnode:=ctryfinallynode.create(
-                whileloopnode, // try node
-                ccallnode.create(nil,tprocsym(enumerator_destructor.procsym), // finally node
-                  enumerator_destructor.procsym.owner,ctemprefnode.create(enumvar),[]));
-            end;
-            { if getenumerator <> nil then do the loop }
-            whileloopnode:=cifnode.create(
-              caddnode.create(unequaln, ctemprefnode.create(enumvar), cnilnode.create),
-              whileloopnode,
-              nil
-              );
-          end;
-
-          addstatement(loopstatement, whileloopnode);
-
-          if is_object(enumerator_get.returndef) then
-          begin
-            // call the object destructor too
-            enumerator_destructor:=tobjectdef(enumerator_get.returndef).Finddestructor;
-            if assigned(enumerator_destructor) then
-            begin
-              addstatement(loopstatement,
-                ccallnode.create(nil,tprocsym(enumerator_destructor.procsym),
-                    enumerator_destructor.procsym.owner,ctemprefnode.create(enumvar),[]));
-            end;
-          end;
-
-          { free the temp variable for enumerator }
-          addstatement(loopstatement,ctempdeletenode.create(enumvar));
-        end;
-
         function for_in_loop_create(hloopvar: tnode): tnode;
         var
-          expr, hloopbody: tnode;
-          pd, movenext: tprocdef;
-          current: tpropertysym;
+          expr: tnode;
         begin
           expr := comp_expr(true);
 
@@ -808,53 +512,8 @@ implementation
           set_varstate(hloopvar,vs_written,[]);
           set_varstate(hloopvar,vs_read,[vsf_must_be_valid]);
 
-          hloopbody:=statement;
+          result := create_for_in_loop(hloopvar, statement, expr);
  
-          if expr.nodetype=typen then
-            result:=create_type_loop(hloopvar, hloopbody, expr)
-          else
-          begin
-            { loop is made for an expression }
-            // search for operator first
-            pd:=search_enumerator_operator(expr.resultdef);
-            // if there is no operator then search for class/object enumerator method
-            if (pd=nil) and (expr.resultdef.typ=objectdef) then
-              pd:=tobjectdef(expr.resultdef).search_enumerator_get;
-            if pd<>nil then
-            begin
-              // seach movenext and current symbols
-              movenext:=tobjectdef(pd.returndef).search_enumerator_move;
-              if movenext = nil then
-              begin
-                result:=cerrornode.create;
-                Message1(sym_e_no_enumerator_move,pd.returndef.GetTypeName);
-              end
-              else
-              begin
-                current:=tpropertysym(tobjectdef(pd.returndef).search_enumerator_current);
-                if current = nil then
-                begin
-                  result:=cerrornode.create;
-                  Message1(sym_e_no_enumerator_current,pd.returndef.GetTypeName);
-                end
-                else
-                  result:=create_enumerator_loop(hloopvar, hloopbody, expr, pd, movenext, current);
-              end;
-            end
-            else
-            begin
-              case expr.resultdef.typ of
-                stringdef: result:=create_string_loop(hloopvar, hloopbody, expr);
-                arraydef: result:=create_array_loop(hloopvar, hloopbody, expr);
-                setdef: result:=create_set_loop(hloopvar, hloopbody, expr);
-              else
-                begin
-                  result:=cerrornode.create;
-                  Message1(sym_e_no_enumerator,expr.resultdef.GetTypeName);
-                end;
-              end;
-            end;
-          end;
           expr.free;
         end;