- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在为 JavaScript 实现一个突变测试工具。修改 AST 并针对修改后的代码执行测试用例。运行测试用例后,我想将修改后的 AST 恢复为原始 AST,以便我可以重复变异过程。但是,我不知道如何恢复它。有帮助吗?
最佳答案
我不是特别了解 Rhino,所以我不知道它是否为此提供了特定的帮助。但总的来说,您可以直接自己做,通过跟踪您所做的更改,作为“反更改”。该方案适用于任何 AST 系统,而不仅仅是 Rhino。
树由节点以及节点与其子节点之间的关系组成。
要构造一棵树,您可以执行创建节点、创建其子节点并将它们链接在一起的命令。当然,Rhino API 对此提供了原始支持。
为了稍后重新构建树,我们只需根据节点构建和子节点连接/断开列出要完成的操作列表。
想象一下下面的树:
1:*
/ \
2:+ 3:[]
/ \ / \
4:x 5:17 6:a 7:i
我已将节点标记为 n:t,其中 n 是节点编号,t 是节点类型或文字值。我们将节点的子节点从左到右编号为 1, 2, ...
现在我们通过将 2:+ 替换为新节点 8:mod 并将 5:17 替换为 9:j 来修改(“变异”)树。我们为此采取的行动是抽象的,顺序是:
disconnect(2,1); // disconnect node N from its Mth child
disconnect(2,2);
disconnect(1,1);
delete(2);
delete(5);
n1=create(mod); // node 8
n2=create(j); // node 9
connect(1,1,n1); // connect node 1 child 1 to n1
connect(n1,1,4);
connect(n1,2,n2);
我们在(事务)“撤消”列表中以相反的顺序记录逆向操作,以便稍后处理:
[ [disconnect,n1,2],
[disconnect,n1,1],
[disconnect,1,1],
[delete,n2],
[delete,n1],
[create,n5,17],
[create,n2,+],
[connect,1,1,n2],
[connect,2,2,n5],
[connect,2,1,4] ]
这个列表可以通过按顺序遍历元素并简单地用一个简单的解释器做元素所说的来“执行”。
而且它很容易构建;对于每个树变异操作,我们将一个新的逆操作推到撤消列表的前面。我们可以通过用树变异和内存逆操作替换我们的树变异操作来使这变得容易,例如,
fn disconnect_and_remember_inverse(node,child) {
push(undo_list,[connect,node,child,nth_child(node,child)]);
disconnect(node,child);
}
在使用“删除”操作的地方,逆运算将重新创建相应的节点类型,或者,如果您总是恢复树,只是不要删除节点并将其记住在“撤消”列表中:
[ [disconnect,n1,2],
[disconnect,n1,1],
[disconnect,1,1],
[delete,n2],
[delete,n1],
// [create,n5,17],
// [create,n2,+],
[connect,1,1,2],
[connect,2,2,5],
[connect,2,1,4] ]
这可能会给您带来麻烦的地方是 Rhino 实现的复合树粉碎操作;您显然希望这些操作调用这些 remember_inverse 过程。那可能不方便;你会必须使用您自己的等效程序复制这些程序。
留给读者的细节和微妙之处。 (我也不是 JavaScript 编码员,所以请原谅我犯下的任何语法错误)。
关于javascript - Rhino - 有没有办法在不重新解析代码的情况下将修改后的 AST 恢复为原始 AST?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35251630/
我是一名优秀的程序员,十分优秀!