@@ -51,3 +51,182 @@ function testSharedEnvironment(): i32 {
5151 return getter ( ) ;
5252}
5353assert ( testSharedEnvironment ( ) == 50 ) ;
54+
55+ // ============================================================================
56+ // Tests for closure capture from various control flow constructs
57+ // ============================================================================
58+
59+ // Test 7: Capture from while loop
60+ function testCaptureInWhile ( ) : i32 {
61+ let sum = 0 ;
62+ let i = 0 ;
63+ while ( i < 3 ) {
64+ let adder = ( ) : void => { sum = sum + i ; } ;
65+ adder ( ) ;
66+ i ++ ;
67+ }
68+ return sum ; // 0 + 1 + 2 = 3
69+ }
70+ assert ( testCaptureInWhile ( ) == 3 ) ;
71+
72+ // Test 8: Capture from do-while loop
73+ function testCaptureInDoWhile ( ) : i32 {
74+ let product = 1 ;
75+ let i = 1 ;
76+ do {
77+ let multiplier = ( ) : void => { product = product * i ; } ;
78+ multiplier ( ) ;
79+ i ++ ;
80+ } while ( i <= 4 ) ;
81+ return product ; // 1 * 1 * 2 * 3 * 4 = 24
82+ }
83+ assert ( testCaptureInDoWhile ( ) == 24 ) ;
84+
85+ // Test 9: Capture from for loop
86+ function testCaptureInFor ( ) : i32 {
87+ let result = 0 ;
88+ for ( let i = 1 ; i <= 5 ; i ++ ) {
89+ let addI = ( ) : void => { result = result + i ; } ;
90+ addI ( ) ;
91+ }
92+ return result ; // 1 + 2 + 3 + 4 + 5 = 15
93+ }
94+ assert ( testCaptureInFor ( ) == 15 ) ;
95+
96+ // Test 10: Capture from switch statement
97+ function testCaptureInSwitch ( x : i32 ) : i32 {
98+ let captured = 0 ;
99+ switch ( x ) {
100+ case 1 : {
101+ let setCaptured = ( ) : void => { captured = 10 ; } ;
102+ setCaptured ( ) ;
103+ break ;
104+ }
105+ case 2 : {
106+ let setCaptured = ( ) : void => { captured = 20 ; } ;
107+ setCaptured ( ) ;
108+ break ;
109+ }
110+ default : {
111+ let setCaptured = ( ) : void => { captured = 99 ; } ;
112+ setCaptured ( ) ;
113+ break ;
114+ }
115+ }
116+ return captured ;
117+ }
118+ assert ( testCaptureInSwitch ( 1 ) == 10 ) ;
119+ assert ( testCaptureInSwitch ( 2 ) == 20 ) ;
120+ assert ( testCaptureInSwitch ( 3 ) == 99 ) ;
121+
122+ // Test 11: Capture from array literal
123+ function testCaptureInArrayLiteral ( ) : i32 {
124+ let x = 5 ;
125+ let y = 10 ;
126+ let fns = [
127+ ( ) : i32 => x ,
128+ ( ) : i32 => y ,
129+ ( ) : i32 => x + y
130+ ] ;
131+ return fns [ 0 ] ( ) + fns [ 1 ] ( ) + fns [ 2 ] ( ) ; // 5 + 10 + 15 = 30
132+ }
133+ assert ( testCaptureInArrayLiteral ( ) == 30 ) ;
134+
135+ // Test 12: Closure returning closure (nested capture)
136+ function testNestedClosureCapture ( ) : i32 {
137+ let outer = 100 ;
138+ let makeAdder = ( ) : ( y : i32 ) => i32 => {
139+ return ( y : i32 ) : i32 => outer + y ;
140+ } ;
141+ let adder = makeAdder ( ) ;
142+ return adder ( 23 ) ; // 100 + 23 = 123
143+ }
144+ assert ( testNestedClosureCapture ( ) == 123 ) ;
145+
146+ // Test 13: Multiple closures in array capturing same variable
147+ function testMultipleClosuresInArray ( ) : i32 {
148+ let shared = 0 ;
149+ let incrementers : Array < ( ) => void > = [ ] ;
150+
151+ for ( let i = 0 ; i < 3 ; i ++ ) {
152+ incrementers . push ( ( ) : void => { shared = shared + 1 ; } ) ;
153+ }
154+
155+ for ( let i = 0 ; i < incrementers . length ; i ++ ) {
156+ incrementers [ i ] ( ) ;
157+ }
158+
159+ return shared ; // Should be 3
160+ }
161+ assert ( testMultipleClosuresInArray ( ) == 3 ) ;
162+
163+ // Test 14: Closure with ternary expression using captured variable
164+ function testCaptureInTernary ( ) : i32 {
165+ let flag = true ;
166+ let a = 10 ;
167+ let b = 20 ;
168+ let chooser = ( ) : i32 => flag ? a : b ;
169+
170+ assert ( chooser ( ) == 10 ) ;
171+ flag = false ;
172+ return chooser ( ) ; // Should be 20 now
173+ }
174+ assert ( testCaptureInTernary ( ) == 20 ) ;
175+
176+ // Test 15: Closure capturing from condition expression
177+ function testCaptureFromCondition ( ) : i32 {
178+ let threshold = 50 ;
179+ let value = 75 ;
180+ let isAboveThreshold = ( ) : bool => value > threshold ;
181+
182+ assert ( isAboveThreshold ( ) == true ) ;
183+ value = 25 ;
184+ return isAboveThreshold ( ) ? 1 : 0 ; // Should be 0
185+ }
186+ assert ( testCaptureFromCondition ( ) == 0 ) ;
187+
188+ // Test 16: Deeply nested loops with closure
189+ function testDeepLoopCapture ( ) : i32 {
190+ let total = 0 ;
191+ for ( let i = 0 ; i < 2 ; i ++ ) {
192+ for ( let j = 0 ; j < 2 ; j ++ ) {
193+ let addBoth = ( ) : void => { total = total + i + j ; } ;
194+ addBoth ( ) ;
195+ }
196+ }
197+ // i=0,j=0: +0, i=0,j=1: +1, i=1,j=0: +1, i=1,j=1: +2 = 4
198+ return total ;
199+ }
200+ assert ( testDeepLoopCapture ( ) == 4 ) ;
201+
202+ // Test 17: Closure capturing counter pattern
203+ function makeCounter ( ) : ( ) => i32 {
204+ let count = 0 ;
205+ return ( ) : i32 => {
206+ count = count + 1 ;
207+ return count ;
208+ } ;
209+ }
210+ let counter1 = makeCounter ( ) ;
211+ let counter2 = makeCounter ( ) ;
212+ assert ( counter1 ( ) == 1 ) ;
213+ assert ( counter1 ( ) == 2 ) ;
214+ assert ( counter2 ( ) == 1 ) ; // Independent counter
215+ assert ( counter1 ( ) == 3 ) ;
216+ assert ( counter2 ( ) == 2 ) ;
217+
218+ // Test 18: Closure with parameter default value capturing outer variable
219+ function testDefaultParamCapture ( ) : i32 {
220+ let defaultVal = 42 ;
221+ let fn = ( x : i32 = defaultVal ) : i32 => x ;
222+ return fn ( ) ;
223+ }
224+ assert ( testDefaultParamCapture ( ) == 42 ) ;
225+
226+ // Test 19: Closure with parameter default value using another param
227+ function testDefaultParamWithOtherParam ( ) : i32 {
228+ let multiplier = 3 ;
229+ let fn = ( a : i32 , b : i32 = a * multiplier ) : i32 => b ;
230+ return fn ( 10 ) ; // b defaults to 10 * 3 = 30
231+ }
232+ assert ( testDefaultParamWithOtherParam ( ) == 30 ) ;
0 commit comments