Re: [Pharo-users] [Ann] BPatterns: The rewrite engine at your fingertips

DK
Denis Kudriashov
Tue, Feb 3, 2026 6:41 PM

Hi Richard.

I checked the code and the double backticks are for the recursion mode. It
forces the search to dive into the current matching node to find more cases
inside it.
For example:

(instVar isNil ifTrue: [ 'inside recursion' ]) isNil ifTrue: [ 'outer node'
]

The syntax with single backtick will not find the internal "instVar isNil"
expression.

In BPatterns the recursion mode is enabled by default for the pattern
variables. So the default mode covers the maximum scope for a search.
Currently you can't not disable the #recurseInto flag as there is not
suitable accessor for this. But if it would be there the pattern would like:

[ anyVar isNil ifTrue: anyBlock ] bpattern with: [ anyVar ] -> [:pattern |
pattern recurseInto: false ]

Anyway I adjusted my blog accordingly. Thanks for the attention.

вт, 3 февр. 2026 г. в 10:47, Richard O'Keefe raoknz@gmail.com:

Thank you.  One of the reasons given for introducing BPatterns is a subtle
difference between
single backticks and double backticks, which is mentioned but not
explained in the BPatterns
blog entry.  The help screen you directed me to does not explain that.

Is there any documentation which is complete and proofread?

On Tue, 3 Feb 2026 at 23:16, Denis Kudriashov dionisiydk@gmail.com
wrote:

Yes. There is nice help presenter in the Pharo:

StRewriterHelpBrowserPresenter new open

[image: Screenshot 2026-02-03 at 10.15.45.png]

вт, 3 февр. 2026 г. в 01:36, Richard O'Keefe raoknz@gmail.com:

Is the "classic" rewriting syntax documented anywhere?

On Mon, 2 Feb 2026 at 22:52, Denis Kudriashov via Pharo-users <
pharo-users@lists.pharo.org> wrote:

Hi all.

This is the release of BPatterns project, one of my old ideas on how
to make the rewrite engine usable for scripting.

As a quick reminder, here is an example of the classic rewrite-engine
matching syntax:

@receiver isNil ifTrue: @nilBlock

In practice, patterns like this usually live inside string
literals—hidden away in lint rules, deprecations, or refactorings.
To use them for manual code search or rewriting, you typically need
a dedicated tool.

Now compare that with the same pattern expressed as a BPattern:

[ any isNil ifTrue: anyBlock ] bpattern

No special syntax.
No magical tools.
Just pure Smalltalk.

You write a block.
You send #bpattern.
You’re done.

Every editor understands it.
Every tool respects it.

Want to see where this pattern appears?

  • [ any isNil ifTrue: anyBlock ] bpattern browseUsers*

[image: Screenshot 2026-01-31 at 12.16.19.png]

Want to rewrite all of them?

[[ any isNil ifTrue: anyBlock ] -> [ any ifNil: anyBlock ]] brewrite
preview

[image: Screenshot 2026-01-31 at 12.17.57.png]

Because BPatterns are real Smalltalk code, all development tools
work out of the box:
syntax highlighting, completion, navigation, refactorings.

This is the rewrite engine treated as a first-class citizen.

Not strings.
Not tooling sidecars.
Not just for advanced users.

A rewrite engine you can actually use.

And follow the project on GitHub:

- https://github.com/dionisiydk/BPatterns


-
Hi Richard. I checked the code and the double backticks are for the recursion mode. It forces the search to dive into the current matching node to find more cases inside it. For example: (instVar isNil ifTrue: [ 'inside recursion' ]) isNil ifTrue: [ 'outer node' ] The syntax with single backtick will not find the internal "instVar isNil" expression. In BPatterns the recursion mode is enabled by default for the pattern variables. So the default mode covers the maximum scope for a search. Currently you can't not disable the #recurseInto flag as there is not suitable accessor for this. But if it would be there the pattern would like: [ anyVar isNil ifTrue: anyBlock ] bpattern with: [ anyVar ] -> [:pattern | pattern recurseInto: false ] Anyway I adjusted my blog accordingly. Thanks for the attention. вт, 3 февр. 2026 г. в 10:47, Richard O'Keefe <raoknz@gmail.com>: > Thank you. One of the reasons given for introducing BPatterns is a subtle > difference between > single backticks and double backticks, which is mentioned but not > explained in the BPatterns > blog entry. The help screen you directed me to does not explain that. > > Is there any documentation which is *complete* and *proofread*? > > On Tue, 3 Feb 2026 at 23:16, Denis Kudriashov <dionisiydk@gmail.com> > wrote: > >> Yes. There is nice help presenter in the Pharo: >> >> StRewriterHelpBrowserPresenter new open >> >> >> [image: Screenshot 2026-02-03 at 10.15.45.png] >> >> >> вт, 3 февр. 2026 г. в 01:36, Richard O'Keefe <raoknz@gmail.com>: >> >>> Is the "classic" rewriting syntax documented anywhere? >>> >>> On Mon, 2 Feb 2026 at 22:52, Denis Kudriashov via Pharo-users < >>> pharo-users@lists.pharo.org> wrote: >>> >>>> Hi all. >>>> >>>> This is the release of *BPatterns* project, one of my old ideas on how >>>> to make the rewrite engine usable for scripting. >>>> >>>> As a quick reminder, here is an example of the classic rewrite-engine >>>> matching syntax: >>>> >>>> *``@receiver isNil ifTrue: ``@nilBlock* >>>> >>>> >>>> In practice, patterns like this usually live inside string >>>> literals—hidden away in lint rules, deprecations, or refactorings. >>>> To use them for *manual* code search or rewriting, you typically need >>>> a dedicated tool. >>>> >>>> Now compare that with the same pattern expressed as a *BPattern*: >>>> >>>> *[ any isNil ifTrue: anyBlock ] bpattern* >>>> >>>> No special syntax. >>>> No magical tools. >>>> Just pure Smalltalk. >>>> >>>> You write a block. >>>> You send #bpattern. >>>> You’re done. >>>> >>>> Every editor understands it. >>>> Every tool respects it. >>>> >>>> Want to see where this pattern appears? >>>> >>>> * [ any isNil ifTrue: anyBlock ] bpattern browseUsers* >>>> >>>> >>>> [image: Screenshot 2026-01-31 at 12.16.19.png] >>>> >>>> Want to rewrite all of them? >>>> >>>> *[[ any isNil ifTrue: anyBlock ] -> [ any ifNil: anyBlock ]] brewrite >>>> preview* >>>> >>>> >>>> [image: Screenshot 2026-01-31 at 12.17.57.png] >>>> >>>> Because *BPatterns are real Smalltalk code*, all development tools >>>> work out of the box: >>>> syntax highlighting, completion, navigation, refactorings. >>>> >>>> This is the rewrite engine treated as a *first-class citizen*. >>>> >>>> Not strings. >>>> Not tooling sidecars. >>>> Not just for advanced users. >>>> >>>> *A rewrite engine you can actually use.* >>>> * A rewrite engine at your fingertips.* >>>> More details are in the blog post: >>>> >>>> - >>>> https://dionisiydk.blogspot.com/2026/02/bpatterns-rewrite-engine-with-smalltalk.html >>>> >>>> And follow the project on GitHub: >>>> >>>> - https://github.com/dionisiydk/BPatterns >>>> >>>> >>>> - >>>> >>>>
DS
Daniel Slomovits
Tue, Feb 3, 2026 11:50 PM

I love the basic idea, but at a glance, it seems like the syntax rapidly
becomes much more verbose than the equivalent using the special pattern
syntax. For simple examples it's more-or-less equivalent, but the with: [
anyVar ] -> [:pattern | ...] syntax is very clunky.

What I would really love to see is an extension to the Compiler, that
allows for mixing the actual pattern syntax directly into code. Perhaps
initiated by a backtick-parenthesis, so you could write:

((``@receiver isNil ifTrue: ``@nilBlock) -> (@receiver ifNil: @nilBlock)) rewrite preview

