Skip to content

Commit e091796

Browse files
Copilotjackfirth
andauthored
Consolidate let-binding rules into let-replacement directory (#642)
Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: jackfirth <[email protected]>
1 parent 567ef67 commit e091796

20 files changed

+419
-381
lines changed

default-recommendations.rkt

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@
2121
resyntax/default-recommendations/legacy-contract-migrations
2222
resyntax/default-recommendations/legacy-struct-migrations
2323
resyntax/default-recommendations/legacy-syntax-migrations
24-
resyntax/default-recommendations/let-binding-suggestions
24+
resyntax/default-recommendations/let-replacement/cond-let-replacement
25+
resyntax/default-recommendations/let-replacement/let-binding-suggestions
26+
resyntax/default-recommendations/let-replacement/let-replacement
27+
resyntax/default-recommendations/let-replacement/match-let-replacement
2528
resyntax/default-recommendations/list-shortcuts
2629
resyntax/default-recommendations/loops/for-loop-shortcuts
2730
resyntax/default-recommendations/loops/list-loopification
@@ -58,7 +61,10 @@
5861
resyntax/default-recommendations/legacy-contract-migrations
5962
resyntax/default-recommendations/legacy-struct-migrations
6063
resyntax/default-recommendations/legacy-syntax-migrations
61-
resyntax/default-recommendations/let-binding-suggestions
64+
resyntax/default-recommendations/let-replacement/cond-let-replacement
65+
resyntax/default-recommendations/let-replacement/let-binding-suggestions
66+
resyntax/default-recommendations/let-replacement/let-replacement
67+
resyntax/default-recommendations/let-replacement/match-let-replacement
6268
resyntax/default-recommendations/list-shortcuts
6369
resyntax/default-recommendations/loops/for-loop-shortcuts
6470
resyntax/default-recommendations/loops/list-loopification
@@ -83,6 +89,7 @@
8389
class-shortcuts
8490
comparison-shortcuts
8591
conditional-shortcuts
92+
cond-let-replacement
8693
console-io-suggestions
8794
contract-shortcuts
8895
definition-shortcuts
@@ -104,8 +111,10 @@
104111

105112
legacy-syntax-migrations
106113
let-binding-suggestions
114+
let-replacement
107115
list-loopification
108116
list-shortcuts
117+
match-let-replacement
109118
match-shortcuts
110119
miscellaneous-suggestions
111120
mutability-predicates

default-recommendations/conditional-shortcuts-test.rkt

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -532,41 +532,6 @@ no-change-test: "`if-else-false-to-and` is not refactorable when `and` is shadow
532532
------------------------------
533533

534534

535-
test: "cond with nested let refactorable to cond with define"
536-
------------------------------
537-
(define (f a c)
538-
(cond
539-
[a
540-
(let ([x "stuff"])
541-
x)]
542-
[else c]))
543-
==============================
544-
(define (f a c)
545-
(cond
546-
[a
547-
(define x "stuff")
548-
x]
549-
[else c]))
550-
------------------------------
551-
552-
553-
test: "cond with nested let in else clause refactorable to cond with define"
554-
------------------------------
555-
(define (f a b)
556-
(cond
557-
[a b]
558-
[else
559-
(let ([x "stuff"])
560-
x)]))
561-
==============================
562-
(define (f a b)
563-
(cond
564-
[a b]
565-
[else
566-
(define x "stuff")
567-
x]))
568-
------------------------------
569-
570535

571536
test: "if clause with begin in true branch refactorable to cond"
572537
------------------------------

default-recommendations/conditional-shortcuts.rkt

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
resyntax/base
1515
resyntax/default-recommendations/private/boolean
1616
resyntax/default-recommendations/private/exception
17-
resyntax/default-recommendations/private/let-binding
17+
resyntax/default-recommendations/let-replacement/private/let-binding
1818
resyntax/default-recommendations/private/metafunction
1919
resyntax/default-recommendations/private/syntax-equivalence
2020
syntax/parse)
@@ -183,21 +183,6 @@
183183
(~@ . (~splicing-replacement (nested-clause ...) #:original outer-else-clause))))
184184

185185

186-
(define-syntax-class let-refactorable-cond-clause
187-
#:attributes (refactored)
188-
(pattern [condition:expr leading-body ... let-expr:refactorable-let-expression]
189-
#:with refactored
190-
#`(~replacement
191-
[condition leading-body ... (~@ . (~focus-replacement-on (let-expr.refactored ...)))]
192-
#:original #,this-syntax)))
193-
194-
195-
(define-refactoring-rule cond-let-to-cond-define
196-
#:description
197-
"Internal definitions are recommended instead of `let` expressions, to reduce nesting."
198-
#:literals (cond)
199-
(cond-id:cond clause-before ... clause:let-refactorable-cond-clause clause-after ...)
200-
(cond-id clause-before ... clause.refactored clause-after ...))
201186

202187

203188
(define-syntax-class if-arm
@@ -297,7 +282,6 @@ tail expression outside `cond` lets you replace `cond` with `when`."
297282
always-throwing-if-to-when
298283
and-let-to-cond
299284
cond-else-cond-to-cond
300-
cond-let-to-cond-define
301285
cond-void-to-when-or-unless
302286
explicit-cond-else-void
303287
if-begin-to-cond
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#lang resyntax/test
2+
3+
4+
require: resyntax/default-recommendations cond-let-replacement
5+
6+
7+
header:
8+
- #lang racket/base
9+
10+
11+
test: "cond with nested let refactorable to cond with define"
12+
------------------------------
13+
(define (f a c)
14+
(cond
15+
[a
16+
(let ([x "stuff"])
17+
x)]
18+
[else c]))
19+
==============================
20+
(define (f a c)
21+
(cond
22+
[a
23+
(define x "stuff")
24+
x]
25+
[else c]))
26+
------------------------------
27+
28+
29+
test: "cond with nested let in else clause refactorable to cond with define"
30+
------------------------------
31+
(define (f a b)
32+
(cond
33+
[a b]
34+
[else
35+
(let ([x "stuff"])
36+
x)]))
37+
==============================
38+
(define (f a b)
39+
(cond
40+
[a b]
41+
[else
42+
(define x "stuff")
43+
x]))
44+
------------------------------
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#lang racket/base
2+
3+
4+
(require racket/contract/base)
5+
6+
7+
(provide
8+
(contract-out
9+
[cond-let-replacement refactoring-suite?]))
10+
11+
12+
(require resyntax/base
13+
resyntax/default-recommendations/let-replacement/private/let-binding
14+
syntax/parse)
15+
16+
17+
;@----------------------------------------------------------------------------------------------------
18+
19+
20+
(define-syntax-class let-refactorable-cond-clause
21+
#:attributes (refactored)
22+
(pattern [condition:expr leading-body ... let-expr:refactorable-let-expression]
23+
#:with refactored
24+
#`(~replacement
25+
[condition leading-body ... (~@ . (~focus-replacement-on (let-expr.refactored ...)))]
26+
#:original #,this-syntax)))
27+
28+
29+
(define-refactoring-rule cond-let-to-cond-define
30+
#:description
31+
"Internal definitions are recommended instead of `let` expressions, to reduce nesting."
32+
#:literals (cond)
33+
(cond-id:cond clause-before ... clause:let-refactorable-cond-clause clause-after ...)
34+
(cond-id clause-before ... clause.refactored clause-after ...))
35+
36+
37+
(define-refactoring-suite cond-let-replacement
38+
#:rules (cond-let-to-cond-define))

default-recommendations/let-binding-suggestions-comment-test.rkt renamed to default-recommendations/let-replacement/let-binding-suggestions-comment-test.rkt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#lang resyntax/test
22

33

4-
require: resyntax/default-recommendations let-binding-suggestions
4+
require: resyntax/default-recommendations let-replacement
55

66

77
header:

default-recommendations/let-binding-suggestions-function-shortcuts-test.rkt renamed to default-recommendations/let-replacement/let-binding-suggestions-function-shortcuts-test.rkt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#lang resyntax/test
22

33

4-
require: resyntax/default-recommendations let-binding-suggestions
4+
require: resyntax/default-recommendations let-replacement
55

66

77
header:

default-recommendations/let-binding-suggestions-nesting-test.rkt renamed to default-recommendations/let-replacement/let-binding-suggestions-nesting-test.rkt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#lang resyntax/test
22

33

4-
require: resyntax/default-recommendations let-binding-suggestions
4+
require: resyntax/default-recommendations let-replacement
55

66

77
header:
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#lang resyntax/test
2+
3+
4+
require: resyntax/default-recommendations let-binding-suggestions
5+
6+
7+
header:
8+
- #lang racket/base
9+
test: "named lets which don't refer to the name are refactorable to unnamed lets"
10+
------------------------------
11+
(let loop ([x 1]) x)
12+
==============================
13+
(let ([x 1]) x)
14+
------------------------------
15+
16+
17+
no-change-test: "named lets which do refer to the name aren't refactorable to unnamed lets"
18+
------------------------------
19+
(let loop ([x 1])
20+
(if (zero? x)
21+
x
22+
(loop (sub1 x))))
23+
------------------------------
24+
25+
26+
test: "let-values expressions with an immediate call are refactorable to call-with-values"
27+
- (let-values ([(x y z) (values 1 2 3)]) (list x y z))
28+
- (call-with-values (λ () (values 1 2 3)) list)
29+
30+
31+
no-change-test:
32+
"let-values expressions with an immediate call with different order aren't refactorable"
33+
- (let-values ([(x y z) (values 1 2 3)]) (list z y x))
34+
test: "redundant let bindings can be removed"
35+
------------------------------
36+
(define x 1)
37+
(let ([x x])
38+
(* x 2))
39+
==============================
40+
(define x 1)
41+
(* x 2)
42+
------------------------------
43+
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#lang racket/base
2+
3+
4+
(require racket/contract/base)
5+
6+
7+
(provide
8+
(contract-out
9+
[let-binding-suggestions refactoring-suite?]))
10+
11+
12+
(require racket/list
13+
racket/set
14+
resyntax/base
15+
resyntax/default-recommendations/private/syntax-equivalence
16+
resyntax/default-recommendations/private/syntax-identifier-sets
17+
syntax/parse)
18+
19+
20+
;@----------------------------------------------------------------------------------------------------
21+
22+
23+
(define-refactoring-rule named-let-to-plain-let
24+
#:description
25+
"This named `let` loop doesn't actually perform any recursive calls, and can be replaced with an\
26+
unnamed `let`."
27+
#:literals (let)
28+
(let name:id header body ...)
29+
#:when (not (set-member? (syntax-free-identifiers #'(body ...)) #'name))
30+
(let header body ...))
31+
32+
33+
(define-refactoring-rule let-values-then-call-to-call-with-values
34+
#:description
35+
"This `let-values` expression can be replaced with a simpler, equivalent `call-with-values`\
36+
expression."
37+
#:literals (let-values)
38+
(let-values ([(bound-id:id ...+) expr])
39+
(receiver:id arg-id:id ...+))
40+
#:when (syntax-free-identifier=? #'(bound-id ...) #'(arg-id ...))
41+
(call-with-values (λ () expr) receiver))
42+
43+
44+
(define-refactoring-rule delete-redundant-let
45+
#:description "This `let` binding does nothing and can be removed."
46+
#:literals (let)
47+
(let ([left-id:id right-id:id]) body)
48+
#:when (equal? (syntax-e (attribute left-id)) (syntax-e (attribute right-id)))
49+
body)
50+
51+
52+
(define-refactoring-suite let-binding-suggestions
53+
#:rules (delete-redundant-let
54+
let-values-then-call-to-call-with-values
55+
named-let-to-plain-let))

0 commit comments

Comments
 (0)