summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2011-07-07 09:08:23 -0500
committerJesse Luehrs <doy@tozt.net>2011-07-07 09:08:23 -0500
commit19e79470e7b6e4e654520fce7bb02d09caeb8a5e (patch)
tree98753b171a4a0be5b35489aadbb1c880ba4e52a1
parent1172d8b556c93d35aff699eadfc10f93296d7319 (diff)
downloadsmartmatch-engine-core-19e79470e7b6e4e654520fce7bb02d09caeb8a5e.tar.gz
smartmatch-engine-core-19e79470e7b6e4e654520fce7bb02d09caeb8a5e.zip
fix circular data structures
-rw-r--r--lib/smartmatch/engine/core.pm23
1 files changed, 20 insertions, 3 deletions
diff --git a/lib/smartmatch/engine/core.pm b/lib/smartmatch/engine/core.pm
index e172b6c..cad2e5c 100644
--- a/lib/smartmatch/engine/core.pm
+++ b/lib/smartmatch/engine/core.pm
@@ -3,6 +3,7 @@ use strict;
use warnings;
use B;
+use Hash::Util::FieldHash qw(idhash);
use Scalar::Util qw(blessed looks_like_number reftype);
use overload ();
@@ -48,7 +49,7 @@ sub type {
}
sub match {
- my ($a, $b) = @_;
+ my ($a, $b, $seen) = @_;
if (type($b) eq 'undef') {
return !defined($a);
@@ -109,8 +110,15 @@ sub match {
}
elsif (type($a) eq 'Array') {
return unless @$a == @$b;
+ if (!$seen) {
+ $seen = {};
+ idhash %$seen;
+ }
for my $i (0..$#$a) {
- return unless match($a->[$i], $b->[$i]);
+ if (defined($b->[$i]) && $seen->{$b->[$i]}++) {
+ return $a->[$i] == $b->[$i];
+ }
+ return unless match($a->[$i], $b->[$i], $seen);
}
return 1;
}
@@ -121,7 +129,16 @@ sub match {
return grep !defined, @$b;
}
else {
- return grep { match($a, $_) } @$b;
+ if (!$seen) {
+ $seen = {};
+ idhash %$seen;
+ }
+ return grep {
+ if (defined($_) && $seen->{$_}++) {
+ return $a == $_;
+ }
+ match($a, $_, $seen)
+ } @$b;
}
}
elsif (type($b) eq 'Regex') {