I'm not even sure this would be all that hard—it would mean adding one new
type of parse node, call it a "pattern literal", delimited by (), whose implementation would be very straightforward for the most part, with the only complication being that pattern blocks ({}) would have to be compiled
properly in the outer scope. As additional niceties, individual pattern
nodes should ideally be able to appear bare, rather than needing to be
wrapped in `(), and we would want a syntax for "this is a whole-method
pattern"

On another note, I want to call attention to one thing that BPattern has
going for it that string-literal-based patterns can't (easily) do: modifier
blocks are closures in the method that generated them, so you can do things
like have methods that return a pattern which closes over the arguments of
the method...having trouble coming up with an example off the top of my
head, but this is very powerful. (Well. Actually you can do this with
string-based patterns, by reaching in after the pattern is parsed and
editing the modifier block. I've written methods to support the following
syntax: '`@exp' withPatternBlock: [:exp | "this is a real block, although
the expression it wraps was still parsed from a string literal"].)

Quick question: Does this use the same underlying parse nodes, and helper
classes like ParseTreeRewriter, as the old system, just generating them a
different way? If so, I think the value here is as much in the convenience
methods for performing searches and rewrites as the pattern syntax—so thank
you for that, regardless!

While we're on the subject of rewrite tools, a while back I noticed that I
often wanted to rewrite sequences of statements to a single method call,
where that sequence might recur several times in the same method. This
especially comes up in tests—perhaps I notice that the pattern:

self assert: obj foo equals: #expectedFoo. self assert: obj bar equals: #expectedBar.
self assert: obj baz equals: `#expectedBaz.

occurs a lot, and those properties are related enough that it makes more
sense to say self verifyFooBarBaz: obj equal: {#expectedFoo. #expectedBar. `#expectedBaz}. (This is a poor example, in truth, but there
are cases where it's much more clearly justified.) By default you can only
get one of these occurrences per run of the rewrite tool, because any
pattern you write has to match the entire sequence, and once it has
matched, the entire sequence is disqualified from further matching. I was
able to extend the matching semantics so that a
recurse-into-list-of-statements pattern (i.e. ``@.stmts,
double-backtick-at-period) effectively builds a new sequence containing
only the statements it matched, and retries the rule against that. It
could definitely stand to be more elegant, but for me it filled an
important hole in the existing capabilities. Is that something anyone would
be interested in helping me dust off and contribute?

On Tue, Feb 3, 2026 at 1:41 PM Denis Kudriashov dionisiydk@gmail.com
wrote:

Hi Richard.

I checked the code and the double backticks are for the recursion mode. It
forces the search to dive into the current matching node to find more cases
inside it.
For example:

(instVar isNil ifTrue: [ 'inside recursion' ]) isNil ifTrue: [ 'outer
node' ]

The syntax with single backtick will not find the internal "instVar isNil"
expression.

In BPatterns the recursion mode is enabled by default for the pattern
variables. So the default mode covers the maximum scope for a search.
Currently you can't not disable the #recurseInto flag as there is not
suitable accessor for this. But if it would be there the pattern would like:

[ anyVar isNil ifTrue: anyBlock ] bpattern with: [ anyVar ] -> [:pattern |
pattern recurseInto: false ]

Anyway I adjusted my blog accordingly. Thanks for the attention.

вт, 3 февр. 2026 г. в 10:47, Richard O'Keefe raoknz@gmail.com:

Thank you.  One of the reasons given for introducing BPatterns is a
subtle difference between
single backticks and double backticks, which is mentioned but not
explained in the BPatterns
blog entry.  The help screen you directed me to does not explain that.

Is there any documentation which is complete and proofread?

On Tue, 3 Feb 2026 at 23:16, Denis Kudriashov dionisiydk@gmail.com
wrote:

Yes. There is nice help presenter in the Pharo:

StRewriterHelpBrowserPresenter new open

[image: Screenshot 2026-02-03 at 10.15.45.png]

вт, 3 февр. 2026 г. в 01:36, Richard O'Keefe raoknz@gmail.com:

Is the "classic" rewriting syntax documented anywhere?

On Mon, 2 Feb 2026 at 22:52, Denis Kudriashov via Pharo-users <
pharo-users@lists.pharo.org> wrote:

Hi all.

This is the release of BPatterns project, one of my old ideas on
how to make the rewrite engine usable for scripting.

As a quick reminder, here is an example of the classic rewrite-engine
matching syntax:

@receiver isNil ifTrue: @nilBlock

In practice, patterns like this usually live inside string
literals—hidden away in lint rules, deprecations, or refactorings.
To use them for manual code search or rewriting, you typically need
a dedicated tool.

Now compare that with the same pattern expressed as a BPattern:

[ any isNil ifTrue: anyBlock ] bpattern

No special syntax.
No magical tools.
Just pure Smalltalk.

You write a block.
You send #bpattern.
You’re done.

Every editor understands it.
Every tool respects it.

Want to see where this pattern appears?

  • [ any isNil ifTrue: anyBlock ] bpattern browseUsers*

[image: Screenshot 2026-01-31 at 12.16.19.png]

Want to rewrite all of them?

[[ any isNil ifTrue: anyBlock ] -> [ any ifNil: anyBlock ]] brewrite
preview

[image: Screenshot 2026-01-31 at 12.17.57.png]

Because BPatterns are real Smalltalk code, all development tools
work out of the box:
syntax highlighting, completion, navigation, refactorings.

This is the rewrite engine treated as a first-class citizen.

Not strings.
Not tooling sidecars.
Not just for advanced users.

A rewrite engine you can actually use.

And follow the project on GitHub:

- https://github.com/dionisiydk/BPatterns


-
I love the basic idea, but at a glance, it seems like the syntax rapidly becomes *much* more verbose than the equivalent using the special pattern syntax. For simple examples it's more-or-less equivalent, but the with: [ anyVar ] -> [:pattern | ...] syntax is *very* clunky. What I would *really* love to see is an extension to the Compiler, that allows for mixing the actual pattern syntax directly into code. Perhaps initiated by a backtick-parenthesis, so you could write: (`(``@receiver isNil ifTrue: ``@nilBlock) -> `(``@receiver ifNil: ``@nilBlock)) rewrite preview I'm not even sure this would be all that hard—it would mean adding one new type of parse node, call it a "pattern literal", delimited by `(), whose implementation would be very straightforward for the most part, with the only complication being that pattern blocks (`{}) would have to be compiled properly in the outer scope. As additional niceties, individual pattern nodes should ideally be able to appear bare, rather than needing to be wrapped in `(), and we would want a syntax for "this is a whole-method pattern" On another note, I want to call attention to one thing that BPattern has going for it that string-literal-based patterns can't (easily) do: modifier blocks are closures in the method that generated them, so you can do things like have methods that return a pattern which closes over the arguments of the method...having trouble coming up with an example off the top of my head, but this is very powerful. (Well. Actually you *can* do this with string-based patterns, by reaching in after the pattern is parsed and editing the modifier block. I've written methods to support the following syntax: '`@exp' withPatternBlock: [:exp | "this is a real block, although the expression it wraps was still parsed from a string literal"].) Quick question: Does this use the same underlying parse nodes, and helper classes like ParseTreeRewriter, as the old system, just generating them a different way? If so, I think the value here is as much in the convenience methods for performing searches and rewrites as the pattern syntax—so thank you for that, regardless! While we're on the subject of rewrite tools, a while back I noticed that I often wanted to rewrite sequences of statements to a single method call, where that sequence might recur several times in the same method. This especially comes up in tests—perhaps I notice that the pattern: self assert: obj foo equals: `#expectedFoo. self assert: obj bar equals: `#expectedBar. self assert: obj baz equals: `#expectedBaz. occurs a lot, and those properties are related enough that it makes more sense to say self verifyFooBarBaz: obj equal: {`#expectedFoo. `#expectedBar. `#expectedBaz}. (This is a poor example, in truth, but there are cases where it's much more clearly justified.) By default you can only get one of these occurrences per run of the rewrite tool, because any pattern you write has to match the *entire sequence*, and once it has matched, the entire sequence is disqualified from further matching. I was able to extend the matching semantics so that a recurse-into-list-of-statements pattern (i.e. ``@.stmts, double-backtick-at-period) effectively builds a *new* sequence containing only the statements it matched, and retries the rule against *that*. It could definitely stand to be more elegant, but for me it filled an important hole in the existing capabilities. Is that something anyone would be interested in helping me dust off and contribute? On Tue, Feb 3, 2026 at 1:41 PM Denis Kudriashov <dionisiydk@gmail.com> wrote: > Hi Richard. > > I checked the code and the double backticks are for the recursion mode. It > forces the search to dive into the current matching node to find more cases > inside it. > For example: > > (instVar isNil ifTrue: [ 'inside recursion' ]) isNil ifTrue: [ 'outer > node' ] > > The syntax with single backtick will not find the internal "instVar isNil" > expression. > > In BPatterns the recursion mode is enabled by default for the pattern > variables. So the default mode covers the maximum scope for a search. > Currently you can't not disable the #recurseInto flag as there is not > suitable accessor for this. But if it would be there the pattern would like: > > [ anyVar isNil ifTrue: anyBlock ] bpattern with: [ anyVar ] -> [:pattern | > pattern recurseInto: false ] > > > Anyway I adjusted my blog accordingly. Thanks for the attention. > > вт, 3 февр. 2026 г. в 10:47, Richard O'Keefe <raoknz@gmail.com>: > >> Thank you. One of the reasons given for introducing BPatterns is a >> subtle difference between >> single backticks and double backticks, which is mentioned but not >> explained in the BPatterns >> blog entry. The help screen you directed me to does not explain that. >> >> Is there any documentation which is *complete* and *proofread*? >> >> On Tue, 3 Feb 2026 at 23:16, Denis Kudriashov <dionisiydk@gmail.com> >> wrote: >> >>> Yes. There is nice help presenter in the Pharo: >>> >>> StRewriterHelpBrowserPresenter new open >>> >>> >>> [image: Screenshot 2026-02-03 at 10.15.45.png] >>> >>> >>> вт, 3 февр. 2026 г. в 01:36, Richard O'Keefe <raoknz@gmail.com>: >>> >>>> Is the "classic" rewriting syntax documented anywhere? >>>> >>>> On Mon, 2 Feb 2026 at 22:52, Denis Kudriashov via Pharo-users < >>>> pharo-users@lists.pharo.org> wrote: >>>> >>>>> Hi all. >>>>> >>>>> This is the release of *BPatterns* project, one of my old ideas on >>>>> how to make the rewrite engine usable for scripting. >>>>> >>>>> As a quick reminder, here is an example of the classic rewrite-engine >>>>> matching syntax: >>>>> >>>>> *``@receiver isNil ifTrue: ``@nilBlock* >>>>> >>>>> >>>>> In practice, patterns like this usually live inside string >>>>> literals—hidden away in lint rules, deprecations, or refactorings. >>>>> To use them for *manual* code search or rewriting, you typically need >>>>> a dedicated tool. >>>>> >>>>> Now compare that with the same pattern expressed as a *BPattern*: >>>>> >>>>> *[ any isNil ifTrue: anyBlock ] bpattern* >>>>> >>>>> No special syntax. >>>>> No magical tools. >>>>> Just pure Smalltalk. >>>>> >>>>> You write a block. >>>>> You send #bpattern. >>>>> You’re done. >>>>> >>>>> Every editor understands it. >>>>> Every tool respects it. >>>>> >>>>> Want to see where this pattern appears? >>>>> >>>>> * [ any isNil ifTrue: anyBlock ] bpattern browseUsers* >>>>> >>>>> >>>>> [image: Screenshot 2026-01-31 at 12.16.19.png] >>>>> >>>>> Want to rewrite all of them? >>>>> >>>>> *[[ any isNil ifTrue: anyBlock ] -> [ any ifNil: anyBlock ]] brewrite >>>>> preview* >>>>> >>>>> >>>>> [image: Screenshot 2026-01-31 at 12.17.57.png] >>>>> >>>>> Because *BPatterns are real Smalltalk code*, all development tools >>>>> work out of the box: >>>>> syntax highlighting, completion, navigation, refactorings. >>>>> >>>>> This is the rewrite engine treated as a *first-class citizen*. >>>>> >>>>> Not strings. >>>>> Not tooling sidecars. >>>>> Not just for advanced users. >>>>> >>>>> *A rewrite engine you can actually use.* >>>>> * A rewrite engine at your fingertips.* >>>>> More details are in the blog post: >>>>> >>>>> - >>>>> https://dionisiydk.blogspot.com/2026/02/bpatterns-rewrite-engine-with-smalltalk.html >>>>> >>>>> And follow the project on GitHub: >>>>> >>>>> - https://github.com/dionisiydk/BPatterns >>>>> >>>>> >>>>> - >>>>> >>>>>
EM
Eliot Miranda
Wed, Feb 4, 2026 1:16 AM

