initial commit
[chaz/p5-Acme-Test-LogicalEquivalence] / bin / test-logical-equivalence
1 #!perl
2 # ABSTRACT: Test if expressions are logically equivalent
3 # PODNAME: test-logical-equivalence
4
5 =head1 SYNOPSIS
6
7 # be sure to escape $ and other special characters from your shell
8 test-logical-equivalence '$a && $b' '$b && $a'
9
10 =head1 SEE ALSO
11
12 =for :list
13 * L<Acme::Test::LogicalEquivalence>
14
15 =cut
16
17 use 5.008;
18 use warnings FATAL => 'all';
19 use strict;
20
21 use Test::More;
22 use Acme::Test::LogicalEquivalence qw(is_logically_equivalent);
23
24 sub usage {
25 print <<END;
26 $0 EXPR1 EXPR2
27 Test if two simple expressions are logically equivalent.
28
29 Exactly two expressions must be given.
30
31 Example: $0 '\$a || \$b' '\$b || \$a'
32 Remember that you may need to escape special characters like "\$" from your shell.
33 END
34 exit 1;
35 }
36
37 sub find_num_vars {
38 my $expr = shift;
39
40 my $highest = -1;
41
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;
46 }
47
48 # check for scalars that index $_
49 for my $varname ($expr =~ /\$_\[(\d+)\]/g) {
50 my $num = $varname;
51 $highest = $num if $highest < $num;
52 }
53
54 return $highest + 1;
55 }
56
57 my $expr1 = shift or usage;
58 my $expr2 = shift or usage;
59
60 my $numvars1 = find_num_vars($expr1);
61 my $numvars2 = find_num_vars($expr2);
62 my $num = $numvars1 > $numvars2 ? $numvars1 : $numvars2;
63
64 if ($num < 1) {
65 print STDERR 'No variables detected. Variables should be one or more of $a, $b, ..., $z', "\n";
66 exit 2;
67 }
68
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;
72
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)
75
76 plan tests => (2 ** $num);
77 note "Testing for logical equivalence of two expressions with $num variable(s)...";
78
79 my $equivalence = is_logically_equivalent($num, $sub1, $sub2);
80 note $equivalence ? 'Logical equivalence proved!' : 'Bummer...';
81
This page took 0.039892 seconds and 4 git commands to generate.