What exactly does the outermost visit strategy do in Rascal? - visitor-pattern

I wrote the below Rascal code that is supposed to build a tree out of a map from node names to nodes, starting at the node mapped from "top". It should repeatedly replace the children of all nodes that have strings as children in result by the nodes nodeMap maps them to, until nothing changes anymore (fixpoint).
getNode returns the node a map[str,node] maps it to, or the key itself if it is not present as a key in the map. This works fine, as proves the fact that other code at the bottom of this question does work. However, the code directly below seems to run infintely even on very small inputs.
node nodeMapToNode(map[str, node] nodeMap) {
node result = nodeMap["top"];
return outermost visit(result) {
case node n: {
if ([*str children] := getChildren(n)) {
insert makeNode(getName(n), [getNode(child, nodeMap) | child <- children]);
}
}
}
}
The following code does work and returns in an instant on small inputs as I expected. This is, however, exactly what I understood outermost-visiting should do from what I understood from the Rascal tutor.
Can anyone explain to me what the difference between these code snippets is (besides the way they are written) and what I thus misunderstood about the effect of outermost visit? Also, I'd like to know if a shorter and/or nicer way to write this code - using something like outermost-visiting instead of writing the fixpoint by hand - does exist.
node nodeMapToNode(map[str, node] nodeMap) {
node result = nodeMap["top"];
node lastResult;
do {
lastResult = result;
result = visit(lastResult) {
case node n: {
if ([*str children] := getChildren(n)) {
insert makeNode(getName(n),
[getNode(child, nodeMap) | child <- children]);
}
}
}
} while (result != lastResult);
return result;
}

What is outermost?
The rascal tutor is very compact in it's explanation but let's start from there.
repeat a top-down traversal as long as the traversal changes the resulting value (compute a fixed-point).
which in rascal terms means that this:
r = outermost visit(x) {
case str s => s + "."
when size(s) < 3
};
is syntactic sugar for:
r = x;
solve(r) {
r = top-down visit(r) {
case str s => s + "."
when size(s) < 3
};
}
I think there are two common cases were outermost/innermost makes sense:
your replacement should be repeated multiple times on the same node
your replacement generate new nodes that match other patterns
Your specific example
Regarding the example in your question. The other manually rewritten outermost is actually an innermost. The default visit strategy is bottom-up.
In general, an bottom-up visit of the tree is a quicker than a top-down. Especially when you are rewriting it, since Rascal is immutable, building a new tree bottom-up is quicker.
So, perhaps replace your code with an innermost visit instead of an outermost?

Related

opengl assimp skeletal node transformation

if i have a setup where in order to transform a bone, I have to:
node.transform = scale(node.transform, 2, 2, 2)
then
bone_transform = inverse:offset_matrix *
(node.parent.transform * node.transform) * (inverse:node.parent.transform) * offset_matrix
However this only works properly for bones that doesn't have any children (or the bottom-most in the node hierarchy)..
therefore having trouble when traversing through the bones part..
how would I do this correctly to get the correct bone_transform for all bones..
So if I want to transform any bone anywhere in the hierarchy (using node.transform), it would also adjust all its children bone_transforms correctly..
maybe something like:
mat4 transform = node.transform
while (node.parent != 0) {
if (node.is_bone) {
transform = node.parent.transform * node.transform
}
node = node.parent
}
or something with node.children recursively?
The offset-matrix is already the global transformation for your bone. It contains already all the transformation data from the root down to your current bone.
That is the reason that your code only works for bones without any parent nodes.

Store values that are created in a loop outside of the loop in rust

