hoaproject/Ruler

Precedence of logical operators

Pittiplatsch opened this issue · 4 comments

Hello,
thank you very much for this wonderful library.

I think I found a bug, where the well-known precedence of logical operators isn't applied.

The following three expressions which are semantically identical yield different results:

The explicit way:
(false and true) or true correctly results in true

The implicit way which is idencal due to mathematical conventions:
false and true or true falsely returns false!

The implice way, but vice-versa:
true or true and false correctly results in true again, presumably due to LAZY_BREAK feature.

Maybe I can later provide a failing unit test if desired. Meanwhile, here is my "test suite":

        $hoaRuler = new Hoa\Ruler\Ruler();

        foreach (['true', 'false'] as $a) {
            foreach (['true', 'false'] as $b) {
                foreach (['true', 'false'] as $c) {

                    $rule1 = "($a and $b) or $c";
                    $rule2 = "$a and $b or $c";
                    $rule3 = "$c or $b and $a";

                    var_dump(
                        $rule1 . intval($hoaRuler->assert($rule1)),
                        $rule2 . intval($hoaRuler->assert($rule2)),
                        $rule3 . intval($hoaRuler->assert($rule3))
                    );
                }
            }
        }

With $a = false, $b = true and $c = false and
with $a = false, $b = false and $c = true the described behaviour can be observed.

Thanks for your attention.

Hywan commented

Hello and thank you for the detailed bug report!

Here is my try:

$ hoa compiler:pp hoa://Library/Ruler/Grammar.pp <( echo 'a and b or c' ) -v dump
>  #expression
>  >  #and
>  >  >  token(identifier, a)
>  >  >  #or
>  >  >  >  token(identifier, b)
>  >  >  >  token(identifier, c)

I guess the tree should look like this:

$ hoa compiler:pp hoa://Library/Ruler/Grammar.pp <( echo '(a and b) or c' ) -v dump
>  #expression
>  >  #or
>  >  >  #and
>  >  >  >  token(identifier, a)
>  >  >  >  token(identifier, b)
>  >  >  token(identifier, c)

So in our implementation, logical operators are right-associatives, whilst they are commonly left-associatives.

Thank you for your reply.

In my eyes the problem isn't a question about left- or right-assiociatives. You can see that if you include my $rule3 in your inspections.

Either way (left- or right-assiociating), $rule2 and $rule3 will yield complementary results whilst they should be identical!

IMO operators must be set in relation to each other to achieve precedence. However I understand that with the current architecture this is far away from trivial.

Actually, I stumbled along this issue will thinking about how to implement new operators + and *, which need the same precedence...

Hywan commented

@Pittiplatsch I am really really really sorry for the too late reply… I have finally time to work back on issues on Hoa. Excuse me. A PR has been proposed, see #107 please. Your feedback is valuable.

I'm still unsure about the right vs. left association thingy...
However, dividing the grammar into separate OR / AND pieces looks reasonable, as does your unit test, which exactly mirrors my test cases.
Thank you for fixing :-)