我正在尝试替换AST中的所有类型。 使用m3模型分析Java语言; the simplest example
如果我们采用以下代码:
Int a = 1;
例如,我能够将1的类型更新为void。 但是我无法更改变量本身的类型。
我提供了一些示例行。 有人能够指出行中的错误吗?
case \method(Type \return, str name, list[Declaration] parameters, list[Expression] exceptions)
=> \method(\int(), "funcHolder", parameters, exceptions)
case \type(Type \type) => \void()
case \type => \void
答案 0 :(得分:1)
好的,很好的问题。首先,您的代码及其可能存在的错误:
这看起来不错:
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不在当前范围内,则此匹配任何字面值。但是可能在某个地方有一个称为\ type的函数或一个变量或其他内容,因此此模式测试与范围内的其他内容是否相等。很讨厌!它不会与我猜到的任何东西匹配。顺便说一句,我们正在计划一项针对语言更改的“大规模修改提案”,以避免在模式范围内对事物进行此类意外绑定。
从后来的评论中我了解到,目标是用Type
替换AST中void()
的所有实例,以帮助克隆检测模块类型名称。这样做如下:
case Type _ => \void()
我们使用[TypedVariable]模式,其变量名称为_
来匹配代数类型为Type
的任何节点,而忽略了绑定。然后,该节点将被void()
替换。
在没有内容辅助工具进行模式匹配的情况下,我的工作方式如下:
Int a = 1;
_
loc
并单击位置将您带到代码中,以查看是否不是假阳性,从而对系统的其余部分进行测试。例如,我想将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)