I am working on a little parser that takes an S-Expression and transforms it into a tree data structure. Since trees are not so easy in Rust to do bidirectional I want to make it only one-directional (each node only knows it's children, not it's parents). To still be able to access nodes that have been created in the past, I want to store all nodes in a Vector and keep an index that tells me which node is where. E.g. a node would have a field parent_index, with the index of it's parent node in the vector, without needing to have a direct reference to it.
So, while I iterate over the String that is my s-expression, I am creating new nodes and want to push them into the vector, as well as assigning child relationships.
for clarifications an S-Expression can be this (w1 (w2 t1) (w3 t2)) or something like this (S (F (FIRSTWORD This) (SECONDWORD is)) (Z (THIRDWORD a) (FOURTHWORD sentence))), or just a terminal like Hello
A lot is still missing but my idea looks like this. My question now is: How can I create all these Trees inside the loop and store them into the vector outside of the loop?
It seems that the borrow checker has some probelems with this...
I am very grateful for any help! Thank you :)
My idea looks like this:
pub struct Tree{
pub root: String,
pub children: Vec<Tree>
}
fn parse_to_tree(mut s_expr: String) -> Tree{
// Vector for all nodes
let mut all_nodes:Vec<&Tree> = Vec::new();
// Index of node we are working on
let mut curr_node_index = 0;
while !s_expr.is_empty(){
// get first char from s expression
let mut c_c = s_expr.remove(0);
//Names: c_c: current_char, c_w: current:word
// only continue if we start with '(', otherwise Leaf
while c_c == '('{
let mut c_w = String::from("");
while c_c != ' '{
c_c = s_expr.remove(0);
c_w.push(c_c);
}
println!("{}", c_w);
let node = Tree{root: c_w, children: Vec::new()};
//Here I want to push the node by reference to the all_nodes_vector
all_nodes.push(&node); // HERE occurs the error: borrowed value does not live long enough...
if !all_nodes.is_empty(){
// Here I want to to push the new node as a child to the old current_node
all_nodes[curr_node_index].children.push(node);
}
curr_node_index += 1;
}
return Tree{root: s_expr, children: Vec::new()};
}
return Tree{root: s_expr, children: Vec::new()};
}
You cannot do that (safely): someone, somewhere, while building this tree, will have to hold both a node and the list of nodes that contains this node. And (at least) the reference to the node will be mutable (because we need to build it), causing a violation of the borrow rules.
The solution is simple: just give up on using references. Store all nodes in a vector, and only keep indices to this vector. This is easy, effective and idiomatic.

How does ng-repeat work?

