|
16 | 16 | resyntax/default-recommendations/private/boolean |
17 | 17 | resyntax/default-recommendations/private/lambda-by-any-name |
18 | 18 | resyntax/default-recommendations/private/let-binding |
| 19 | + resyntax/default-recommendations/private/list-function |
19 | 20 | resyntax/default-recommendations/private/metafunction |
20 | 21 | resyntax/default-recommendations/private/syntax-equivalence |
21 | 22 | resyntax/default-recommendations/private/syntax-identifier-sets |
22 | 23 | resyntax/default-recommendations/private/syntax-lines |
23 | 24 | resyntax/private/identifier-naming |
| 25 | + resyntax/private/logger |
24 | 26 | resyntax/private/syntax-traversal |
25 | 27 | syntax/parse) |
26 | 28 |
|
@@ -376,35 +378,89 @@ return just that result." |
376 | 378 | #:literals (let cond else null? empty? null quote car first cdr rest cons) |
377 | 379 | (let loop:id ([vs:id init-list]) |
378 | 380 | (cond |
379 | | - [((~or null? empty?) vs2:id) (~or null '())] |
| 381 | + [(:empty-predicate-by-any-name vs2:id) :empty-list-by-any-name] |
380 | 382 | [else |
381 | 383 | loop-body:expr ... |
382 | | - (cons loop-element:expr |
383 | | - (loop2:id ((~or cdr rest) vs3:id)))])) |
| 384 | + (cons loop-element:expr (loop2:id (:rest-by-any-name vs3:id)))])) |
384 | 385 | #:when (free-identifier=? #'loop #'loop2) |
385 | 386 | #:when (free-identifier=? #'vs #'vs2) |
386 | 387 | #:when (free-identifier=? #'vs #'vs3) |
387 | | - #:when (for*/and ([body-stx (in-list (cons #'loop-element (attribute loop-body)))] |
388 | | - [vs-usage |
389 | | - (syntax-search body-stx [(~var usage (expression-directly-enclosing #'vs))])] |
390 | | - #:unless (syntax-free-identifier=? vs-usage #'(car vs))) |
391 | | - (syntax-free-identifier=? vs-usage #'(first vs))) |
| 388 | + #:when (not |
| 389 | + (for/or ([body-stx (in-list (cons #'loop-element (attribute loop-body)))]) |
| 390 | + (syntax-find-first body-stx |
| 391 | + (~and (~var usage (expression-directly-enclosing (attribute vs))) |
| 392 | + (~not (:first-by-any-name _)))))) |
392 | 393 | #:cut |
393 | 394 |
|
394 | 395 | #:with element-id (depluralize-id #'vs) |
395 | 396 |
|
396 | 397 | #:with (modified-result-element modified-body ...) |
397 | 398 | (for/list ([body-stx (cons #'loop-element (attribute loop-body))]) |
398 | 399 | (syntax-traverse body-stx |
399 | | - #:literals (car first) |
400 | | - [(car vs-usage:id) #:when (free-identifier=? #'vs-usage #'vs) #'element-id] |
401 | | - [(first vs-usage:id) #:when (free-identifier=? #'vs-usage #'vs) #'element-id])) |
| 400 | + [(:first-by-any-name vs-usage:id) #:when (free-identifier=? #'vs-usage #'vs) #'element-id])) |
402 | 401 |
|
403 | 402 | (for/list ([element-id (in-list init-list)]) |
404 | 403 | modified-body ... |
405 | 404 | modified-result-element)) |
406 | 405 |
|
407 | 406 |
|
| 407 | +(define-refactoring-rule named-let-loop-to-for/and |
| 408 | + #:description "This named `let` expression is equivalent to a `for/and` loop." |
| 409 | + #:literals (let cond else) |
| 410 | + (let loop:id ([vs:id init-list]) |
| 411 | + (cond |
| 412 | + [(:empty-predicate-by-any-name vs2:id) #true] |
| 413 | + [element-condition:expr (loop2:id (:rest-by-any-name vs3:id))] |
| 414 | + [else #false])) |
| 415 | + |
| 416 | + #:when (free-identifier=? (attribute loop) (attribute loop2)) |
| 417 | + #:when (free-identifier=? (attribute vs) (attribute vs2)) |
| 418 | + #:when (free-identifier=? (attribute vs) (attribute vs3)) |
| 419 | + #:when (not (syntax-find-first (attribute element-condition) |
| 420 | + (~and (~var usage (expression-directly-enclosing (attribute vs))) |
| 421 | + (~not (:first-by-any-name _))))) |
| 422 | + #:cut |
| 423 | + |
| 424 | + #:with element-id (depluralize-id (attribute vs)) |
| 425 | + #:with modified-element-condition |
| 426 | + (syntax-traverse (attribute element-condition) |
| 427 | + [(:first-by-any-name vs-usage:id) |
| 428 | + #:when (free-identifier=? (attribute vs) (attribute vs-usage)) |
| 429 | + (attribute element-id)]) |
| 430 | + |
| 431 | + (for/and ([element-id (in-list init-list)]) |
| 432 | + modified-element-condition)) |
| 433 | + |
| 434 | + |
| 435 | +(define-refactoring-rule named-let-loop-to-for/or |
| 436 | + #:description "This named `let` expression is equivalent to a `for/or` loop." |
| 437 | + #:literals (let cond else) |
| 438 | + (let loop:id ([vs:id init-list]) |
| 439 | + (cond |
| 440 | + [(:empty-predicate-by-any-name vs2:id) #false] |
| 441 | + [element-condition:expr #true] |
| 442 | + [else (loop2:id (:rest-by-any-name vs3:id))])) |
| 443 | + |
| 444 | + #:when (free-identifier=? (attribute loop) (attribute loop2)) |
| 445 | + #:when (free-identifier=? (attribute vs) (attribute vs2)) |
| 446 | + #:when (free-identifier=? (attribute vs) (attribute vs3)) |
| 447 | + #:when (not (syntax-find-first (attribute element-condition) |
| 448 | + (~and (~var usage (expression-directly-enclosing (attribute vs))) |
| 449 | + (~not (:first-by-any-name _))))) |
| 450 | + #:cut |
| 451 | + |
| 452 | + #:with element-id (depluralize-id (attribute vs)) |
| 453 | + #:with modified-element-condition |
| 454 | + (syntax-traverse (attribute element-condition) |
| 455 | + [(:first-by-any-name vs-usage:id) |
| 456 | + #:when (free-identifier=? (attribute vs) (attribute vs-usage)) |
| 457 | + (attribute element-id)]) |
| 458 | + |
| 459 | + (for/or ([element-id (in-list init-list)]) |
| 460 | + modified-element-condition)) |
| 461 | + |
| 462 | + |
| 463 | + |
408 | 464 | (define-refactoring-rule named-let-loop-to-for/first-in-vector |
409 | 465 | #:description "This loop can be replaced by a simpler, equivalent `for/first` loop." |
410 | 466 | #:literals (let add1 + vector-length vector-ref if and <) |
@@ -466,8 +522,10 @@ return just that result." |
466 | 522 | list->set-to-for/set |
467 | 523 | list->vector-to-for/vector |
468 | 524 | map-to-for |
469 | | - named-let-loop-to-for/list |
| 525 | + named-let-loop-to-for/and |
470 | 526 | named-let-loop-to-for/first-in-vector |
| 527 | + named-let-loop-to-for/list |
| 528 | + named-let-loop-to-for/or |
471 | 529 | nested-for-to-for* |
472 | 530 | nested-for/and-to-for*/and |
473 | 531 | nested-for/or-to-for*/or |
|
0 commit comments