好的,很好的问题。首先是您的代码及其可能存在的错误:
这看起来不错:
case \method(Type \return, str name, list[Declaration] parameters, list[Expression] exceptions)
=> \method(\int(), "funcHolder", parameters, exceptions)
定义是:data Declaration = \method(Type \return, str name, list[Declaration] parameters, list[Expression] exceptions, Statement impl);(参见here),您的代码完全遵循定义。您已解析的 AST 中的每个 abstract 方法声明都将与此匹配,因为对于带有附加参数的主体的方法还有另一个 \method 声明。
可能是您的示例代码中没有抽象方法体,在这种情况下,它什么也不做。
更简单的版本也可以正常工作:
case \method(_, _, parameters, exceptions) => \method(\int(), "funcHolder", parameters, exceptions)
下一个有问题:
case \type(Type \type) => \void()
因为data Expression = \type(Type \type),这是一个Expression 和data Type = \void(),这是一个Type 或data TypeSymbol = \void() 这是一个TypeSymbol,重写不是类型保留,如果 Rascal 编译器会做错事不会检测到这一点。大多数情况下,它可能对您不起作用,因为您的示例代码不包含这种特定类型的表达式。我怀疑它可能是 int.class 和 Integer.class 之类的抽象符号。
那么这个就“有趣”了:
case \type => \void()
原则上,如果 \type 未绑定在当前范围内,则 this 匹配任何内容。但可能有一个名为 \type 的函数或一个变量或某处的东西,因此这个模式测试与范围内的其他东西是否相等。非常讨厌!它与我猜想的任何东西都不匹配。顺便说一句,我们正在为语言更改计划一个“流氓修正提案”,以避免在模式范围内意外绑定事物。
后来从评论中我了解到,目标是用void() 替换AST 中Type 的所有实例,以帮助克隆检测模类型名称。这样做如下:
case Type _ => \void()
我们使用 [TypedVariable] 模式,变量名称为_ 来匹配代数类型Type 的任何节点,并且忘记绑定。然后该节点将替换为void()。
在没有用于模式匹配的内容辅助工具的情况下,我的工作方式如下:
- 找到你想要匹配的东西的完整的一个 AST 例子,比如
Int a = 1;
- 将其复制到 Rascal 源文件中
- 通过引入变量或
_ 来移除你想要抽象的部分
- 对原始示例进行测试
- 通过打印出匹配的
loc 并单击 locs 将您带到代码并查看它是否不是误报,对系统的其余部分进行测试。
例如,我想将Int 重写为void,我在AST 中找到Int 的示例并粘贴:
visit (ast) {
case simpleType(simpleName("Int")) => Type::\void() // I added Type:: to be sure to disambiguate with TypeSymbol::void()
}
附加一些调试代码以打印出所有匹配项:
visit (ast) {
case e:simpleType(simpleName("Int")) => Type::\void()
when bprintln("found a type at <e.src?|unknown:///|>");
}
也许你发现那匹配太多了,你必须变得更具体,所以我们只更改声明Int _ = ....;,我们先举个例子:
\variables(simpleType(simpleName("Int")), [...lots of stuff here...])
然后我们将其简化:
\variables(simpleType(simpleName("Int")), names)
然后将其包含在访问中:
visit (ast) {
case \variables(simpleType(simpleName("Int")), names) => \variables(Type::\void(), names)
}
最后的话,正如您所见,您可以随意嵌套模式,因此任何组合都可以。一个“复杂”的例子:
\variables(/"Int", names)
此模式查找在某处使用名称“Int”作为类型声明的一部分的任何变量声明。这比我们的原版更宽松,可能会比你想象的要多。这只是为了显示您可能想要做的组合。
最后一个例子:查找所有类型名称以“Int”开头但可以以其他任何内容结尾的变量声明,例如“Integer”或“IntFractal”等:
\variables(simpleType(simpleName(/^Int/)), names)