I dissected ng-repeat and extracted the code blocks attached, seeing that these comprise the logic that handles the repeating algorithm (which I want to understand how it works).
I have quite a few questions, but since they are all about the internals of ng-repeat I chose to ask them all here. I don't see any reason to separate them into different SO questions. I have marked inline to which line(s) of code each question refers to.
Why do they need to make sure that trackById is not the native hasOwnProperty function? (that's what that assertNotHasOwnProperty function does, part of Angular's internal API)
As far as my intuition go, this code executes on items already in the repeater, when it has to update the collection - it just picks them up and pushes them into the list for processing, right?
This code block obviously looks for duplicates in the repeater collection. But how exactly does it do that is beyond me. Please explain.
Why does Angular have to store the block object both nextBlockMap and in nextBlockOrder?
What are block.endNode and block.startNode?
I assume the answer to the above question will clarify how this algorithm work, but please explain why it has to check if the nextNode has (been) '$$NG_REMOVED'?
What happens here? Again, I assume question 6 will already provide an answer to this one. But still pointing that out.
Like I said, I dug through ng-repeat to find the code I deemed relevant to the repeating mechanism. Plus, I do understand the rest of the directive. So without further ado, here is the code (from v1.2.0):
length = nextBlockOrder.length = collectionKeys.length;
for (index = 0; index < length; index++) {
key = (collection === collectionKeys) ? index : collectionKeys[index];
value = collection[key];
trackById = trackByIdFn(key, value, index);
// question #1
assertNotHasOwnProperty(trackById, '`track by` id');
// question #2
if (lastBlockMap.hasOwnProperty(trackById)) {
block = lastBlockMap[trackById];
delete lastBlockMap[trackById];
nextBlockMap[trackById] = block;
nextBlockOrder[index] = block;
// question #3
} else if (nextBlockMap.hasOwnProperty(trackById)) {
// restore lastBlockMap
forEach(nextBlockOrder, function(block) {
if (block && block.startNode) lastBlockMap[block.id] = block;
});
// This is a duplicate and we need to throw an error
throw ngRepeatMinErr('dupes', "Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}",
expression, trackById);
// question #4
} else {
// new never before seen block
nextBlockOrder[index] = { id: trackById };
nextBlockMap[trackById] = false;
}
}
for (index = 0, length = collectionKeys.length; index < length; index++) {
key = (collection === collectionKeys) ? index : collectionKeys[index];
value = collection[key];
block = nextBlockOrder[index];
// question #5
if (nextBlockOrder[index - 1]) previousNode = nextBlockOrder[index - 1].endNode;
if (block.startNode) {
// if we have already seen this object, then we need to reuse the
// associated scope/element
childScope = block.scope;
// question #6
nextNode = previousNode;
do {
nextNode = nextNode.nextSibling;
} while(nextNode && nextNode[NG_REMOVED]);
if (block.startNode != nextNode) {
// existing item which got moved
$animate.move(getBlockElements(block), null, jqLite(previousNode));
}
previousNode = block.endNode;
} else {
// new item which we don't know about
childScope = $scope.$new();
}
// question #7
if (!block.startNode) {
linker(childScope, function(clone) {
clone[clone.length++] = document.createComment(' end ngRepeat: ' + expression + ' ');
$animate.enter(clone, null, jqLite(previousNode));
previousNode = clone;
block.scope = childScope;
block.startNode = previousNode && previousNode.endNode ? previousNode.endNode : clone[0];
block.endNode = clone[clone.length - 1];
nextBlockMap[block.id] = block;
});
}
}
lastBlockMap = nextBlockMap;
After some tinkering with the directive, I became familiar with ng-repeaters code, and managed to answer some of my questions. I highlighted in bold the things I couldn't yet figure out on my own, and would appreciate if anyone could shed some light on the bold parts:
The ID is tested for hasOwnProperty, because they use that method to check whether the ID is present in the iteration objects (lastBlockMap, nextBlockMap) (this process explained below). I couldn't find out on what scenario this can actually happen, however.
I was correct in my assumption. nextBlockMap contains all items that will be transcluded on the current model change. lastBlockMap contains everything from the previous model update. It used for finding duplicates in the collection.
OK, this one is pretty straightforward actually. In this for loop, ng-repeat fills up nextBlockMap with items from lastBlockMap. Looking at the order of ifs, it's easy to see that if the item cannot be found in lastBlockMap, but it is already present in nextBlockMap (meaning, it was already copied there from lastBlockMap, and therefore its trackById appears twice in the collection) - it's a duplicate. What the forEach does is simply run through all initialized items in nextBlockMap (blocks that have a startNode property) and push their ID back into lastBlockMap. I cannot however understand why this is necessary.
The only reason I could find for separating nextBlockOrder (all trackByIds in an array) from nextBlockMap (all block objects in a trackById hash), is this line, which working with an array makes it an easy and simple operation: if (nextBlockOrder[index - 1]) previousNode = nextBlockOrder[index - 1].endNode;. It is explained in the answers to question 5 and 6:
block.startNode and block.endNode are the first and last DOM nodes in the block belonging to an item in the collected being repeated. Therefore, this line here sets previousNode to reference the last DOM node of the previous item in the repeater.
previousNode is then used as the first node, in a loop that checks how the DOM changed when items have been moved around or removed from the repeater collection - again, only in case we are not working with the first block in the array.
This is easy - it initializes the block - assigning the $scope and startNode and endNode for later reference, and saves everything in nextBlockMap. The comment created right after the cloned element, is there to guarantee we always have an endNode.

Merge two binary trees in C

I am trying to merge two binary trees and this is what I have come up with. I believe that my Insertmerge functions are correct as well as my and merge functions work...I am having trouble with my merge helper. I need to do is post order, left then right, but I am not sure if what I am doing makes sense. Any thoughts?
SparseNode * mergehelper(SparseNode* C_array_1, SparseNode * array_2)
{
if(array_2 ==NULL)
{
return(C_array_1);
}
C_array_1= SparseArray_InsertMerge(C_array_1, ((array_2->left)->index),((array_2->left)-
>value));
C_array_1= SparseArray_InsertMerge(C_array_1, ((array_2->right)->index),((array_2->right)->value));
}
SparseNode* SparseArray_InsertMerge(SparseNode * array, int index, int value)
{
check(array);
if(array ==NULL)
{
return SparseNode_create(index, value);
}
if((array->index)==index)
{
if(array->value == -value)
array= SparseArray_remove (array, array->index);
else
array->value += value;
check(array);
return array;
}
if((array->index)>index)
{
array->left = SparseArray_insert(array->left, index, value);
}
if((array->index)<index)
{
array->right = SparseArray_insert(array->right, index, value);
}
check(array);
return array;
}
/*
post order traversal
new insert for merge
adapt for nonoverwriting
do a tree traversal
then add the node into the copied list in the work of the tree traversal
in merge. copy array1. call mergehelper with copy.
in helper. if null return, then insert left and insert right. print function is similiar
*/
SparseNode * SparseArray_merge(SparseNode * array_1, SparseNode * array_2)
{
SparseNode*Arr1_copy = copy(array_1);
Arr1_copy = mergehelper(Arr1_copy, array_2);
return (Arr1_copy);
}
The easiest way to merge two binary trees is to simply use the functionality that the trees already provide:
a traversal, extracting the values.
a means of inserting values.
So the solution then becomes (pseudo-code):
def mergeTrees (tree1, tree2):
valuePtr = tree2.getFirst();
while valuePtr != NULL:
tree1.addNode (valuePtr->value)
valuePtr = tree2.getNextAfter (valuePtr)
Following that, tree1 will then be a merge of the two trees and you can do what you want with tree2.
Now that's the basic idea - you may want to handle things like duplicate removal or error conditions, but it should be a good enough start to get you going. There's often little point in using the internals of a data structure when the published interface gives you a cleaner way.

