5

在使用宏时,我已经到了需要更新 AST 中保持特定条件的那些节点的地步(我一直在努力避免它)。例如,假设我想更新每个节点:

Literal(Constant(1))

价值:

Literal(Constant(2))

这些 AST 节点可能位于表达式树中的任何位置,因此我不能使用 ad-hoc 模式匹配器。显然,我想做的最后一件事是编写一个能够覆盖所有编译器原语的完整模式匹配器。我一直在API中搜索,但我的印象是collecttraversable family 之类的方法不足以满足我的需求,因为它们将树视为线性事物,因此我想要整个更新的树. 那么,是否有可能以一种智能的方式更新不可变的表达式树?为什么标准 API 中不存在这样的“更新”操作?

4

2 回答 2

3

这是在 Scala 宏中使用 AST 转换器的示例:

https://github.com/retronym/macrocosm/blob/171be7e/src/main/scala/com/github/retronym/macrocosm/Macrocosm.scala#L129

于 2012-07-09T18:57:14.507 回答
2

修改数据结构中的多类型节点一般是数据类型泛型的经典案例(通过类型构造函数对代码进行参数化)。

此类操作存在几种方法,例如“Scrap Your Boilerplate”方法,它定义了数据类型通用遍历函数。

在 Haskell 中,节点更新函数在两个维度上进行参数化:按数据类型和按代码——因此您可以将不同的更新函数应用于结构中的任何位置的不同类型:

-- | Apply a transformation everywhere in bottom-up manner
everywhere :: (forall a. Data a => a -> a)
           -> (forall a. Data a => a -> a)

在 Haskell 中这样做很大程度上依赖于类型类。在 Scala 中,有几个移植的示例

于 2012-07-09T15:19:30.093 回答