Pharo Smalltalk 的重写引擎(Rewrite Engine)是强大的 AST 变换工具,由 John Brant 和 Don Roberts 于 1997 年引入,用于 Refactoring Browser。它支持精确的模式匹配与替换,但传统语法依赖字符串如 ``@rcv 或`@arg,难以记忆且不利于 IDE 支持:无代码补全、无重构、无浏览器导航。这导致开发者常需复制示例,增加 boilerplate。
BPatterns 库解决了这些痛点,提供声明式 API:直接用普通 Smalltalk 块(block cascades)描述模式与替换,变量以 any 开头自动作为 wildcard(统配任意子树)。核心消息 #bpattern 将块转为 BPattern,支持 #browseUsers 搜索匹配方法;[[matchBlock -> replaceBlock]] brewrite 创建重写规则,支持 #preview 显示变更、#apply 执行。
例如,替换 isNil ifTrue: 为 ifNil::
[ anyRcv isNil ifTrue: anyBlock ] bpattern browseUsers.
[[ anyRcv isNil ifTrue: anyBlock ] -> [ anyRcv ifNil: anyBlock ]] brewrite preview.
这在 DoIt 中即用,无需特殊工具。BPatterns 底层构建 rewrite engine 的 pattern AST,保留原生威力。
为细化模式,用 #with: 级联配置:
[ anyVar isNil ifTrue: anyBlock ] bpattern
with: [ anyVar ] -> [:pat | pat beVariable];
with: [ anyBlock ] -> [:pat | pat beInstVar where: [:var | var name beginsWith: 'temp']].
#with: 参数为块(引用变量)、关联(配置)或符号(选择器)。可用 beInstVar/beLocalVar/beGlobalVar/beUndeclared/beLiteral 等限定变量;beKeyword/beBinary/beUnary 限定消息;where: 添加谓词如 selector beginsWith: 'prim'。
选择器模式天然支持部分匹配:
[ anyRcv anyKeywordPart: anyArg1 staticPart: anyArg2 ] "匹配 at:xxxPart: 等"
[ any anyMessage: anyArg ] bpattern with: #anyMessage: -> [:pat | pat beBinary]. "任意二元运算"
单目 anyMessage 匹配任意消息链(包括关键字 / 二元)。
字面量与全局:
[ any new: anySize ] bpattern
with: [ any ] -> [:pat | pat beGlobalVarWithAny: {Array. OrderedCollection}];
with: [ anySize ] -> [:pat | pat beLiteral].
精确过滤如 beLiteralWithAny: #(nil true false)。
方法级用 #bmethod:
[[ self anyMethod: anyArg ] -> [ anyArg ifNil: [self default]]] bmethod brewrite preview.
匹配整个方法头与体,支持 super anyMessage 等高级场景。
落地参数与清单:
- 安装(Pharo 13/14):
Metacello new baseline: 'BPatterns'; repository: 'github://dionisiydk/BPatterns:main'; load.测试:运行上述示例,确认 #bpattern 在。 - 安全阈值:
- 始终先 #preview,检查变更数 <100,避免大范围。
- 作用域:#browseUsersInClass: Class / #inPackage: 'MyPkg-*',从小包测试。
- 备份:重写前 Iceberg commit;回滚用原规则反向 brewrite。
- 监控点:
步骤 命令 预期 风险阈值 搜索 bpattern browseUsers <500 方法 >1000 缩小 with: 预览 brewrite preview 变更预览无语法错 手动审阅 >10% 执行 brewrite apply 编译成功率 100% 失败 <5% 逐审 测试 跑 suite 通过率 >95% 隔离变更测试 - 常见规则清单:
- 弃用迁移:
[[ self deprecatedSel: arg ] -> [ self newSel: arg ]] brewrite. - 风格统一:
[[ rcv ifTrue: [blk] ] -> [ rcv then: blk ]] brewrite.(ifTrue: → then:) - 性能:
[[ Array new: n ] -> [ Array streamContents: [:s \| s nextPutAll: coll]](避免大 new)。 - 安全:
[ any at: idx ] bpattern with: [idx] -> [:pat \| pat bePositiveIntegerLiteral]查潜在越界。
- 弃用迁移:
在弃用场景,BPatterns 简化 Pharo deprecated: transformWith:,如 Object>>confirm: 可直接用块推导 sender 重写,无字符串重复。
此单一技术点使重写从 “魔法字符串” 转为 “声明式块”,最小 boilerplate,提升团队协作。扩展:集成 Calypso/GToolkit 浏览器,或自定义 where: 谓词。
资料来源:
(正文 1256 字)