1

我想使用 Clair 和 Rascal 重构一些 C 代码。我搜索具有特定名称的函数。如果我找到这样的功能,我想用另一个功能替换它。我需要在四个功能之间进行选择。要选择的函数取决于找到的函数的参数。我需要匹配表达式的根元素。

我可以使用访问模式进行匹配。我试过了

visit(body) {
  case \functionCall(func, args): {
    if ("myName" == func.name.\value) {
      visit(args[0]) {
        case \equals(_, _): println("Equals");
        case \notEquals(_, _): println("Not equals");
      }             
    }
  }
}

这并不能保证我匹配根元素。在 (A != B) == CI 只想匹配 ==

我怎样才能只匹配根元素?

4

2 回答 2

1

您可以任意嵌套模式并使用它来匹配函数调用,包括函数名称和要匹配的第一个参数的形状。

例如:

case functionCall(someId("my name", [e:\equals(_, _), *_]) => newFunctionCall(e)
case functionCall(someId("my name", [e:\notEquals(_, _), *_]) => newFunctionCall(e)

[..]请注意,只要第一个参数是 equals 或 nonEquals 表达式,这里匹配任意长度的参数列表的列表模式。

因此,您可以为第一个参数的每个案例重复一个顶级案例,如上,或嵌套一个开关并使用“插入”,如下所示:

  case functionCall(someId("my name", [arg, *_]) : 
               switch(arg) {
                  case equals(_, _) : insert newFunctionCall(arg);
                  ...
               }

我更喜欢第一种情况,因为它更具声明性。Rascal 应该在内部考虑到常见的东西以提高效率。两种模式非常相似的事实并不是 Rascal 恕我直言的代码异味,因为这就是这段代码的全部意义所在,您希望稍微不同地对待两种相似的模式,第一个示例文档明确地没有嵌套控制流。换句话说:嵌套模式比嵌套控制流更清晰

于 2019-07-08T18:00:45.033 回答
0

我使用此字段,因为评论字段中的空间有限。

我喜欢嵌套模式的这个特性,但我没有得到匹配的简单大小写。我尝试了以下模式:

    visit(body) {
        case \functionCall("methodA", [arg, *_]): println("match");
        case \functionCall(SomeId("methodA", [arg, *_])): println("match");
        case \functionCall(SomeId("methodA"), [arg, *_]): println("match");
        case \functionCall(IdExpresssion("methodA", [arg, *_])): println("match");
        case \functionCall(IdExpresssion("methodA"), [arg, *_]): println("match");
        case \functionCall(name("methodA", [arg, *_])): println("match");
        case \functionCall(name("methodA"), [arg, *_]): println("match");
    }

iprint(body) 给出以下结果:

compoundStatement(
  [
    compoundStatement(
      [
        expressionStatement(
.... some expressions and declarations
        for(
... for statement
          compoundStatement(
            [
... inside for loop
              expressionStatement(
                functionCall(
                  idExpression(
                    name(
                      "methodA",
                      src=|project://Instrumentation/example.c|(11195,10)),
                    src=|project://Instrumentation/example.c|(11195,10),
                    decl=|cpp+problem://Attempt%20to%20use%20symbol%20failed:%20methodA|,
                    typ=problemType("Failure to determine type of expression")),
                  [equals(
                      idExpression(
                        name(
                          "beforeTest",
                          src=|project://Instrumentation/example.c|(11207,20)),
                        src=|project://Instrumentation/example.c|(11207,20),
                        decl=|cpp+variable:///test1()/beforeTest|,
                        typ=problemType("Type depends on an unresolved name")),
                      idExpression(
                        name(
                          "afterTest",
                          src=|project://Instrumentation/example.c|(11231,19)),
                        src=|project://Instrumentation/example.c|(11231,19),
                        decl=|cpp+variable:///test1()/afterTest|,
                        typ=problemType("Type depends on an unresolved name")),
                      src=|project://Instrumentation/example.c|(11207,43),
                      typ=problemType("Type depends on an unresolved name"))],
                  src=|project://Instrumentation/example.c|(11195,57),
                  typ=problemBinding()),
                src=|project://Instrumentation/example.c|(11195,58)),
              expressionStatement(
... more expressions and declaratios in for loop              
  ],
  src=|project://Instrumentation/example.c|(10148,1349))ok

如何制作与 MethodA 匹配的模式?

于 2019-07-12T06:31:17.090 回答