From dd2b5433ffcd0cc32e5b2c2e20b6e2314df9c9e8 Mon Sep 17 00:00:00 2001 From: Jack Firth Date: Sun, 1 Sep 2024 20:26:51 -0700 Subject: [PATCH] Add `begin0-let-to-define-begin0` rule (#263) In [this code](https://github.com/jackfirth/yaragg/blob/9d48ab7152003e39aa6c1bab11a601d3723143fa/parser-tools/yacc-to-scheme.rkt#L115-L129), there's a `let` expression immediately within a `begin0` expression to compute a variable needed for the result of the `begin0` expression. But if that `let` is lifted up into a `define`, the code becomes far more readable. --- .../let-binding-suggestions-test.rkt | 14 ++++++++++++++ .../let-binding-suggestions.rkt | 17 ++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/default-recommendations/let-binding-suggestions-test.rkt b/default-recommendations/let-binding-suggestions-test.rkt index 4f6b91e..18d35ed 100644 --- a/default-recommendations/let-binding-suggestions-test.rkt +++ b/default-recommendations/let-binding-suggestions-test.rkt @@ -503,6 +503,20 @@ test: "variable definition with nested let binding of name bound earlier not ref ------------------------------ +test: "let binding nested in begin0 extractable to definition" +------------------------------ +(define (f) + (begin0 (let ([x 1]) x) + (displayln "foo"))) +------------------------------ +------------------------------ +(define (f) + (define x 1) + (begin0 x + (displayln "foo"))) +------------------------------ + + test: "redundant let bindings can be removed" ------------------------------ (define x 1) diff --git a/default-recommendations/let-binding-suggestions.rkt b/default-recommendations/let-binding-suggestions.rkt index db6330f..97f5363 100644 --- a/default-recommendations/let-binding-suggestions.rkt +++ b/default-recommendations/let-binding-suggestions.rkt @@ -78,6 +78,20 @@ body-after ...)]) +(define-definition-context-refactoring-rule begin0-let-to-define-begin0 + #:description "This `let` expression can be pulled up into a `define` expression." + #:literals (begin0 let) + [(~seq body-before ... + (begin0 + (~and original-let (let ([nested-id:id nested-expr:expr]) result-expr:expr)) + body-after ...)) + #:when (not + (set-member? (syntax-bound-identifiers #'(body-before ... body-after ...)) #'nested-id)) + (body-before ... + (define nested-id nested-expr) + (begin0 (~replacement result-expr #:original original-let) body-after ...))]) + + (define-refactoring-rule delete-redundant-let #:description "This `let` binding does nothing and can be removed." #:literals (let) @@ -90,7 +104,8 @@ (refactoring-suite #:name (name let-binding-suggestions) #:rules - (list define-let-to-double-define + (list begin0-let-to-define-begin0 + define-let-to-double-define delete-redundant-let let-to-define let-values-then-call-to-call-with-values