我正在用 Go 编写一个解释器,我正在寻找存储 AST 的惯用方法。我阅读了 Go 编译器源代码,似乎他们使用带有空方法的接口来表示 AST。例如,我们有以下层次结构,
Object
--Immovable
----Building
----Mountain
--Movable
----Car
----Bike
这就是以“空方法”方式实现上述层次结构的方式。
type Object interface {
object()
}
type Immovable interface {
Object
immovable()
}
type Building struct {
...
}
type Mountain struct {
...
}
type Movable interface {
Object
movable()
}
type Car struct {
...
}
type Mountain struct {
...
}
func (*Building) object() {}
func (*Mountain) object() {}
func (*Car) object() {}
func (*Bike) object() {}
func (*Building) immovable() {}
func (*Mountain) immovable() {}
func (*Car) movable() {}
func (*Bike) movable() {}
上面的代码是一个人为的例子,这就是 Go 编译器如何使用数十个空方法实现AST。但为什么?注意定义了多少空方法。随着层次结构深度的增加,它可能会变得非常复杂。
注释中指出,空方法不允许分配不兼容的类型。例如,在我们的示例中,*Car不能将 a 分配给 a *Immovable。
这在支持继承的其他语言(如 C++)中非常容易。我想不出任何其他方式来表示 AST。
Go 编译器 AST 的实现方式可能是惯用的,但不是不那么直接吗?
芜湖不芜
相关分类