@@ -243,7 +243,13 @@ function resolve!(mod::Module, ts::TestsetExpr, pat::Pattern;
243
243
strings = empty! (ts. strings)
244
244
desc = ts. desc
245
245
ts. loopvalues = nothing # unnecessary ?
246
- ts. loopiters = nothing
246
+ loopiters = ts. loopiters =
247
+ if ts. loops === nothing
248
+ nothing
249
+ else
250
+ Expr (:tuple , (arg. args[1 ] for arg in ts. loops). .. )
251
+ end
252
+
247
253
if 0 != ts. id != id && ! warned[] && has (pat, Integer)
248
254
# this can happen when nested testsets are added and Revise is active
249
255
@warn " testset IDs have changed since last run"
@@ -337,7 +343,6 @@ function resolve!(mod::Module, ts::TestsetExpr, pat::Pattern;
337
343
else # we have a testset-for with description which needs interpolation, or
338
344
# the iterator must be computed to get an iterator counter
339
345
xs = ()
340
- loopiters = Expr (:tuple , (arg. args[1 ] for arg in loops). .. )
341
346
342
347
try
343
348
# we need to evaluate roughly the following:
@@ -359,7 +364,6 @@ function resolve!(mod::Module, ts::TestsetExpr, pat::Pattern;
359
364
xs = Core. eval (mod, xsgen)
360
365
@assert xs isa Vector
361
366
ts. loopvalues = xs
362
- ts. loopiters = loopiters
363
367
catch
364
368
@assert xs == ()
365
369
ts. descwidth = shown ? descwidth (missing ) : 0
@@ -409,15 +413,20 @@ function resolve!(mod::Module, ts::TestsetExpr, pat::Pattern;
409
413
run, id
410
414
end
411
415
412
- eval_desc (mod, ts, x) =
416
+ eval_desc (mod, ts, x; stack = false ) = # stack => x == iterstack in dryrun
413
417
if ts. desc isa String
414
418
ts. desc
415
419
else
416
420
try
417
- Core. eval (mod, quote
418
- let $ (ts. loopiters) = $ x
419
- $ (ts. desc)
420
- end
421
+ Core. eval (mod,
422
+ if stack
423
+ Expr (:let , x, ts. desc)
424
+ else
425
+ quote
426
+ let $ (ts. loopiters) = $ x
427
+ $ (ts. desc)
428
+ end
429
+ end
421
430
end ):: String
422
431
catch
423
432
missing
@@ -442,7 +451,7 @@ function make_ts(ts::TestsetExpr, pat::Pattern, stats, chan)
442
451
end
443
452
else
444
453
c = count (x -> x === nothing , (ts. loopvalues, ts. loopiters))
445
- @assert c == 0 || c == 2
454
+ @assert c == 0 || c == 1
446
455
if c == 0
447
456
loops = [Expr (:(= ), ts. loopiters, ts. loopvalues)]
448
457
else
@@ -1448,7 +1457,7 @@ function dryrun(mod::Module, ts::TestsetExpr, pat::Pattern, align::Int=0,
1448
1457
# external calls:
1449
1458
; maxidw:: Int , marks:: Bool , tag:: Vector , clear:: Bool ,
1450
1459
# only recursive calls:
1451
- evaldesc= true , repeated= nothing , show:: Bool = true )
1460
+ evaldesc= true , repeated= nothing , show:: Bool = true , iterstack = Expr ( :block ) )
1452
1461
@assert ts. run
1453
1462
desc = ts. desc
1454
1463
@@ -1518,7 +1527,8 @@ function dryrun(mod::Module, ts::TestsetExpr, pat::Pattern, align::Int=0,
1518
1527
for tsc in ts. children
1519
1528
tsc. run || continue
1520
1529
dryrun (mod, tsc, pat, align + 2 , subject,
1521
- maxidw= maxidw, marks= marks, tag= tag, clear= clear, show= true )
1530
+ maxidw= maxidw, marks= marks, tag= tag, clear= clear, show= true ,
1531
+ iterstack= iterstack)
1522
1532
end
1523
1533
false , false , false # meaningless unused triple
1524
1534
elseif marks
@@ -1536,7 +1546,7 @@ function dryrun(mod::Module, ts::TestsetExpr, pat::Pattern, align::Int=0,
1536
1546
tsc. run || continue
1537
1547
cp, cf, cu = dryrun (mod, tsc, pat, align + 2 , subject,
1538
1548
maxidw= maxidw, marks= marks, tag= tag, clear= clear,
1539
- show= false )
1549
+ show= false , iterstack = iterstack )
1540
1550
passes |= cp
1541
1551
fails |= cf
1542
1552
unrun |= cu
@@ -1585,10 +1595,30 @@ function dryrun(mod::Module, ts::TestsetExpr, pat::Pattern, align::Int=0,
1585
1595
ts. iter = iter # necessary when reachable is used
1586
1596
dryrun (mod, beginend, pat, align, parentsubj; evaldesc= false ,
1587
1597
repeated= repeated, maxidw= maxidw, marks= marks, tag= tag,
1588
- clear= clear, show= show)
1598
+ clear= clear, show= show, iterstack = iterstack )
1589
1599
end
1590
1600
1591
1601
loopvalues = ts. loopvalues
1602
+ if loopvalues === nothing
1603
+ # we check whether we can now evaluate loopvalues via iterstack
1604
+ try
1605
+ # cf. resolve!
1606
+ xssym = gensym ()
1607
+ xsgen = quote
1608
+ let $ xssym = []
1609
+ $ (Expr (:for , Expr (:block , ts. loops... ),
1610
+ Expr (:call , Expr (:., :Base , QuoteNode (:push! )),
1611
+ xssym, ts. loopiters)))
1612
+ $ xssym
1613
+ end
1614
+ end
1615
+ loopvalues = Core. eval (mod, Expr (:let , iterstack, xsgen))
1616
+ @assert loopvalues isa Vector
1617
+ catch
1618
+ @assert loopvalues == nothing
1619
+ end
1620
+ end
1621
+
1592
1622
if loopvalues === nothing
1593
1623
# ts.desc is probably a String (cf. resolve!); if so, don't print repeated
1594
1624
# identitical lines (caveat: if subjects of children would change randomly)
@@ -1615,7 +1645,8 @@ function dryrun(mod::Module, ts::TestsetExpr, pat::Pattern, align::Int=0,
1615
1645
else
1616
1646
passes, fails, unrun = false , false , false
1617
1647
for (i, x) in enumerate (loopvalues)
1618
- descx = eval_desc (mod, ts, x)
1648
+ push! (iterstack. args, Expr (:(= ), ts. loopiters, x))
1649
+ descx = eval_desc (mod, ts, iterstack, stack= true )
1619
1650
if descx === missing
1620
1651
# we would usually have `i == 1`, but not in some rare cases;
1621
1652
# once we find an uninterpolated description, we still assume
@@ -1628,6 +1659,7 @@ function dryrun(mod::Module, ts::TestsetExpr, pat::Pattern, align::Int=0,
1628
1659
else
1629
1660
lp, lf, lu = dryrun_beginend (descx, iter= i)
1630
1661
end
1662
+ pop! (iterstack. args)
1631
1663
passes |= lp
1632
1664
fails |= lf
1633
1665
unrun |= lu
0 commit comments