I don’t know Rhino specifically, so I don’t know if he offers specific help for this. But in general, you can directly do it yourself by tracking the changes you make as “anti-changes.” This scheme works for any AST system, and not just for rhinos.
A tree consists of nodes and the relationship between a node and its children.
To build a tree, you can execute commands to create a node, create its children and bind them together. Of course, the Rhino API offers primitive support for this.
To rebuild the tree at a later time, we simply compile a list of actions to perform based on the node construct and the child join / disconnect.
Imagine the following tree:
1:*
/ \
2:+ 3:[]
/ \ / \
4:x 5:17 6:a 7:i
n: t, n - node, t - node. node 1, 2,...
( "" ) , 2: + node 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] ]
"" , .
; . , tree-mutate-and-remember-inverse, ,
fn disconnect_and_remember_inverse(node,child) {
push(undo_list,[connect,node,child,nth_child(node,child)]);
disconnect(node,child);
}
"", node, , ,
node "":
[ [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; , , , ign_inverse . ;
.
, . ( JavaScript, , ).