Skip to content

Instantly share code, notes, and snippets.

@wayland
Last active February 21, 2025 23:59
XML Infinite Loop bug
#!/usr/bin/raku
use XML;
sub WalkTreeMatch(@inputs) {
my (@retvals);
# Unindented lines were just inserted for debugging, and should be removed later (but see output)
say "-----";
say "inputs count: " ~ @inputs.elems;
say "inputs: " ~ @inputs.raku().substr(0..100);
for @inputs -> $input { # Input nodes in NodeSet
$input ~~ Positional or next;
say "input count: " ~ ($input[]).elems;
say "input: " ~ $input.raku().substr(0..100);
say "input child: " ~ $input[0].raku().substr(0..100);
say "name" ~ $input.^name();
for @$input -> $child { # Children of node from NodeSet
if ($child ~~ Positional) {
WalkTreeMatch($child) ==> @retvals;
} else {
if $child.can('name') {
say "Got to " ~ $child.name;
} else {
say "Got to " ~ $child;
}
}
}
}
return @retvals;
}
# Test on regular array
my (@inputs) = ( ('A',), ('B','C', ('E','F','G', %( 'A' => 'E', 'E' => 'A'))));
WalkTreeMatch(@inputs);
# Test with XML
my ($xmlstring) = qq:to/EOT/;
<rootnode>
<item level="1">
<inner>text</inner>
</item>
</rootnode>
EOT
my ($doc) = from-xml($xmlstring);
WalkTreeMatch($doc.root);
$ ./infinite-loop.raku | head -50
-----
inputs count: 2
inputs: [("A",), ("B", "C", ("E", "F", "G", {:A("E"), :E("A")}))]
input count: 1
input: $("A",)
input child: "A"
nameList
Got to A
input count: 3
input: $("B", "C", ("E", "F", "G", {:A("E"), :E("A")}))
input child: "B"
nameList
Got to B
Got to C
-----
inputs count: 4
inputs: ("E", "F", "G", {:A("E"), :E("A")})
-----
inputs count: 3
inputs: (my \XML::Element_3298568580792 = XML::Element.new(name => "rootnode", nodes => [XML::Text.new(text =
input count: 3
input: (my \XML::Element_3298568580792 = XML::Element.new(name => "rootnode", nodes => [XML::Text.new(text =
input child: (my \XML::Text_3298571614976 = XML::Text.new(text => "\n\t", parent => (my \XML::Element_329856858079
nameXML::Element
-----
inputs count: 3
inputs: (my \XML::Element_3298568580792 = XML::Element.new(name => "rootnode", nodes => [XML::Text.new(text =
input count: 3
input: (my \XML::Element_3298568580792 = XML::Element.new(name => "rootnode", nodes => [XML::Text.new(text =
input child: (my \XML::Text_3298571614976 = XML::Text.new(text => "\n\t", parent => (my \XML::Element_329856858079
nameXML::Element
-----
inputs count: 3
....
@wayland
Copy link
Author

wayland commented Feb 21, 2025

Hi all!

I'm using the XML library for Raku, and think I've found a bug. The infinite-loop.raku above is the code, and output.txt is the output of the code.

Context: I'm attempting to make a universal tree-walker that will work with both Raku arrays and XML documents, and hopefully other data structures in future.

You'll note that, for the regular array, it pretty much does what I expected, but for the XML document, I was expecting the recursion to descend to the children, but that isn't happening for some reason; it keeps feeding the root node back into the recursion.

The bug seems to be that when I request the children in a list/array, it keeps putting the parent in a list/array, and then revisiting the parent. Given that I've already fixed some bugs in the XML lib, I'm assuming this is another, but am not sure where to go from here. If someone could give me some assistance, that'd be greatly appreciated.

Thanks!

@wayland
Copy link
Author

wayland commented Feb 21, 2025

To clarify, I'm trying mainly to debug line 19 and maybe also line 5 -- why does line the passing in of the child not result in descent down the XML tree, when it does for the regular tree?

@wayland
Copy link
Author

wayland commented Feb 21, 2025

...no, turns out it's line 17 that I need to debug. It's not pulling the children out of the array for the for loop.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment