@@ -776,12 +776,19 @@ def _visit_for_in(self, node: ASTNode) -> None:
776776
777777 iterable_expr = self ._emit_expr (node .iterable )
778778 iterable_type = self ._type_map .get (id (node .iterable )) if node .iterable else None
779+ cache_name = self ._unique_name ("__a7_iter" )
780+ cache_type = self ._iterable_cache_type (iterable_type )
779781 elem_type = self ._iterable_element_type (iterable_type )
780- length_expr = self ._iterable_length_expr (node .iterable , iterable_expr , iterable_type )
782+ length_expr = self ._iterable_length_expr (node .iterable , cache_name , iterable_type )
781783
782784 idx_name = self ._unique_name ("__a7_i" )
783785 iter_name = self ._sanitize_name (node .iterator or "item" )
784786
787+ self ._write_indent ()
788+ self .output .write ("{\n " )
789+ self .indent ()
790+ self ._write_indent ()
791+ self .output .write (f"{ cache_type } { cache_name } = { iterable_expr } ;\n " )
785792 self ._write_indent ()
786793 self .output .write (
787794 f"for (size_t { idx_name } = 0; { idx_name } < { length_expr } ; ++{ idx_name } ) "
@@ -791,7 +798,7 @@ def _visit_for_in(self, node: ASTNode) -> None:
791798 self ._defer_scopes .append ([])
792799 self ._write_indent ()
793800 self .output .write (
794- f"{ elem_type } { iter_name } = { self ._emit_iterable_element_expr (node .iterable , iterable_expr , iterable_type , idx_name )} ;\n "
801+ f"{ elem_type } { iter_name } = { self ._emit_iterable_element_expr (node .iterable , cache_name , iterable_type , idx_name )} ;\n "
795802 )
796803
797804 marker = len (self ._defer_scopes ) - 1
@@ -808,6 +815,9 @@ def _visit_for_in(self, node: ASTNode) -> None:
808815 self .dedent ()
809816 self ._write_indent ()
810817 self .output .write ("}\n " )
818+ self .dedent ()
819+ self ._write_indent ()
820+ self .output .write ("}\n " )
811821
812822 def _visit_for_in_indexed (self , node : ASTNode ) -> None :
813823 if node .label :
@@ -816,13 +826,20 @@ def _visit_for_in_indexed(self, node: ASTNode) -> None:
816826
817827 iterable_expr = self ._emit_expr (node .iterable )
818828 iterable_type = self ._type_map .get (id (node .iterable )) if node .iterable else None
829+ cache_name = self ._unique_name ("__a7_iter" )
830+ cache_type = self ._iterable_cache_type (iterable_type )
819831 elem_type = self ._iterable_element_type (iterable_type )
820- length_expr = self ._iterable_length_expr (node .iterable , iterable_expr , iterable_type )
832+ length_expr = self ._iterable_length_expr (node .iterable , cache_name , iterable_type )
821833
822834 idx_name = self ._unique_name ("__a7_i" )
823835 index_var = self ._sanitize_name (node .index_var or "index" )
824836 iter_name = self ._sanitize_name (node .iterator or "item" )
825837
838+ self ._write_indent ()
839+ self .output .write ("{\n " )
840+ self .indent ()
841+ self ._write_indent ()
842+ self .output .write (f"{ cache_type } { cache_name } = { iterable_expr } ;\n " )
826843 self ._write_indent ()
827844 self .output .write (
828845 f"for (size_t { idx_name } = 0; { idx_name } < { length_expr } ; ++{ idx_name } ) "
@@ -834,7 +851,7 @@ def _visit_for_in_indexed(self, node: ASTNode) -> None:
834851 self .output .write (f"size_t { index_var } = { idx_name } ;\n " )
835852 self ._write_indent ()
836853 self .output .write (
837- f"{ elem_type } { iter_name } = { self ._emit_iterable_element_expr (node .iterable , iterable_expr , iterable_type , idx_name )} ;\n "
854+ f"{ elem_type } { iter_name } = { self ._emit_iterable_element_expr (node .iterable , cache_name , iterable_type , idx_name )} ;\n "
838855 )
839856
840857 marker = len (self ._defer_scopes ) - 1
@@ -851,6 +868,9 @@ def _visit_for_in_indexed(self, node: ASTNode) -> None:
851868 self .dedent ()
852869 self ._write_indent ()
853870 self .output .write ("}\n " )
871+ self .dedent ()
872+ self ._write_indent ()
873+ self .output .write ("}\n " )
854874
855875 def _visit_match (self , node : ASTNode ) -> None :
856876 expr = self ._emit_expr (node .expression ) if node .expression else "0"
@@ -1720,14 +1740,18 @@ def _visit_labeled_for_in(self, node: ASTNode, *, indexed: bool) -> None:
17201740 idx_name = self ._unique_name ("__a7_i" )
17211741 iterable_expr = self ._emit_expr (node .iterable )
17221742 iterable_type = self ._type_map .get (id (node .iterable )) if node .iterable else None
1743+ cache_name = self ._unique_name ("__a7_iter" )
1744+ cache_type = self ._iterable_cache_type (iterable_type )
17231745 elem_type = self ._iterable_element_type (iterable_type )
1724- length_expr = self ._iterable_length_expr (node .iterable , iterable_expr , iterable_type )
1746+ length_expr = self ._iterable_length_expr (node .iterable , cache_name , iterable_type )
17251747 iter_name = self ._sanitize_name (node .iterator or "item" )
17261748
17271749 self ._write_indent ()
17281750 self .output .write ("{\n " )
17291751 self .indent ()
17301752 self ._write_indent ()
1753+ self .output .write (f"{ cache_type } { cache_name } = { iterable_expr } ;\n " )
1754+ self ._write_indent ()
17311755 self .output .write (f"size_t { idx_name } = 0;\n " )
17321756 self ._write_indent ()
17331757 self .output .write (f"{ cond_label } :\n " )
@@ -1743,7 +1767,7 @@ def _visit_labeled_for_in(self, node: ASTNode, *, indexed: bool) -> None:
17431767 self .output .write (f"size_t { index_var } = { idx_name } ;\n " )
17441768 self ._write_indent ()
17451769 self .output .write (
1746- f"{ elem_type } { iter_name } = { self ._emit_iterable_element_expr (node .iterable , iterable_expr , iterable_type , idx_name )} ;\n "
1770+ f"{ elem_type } { iter_name } = { self ._emit_iterable_element_expr (node .iterable , cache_name , iterable_type , idx_name )} ;\n "
17471771 )
17481772 marker = len (self ._defer_scopes ) - 1
17491773 self ._push_loop_frame (
@@ -1836,6 +1860,17 @@ def _emit_iterable_element_expr(
18361860 return f"({ iterable_expr } ).data[{ idx_name } ]"
18371861 return f"{ iterable_expr } [{ idx_name } ]"
18381862
1863+ def _iterable_cache_type (self , iterable_type ) -> str :
1864+ if isinstance (iterable_type , SliceType ):
1865+ return self ._semantic_type_to_c (iterable_type ) or "void*"
1866+ if isinstance (iterable_type , ArrayType ):
1867+ elem = self ._semantic_type_to_c (iterable_type .element_type ) or "int32_t"
1868+ return f"{ elem } *"
1869+ raise CodegenError (
1870+ "C backend: for-in iteration currently requires an array or slice value" ,
1871+ None ,
1872+ )
1873+
18391874 def _iterable_element_type (self , iterable_type ) -> str :
18401875 if isinstance (iterable_type , ArrayType ):
18411876 return self ._semantic_type_to_c (iterable_type .element_type ) or "int32_t"
0 commit comments