# convert the expression into tokens
#use strict;
use feature qw/switch/;

sub symbolify
{
    my %hash = ();
    my $i = 0;
    my $symstring = "";
    for (@_)
    {
        if (/AND/)
        {
            $symstring .= "/";
        }
        elsif (/OR/)
        {
            $symstring .= "\\";
        }
        elsif (exists $hash{$_})
        {
            $symstring .= $hash{$_};
        }
        else
        {
            $hash{$_} = $i;
            $symstring .= $i;
            $i++;
        }
    }
    ($symstring, \%hash);
}
sub unsymbolify
{
    my ($hash, $symstring) = @_;
    my @desym = ();
    while ($symstring =~ /(.)/g)
    {
        if ($1 =~ m%/%)
        {
            push @desym, "AND";
        }
        elsif ($1 =~ m%\\%)
        {
            push @desym, "OR";
        }
        else
        {
            push @desym, $hash->{$1};
        }
    }
    return @desym;
}
sub uniq
{
    %seen = ();
    grep { ! $seen{$_} ++ } @_;
}
sub transform
{
    given (shift)
    {
        when(m%0/0%) {  "0" }
        when(m%0\\0%) {  "0" }
        when(m%0/0/(.)%) {  "0/$1" }
        when(m%0\\0/(.)%) {  "0\\$1" }
        when(m%0/(.)/0%) {  "0/$1" }
        when(m%0\\(.)/0%) {  "0" }
        when(m%0/(.)\\0%) {  "0" }
        when(m%(.)/1\\1%) {  "1" }
        when(m%(.)\\1/1%) {  "1" }
        when(m%0/((./|.\\)+)/0%) {  "$1/0" } # don't hold me to this one
        when(m%0\\((./|.\\)+)\\0%) {  "$1\\0" } # or this one
        default { $_ }
    }
}
sub transformr
{
    # grab the first 5 items in the list
    my @result = ();
    for (@_)
    {
        #my ($s, $sh) = symbolify
    }
    # symbolify
    # transform
    # smybolify back?
}
sub blist_to_expr
{
    my $rsym = pop;
    my $op = pop;
    if (@_)
    {
        return sprintf("(%s %s %s)", blist_to_expr(@_), lc $op, $rsym);
    }
    else
    {
        return $rsym;
    }
}

# takes a list
# turns it into a special type of boolean (not really special)
# evaluates permutations on the values
sub eval_permutes
{
    # extract the vars in the list
    my @vars = sort(uniq(grep(m/^\$.+/, @_)));
    my $max = 2 ** @vars;
    my $i;
    my $texpr = blist_to_expr(@_);
    print "$texpr : \n";
    # eval("local (" . join(", ", @vars) . ");"); warn $@ if $@;

    for ($i = 0; $i < $max; $i++)
    {
        #print "i=$i\n";
        my $n = $i;
        for (@vars)
        {
            my $m = $n % 2;
            #print "m=$m\n";
            eval("$_ = $m"); warn $@ if $@;
            $n = int($n / 2);
        }
        #print "vars:  \n";
        for (@vars)
        {
            print $_ . " = " . eval($_) . "\n"; warn $@ if $@;
        }
        #print eval("\"$texpr\"") . " ==> "; warn $@ if $@;
        print (eval($texpr)?"true\n":"false\n"); warn $@ if $@;
        print "\n";
    }
}

my @test = qw/dill OR bib AND bob OR bob/;
my @test2 = qw/$v1 AND $v2 AND $v3 OR $v4 AND $v5 AND $v8 OR $v9 OR $v7 AND $v4 OR $v2 AND $v6 AND $v1/;
my @test3 = qw/$v2 AND $v3 OR $v4 AND $v5 AND $v8 OR $v9 OR $v7 AND $v4 OR $v2 AND $v6 AND $v1/;
#print join (", ", @test) . "\n";
#my ($ss, $symhash) = symbolify(@test);
#%$symhash = reverse(%$symhash);
#print join (", ", unsymbolify($symhash, $ss)) . "\n";
#print "transform: " . transform($ss) . "\n";
#print blist_to_expr(@test) . "\n";
#my $texpr = blist_to_expr(@test2);
#print $texpr . "\n";
#my $tvar1 = 1;
#my $tvar2 = 1;
#print (eval($texpr)?"true\n":"false\n"); warn $@ if $@;
open STDOUT, ">", "out1";
eval_permutes(@test2);
open STDOUT, ">", "out2";
eval_permutes(@test3);
# transform the tokens
# spit it out
