1647
1647
(cons (car e)
1648
1648
(map expand-forms (cdr e)))))))
1649
1649
1650
+ ; ; If true, this will warn on all `for` loop variables that overwrite outer variables.
1651
+ ; ; If false, this will try to warn only for uses of the last value after the loop.
1652
+ (define *warn-all-loop-vars* #f )
1653
+
1650
1654
(define (expand-for while lhs X body )
1651
1655
; ; (for (= lhs X) body)
1652
1656
(let ((coll (make-ssavalue))
1661
1665
(block
1662
1666
; ; NOTE: enable this to force loop-local var
1663
1667
#; ,@(map (lambda (v) `(local ,v)) (lhs-vars lhs))
1668
+ ,@(if (or *depwarn* *deperror*)
1669
+ (map (lambda (v ) `(warn-if-existing ,v)) (lhs-vars lhs))
1670
+ '() )
1664
1671
,(lower-tuple-assignment (list lhs state)
1665
1672
`(call (top next) ,coll ,state))
1666
1673
,body))))))))
2491
2498
((eq? (car e) 'break-block ) (unbound-vars (caddr e) bound tab))
2492
2499
((eq? (car e) 'with-static-parameters ) (unbound-vars (cadr e) bound tab))
2493
2500
(else (for-each (lambda (x ) (unbound-vars x bound tab))
2494
- (cdr e))
2501
+ (cdr e))
2495
2502
tab)))
2496
2503
2497
2504
; ; local variable identification and renaming, derived from:
2507
2514
((eq? (car e) 'local ) ' (null)) ; ; remove local decls
2508
2515
((eq? (car e) 'local-def ) ' (null)) ; ; remove local decls
2509
2516
((eq? (car e) 'implicit-global ) ' (null)) ; ; remove implicit-global decls
2517
+ ((eq? (car e) 'warn-if-existing ) ' (null))
2510
2518
((eq? (car e) 'lambda )
2511
2519
(let* ((lv (lam:vars e))
2512
2520
(env (append lv env))
2547
2555
vars))))
2548
2556
(need-rename (need-rename? vars))
2549
2557
(need-rename-def (need-rename? vars-def))
2558
+ (deprecated-loop-vars
2559
+ (filter (lambda (v ) (memq v env))
2560
+ (delete-duplicates (find-decls 'warn-if-existing blok))))
2550
2561
; ; new gensym names for conflicting variables
2551
2562
(renamed (map named-gensy need-rename))
2552
2563
(renamed-def (map named-gensy need-rename-def))
2576
2587
(if lam ; ; update in-place the list of local variables in lam
2577
2588
(set-car! (cddr lam)
2578
2589
(append! (caddr lam) real-new-vars real-new-vars-def)))
2579
- (insert-after-meta ; ; return the new, expanded scope-block
2580
- (if (and (pair? body) (eq? (car body) 'block ))
2581
- body
2582
- `(block ,body))
2583
- (append! (map (lambda (v ) `(local ,v)) real-new-vars)
2584
- (map (lambda (v ) `(local-def ,v)) real-new-vars-def)))))
2590
+ (let* ((warnings (map (lambda (v ) `(warn-loop-var ,v)) deprecated-loop-vars))
2591
+ (body (if *warn-all-loop-vars*
2592
+ body
2593
+ (if (and (pair? body) (eq? (car body) 'block ))
2594
+ (append body warnings)
2595
+ `(block ,body ,@warnings)))))
2596
+ (insert-after-meta ; ; return the new, expanded scope-block
2597
+ (if (and (pair? body) (eq? (car body) 'block ))
2598
+ body
2599
+ `(block ,body))
2600
+ (append! (map (lambda (v ) `(local ,v)) real-new-vars)
2601
+ (map (lambda (v ) `(local-def ,v)) real-new-vars-def)
2602
+ (if *warn-all-loop-vars*
2603
+ (map (lambda (v ) `(warn-loop-var ,v)) deprecated-loop-vars)
2604
+ '() ))))))
2585
2605
((eq? (car e) 'module )
2586
2606
(error " module expression not at top level" ))
2587
2607
((eq? (car e) 'break-block )
@@ -3035,7 +3055,7 @@ f(x) = yt(x)
3035
3055
((atom? e) e)
3036
3056
(else
3037
3057
(case (car e)
3038
- ((quote top core globalref outerref line break inert module toplevel null meta) e)
3058
+ ((quote top core globalref outerref line break inert module toplevel null meta warn-loop-var ) e)
3039
3059
((=)
3040
3060
(let ((var (cadr e))
3041
3061
(rhs (cl-convert (caddr e) fname lam namemap toplevel interp)))
@@ -3282,6 +3302,11 @@ f(x) = yt(x)
3282
3302
(else (for-each linearize (cdr e))))
3283
3303
e)
3284
3304
3305
+ (define (deprecation-message msg )
3306
+ (if *deperror*
3307
+ (error msg)
3308
+ (io.write *stderr* msg)))
3309
+
3285
3310
; ; this pass behaves like an interpreter on the given code.
3286
3311
; ; to perform stateful operations, it calls `emit` to record that something
3287
3312
; ; needs to be done. in value position, it returns an expression computing
@@ -3294,6 +3319,7 @@ f(x) = yt(x)
3294
3319
(first-line #t )
3295
3320
(current-loc #f )
3296
3321
(rett #f )
3322
+ (deprecated-loop-vars (table))
3297
3323
(arg-map #f ) ; ; map arguments to new names if they are assigned
3298
3324
(label-counter 0 ) ; ; counter for generating label addresses
3299
3325
(label-map (table)) ; ; maps label names to generated addresses
@@ -3387,6 +3413,11 @@ f(x) = yt(x)
3387
3413
(eq? (cadr e) '_ ))))
3388
3414
(syntax-deprecation #f (string " _ as an rvalue" (linenode-string current-loc))
3389
3415
" " ))
3416
+ (if (and (not *warn-all-loop-vars*) (has? deprecated-loop-vars e))
3417
+ (begin (deprecation-message
3418
+ (string " Use of final value of loop variable \" " e " \" " (linenode-string current-loc) " "
3419
+ " is deprecated. In the future the variable will be local to the loop instead." #\newline ))
3420
+ (del! deprecated-loop-vars e)))
3390
3421
(cond (tail (emit-return e1))
3391
3422
(value e1)
3392
3423
((or (eq? e1 'true ) (eq? e1 'false )) #f )
@@ -3416,6 +3447,8 @@ f(x) = yt(x)
3416
3447
(lhs (if (and arg-map (symbol? lhs))
3417
3448
(get arg-map lhs lhs)
3418
3449
lhs)))
3450
+ (if (and (not *warn-all-loop-vars*) (has? deprecated-loop-vars lhs))
3451
+ (del! deprecated-loop-vars lhs))
3419
3452
(if value
3420
3453
(let ((rr (if (or (atom? rhs) (ssavalue? rhs) (eq? (car rhs) 'null ))
3421
3454
rhs (make-ssavalue))))
@@ -3602,6 +3635,14 @@ f(x) = yt(x)
3602
3635
((implicit-global) #f )
3603
3636
((const) (emit e))
3604
3637
((isdefined) (if tail (emit-return e) e))
3638
+ ((warn-loop-var)
3639
+ (if *warn-all-loop-vars*
3640
+ (deprecation-message
3641
+ (string " Loop variable \" " (cadr e) " \" " (linenode-string current-loc) " "
3642
+ " overwrites a variable in an enclosing scope. "
3643
+ " In the future the variable will be local to the loop instead." #\newline ))
3644
+ (put! deprecated-loop-vars (cadr e) #t ))
3645
+ ' (null))
3605
3646
3606
3647
; ; top level expressions returning values
3607
3648
((abstract_type bits_type composite_type thunk toplevel module)
0 commit comments