When the original version of multi-root patterns was reviewed, several improvements were made to the pdl_interp operations during the review process. Specifically, the "get users of a value at the specified operand index" was split up into "get users" and "compare the users' operands with that value". The iterative execution was also cleaned up to pdl_interp.foreach. However, the positions in the pdl-to-pdl_interp lowering were not similarly refactored. This introduced several problems, including hard-to-detect bugs in the lowering and duplicate evaluation of pdl_interp.get_users.
This diff cleans up the positions. The "upward" OperationPosition was split-out into UsersPosition and ForEachPosition, and the operand comparison was replaced with a simple predicate. In the process, I fixed three bugs:
- When multiple roots were had the same connector (i.e., a node that they shared with a subtree at the previously visited root), we would generate a single foreach loop rather than one foreach loop for each such root. The reason for this is that such connectors shared the position. The solution for this is to add root index as an id to the newly introduced ForEachPosition.
- Previously, we would use pdl_interp.get_operands indiscriminately, whether or not the operand was variadic. We now correctly detect variadic operands and insert pdl_interp.get_operand when needed.
- In certain corner cases, we would trigger the "connector has not been traversed yet" assertion. This was caused by not inserting the values during the upward traversal correctly. This has now been fixed.