Hi Denis,

could you support single & double ticks/non-recursive & recursive modes by providing eg shallowBpattern and bpattern?

Also why bpattern and not bPattern or rewritePattern?
_,,,^..^,,,_ (phone)

On Feb 3, 2026, at 10:41 AM, Denis Kudriashov <dionisiydk@gmail.com> wrote:

Hi Richard.

I checked the code and the double backticks are for the recursion mode. It forces the search to dive into the current matching node to find more cases inside it.

For example:

(instVar isNil ifTrue: [ 'inside recursion' ]) isNil ifTrue: [ 'outer node' ]

The syntax with single backtick will not find the internal "instVar isNil" expression.

In BPatterns the recursion mode is enabled by default for the pattern variables. So the default mode covers the maximum scope for a search.

Currently you can't not disable the #recurseInto flag as there is not suitable accessor for this. But if it would be there the pattern would like:

[ anyVar isNil ifTrue: anyBlock ] bpattern with: [ anyVar ] -> [:pattern | pattern recurseInto: false ]

Anyway I adjusted my blog accordingly. Thanks for the attention.

вт, 3 февр. 2026 г. в 10:47, Richard O'Keefe <raoknz@gmail.com>:

Thank you. One of the reasons given for introducing BPatterns is a subtle difference between

single backticks and double backticks, which is mentioned but not explained in the BPatterns

blog entry. The help screen you directed me to does not explain that.

Is there any documentation which is complete and proofread?

On Tue, 3 Feb 2026 at 23:16, Denis Kudriashov <dionisiydk@gmail.com> wrote:

Yes. There is nice help presenter in the Pharo:

StRewriterHelpBrowserPresenter new open

<Screenshot 2026-02-03 at 10.15.45.png>

вт, 3 февр. 2026 г. в 01:36, Richard O'Keefe <raoknz@gmail.com>:

Is the "classic" rewriting syntax documented anywhere?

On Mon, 2 Feb 2026 at 22:52, Denis Kudriashov via Pharo-users <pharo-users@lists.pharo.org> wrote:

Hi all.

This is the release of BPatterns project, one of my old ideas on how to make the rewrite engine usable for scripting.

As a quick reminder, here is an example of the classic rewrite-engine matching syntax:

@receiver isNil ifTrue: @nilBlock

In practice, patterns like this usually live inside string literals—hidden away in lint rules, deprecations, or refactorings.

To use them for manual code search or rewriting, you typically need a dedicated tool.

Now compare that with the same pattern expressed as a BPattern:

[ any isNil ifTrue: anyBlock ] bpattern

No special syntax.
No magical tools.
Just pure Smalltalk.

You write a block.
You send #bpattern.
You’re done.

Every editor understands it.
Every tool respects it.

Want to see where this pattern appears?

[ any isNil ifTrue: anyBlock ] bpattern browseUsers

<Screenshot 2026-01-31 at 12.16.19.png>

Want to rewrite all of them?

[[ any isNil ifTrue: anyBlock ] -> [ any ifNil: anyBlock ]] brewrite preview

<Screenshot 2026-01-31 at 12.17.57.png>

Because BPatterns are real Smalltalk code, all development tools work out of the box:
syntax highlighting, completion, navigation, refactorings.

This is the rewrite engine treated as a first-class citizen.

Not strings.
Not tooling sidecars.
Not just for advanced users.

A rewrite engine you can actually use.
A rewrite engine at your fingertips.

More details are in the blog post:

And follow the project on GitHub:

DK
Denis Kudriashov
Sat, Feb 7, 2026 11:51 AM

Hi Daniel.

Quick question: Does this use the same underlying parse nodes, and helper

classes like ParseTreeRewriter, as the old system, just generating them a
different way? If so, I think the value here is as much in the convenience
methods for performing searches and rewrites as the pattern syntax—so thank
you for that, regardless!

Yes, underhood BPatterns is based on the pattern AST nodes and the
matching/rewrite machinery. It's just a different DSL to the original
engine.
There are some changes to better follow my idea but it is not significant.

While we're on the subject of rewrite tools, a while back I noticed that I

often wanted to rewrite sequences of statements to a single method call,
where that sequence might recur several times in the same method. This
especially comes up in tests—perhaps I notice that the pattern:

self assert: obj foo equals: `#expectedFoo.

self assert: obj bar equals: #expectedBar. self assert: obj baz equals: #expectedBaz.

Agree, I have the same feeling about the sequences. And it can be quite
confusing when you do not know the internal details.
I don't think I will have any time to change this.

вт, 3 февр. 2026 г. в 23:51, Daniel Slomovits daniels220@gmail.com:

I love the basic idea, but at a glance, it seems like the syntax rapidly
becomes much more verbose than the equivalent using the special pattern
syntax. For simple examples it's more-or-less equivalent, but the with: [
anyVar ] -> [:pattern | ...] syntax is very clunky.

What I would really love to see is an extension to the Compiler, that
allows for mixing the actual pattern syntax directly into code. Perhaps
initiated by a backtick-parenthesis, so you could write:

((``@receiver isNil ifTrue: ``@nilBlock) -> (@receiver ifNil: @nilBlock)) rewrite preview

I'm not even sure this would be all that hard—it would mean adding one new
type of parse node, call it a "pattern literal", delimited by (), whose implementation would be very straightforward for the most part, with the only complication being that pattern blocks ({}) would have to be
compiled properly in the outer scope. As additional niceties, individual
pattern nodes should ideally be able to appear bare, rather than needing to
be wrapped in `(), and we would want a syntax for "this is a whole-method
pattern"

