2 # ABSTRACT: Test if expressions are logically equivalent
3 # PODNAME: test-logical-equivalence
7 # be sure to escape $ and other special characters from your shell
8 test-logical-equivalence '$a && $b' '$b && $a'
13 * L<Acme::Test::LogicalEquivalence>
18 use warnings FATAL => 'all';
22 use Acme::Test::LogicalEquivalence qw(is_logically_equivalent);
27 Test if two simple expressions are logically equivalent.
29 Exactly two expressions must be given.
31 Example: $0 '\$a || \$b' '\$b || \$a'
32 Remember that you may need to escape special characters like "\$" from your shell.
42 # check for scalars that look like $a or $b
43 for my $varname ($expr =~ /\$([a-z])/g) {
44 my $num = ord($varname) - 97;
45 $highest = $num if $highest < $num;
48 # check for scalars that index $_
49 for my $varname ($expr =~ /\$_\[(\d+)\]/g) {
51 $highest = $num if $highest < $num;
57 my $expr1 = shift or usage;
58 my $expr2 = shift or usage;
60 my $numvars1 = find_num_vars($expr1);
61 my $numvars2 = find_num_vars($expr2);
62 my $num = $numvars1 > $numvars2 ? $numvars1 : $numvars2;
65 print STDERR 'No variables detected. Variables should be one or more of $a, $b, ..., $z', "\n";
69 # convert $a-style vars to $_[0]-style to support more than just $a and $b
70 $expr1 =~ s/\$([a-z])/'$_['.(ord($1) - 97).']'/ge;
71 $expr2 =~ s/\$([a-z])/'$_['.(ord($1) - 97).']'/ge;
73 my $sub1 = eval "sub { $expr1 }" or die "Expression 1: $@\n"; ## no critic (ProhibitStringyEval)
74 my $sub2 = eval "sub { $expr2 }" or die "Expression 2: $@\n"; ## no critic (ProhibitStringyEval)
76 plan tests => (2 ** $num);
77 note "Testing for logical equivalence of two expressions with $num variable(s)...";
79 my $equivalence = is_logically_equivalent($num, $sub1, $sub2);
80 note $equivalence ? 'Logical equivalence proved!' : 'Bummer...';