@@ -1073,23 +1073,26 @@ def private build_accumulator_perelement_stmts(opName : string;
10731073def private emit_counter_lane (var top : Expression ?; srcName , accName , itName : string ; names : RangeStateNames ;
10741074 var skipExpr , takeExpr , skipWhileCond : Expression ?;
10751075 var loopBody : Expression ?; at : LineInfo ) : Expression ? {
1076- // Counter lane: `[skip/take init]; var acc = 0; for (it in src) { $loopBody }; return acc`
1077- var topExpr = clone_expression (top )
1078- topExpr .genFlags .alwaysSafe = true
1079- var srcParamType = invoke_src_param_type (top )
1080- var bodyStmts : array < Expression ?>
1081- append_ranges_prelude (bodyStmts , skipExpr , takeExpr , skipWhileCond , names )
1082- bodyStmts | > push_from < | qmacro_block_to_array () {
1076+ // loopBody is caller-pre-wrapped (where/binds/post-take/in-loop ranges); spec only handles prelude+prologue+tail.
1077+ var prologue : array < Expression ?>
1078+ append_ranges_prelude (prologue , skipExpr , takeExpr , skipWhileCond , names )
1079+ prologue | > push_from < | qmacro_block_to_array () {
10831080 var $ i(accName) = 0
1084- for ($ i(itName) in $i(srcName)) {
1085- $ e(loopBody)
1086- }
1081+ }
1082+ var perElementStmts : array < Expression ?>
1083+ perElementStmts | > push (loopBody )
1084+ var tailStmts < - qmacro_block_to_array () {
10871085 return $ i(accName)
10881086 }
1089- var res = qmacro (invoke ($ ($ i (srcName ) : $ t (srcParamType )) {
1090- $ b(bodyStmts)
1091- }, $ e (topExpr )))
1092- return finalize_invoke (res , at )
1087+ var laneTops : array < Expression ?>
1088+ laneTops | > push (top )
1089+ var laneSrcs : array < string >
1090+ laneSrcs | > push (srcName )
1091+ return emit_terminator_lane (TerminatorSpec (
1092+ prologue < - prologue ,
1093+ perElementStmts < - perElementStmts ,
1094+ tailStmts < - tailStmts
1095+ ), build_lane_adapter (laneTops , laneSrcs ), at )
10931096}
10941097
10951098[clone (top), macro_function ]
@@ -1155,6 +1158,8 @@ struct private TerminatorSpec {
11551158 takeWhileCond : Expression?
11561159 rangeNames : RangeStateNames
11571160 tailStmts : array<Expression?> // post-loop; INCLUDES the return
1161+ outElemType : TypeDeclPtr // invoke retType; null = infer
1162+ wrapIter : bool // adapter_wrap_invoke wraps emission with .to_sequence_move()
11581163}
11591164
11601165[macro_function ]
@@ -1174,7 +1179,7 @@ def private emit_terminator_lane(var spec : TerminatorSpec; adapter : SourceAdap
11741179 bodyStmts | > push_from (spec .prologue )
11751180 bodyStmts | > push < | adapter_wrap_source_loop (adapter , loopBody , at )
11761181 bodyStmts | > push_from (spec .tailStmts )
1177- return adapter_wrap_invoke (adapter , bodyStmts , null , false , at )
1182+ return adapter_wrap_invoke (adapter , bodyStmts , spec . outElemType , spec . wrapIter , at )
11781183}
11791184
11801185// Bridge for orchestrators that still take parallel (topExprs, srcNames) arrays. 1-source → Array;
@@ -2075,36 +2080,30 @@ def private emit_streaming_min(var c : Captures; var ctx : EmitCtx; at : LineInf
20752080 var elemType = clone_type (oc .orderElemType )
20762081 var lessTest = make_inline_less_call (oc .orderKey , oc .orderName ,
20772082 qmacro ($ i (bindName )), qmacro ($ i (bestName )), at )
2078- var perElement : Expression ? = qmacro_expr () {
2083+ var perElementStmts : array < Expression ?>
2084+ perElementStmts | > push < | qmacro_expr () {
20792085 if (! $ i(seenName)) {
20802086 $ i(bestName) := $i(bindName)
20812087 $ i(seenName) = true
20822088 } elif ($ e(lessTest)) {
20832089 $ i(bestName) := $i(bindName)
20842090 }
20852091 }
2086- if (oc .whereCond ! = null ) {
2087- perElement = qmacro_expr () {
2088- if ($ e(oc.whereCond)) {
2089- $ e(perElement)
2090- }
2091- }
2092- }
2093- let outElemType = (oc .selectLam ! = null ) ? oc .selectElemType : elemType
2094- var stmts : array < Expression ?>
2092+ var outElemType = (oc .selectLam ! = null ) ? oc .selectElemType : elemType
2093+ var prologue : array < Expression ?>
2094+ var tailStmts : array < Expression ?>
20952095 if (oc .firstName == "first" ) {
20962096 var firstRetExpr : Expression ?
20972097 if (oc .selectLam ! = null ) {
20982098 firstRetExpr = peel_lambda_replace_var (oc .selectLam , qmacro ($ i (bestName )))
20992099 } else {
21002100 firstRetExpr = qmacro ($ i (bestName ))
21012101 }
2102- stmts | > push_from < | qmacro_block_to_array () {
2102+ prologue < - qmacro_block_to_array () {
21032103 var $ i(bestName) = default<$t(elemType)>
21042104 var $ i(seenName) = false
21052105 }
2106- stmts | > push < | adapter_wrap_source_loop (ctx .src , perElement , at )
2107- stmts | > push_from < | qmacro_block_to_array () {
2106+ tailStmts < - qmacro_block_to_array () {
21082107 panic ("sequence contains no elements" ) if (! $ i(seenName))
21092108 return $ e(firstRetExpr)
21102109 }
@@ -2119,18 +2118,23 @@ def private emit_streaming_min(var c : Captures; var ctx : EmitCtx; at : LineInf
21192118 bestRetExpr = qmacro ($ i (bestName ))
21202119 dRetExpr = qmacro ($ i (dBindName ))
21212120 }
2122- stmts | > push_from < | qmacro_block_to_array () {
2121+ prologue < - qmacro_block_to_array () {
21232122 let $ i(dBindName) = $e(oc.firstDefaultExpr)
21242123 var $ i(bestName) = default<$t(elemType)>
21252124 var $ i(seenName) = false
21262125 }
2127- stmts | > push < | adapter_wrap_source_loop (ctx .src , perElement , at )
2128- stmts | > push_from < | qmacro_block_to_array () {
2126+ tailStmts < - qmacro_block_to_array () {
21292127 return $ e(bestRetExpr) if ($i(seenName))
21302128 return $ e(dRetExpr)
21312129 }
21322130 }
2133- return adapter_wrap_invoke (ctx .src , stmts , outElemType , false , at )
2131+ return emit_terminator_lane (TerminatorSpec (
2132+ prologue < - prologue ,
2133+ whereCond = oc .whereCond ,
2134+ perElementStmts < - perElementStmts ,
2135+ tailStmts < - tailStmts ,
2136+ outElemType = outElemType
2137+ ), ctx .src , at )
21342138}
21352139
21362140// emit_bounded_heap — take(N) with inline-cmp key. Heap of size N during walk; distinct gate variant + terminal _select.
@@ -2798,27 +2802,30 @@ def private emit_reverse_counter(var c : Captures; var ctx : EmitCtx; at : LineI
27982802 if (c .single | > key_exists ("proj" )) {
27992803 projection = peel_lambda_rename_var (c .single ["proj" ].arguments [1 ], bindName )
28002804 }
2801- var perElement : Expression ?
2805+ var perElementStmts : array < Expression ?>
28022806 if (projection ! = null && has_sideeffects (projection )) {
28032807 let vfinalName = qn ("vfinal" , at )
2804- perElement = qmacro_block () {
2808+ perElementStmts | > push_from < | qmacro_block_to_array () {
28052809 var $ i(vfinalName) = $e(projection)
28062810 $ i(cntName) ++
28072811 }
28082812 } else {
2809- perElement = qmacro_expr () {
2813+ perElementStmts | > push < | qmacro_expr () {
28102814 $ i(cntName) ++
28112815 }
28122816 }
2813- perElement = wrap_with_condition (perElement , whereCond )
2814- var stmts < - qmacro_block_to_array () {
2817+ var prologue < - qmacro_block_to_array () {
28152818 var $ i(cntName) = 0
28162819 }
2817- stmts | > push < | adapter_wrap_source_loop (ctx .src , perElement , at )
2818- stmts | > push_from < | qmacro_block_to_array () {
2820+ var tailStmts < - qmacro_block_to_array () {
28192821 return $ i(cntName)
28202822 }
2821- return adapter_wrap_invoke (ctx .src , stmts , null , false , at )
2823+ return emit_terminator_lane (TerminatorSpec (
2824+ prologue < - prologue ,
2825+ whereCond = whereCond ,
2826+ perElementStmts < - perElementStmts ,
2827+ tailStmts < - tailStmts
2828+ ), ctx .src , at )
28222829}
28232830
28242831// Rb — walk + overwrite-last scalar (terminator: first / first_or_default).
@@ -2858,7 +2865,7 @@ def private emit_reverse_walk_overwrite_scalar(var c : Captures; var ctx : EmitC
28582865 lastType = strip_const_ref (srcElemType )
28592866 }
28602867 // outElemType drives the invoke retType; terminal _select projects the survivor at return so the lane returns post-select shape.
2861- let outElemType = (terminalSelectLam ! = null ) ? terminalSelectElemType : lastType
2868+ var outElemType = (terminalSelectLam ! = null ) ? terminalSelectElemType : lastType
28622869 var valueExpr : Expression ?
28632870 if (projection ! = null ) {
28642871 valueExpr = clone_expression (projection )
@@ -2867,11 +2874,10 @@ def private emit_reverse_walk_overwrite_scalar(var c : Captures; var ctx : EmitC
28672874 $ i(bindName)
28682875 }
28692876 }
2870- var matchBlock : Expression ? = qmacro_block () {
2877+ var perElementStmts < - qmacro_block_to_array () {
28712878 $ i(lastName) := $e(valueExpr)
28722879 $ i(foundName) = true
28732880 }
2874- var perElement = wrap_with_condition (matchBlock , whereCond )
28752881 var lastRetExpr : Expression ?
28762882 if (terminalSelectLam ! = null ) {
28772883 lastRetExpr = peel_lambda_replace_var (terminalSelectLam , qmacro ($ i (lastName )))
@@ -2880,30 +2886,36 @@ def private emit_reverse_walk_overwrite_scalar(var c : Captures; var ctx : EmitC
28802886 }
28812887 // first_or_default's user default is already at post-termsel type — re-projecting through `termsel` double-applies.
28822888 var dRetExpr : Expression ? = qmacro ($ i (dBindName ))
2883- var stmts : array < Expression ?>
2889+ var prologue : array < Expression ?>
28842890 if (terminatorName == "first_or_default" ) {
2885- stmts | > push_from < | qmacro_block_to_array () {
2891+ prologue | > push_from < | qmacro_block_to_array () {
28862892 let $ i(dBindName) = $e(terminatorCall.arguments[1])
28872893 }
28882894 }
2889- stmts | > push_from < | qmacro_block_to_array () {
2895+ prologue | > push_from < | qmacro_block_to_array () {
28902896 var $ i(foundName) = false
28912897 var $ i(lastName) : $t(lastType) = default<$t(lastType)>
28922898 }
2893- stmts | > push < | adapter_wrap_source_loop ( ctx . src , perElement , at )
2899+ var tailStmts : array < Expression ? >
28942900 if (terminatorName == "first" ) {
2895- stmts | > push_from < | qmacro_block_to_array () {
2901+ tailStmts < - qmacro_block_to_array () {
28962902 if (! $ i(foundName)) {
28972903 panic ("sequence contains no elements" )
28982904 }
28992905 return $ e(lastRetExpr)
29002906 }
29012907 } else {
2902- stmts | > push_from < | qmacro_block_to_array () {
2908+ tailStmts < - qmacro_block_to_array () {
29032909 return $ i(foundName) ? $e(lastRetExpr) : $e(dRetExpr)
29042910 }
29052911 }
2906- return adapter_wrap_invoke (ctx .src , stmts , outElemType , false , at )
2912+ return emit_terminator_lane (TerminatorSpec (
2913+ prologue < - prologue ,
2914+ whereCond = whereCond ,
2915+ perElementStmts < - perElementStmts ,
2916+ tailStmts < - tailStmts ,
2917+ outElemType = outElemType
2918+ ), ctx .src , at )
29072919}
29082920
29092921// R6 — backward index walk (bare reverse + take(N) + implicit to_array on array source).
0 commit comments