mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-10-31 22:11:12 +01:00 
			
		
		
		
	* fixed indentation of for-in code
git-svn-id: trunk@15449 -
This commit is contained in:
		
							parent
							
								
									45d60dbb97
								
							
						
					
					
						commit
						df525d98a3
					
				| @ -241,426 +241,429 @@ 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, expression: tnode; | ||||
|   is_string: boolean; | ||||
|   tmpdef, convertdef: tdef; | ||||
|   elementcount: aword; | ||||
| begin | ||||
|   expression := expr; | ||||
| 
 | ||||
|   { result is a block of statements } | ||||
|   result:=internalstatements(loopstatement); | ||||
| 
 | ||||
|   is_string:=ado_IsConstString in tarraydef(expr.resultdef).arrayoptions; | ||||
| 
 | ||||
|   // if array element type <> loovar type then create a conversion if possible | ||||
|   if compare_defs(tarraydef(expression.resultdef).elementdef,hloopvar.resultdef,nothingn)=te_incompatible then | ||||
|   begin | ||||
|     tmpdef:=expression.resultdef; | ||||
|     elementcount:=1; | ||||
|     while assigned(tmpdef) and (tmpdef.typ=arraydef) and | ||||
|           (tarraydef(tmpdef).arrayoptions = []) and | ||||
|           (compare_defs(tarraydef(tmpdef).elementdef,hloopvar.resultdef,nothingn)=te_incompatible) do | ||||
|     begin | ||||
|       elementcount:=elementcount*tarraydef(tmpdef).elecount; | ||||
|       tmpdef:=tarraydef(tmpdef).elementdef; | ||||
|     end; | ||||
|     if assigned(tmpdef) and (tmpdef.typ=arraydef) and (tarraydef(tmpdef).arrayoptions = []) then | ||||
|     begin | ||||
|       elementcount:=elementcount*tarraydef(tmpdef).elecount; | ||||
|       convertdef:=tarraydef.create(0,elementcount-1,s32inttype); | ||||
|       tarraydef(convertdef).elementdef:=tarraydef(tmpdef).elementdef; | ||||
|       expression:=expr.getcopy; | ||||
|       expression:=ctypeconvnode.create_internal(expression,convertdef); | ||||
|       typecheckpass(expression); | ||||
|       addstatement(loopstatement,expression); | ||||
|     end; | ||||
|   end; | ||||
| 
 | ||||
|   if (node_complexity(expression) > 1) and not is_open_array(expression.resultdef) then | ||||
|   begin | ||||
|     { create a temp variable for expression } | ||||
|     arrayvar := ctempcreatenode.create( | ||||
|       expression.resultdef, | ||||
|       expression.resultdef.size, | ||||
|       tt_persistent,true); | ||||
| 
 | ||||
|     if is_string then | ||||
|     begin | ||||
|       lowbound:=genintconstnode(1); | ||||
|       highbound:=cinlinenode.create(in_length_x,false,ctemprefnode.create(arrayvar)) | ||||
|     end | ||||
|     else | ||||
|     begin | ||||
|       lowbound:=cinlinenode.create(in_low_x,false,ctemprefnode.create(arrayvar)); | ||||
|       highbound:=cinlinenode.create(in_high_x,false,ctemprefnode.create(arrayvar)); | ||||
|     end; | ||||
| 
 | ||||
|     addstatement(loopstatement,arrayvar); | ||||
|     addstatement(loopstatement,cassignmentnode.create(ctemprefnode.create(arrayvar),expression.getcopy)); | ||||
|   end | ||||
|   else | ||||
|   begin | ||||
|     arrayvar:=nil; | ||||
|     if is_string then | ||||
|     begin | ||||
|       lowbound:=genintconstnode(1); | ||||
|       highbound:=cinlinenode.create(in_length_x,false,expression.getcopy); | ||||
|     end | ||||
|     else | ||||
|     begin | ||||
|       lowbound:=cinlinenode.create(in_low_x,false,expression.getcopy); | ||||
|       highbound:=cinlinenode.create(in_high_x,false,expression.getcopy); | ||||
|     end; | ||||
|   end; | ||||
| 
 | ||||