Loops' iterating in ANTLR

I'm trying to make a Pascal interpreter using ANTLR and currently have some troubles with processing loops while walking the AST tree.
For example for loop is parsed as:
parametricLoop
: FOR IDENTIFIER ASSIGN start = integerExpression TO end = integerExpression DO
statement
-> ^( PARAMETRIC_LOOP IDENTIFIER $start $end statement )
;
(variant with DOWNTO is ignored).
In what way can I make walker to repeat the loop's execution so much times as needed? I know that I should use input.Mark() and input.Rewind() for that. But exactly where should they be put? My current wrong variant looks so (target language is C#):
parametricLoop
:
^(
PARAMETRIC_LOOP
IDENTIFIER
start = integerExpression
{
Variable parameter = Members.variable($IDENTIFIER.text);
parameter.value = $start.result;
}
end = integerExpression
{
int end_value = $end.result;
if ((int)parameter.value > end_value) goto EndLoop;
parametric_loop_start = input.Mark();
}
statement
{
parameter.value = (int)parameter.value + 1;
if ((int)parameter.value <= end_value)
input.Rewind(parametric_loop_start);
)
{
EndLoop: ;
}
;
(Hope everything is understandable). The condition of repeating should be checked before the statement's first execution.
I tried to play with placing Mark and Rewind in different code blocks including #init and #after, and even put trailing goto to loops head, but each time loop either iterated one time or threw exceptions like Unexpected token met, for example ':=' (assignement). I have no idea, how to make that work properly and can't find any working example. Can anybody suggest a solution of this problem?
I haven't used ANTLR, but it seems to me that you are trying to execute the program while you're parsing it, but that's not really what parsers are designed for (simple arithmetic expressions can be executed during parsing, but as you have discovered, loops are problematic). I strongly suggest that you use the parsing only to construct the AST. So the parser code for parametricLoop should only construct a tree node that represents the loop, with child nodes representing the variables, conditions and body. Afterwards, in a separate, regular C# class (to which you provide the AST generated by the parser), you execute the code by traversing the tree in some manner, and then you have complete freedom to jump back and forth between the nodes in order to simulate the loop execution.
I work with ANTLR 3.4 and I found a solution which works with Class CommonTreeNodeStream.
Basically I splitted off new instances of my tree parser, which in turn analyzed all subtrees. My sample code defines a while-loop:
tree grammar Interpreter;
...
#members
{
...
private Interpreter (CommonTree node, Map<String, Integer> symbolTable)
{
this (new CommonTreeNodeStream (node));
...
}
...
}
...
stmt : ...
| ^(WHILE c=. s1=.) // ^(WHILE cond stmt)
{
for (;;)
{
Interpreter condition = new Interpreter (c, this.symbolTable);
boolean result = condition.cond ();
if (! result)
break;
Interpreter statement = new Interpreter (s1, this.symbolTable);
statement.stmt ();
}
}
...
cond returns [boolean result]
: ^(LT e1=expr e2=expr) {$result = ($e1.value < $e2.value);}
| ...
Just solved a similar problem, several points:
Seems you need to use BufferedTreeNodeStream instead of CommonTreeNodeStream, CommonTreeNodeStream never works for me (struggled long time to find out)
Use seek seems to be more clear to me
Here's my code for a list command, pretty sure yours can be easily changed to this style:
list returns [Object r]
: ^(LIST ID
{int e_index = input.Index;}
exp=.
{int s_index = input.Index;}
statements=.
)
{
int next = input.Index;
input.Seek(e_index);
object list = expression();
foreach(object o in (IEnumerable<object>)list)
{
model[$ID.Text] = o;
input.Seek(s_index);
$r += optional_block().ToString();
}
input.Seek(next);
}

Resources