Bug resolving pin type?

While trying to update my queue-buffer node, I changed OLD & NEW pins to input-t1 and MEM & oMEM pins to output-t1. If I create two queue-buffer nodes and daisy-chain them together for push, everything works fine if I feed a number into the 1st node:

image

Xod recognizes that all related pins for input & output should be numbers, but when I add an additional link to allow pop, all the pins go back to white and I get a compile error (Can’t deduce types for patch; Connect links or bind values to generic inputs):

image

Adding a generic defer node doesn’t help, but adding a defer(number) does keep pins from turning white, but breaks functionality. Code does work if I use add nodes to add zero between oMEM and OLD of previous queue. This obviously is not going to work if someone wants to build a generic queue patch that uses queue-buffer…

The REALLY weird part is even un-connected queue-buffer nodes are affected. I had an extra queue-buffer node on the page with just a constant-number connected to NEW pin. Even its pins turn white when I create the loop in the other queue-buffer nodes. Since it is not connected to the other buffer-queue nodes, its pin-type should be completely independent…I might want a string queue and a number queue in the same patch…

The queue-buffer node:
image

The problem is in the algorithm XOD uses for type deducing. The generic types are matched by input link types and the traversal is performed in the top-down topo-sorted order. The patch you’ve made contains loops, that is the graph is no longer a DAG and so can’t be toposorted. If a graph can’t be toposorted the deducing algorithm gives up and leaves all pins unresolved. That’s the reason why unlinked nodes affected as well.

So, you need a graph breakpoint: the defer node between queue-buffers. You’ve said it won’t work for you because PUSH/POP pulses will fire “faster” than the memoized output changed. Not sure at 100% but it looks like the issue might be resolved by moving the pair of the bottom defers in queue-buffer implementation to the top. That is, what if defers will guard the input PUSH and POP?

1 Like

The defers at the bottom are only there because MEM & oMEM usually loop back to NEW & OLD. Having them in the queue-buffer removes the need to always add them outside. If we are going to need defers outside anyway, maybe it makes more sense just to remove them from inside the node…

Not sure I understand why having defer (which has generic pins) provides a graph breakpoint when outside my node, but not when inside my node… Doesn’t the graph have to span all inter-connected generic pins to resolve correctly?

The type deducing process does not flattens the graphs. It works on the shallow level where only the patch contents are considered as is. Otherwise, the implementation would be much harder and performance is worse.

I tried moving defer pins outside the queue-buffer node. Now I understand why that creates a graph breakpoint…only the 1st node tied to count knows to use type number. The other two nodes assume string because output is tied to watch node; pins stay white when I delete that link. Current algorithm is not able to traverse multiple generic nodes to determine what type the pin should be.

image

Algorithm determines that defer node should be a number, but 2nd queue-buffer does not resolve to number when it is tied to defer (even though link to it displays as a number).

Even if I force queue-buffer numeric by casting output, it is not able to determine that additional defer node should be numeric. Not sure why one defer node works & the other doesn’t; perhaps because one queue-buffer has type determined by input pin & the other is determined by output pin?

image

It would seem that with the current implementation, it is not possible to create a node with generic pins if a loop for the generic type is required for the algorithm. queue-buffer can still be used with generic pins, but it cannot be incorporated into a node that requires loops without forcing a specific data type within the loops.

UPDATE: I just realized a loop isn’t even needed to cause issues. Just chaining two queue-buffer nodes requires an intermediate node that explicitly sets the data-type in order to set data-type on the second node.

1 Like