|   { create a loop counter } | ||||
|   loopvar := ctempcreatenode.create( | ||||
|     tarraydef(expression.resultdef).rangedef, | ||||
|     tarraydef(expression.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(expression.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 | ||||
|   // first check is set is empty and if it so then skip other processing | ||||
|   if not Assigned(tsetdef(expr.resultdef).elementdef) then | ||||
|   begin | ||||
|     result:=cnothingnode.create; | ||||
|     // free unused nodes | ||||
|     hloopvar.free; | ||||
|     hloopbody.free; | ||||
|     exit; | ||||
|   end; | ||||
|   { 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).find_destructor; | ||||
|     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).find_destructor; | ||||
|     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; | ||||
|   storefilepos: tfileposinfo; | ||||
| begin | ||||
|   storefilepos:=current_filepos; | ||||
|   current_filepos:=hloopvar.fileinfo; | ||||
|   if expr.nodetype=typen then | ||||
|   begin | ||||
|     if (expr.resultdef.typ=enumdef) and tenumdef(expr.resultdef).has_jumps then | ||||
|     begin | ||||
|       result:=cerrornode.create; | ||||
|       hloopvar.free; | ||||
|       hloopbody.free; | ||||
|       MessagePos1(expr.fileinfo,parser_e_for_in_loop_cannot_be_used_for_the_type,expr.resultdef.typename); | ||||
|     end | ||||
|     else  | ||||
|       result:=create_type_for_in_loop(hloopvar, hloopbody, expr); | ||||
|   end | ||||
|   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 | ||||
|     function create_type_for_in_loop(hloopvar, hloopbody, expr: tnode): tnode; | ||||
|       begin | ||||
|         result:=cerrornode.create; | ||||
|         hloopvar.free; | ||||
|         hloopbody.free; | ||||
|         MessagePos1(expr.fileinfo,sym_e_no_enumerator_move,pd.returndef.GetTypeName); | ||||
|       end | ||||
|       else | ||||
|         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 | ||||
|         current:=tpropertysym(tobjectdef(pd.returndef).search_enumerator_current); | ||||
|         if current = nil then | ||||
|         begin | ||||
|           result:=cerrornode.create; | ||||
|           hloopvar.free; | ||||
|           hloopbody.free; | ||||
|           MessagePos1(expr.fileinfo,sym_e_no_enumerator_current,pd.returndef.GetTypeName); | ||||
|         end | ||||
|         { 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, expression: tnode; | ||||
|         is_string: boolean; | ||||
|         tmpdef, convertdef: tdef; | ||||
|         elementcount: aword; | ||||
|       begin | ||||
|         expression := expr; | ||||
| 
 | ||||
|         { result is a block of statements } | ||||
|         result:=internalstatements(loopstatement); | ||||
| 
 | ||||
|         is_string:=ado_IsConstString in tarraydef(expr.resultdef).arrayoptions; | ||||
| 
 | ||||
|         // if array element type <> loovar type then create a conversion if possible | ||||
|         if compare_defs(tarraydef(expression.resultdef).elementdef,hloopvar.resultdef,nothingn)=te_incompatible then | ||||
|           begin | ||||
|             tmpdef:=expression.resultdef; | ||||
|             elementcount:=1; | ||||
|             while assigned(tmpdef) and (tmpdef.typ=arraydef) and | ||||
|                   (tarraydef(tmpdef).arrayoptions = []) and | ||||
|                   (compare_defs(tarraydef(tmpdef).elementdef,hloopvar.resultdef,nothingn)=te_incompatible) do | ||||
|               begin | ||||
|                 elementcount:=elementcount*tarraydef(tmpdef).elecount; | ||||
|                 tmpdef:=tarraydef(tmpdef).elementdef; | ||||
|               end; | ||||
|             if assigned(tmpdef) and (tmpdef.typ=arraydef) and (tarraydef(tmpdef).arrayoptions = []) then | ||||
|               begin | ||||
|                 elementcount:=elementcount*tarraydef(tmpdef).elecount; | ||||
|                 convertdef:=tarraydef.create(0,elementcount-1,s32inttype); | ||||
|                 tarraydef(convertdef).elementdef:=tarraydef(tmpdef).elementdef; | ||||
|                 expression:=expr.getcopy; | ||||
|                 expression:=ctypeconvnode.create_internal(expression,convertdef); | ||||
|                 typecheckpass(expression); | ||||
|                 addstatement(loopstatement,expression); | ||||
|               end; | ||||
|           end; | ||||
| 
 | ||||
|         if (node_complexity(expression) > 1) and not is_open_array(expression.resultdef) then | ||||
|           begin | ||||
|             { create a temp variable for expression } | ||||
|             arrayvar := ctempcreatenode.create( | ||||
|               expression.resultdef, | ||||
|               expression.resultdef.size, | ||||
|               tt_persistent,true); | ||||
| 
 | ||||
|             if is_string then | ||||
|               begin | ||||
|                 lowbound:=genintconstnode(1); | ||||
|                 highbound:=cinlinenode.create(in_length_x,false,ctemprefnode.create(arrayvar)) | ||||
|               end | ||||
|             else | ||||
|               begin | ||||
|                 lowbound:=cinlinenode.create(in_low_x,false,ctemprefnode.create(arrayvar)); | ||||
|                 highbound:=cinlinenode.create(in_high_x,false,ctemprefnode.create(arrayvar)); | ||||
|               end; | ||||
| 
 | ||||
|             addstatement(loopstatement,arrayvar); | ||||
|             addstatement(loopstatement,cassignmentnode.create(ctemprefnode.create(arrayvar),expression.getcopy)); | ||||
|           end | ||||
|         else | ||||
|           result:=create_enumerator_for_in_loop(hloopvar, hloopbody, expr, pd, movenext, current); | ||||
|           begin | ||||
|             arrayvar:=nil; | ||||
|             if is_string then | ||||
|               begin | ||||
|                 lowbound:=genintconstnode(1); | ||||
|                 highbound:=cinlinenode.create(in_length_x,false,expression.getcopy); | ||||
|               end | ||||
|             else | ||||
|               begin | ||||
|                 lowbound:=cinlinenode.create(in_low_x,false,expression.getcopy); | ||||
|                 highbound:=cinlinenode.create(in_high_x,false,expression.getcopy); | ||||
|               end; | ||||
|           end; | ||||
| 
 | ||||
|         { create a loop counter } | ||||
|         loopvar := ctempcreatenode.create( | ||||
|           tarraydef(expression.resultdef).rangedef, | ||||
|           tarraydef(expression.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(expression.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; | ||||
|     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; | ||||
|           hloopvar.free; | ||||
|           hloopbody.free; | ||||
|           MessagePos1(expr.fileinfo,sym_e_no_enumerator,expr.resultdef.GetTypeName); | ||||
|         end; | ||||
| 
 | ||||
| 
 | ||||
|     function create_set_for_in_loop(hloopvar, hloopbody, expr: tnode): tnode; | ||||
|       var | ||||
|         loopstatement, loopbodystatement: tstatementnode; | ||||
|         loopvar, setvar: ttempcreatenode; | ||||
|         loopbody, forloopnode: tnode; | ||||
|       begin | ||||
|         // first check is set is empty and if it so then skip other processing | ||||
|         if not Assigned(tsetdef(expr.resultdef).elementdef) then | ||||
|           begin | ||||
|             result:=cnothingnode.create; | ||||
|             // free unused nodes | ||||
|             hloopvar.free; | ||||
|             hloopbody.free; | ||||
|             exit; | ||||
|           end; | ||||
|         { 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).find_destructor; | ||||
|             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).find_destructor; | ||||
|             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; | ||||
|         storefilepos: tfileposinfo; | ||||
|       begin | ||||
|         storefilepos:=current_filepos; | ||||
|         current_filepos:=hloopvar.fileinfo; | ||||
|         if expr.nodetype=typen then | ||||
|           begin | ||||
|             if (expr.resultdef.typ=enumdef) and tenumdef(expr.resultdef).has_jumps then | ||||
|               begin | ||||
|                 result:=cerrornode.create; | ||||
|                 hloopvar.free; | ||||
|                 hloopbody.free; | ||||
|                 MessagePos1(expr.fileinfo,parser_e_for_in_loop_cannot_be_used_for_the_type,expr.resultdef.typename); | ||||
|               end | ||||
|             else | ||||
|               result:=create_type_for_in_loop(hloopvar, hloopbody, expr); | ||||
|           end | ||||
|         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; | ||||
|                     hloopvar.free; | ||||
|                     hloopbody.free; | ||||
|                     MessagePos1(expr.fileinfo,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; | ||||
|                         hloopvar.free; | ||||
|                         hloopbody.free; | ||||
|                         MessagePos1(expr.fileinfo,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; | ||||
|                     hloopvar.free; | ||||
|                     hloopbody.free; | ||||
|                     MessagePos1(expr.fileinfo,sym_e_no_enumerator,expr.resultdef.GetTypeName); | ||||
|                   end; | ||||
|                 end; | ||||
|               end; | ||||
|           end; | ||||
|         current_filepos:=storefilepos; | ||||
|       end; | ||||
|     end; | ||||
|   end; | ||||
|   current_filepos:=storefilepos; | ||||
| end; | ||||
| 
 | ||||
| {**************************************************************************** | ||||
|                                  TLOOPNODE | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Jonas Maebe
						Jonas Maebe