On another note, I want to call attention to one thing that BPattern has
going for it that string-literal-based patterns can't (easily) do: modifier
blocks are closures in the method that generated them, so you can do things
like have methods that return a pattern which closes over the arguments of
the method...having trouble coming up with an example off the top of my
head, but this is very powerful. (Well. Actually you can do this with
string-based patterns, by reaching in after the pattern is parsed and
editing the modifier block. I've written methods to support the following
syntax: '`@exp' withPatternBlock: [:exp | "this is a real block, although
the expression it wraps was still parsed from a string literal"].)

Quick question: Does this use the same underlying parse nodes, and helper
classes like ParseTreeRewriter, as the old system, just generating them a
different way? If so, I think the value here is as much in the convenience
methods for performing searches and rewrites as the pattern syntax—so thank
you for that, regardless!

While we're on the subject of rewrite tools, a while back I noticed that I
often wanted to rewrite sequences of statements to a single method call,
where that sequence might recur several times in the same method. This
especially comes up in tests—perhaps I notice that the pattern:

self assert: obj foo equals: #expectedFoo. self assert: obj bar equals: #expectedBar.
self assert: obj baz equals: `#expectedBaz.

occurs a lot, and those properties are related enough that it makes more
sense to say self verifyFooBarBaz: obj equal: {#expectedFoo. #expectedBar. `#expectedBaz}. (This is a poor example, in truth, but there
are cases where it's much more clearly justified.) By default you can only
get one of these occurrences per run of the rewrite tool, because any
pattern you write has to match the entire sequence, and once it has
matched, the entire sequence is disqualified from further matching. I was
able to extend the matching semantics so that a
recurse-into-list-of-statements pattern (i.e. ``@.stmts,
double-backtick-at-period) effectively builds a new sequence containing
only the statements it matched, and retries the rule against that. It
could definitely stand to be more elegant, but for me it filled an
important hole in the existing capabilities. Is that something anyone would
be interested in helping me dust off and contribute?

On Tue, Feb 3, 2026 at 1:41 PM Denis Kudriashov dionisiydk@gmail.com
wrote:

Hi Richard.

I checked the code and the double backticks are for the recursion mode.
It forces the search to dive into the current matching node to find more
cases inside it.
For example:

(instVar isNil ifTrue: [ 'inside recursion' ]) isNil ifTrue: [ 'outer
node' ]

The syntax with single backtick will not find the internal "instVar
isNil" expression.

In BPatterns the recursion mode is enabled by default for the pattern
variables. So the default mode covers the maximum scope for a search.
Currently you can't not disable the #recurseInto flag as there is not
suitable accessor for this. But if it would be there the pattern would like:

[ anyVar isNil ifTrue: anyBlock ] bpattern with: [ anyVar ] -> [:pattern
| pattern recurseInto: false ]

Anyway I adjusted my blog accordingly. Thanks for the attention.

вт, 3 февр. 2026 г. в 10:47, Richard O'Keefe raoknz@gmail.com:

Thank you.  One of the reasons given for introducing BPatterns is a
subtle difference between
single backticks and double backticks, which is mentioned but not
explained in the BPatterns
blog entry.  The help screen you directed me to does not explain that.

Is there any documentation which is complete and proofread?

On Tue, 3 Feb 2026 at 23:16, Denis Kudriashov dionisiydk@gmail.com
wrote:

Yes. There is nice help presenter in the Pharo:

StRewriterHelpBrowserPresenter new open

[image: Screenshot 2026-02-03 at 10.15.45.png]

вт, 3 февр. 2026 г. в 01:36, Richard O'Keefe raoknz@gmail.com:

Is the "classic" rewriting syntax documented anywhere?

On Mon, 2 Feb 2026 at 22:52, Denis Kudriashov via Pharo-users <
pharo-users@lists.pharo.org> wrote:

Hi all.

This is the release of BPatterns project, one of my old ideas on
how to make the rewrite engine usable for scripting.

As a quick reminder, here is an example of the classic rewrite-engine
matching syntax:

@receiver isNil ifTrue: @nilBlock

In practice, patterns like this usually live inside string
literals—hidden away in lint rules, deprecations, or refactorings.
To use them for manual code search or rewriting, you typically
need a dedicated tool.

Now compare that with the same pattern expressed as a BPattern:

[ any isNil ifTrue: anyBlock ] bpattern

No special syntax.
No magical tools.
Just pure Smalltalk.

You write a block.
You send #bpattern.
You’re done.

Every editor understands it.
Every tool respects it.

Want to see where this pattern appears?

  • [ any isNil ifTrue: anyBlock ] bpattern browseUsers*

[image: Screenshot 2026-01-31 at 12.16.19.png]

Want to rewrite all of them?

[[ any isNil ifTrue: anyBlock ] -> [ any ifNil: anyBlock ]] brewrite
preview

[image: Screenshot 2026-01-31 at 12.17.57.png]

Because BPatterns are real Smalltalk code, all development tools
work out of the box:
syntax highlighting, completion, navigation, refactorings.

This is the rewrite engine treated as a first-class citizen.

Not strings.
Not tooling sidecars.
Not just for advanced users.

A rewrite engine you can actually use.

And follow the project on GitHub:

- https://github.com/dionisiydk/BPatterns


-
Hi Daniel. Quick question: Does this use the same underlying parse nodes, and helper > classes like ParseTreeRewriter, as the old system, just generating them a > different way? If so, I think the value here is as much in the convenience > methods for performing searches and rewrites as the pattern syntax—so thank > you for that, regardless! Yes, underhood BPatterns is based on the pattern AST nodes and the matching/rewrite machinery. It's just a different DSL to the original engine. There are some changes to better follow my idea but it is not significant. While we're on the subject of rewrite tools, a while back I noticed that I > often wanted to rewrite sequences of statements to a single method call, > where that sequence might recur several times in the same method. This > especially comes up in tests—perhaps I notice that the pattern: self assert: obj foo equals: `#expectedFoo. > self assert: obj bar equals: `#expectedBar. > self assert: obj baz equals: `#expectedBaz. Agree, I have the same feeling about the sequences. And it can be quite confusing when you do not know the internal details. I don't think I will have any time to change this. вт, 3 февр. 2026 г. в 23:51, Daniel Slomovits <daniels220@gmail.com>: > I love the basic idea, but at a glance, it seems like the syntax rapidly > becomes *much* more verbose than the equivalent using the special pattern > syntax. For simple examples it's more-or-less equivalent, but the with: [ > anyVar ] -> [:pattern | ...] syntax is *very* clunky. > > What I would *really* love to see is an extension to the Compiler, that > allows for mixing the actual pattern syntax directly into code. Perhaps > initiated by a backtick-parenthesis, so you could write: > > (`(``@receiver isNil ifTrue: ``@nilBlock) -> `(``@receiver ifNil: > ``@nilBlock)) rewrite preview > > I'm not even sure this would be all that hard—it would mean adding one new > type of parse node, call it a "pattern literal", delimited by `(), whose > implementation would be very straightforward for the most part, with the > only complication being that pattern blocks (`{}) would have to be > compiled properly in the outer scope. As additional niceties, individual > pattern nodes should ideally be able to appear bare, rather than needing to > be wrapped in `(), and we would want a syntax for "this is a whole-method > pattern" > > On another note, I want to call attention to one thing that BPattern has > going for it that string-literal-based patterns can't (easily) do: modifier > blocks are closures in the method that generated them, so you can do things > like have methods that return a pattern which closes over the arguments of > the method...having trouble coming up with an example off the top of my > head, but this is very powerful. (Well. Actually you *can* do this with > string-based patterns, by reaching in after the pattern is parsed and > editing the modifier block. I've written methods to support the following > syntax: '`@exp' withPatternBlock: [:exp | "this is a real block, although > the expression it wraps was still parsed from a string literal"].) > > Quick question: Does this use the same underlying parse nodes, and helper > classes like ParseTreeRewriter, as the old system, just generating them a > different way? If so, I think the value here is as much in the convenience > methods for performing searches and rewrites as the pattern syntax—so thank > you for that, regardless! > > While we're on the subject of rewrite tools, a while back I noticed that I > often wanted to rewrite sequences of statements to a single method call, > where that sequence might recur several times in the same method. This > especially comes up in tests—perhaps I notice that the pattern: > > self assert: obj foo equals: `#expectedFoo. > self assert: obj bar equals: `#expectedBar. > self assert: obj baz equals: `#expectedBaz. > > occurs a lot, and those properties are related enough that it makes more > sense to say self verifyFooBarBaz: obj equal: {`#expectedFoo. > `#expectedBar. `#expectedBaz}. (This is a poor example, in truth, but there > are cases where it's much more clearly justified.) By default you can only > get one of these occurrences per run of the rewrite tool, because any > pattern you write has to match the *entire sequence*, and once it has > matched, the entire sequence is disqualified from further matching. I was > able to extend the matching semantics so that a > recurse-into-list-of-statements pattern (i.e. ``@.stmts, > double-backtick-at-period) effectively builds a *new* sequence containing > only the statements it matched, and retries the rule against *that*. It > could definitely stand to be more elegant, but for me it filled an > important hole in the existing capabilities. Is that something anyone would > be interested in helping me dust off and contribute? > > On Tue, Feb 3, 2026 at 1:41 PM Denis Kudriashov <dionisiydk@gmail.com> > wrote: > >> Hi Richard. >> >> I checked the code and the double backticks are for the recursion mode. >> It forces the search to dive into the current matching node to find more >> cases inside it. >> For example: >> >> (instVar isNil ifTrue: [ 'inside recursion' ]) isNil ifTrue: [ 'outer >> node' ] >> >> The syntax with single backtick will not find the internal "instVar >> isNil" expression. >> >> In BPatterns the recursion mode is enabled by default for the pattern >> variables. So the default mode covers the maximum scope for a search. >> Currently you can't not disable the #recurseInto flag as there is not >> suitable accessor for this. But if it would be there the pattern would like: >> >> [ anyVar isNil ifTrue: anyBlock ] bpattern with: [ anyVar ] -> [:pattern >> | pattern recurseInto: false ] >> >> >> Anyway I adjusted my blog accordingly. Thanks for the attention. >> >> вт, 3 февр. 2026 г. в 10:47, Richard O'Keefe <raoknz@gmail.com>: >> >>> Thank you. One of the reasons given for introducing BPatterns is a >>> subtle difference between >>> single backticks and double backticks, which is mentioned but not >>> explained in the BPatterns >>> blog entry. The help screen you directed me to does not explain that. >>> >>> Is there any documentation which is *complete* and *proofread*? >>> >>> On Tue, 3 Feb 2026 at 23:16, Denis Kudriashov <dionisiydk@gmail.com> >>> wrote: >>> >>>> Yes. There is nice help presenter in the Pharo: >>>> >>>> StRewriterHelpBrowserPresenter new open >>>> >>>> >>>> [image: Screenshot 2026-02-03 at 10.15.45.png] >>>> >>>> >>>> вт, 3 февр. 2026 г. в 01:36, Richard O'Keefe <raoknz@gmail.com>: >>>> >>>>> Is the "classic" rewriting syntax documented anywhere? >>>>> >>>>> On Mon, 2 Feb 2026 at 22:52, Denis Kudriashov via Pharo-users < >>>>> pharo-users@lists.pharo.org> wrote: >>>>> >>>>>> Hi all. >>>>>> >>>>>> This is the release of *BPatterns* project, one of my old ideas on >>>>>> how to make the rewrite engine usable for scripting. >>>>>> >>>>>> As a quick reminder, here is an example of the classic rewrite-engine >>>>>> matching syntax: >>>>>> >>>>>> *``@receiver isNil ifTrue: ``@nilBlock* >>>>>> >>>>>> >>>>>> In practice, patterns like this usually live inside string >>>>>> literals—hidden away in lint rules, deprecations, or refactorings. >>>>>> To use them for *manual* code search or rewriting, you typically >>>>>> need a dedicated tool. >>>>>> >>>>>> Now compare that with the same pattern expressed as a *BPattern*: >>>>>> >>>>>> *[ any isNil ifTrue: anyBlock ] bpattern* >>>>>> >>>>>> No special syntax. >>>>>> No magical tools. >>>>>> Just pure Smalltalk. >>>>>> >>>>>> You write a block. >>>>>> You send #bpattern. >>>>>> You’re done. >>>>>> >>>>>> Every editor understands it. >>>>>> Every tool respects it. >>>>>> >>>>>> Want to see where this pattern appears? >>>>>> >>>>>> * [ any isNil ifTrue: anyBlock ] bpattern browseUsers* >>>>>> >>>>>> >>>>>> [image: Screenshot 2026-01-31 at 12.16.19.png] >>>>>> >>>>>> Want to rewrite all of them? >>>>>> >>>>>> *[[ any isNil ifTrue: anyBlock ] -> [ any ifNil: anyBlock ]] brewrite >>>>>> preview* >>>>>> >>>>>> >>>>>> [image: Screenshot 2026-01-31 at 12.17.57.png] >>>>>> >>>>>> Because *BPatterns are real Smalltalk code*, all development tools >>>>>> work out of the box: >>>>>> syntax highlighting, completion, navigation, refactorings. >>>>>> >>>>>> This is the rewrite engine treated as a *first-class citizen*. >>>>>> >>>>>> Not strings. >>>>>> Not tooling sidecars. >>>>>> Not just for advanced users. >>>>>> >>>>>> *A rewrite engine you can actually use.* >>>>>> * A rewrite engine at your fingertips.* >>>>>> More details are in the blog post: >>>>>> >>>>>> - >>>>>> https://dionisiydk.blogspot.com/2026/02/bpatterns-rewrite-engine-with-smalltalk.html >>>>>> >>>>>> And follow the project on GitHub: >>>>>> >>>>>> - https://github.com/dionisiydk/BPatterns >>>>>> >>>>>> >>>>>> - >>>>>> >>>>>>
DK
Denis Kudriashov
Mon, Feb 9, 2026 10:02 AM

Hi Eliot.

The recursive mode is per pattern variable. It can be done globally of
course in a way you suggested. But I do not see much value from this.

Do you have an example where we don't want the non recursive search?

ср, 4 февр. 2026 г., 01:16 Eliot Miranda eliot.miranda@gmail.com:

Hi Denis,

 could you support single & double ticks/non-recursive & recursive

modes by providing eg shallowBpattern and bpattern?

Also why bpattern and not bPattern or rewritePattern?
,,,^..^,,, (phone)

On Feb 3, 2026, at 10:41 AM, Denis Kudriashov dionisiydk@gmail.com
wrote:


Hi Richard.

I checked the code and the double backticks are for the recursion mode. It
forces the search to dive into the current matching node to find more cases
inside it.
For example:

(instVar isNil ifTrue: [ 'inside recursion' ]) isNil ifTrue: [ 'outer
node' ]

The syntax with single backtick will not find the internal "instVar isNil"
expression.

In BPatterns the recursion mode is enabled by default for the pattern
variables. So the default mode covers the maximum scope for a search.
Currently you can't not disable the #recurseInto flag as there is not
suitable accessor for this. But if it would be there the pattern would like:

[ anyVar isNil ifTrue: anyBlock ] bpattern with: [ anyVar ] -> [:pattern |
pattern recurseInto: false ]

Anyway I adjusted my blog accordingly. Thanks for the attention.

вт, 3 февр. 2026 г. в 10:47, Richard O'Keefe raoknz@gmail.com:

Thank you.  One of the reasons given for introducing BPatterns is a
subtle difference between
single backticks and double backticks, which is mentioned but not
explained in the BPatterns
blog entry.  The help screen you directed me to does not explain that.

Is there any documentation which is complete and proofread?

On Tue, 3 Feb 2026 at 23:16, Denis Kudriashov dionisiydk@gmail.com
wrote:

Yes. There is nice help presenter in the Pharo:

StRewriterHelpBrowserPresenter new open

<Screenshot 2026-02-03 at 10.15.45.png>

вт, 3 февр. 2026 г. в 01:36, Richard O'Keefe raoknz@gmail.com:

Is the "classic" rewriting syntax documented anywhere?

On Mon, 2 Feb 2026 at 22:52, Denis Kudriashov via Pharo-users <
pharo-users@lists.pharo.org> wrote:

Hi all.

This is the release of BPatterns project, one of my old ideas on
how to make the rewrite engine usable for scripting.

As a quick reminder, here is an example of the classic rewrite-engine
matching syntax:

@receiver isNil ifTrue: @nilBlock

In practice, patterns like this usually live inside string
literals—hidden away in lint rules, deprecations, or refactorings.
To use them for manual code search or rewriting, you typically need
a dedicated tool.

Now compare that with the same pattern expressed as a BPattern:

[ any isNil ifTrue: anyBlock ] bpattern

No special syntax.
No magical tools.
Just pure Smalltalk.

You write a block.
You send #bpattern.
You’re done.

Every editor understands it.
Every tool respects it.

Want to see where this pattern appears?

  • [ any isNil ifTrue: anyBlock ] bpattern browseUsers*

<Screenshot 2026-01-31 at 12.16.19.png>

Want to rewrite all of them?

[[ any isNil ifTrue: anyBlock ] -> [ any ifNil: anyBlock ]] brewrite
preview

<Screenshot 2026-01-31 at 12.17.57.png>

Because BPatterns are real Smalltalk code, all development tools
work out of the box:
syntax highlighting, completion, navigation, refactorings.

This is the rewrite engine treated as a first-class citizen.

Not strings.
Not tooling sidecars.
Not just for advanced users.

A rewrite engine you can actually use.

And follow the project on GitHub:

- https://github.com/dionisiydk/BPatterns


-
Hi Eliot. The recursive mode is per pattern variable. It can be done globally of course in a way you suggested. But I do not see much value from this. Do you have an example where we don't want the non recursive search? ср, 4 февр. 2026 г., 01:16 Eliot Miranda <eliot.miranda@gmail.com>: > Hi Denis, > > could you support single & double ticks/non-recursive & recursive > modes by providing eg shallowBpattern and bpattern? > > > Also why bpattern and not bPattern or rewritePattern? > _,,,^..^,,,_ (phone) > > On Feb 3, 2026, at 10:41 AM, Denis Kudriashov <dionisiydk@gmail.com> > wrote: > >  > Hi Richard. > > I checked the code and the double backticks are for the recursion mode. It > forces the search to dive into the current matching node to find more cases > inside it. > For example: > > (instVar isNil ifTrue: [ 'inside recursion' ]) isNil ifTrue: [ 'outer > node' ] > > The syntax with single backtick will not find the internal "instVar isNil" > expression. > > In BPatterns the recursion mode is enabled by default for the pattern > variables. So the default mode covers the maximum scope for a search. > Currently you can't not disable the #recurseInto flag as there is not > suitable accessor for this. But if it would be there the pattern would like: > > [ anyVar isNil ifTrue: anyBlock ] bpattern with: [ anyVar ] -> [:pattern | > pattern recurseInto: false ] > > > Anyway I adjusted my blog accordingly. Thanks for the attention. > > вт, 3 февр. 2026 г. в 10:47, Richard O'Keefe <raoknz@gmail.com>: > >> Thank you. One of the reasons given for introducing BPatterns is a >> subtle difference between >> single backticks and double backticks, which is mentioned but not >> explained in the BPatterns >> blog entry. The help screen you directed me to does not explain that. >> >> Is there any documentation which is *complete* and *proofread*? >> >> On Tue, 3 Feb 2026 at 23:16, Denis Kudriashov <dionisiydk@gmail.com> >> wrote: >> >>> Yes. There is nice help presenter in the Pharo: >>> >>> StRewriterHelpBrowserPresenter new open >>> >>> >>> <Screenshot 2026-02-03 at 10.15.45.png> >>> >>> >>> >>> вт, 3 февр. 2026 г. в 01:36, Richard O'Keefe <raoknz@gmail.com>: >>> >>>> Is the "classic" rewriting syntax documented anywhere? >>>> >>>> On Mon, 2 Feb 2026 at 22:52, Denis Kudriashov via Pharo-users < >>>> pharo-users@lists.pharo.org> wrote: >>>> >>>>> Hi all. >>>>> >>>>> This is the release of *BPatterns* project, one of my old ideas on >>>>> how to make the rewrite engine usable for scripting. >>>>> >>>>> As a quick reminder, here is an example of the classic rewrite-engine >>>>> matching syntax: >>>>> >>>>> *``@receiver isNil ifTrue: ``@nilBlock* >>>>> >>>>> >>>>> In practice, patterns like this usually live inside string >>>>> literals—hidden away in lint rules, deprecations, or refactorings. >>>>> To use them for *manual* code search or rewriting, you typically need >>>>> a dedicated tool. >>>>> >>>>> Now compare that with the same pattern expressed as a *BPattern*: >>>>> >>>>> *[ any isNil ifTrue: anyBlock ] bpattern* >>>>> >>>>> No special syntax. >>>>> No magical tools. >>>>> Just pure Smalltalk. >>>>> >>>>> You write a block. >>>>> You send #bpattern. >>>>> You’re done. >>>>> >>>>> Every editor understands it. >>>>> Every tool respects it. >>>>> >>>>> Want to see where this pattern appears? >>>>> >>>>> * [ any isNil ifTrue: anyBlock ] bpattern browseUsers* >>>>> >>>>> >>>>> <Screenshot 2026-01-31 at 12.16.19.png> >>>>> >>>>> >>>>> Want to rewrite all of them? >>>>> >>>>> *[[ any isNil ifTrue: anyBlock ] -> [ any ifNil: anyBlock ]] brewrite >>>>> preview* >>>>> >>>>> >>>>> <Screenshot 2026-01-31 at 12.17.57.png> >>>>> >>>>> Because *BPatterns are real Smalltalk code*, all development tools >>>>> work out of the box: >>>>> syntax highlighting, completion, navigation, refactorings. >>>>> >>>>> This is the rewrite engine treated as a *first-class citizen*. >>>>> >>>>> Not strings. >>>>> Not tooling sidecars. >>>>> Not just for advanced users. >>>>> >>>>> *A rewrite engine you can actually use.* >>>>> * A rewrite engine at your fingertips.* >>>>> More details are in the blog post: >>>>> >>>>> - >>>>> https://dionisiydk.blogspot.com/2026/02/bpatterns-rewrite-engine-with-smalltalk.html >>>>> >>>>> And follow the project on GitHub: >>>>> >>>>> - https://github.com/dionisiydk/BPatterns >>>>> >>>>> >>>>> - >>>>> >>>>>
EM
Eliot Miranda
Mon, Feb 9, 2026 1:44 PM

On Feb 9, 2026, at 2:03 AM, Denis Kudriashov <dionisiydk@gmail.com> wrote:

Hi Eliot.

The recursive mode is per pattern variable. It can be done globally of course in a way you suggested. But I do not see much value from this.

Do you have an example where we don't want the non recursive search?

Yes. When I refactored the VM to make the object memory/garbage collector an instance variable of the interpreter, rather than the superclass of the interpreter, this major refactoring needed to be recursive.

ср, 4 февр. 2026 г., 01:16 Eliot Miranda <eliot.miranda@gmail.com>:

Hi Denis,

could you support single & double ticks/non-recursive & recursive modes by providing eg shallowBpattern and bpattern?

P.S.

Also why bpattern and not bPattern or rewritePattern?

_,,,^..^,,,_ (phone)

On Feb 3, 2026, at 10:41 AM, Denis Kudriashov <dionisiydk@gmail.com> wrote:

Hi Richard.

I checked the code and the double backticks are for the recursion mode. It forces the search to dive into the current matching node to find more cases inside it.

For example:

(instVar isNil ifTrue: [ 'inside recursion' ]) isNil ifTrue: [ 'outer node' ]

The syntax with single backtick will not find the internal "instVar isNil" expression.

In BPatterns the recursion mode is enabled by default for the pattern variables. So the default mode covers the maximum scope for a search.

Currently you can't not disable the #recurseInto flag as there is not suitable accessor for this. But if it would be there the pattern would like:

[ anyVar isNil ifTrue: anyBlock ] bpattern with: [ anyVar ] -> [:pattern | pattern recurseInto: false ]

Anyway I adjusted my blog accordingly. Thanks for the attention.

вт, 3 февр. 2026 г. в 10:47, Richard O'Keefe <raoknz@gmail.com>:

Thank you. One of the reasons given for introducing BPatterns is a subtle difference between

single backticks and double backticks, which is mentioned but not explained in the BPatterns

blog entry. The help screen you directed me to does not explain that.

Is there any documentation which is complete and proofread?

On Tue, 3 Feb 2026 at 23:16, Denis Kudriashov <dionisiydk@gmail.com> wrote:

Yes. There is nice help presenter in the Pharo:

StRewriterHelpBrowserPresenter new open

<Screenshot 2026-02-03 at 10.15.45.png>

вт, 3 февр. 2026 г. в 01:36, Richard O'Keefe <raoknz@gmail.com>:

Is the "classic" rewriting syntax documented anywhere?

On Mon, 2 Feb 2026 at 22:52, Denis Kudriashov via Pharo-users <pharo-users@lists.pharo.org> wrote:

Hi all.

This is the release of BPatterns project, one of my old ideas on how to make the rewrite engine usable for scripting.

As a quick reminder, here is an example of the classic rewrite-engine matching syntax:

@receiver isNil ifTrue: @nilBlock

In practice, patterns like this usually live inside string literals—hidden away in lint rules, deprecations, or refactorings.

To use them for manual code search or rewriting, you typically need a dedicated tool.

Now compare that with the same pattern expressed as a BPattern:

[ any isNil ifTrue: anyBlock ] bpattern

No special syntax.
No magical tools.
Just pure Smalltalk.

You write a block.
You send #bpattern.
You’re done.

Every editor understands it.
Every tool respects it.

Want to see where this pattern appears?

[ any isNil ifTrue: anyBlock ] bpattern browseUsers

<Screenshot 2026-01-31 at 12.16.19.png>

Want to rewrite all of them?

[[ any isNil ifTrue: anyBlock ] -> [ any ifNil: anyBlock ]] brewrite preview

<Screenshot 2026-01-31 at 12.17.57.png>

Because BPatterns are real Smalltalk code, all development tools work out of the box:
syntax highlighting, completion, navigation, refactorings.

This is the rewrite engine treated as a first-class citizen.

Not strings.
Not tooling sidecars.
Not just for advanced users.

A rewrite engine you can actually use.
A rewrite engine at your fingertips.

More details are in the blog post:

And follow the project on GitHub:

DK
Denis Kudriashov
Tue, Feb 10, 2026 1:31 PM

Hi Eliot.

Yes, the recursive mode is default in BPatterns.

I wonder when we do not need it

пн, 9 февр. 2026 г., 13:45 Eliot Miranda eliot.miranda@gmail.com:

On Feb 9, 2026, at 2:03 AM, Denis Kudriashov dionisiydk@gmail.com wrote:


Hi Eliot.

The recursive mode is per pattern variable. It can be done globally of
course in a way you suggested. But I do not see much value from this.

Do you have an example where we don't want the non recursive search?

Yes. When I refactored the VM to make the object memory/garbage collector
an instance variable of the interpreter, rather than the superclass of the
interpreter, this major refactoring needed to be recursive.

ср, 4 февр. 2026 г., 01:16 Eliot Miranda eliot.miranda@gmail.com:

Hi Denis,

 could you support single & double ticks/non-recursive & recursive

modes by providing eg shallowBpattern and bpattern?

P.S.

Also why bpattern and not bPattern or rewritePattern?

,,,^..^,,, (phone)

On Feb 3, 2026, at 10:41 AM, Denis Kudriashov dionisiydk@gmail.com
wrote:


Hi Richard.

I checked the code and the double backticks are for the recursion mode.
It forces the search to dive into the current matching node to find more
cases inside it.
For example:

(instVar isNil ifTrue: [ 'inside recursion' ]) isNil ifTrue: [ 'outer
node' ]

The syntax with single backtick will not find the internal "instVar
isNil" expression.

In BPatterns the recursion mode is enabled by default for the pattern
variables. So the default mode covers the maximum scope for a search.
Currently you can't not disable the #recurseInto flag as there is not
suitable accessor for this. But if it would be there the pattern would like:

[ anyVar isNil ifTrue: anyBlock ] bpattern with: [ anyVar ] -> [:pattern
| pattern recurseInto: false ]

Anyway I adjusted my blog accordingly. Thanks for the attention.

вт, 3 февр. 2026 г. в 10:47, Richard O'Keefe raoknz@gmail.com:

Thank you.  One of the reasons given for introducing BPatterns is a
subtle difference between
single backticks and double backticks, which is mentioned but not
explained in the BPatterns
blog entry.  The help screen you directed me to does not explain that.

Is there any documentation which is complete and proofread?

On Tue, 3 Feb 2026 at 23:16, Denis Kudriashov dionisiydk@gmail.com
wrote:

Yes. There is nice help presenter in the Pharo:

StRewriterHelpBrowserPresenter new open

<Screenshot 2026-02-03 at 10.15.45.png>

вт, 3 февр. 2026 г. в 01:36, Richard O'Keefe raoknz@gmail.com:

Is the "classic" rewriting syntax documented anywhere?

On Mon, 2 Feb 2026 at 22:52, Denis Kudriashov via Pharo-users <
pharo-users@lists.pharo.org> wrote:

Hi all.

This is the release of BPatterns project, one of my old ideas on
how to make the rewrite engine usable for scripting.

As a quick reminder, here is an example of the classic rewrite-engine
matching syntax:

@receiver isNil ifTrue: @nilBlock

In practice, patterns like this usually live inside string
literals—hidden away in lint rules, deprecations, or refactorings.
To use them for manual code search or rewriting, you typically
need a dedicated tool.

Now compare that with the same pattern expressed as a BPattern:

[ any isNil ifTrue: anyBlock ] bpattern

No special syntax.
No magical tools.
Just pure Smalltalk.

You write a block.
You send #bpattern.
You’re done.

Every editor understands it.
Every tool respects it.

Want to see where this pattern appears?

  • [ any isNil ifTrue: anyBlock ] bpattern browseUsers*

<Screenshot 2026-01-31 at 12.16.19.png>

Want to rewrite all of them?

[[ any isNil ifTrue: anyBlock ] -> [ any ifNil: anyBlock ]] brewrite
preview

<Screenshot 2026-01-31 at 12.17.57.png>

Because BPatterns are real Smalltalk code, all development tools
work out of the box:
syntax highlighting, completion, navigation, refactorings.

This is the rewrite engine treated as a first-class citizen.

Not strings.
Not tooling sidecars.
Not just for advanced users.

A rewrite engine you can actually use.

And follow the project on GitHub:

- https://github.com/dionisiydk/BPatterns


-
Hi Eliot. Yes, the recursive mode is default in BPatterns. I wonder when we do not need it пн, 9 февр. 2026 г., 13:45 Eliot Miranda <eliot.miranda@gmail.com>: > > > On Feb 9, 2026, at 2:03 AM, Denis Kudriashov <dionisiydk@gmail.com> wrote: > >  > Hi Eliot. > > The recursive mode is per pattern variable. It can be done globally of > course in a way you suggested. But I do not see much value from this. > > Do you have an example where we don't want the non recursive search? > > > Yes. When I refactored the VM to make the object memory/garbage collector > an instance variable of the interpreter, rather than the superclass of the > interpreter, this major refactoring needed to be recursive. > > > ср, 4 февр. 2026 г., 01:16 Eliot Miranda <eliot.miranda@gmail.com>: > >> Hi Denis, >> >> could you support single & double ticks/non-recursive & recursive >> modes by providing eg shallowBpattern and bpattern? >> >> >> > P.S. > > Also why bpattern and not bPattern or rewritePattern? >> > > > _,,,^..^,,,_ (phone) >> >> On Feb 3, 2026, at 10:41 AM, Denis Kudriashov <dionisiydk@gmail.com> >> wrote: >> >>  >> Hi Richard. >> >> I checked the code and the double backticks are for the recursion mode. >> It forces the search to dive into the current matching node to find more >> cases inside it. >> For example: >> >> (instVar isNil ifTrue: [ 'inside recursion' ]) isNil ifTrue: [ 'outer >> node' ] >> >> The syntax with single backtick will not find the internal "instVar >> isNil" expression. >> >> In BPatterns the recursion mode is enabled by default for the pattern >> variables. So the default mode covers the maximum scope for a search. >> Currently you can't not disable the #recurseInto flag as there is not >> suitable accessor for this. But if it would be there the pattern would like: >> >> [ anyVar isNil ifTrue: anyBlock ] bpattern with: [ anyVar ] -> [:pattern >> | pattern recurseInto: false ] >> >> >> Anyway I adjusted my blog accordingly. Thanks for the attention. >> >> вт, 3 февр. 2026 г. в 10:47, Richard O'Keefe <raoknz@gmail.com>: >> >>> Thank you. One of the reasons given for introducing BPatterns is a >>> subtle difference between >>> single backticks and double backticks, which is mentioned but not >>> explained in the BPatterns >>> blog entry. The help screen you directed me to does not explain that. >>> >>> Is there any documentation which is *complete* and *proofread*? >>> >>> On Tue, 3 Feb 2026 at 23:16, Denis Kudriashov <dionisiydk@gmail.com> >>> wrote: >>> >>>> Yes. There is nice help presenter in the Pharo: >>>> >>>> StRewriterHelpBrowserPresenter new open >>>> >>>> >>>> <Screenshot 2026-02-03 at 10.15.45.png> >>>> >>>> >>>> >>>> вт, 3 февр. 2026 г. в 01:36, Richard O'Keefe <raoknz@gmail.com>: >>>> >>>>> Is the "classic" rewriting syntax documented anywhere? >>>>> >>>>> On Mon, 2 Feb 2026 at 22:52, Denis Kudriashov via Pharo-users < >>>>> pharo-users@lists.pharo.org> wrote: >>>>> >>>>>> Hi all. >>>>>> >>>>>> This is the release of *BPatterns* project, one of my old ideas on >>>>>> how to make the rewrite engine usable for scripting. >>>>>> >>>>>> As a quick reminder, here is an example of the classic rewrite-engine >>>>>> matching syntax: >>>>>> >>>>>> *``@receiver isNil ifTrue: ``@nilBlock* >>>>>> >>>>>> >>>>>> In practice, patterns like this usually live inside string >>>>>> literals—hidden away in lint rules, deprecations, or refactorings. >>>>>> To use them for *manual* code search or rewriting, you typically >>>>>> need a dedicated tool. >>>>>> >>>>>> Now compare that with the same pattern expressed as a *BPattern*: >>>>>> >>>>>> *[ any isNil ifTrue: anyBlock ] bpattern* >>>>>> >>>>>> No special syntax. >>>>>> No magical tools. >>>>>> Just pure Smalltalk. >>>>>> >>>>>> You write a block. >>>>>> You send #bpattern. >>>>>> You’re done. >>>>>> >>>>>> Every editor understands it. >>>>>> Every tool respects it. >>>>>> >>>>>> Want to see where this pattern appears? >>>>>> >>>>>> * [ any isNil ifTrue: anyBlock ] bpattern browseUsers* >>>>>> >>>>>> >>>>>> <Screenshot 2026-01-31 at 12.16.19.png> >>>>>> >>>>>> >>>>>> Want to rewrite all of them? >>>>>> >>>>>> *[[ any isNil ifTrue: anyBlock ] -> [ any ifNil: anyBlock ]] brewrite >>>>>> preview* >>>>>> >>>>>> >>>>>> <Screenshot 2026-01-31 at 12.17.57.png> >>>>>> >>>>>> Because *BPatterns are real Smalltalk code*, all development tools >>>>>> work out of the box: >>>>>> syntax highlighting, completion, navigation, refactorings. >>>>>> >>>>>> This is the rewrite engine treated as a *first-class citizen*. >>>>>> >>>>>> Not strings. >>>>>> Not tooling sidecars. >>>>>> Not just for advanced users. >>>>>> >>>>>> *A rewrite engine you can actually use.* >>>>>> * A rewrite engine at your fingertips.* >>>>>> More details are in the blog post: >>>>>> >>>>>> - >>>>>> https://dionisiydk.blogspot.com/2026/02/bpatterns-rewrite-engine-with-smalltalk.html >>>>>> >>>>>> And follow the project on GitHub: >>>>>> >>>>>> - https://github.com/dionisiydk/BPatterns >>>>>> >>>>>> >>>>>> - >>>>>> >>>>>>