Skip to content

Commit

Permalink
Add nested for/or and for/and rules
Browse files Browse the repository at this point in the history
Closes #176.
  • Loading branch information
jackfirth committed Sep 18, 2024
1 parent 0b33a69 commit 1496dc5
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 3 deletions.
30 changes: 30 additions & 0 deletions default-recommendations/for-loop-shortcuts-test.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,36 @@ test: "non-nested for form isn't replaced by a for* form"
------------------------------


test: "nested for/or forms can be flattened to a for*/or form"
------------------------------
(for/or ([x (in-range 0 5)])
(for/or ([y (in-range 0 5)])
(for/or ([z (in-range 0 5)])
(>= (+ x y z) 5))))
------------------------------
------------------------------
(for*/or ([x (in-range 0 5)]
[y (in-range 0 5)]
[z (in-range 0 5)])
(>= (+ x y z) 5))
------------------------------


test: "nested for/and forms can be flattened to a for*/and form"
------------------------------
(for/and ([x (in-range 0 5)])
(for/and ([y (in-range 0 5)])
(for/and ([z (in-range 0 5)])
(<= (+ x y z) 5))))
------------------------------
------------------------------
(for*/and ([x (in-range 0 5)]
[y (in-range 0 5)]
[z (in-range 0 5)])
(<= (+ x y z) 5))
------------------------------


test: "named let loop with conditional return over vector can be replaced by for/first"
------------------------------------------------------------
(define vec (vector 0 1 2 3 4 5))
Expand Down
41 changes: 38 additions & 3 deletions default-recommendations/for-loop-shortcuts.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
(require (for-syntax racket/base)
racket/list
racket/set
rebellion/private/static-name
resyntax/base
resyntax/default-recommendations/private/boolean
resyntax/default-recommendations/private/lambda-by-any-name
Expand All @@ -22,8 +21,6 @@
resyntax/default-recommendations/private/syntax-identifier-sets
resyntax/default-recommendations/private/syntax-lines
resyntax/private/identifier-naming
resyntax/private/logger
resyntax/private/syntax-neighbors
resyntax/private/syntax-traversal
syntax/parse)

Expand Down Expand Up @@ -181,6 +178,42 @@
function.body ...))


(define-syntax-class nested-for/or
#:attributes ([clause 1] [body 1])
#:literals (for/or)

(pattern (for/or (outer-clause ...) nested:nested-for/or ~!)
#:attr [clause 1] (append (attribute outer-clause) (attribute nested.clause))
#:attr [body 1] (attribute nested.body))

(pattern (for/or (clause ...) body ...)))


(define-syntax-class nested-for/and
#:attributes ([clause 1] [body 1])
#:literals (for/and)

(pattern (for/and (outer-clause ...) nested:nested-for/and ~!)
#:attr [clause 1] (append (attribute outer-clause) (attribute nested.clause))
#:attr [body 1] (attribute nested.body))

(pattern (for/and (clause ...) body ...)))


(define-refactoring-rule nested-for/or-to-for*/or
#:description "Nested `for/or` loops can be replaced with a single `for*/loop`."
#:literals (for/or)
(for-id:for/or (clause ...) nested:nested-for/or)
((~replacement for*/or #:original for-id) (clause ... nested.clause ...) nested.body ...))


(define-refactoring-rule nested-for/and-to-for*/and
#:description "Nested `for/or` loops can be replaced with a single `for*/loop`."
#:literals (for/and)
(for-id:for/and (clause ...) nested:nested-for/and)
((~replacement for*/and #:original for-id) (clause ... nested.clause ...) nested.body ...))


(define-syntax-class for-list-id
#:attributes (set-id vector-id)
#:literals (for/list for*/list)
Expand Down Expand Up @@ -388,6 +421,8 @@ return just that result."
named-let-loop-to-for/list
named-let-loop-to-for/first-in-vector
nested-for-to-for*
nested-for/and-to-for*/and
nested-for/or-to-for*/or
or-in-for/and-to-filter-clause
ormap-to-for/or
unless-expression-in-for-loop-to-unless-keyword
Expand Down

0 comments on commit 1496dc5

Please sign in to comment.