更新不可变AST的最简单方法是什么?

时间:2012-07-09 15:10:18

标签: scala macros abstract-syntax-tree scala-2.10

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

Literal(Constant(1))

值为:

Literal(Constant(2))

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

2 个答案:

答案 0 :(得分:3)

答案 1 :(得分: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中,有几个ported examples