Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Different results with and without { true } in a DCG #2809

Open
Kiyoshi364 opened this issue Feb 3, 2025 · 5 comments · May be fixed by #2812
Open

Different results with and without { true } in a DCG #2809

Kiyoshi364 opened this issue Feb 3, 2025 · 5 comments · May be fixed by #2812

Comments

@Kiyoshi364
Copy link

I have a DCG (cbor_minor_value//2), that in some cases only unify arguments,
and in another cases it immediately calls another DCG (numbytes_number//2) and return.

cbor_minor_value( 0, val(i,  0)) --> [].
cbor_minor_value( 1, val(i,  1)) --> [].
...
cbor_minor_value(23, val(i, 23)) --> [].
cbor_minor_value(24, val(x1, V)) --> numbytes_number(1, V).
cbor_minor_value(25, val(x2, V)) --> numbytes_number(2, V).
cbor_minor_value(26, val(x4, V)) --> numbytes_number(4, V).
cbor_minor_value(27, val(x8, V)) --> numbytes_number(8, V).

The predicate by itself works fine.
But when I call it from another predicate (cbor_item//1), it always fails at calling numbytes_number//2, even though a solution exists.
If we add any predicate (such as { true } or []), before or after calling numbytes_number//2, it starts to behave as expected.

I don't know why that is happening.
I use library(clpz) to implement numbytes_number//2.

There is the minimal file with a test case.
min-cbor.pl.txt
It is enough for main/0 to succeed.

The test file is a modified version of cbor.pl.
This problem was first mentioned in #2800.

My scryer-prolog version:

$ scryer-prolog --version
8ac663d
@hurufu
Copy link
Contributor

hurufu commented Feb 3, 2025

This is surprising bug, I think there is a problem with attributed variables unification. For example if you rewrite last 4 cbor_minor_value//2 rules in the following way:

cbor_minor_value(24, val(x1, V), B, C) :- numbytes_number(1,V,B,C).
cbor_minor_value(25, val(x2, V), B, C) :- numbytes_number(2,V,B,C).
cbor_minor_value(26, val(x4, V), B, C) :- numbytes_number(4,V,B,C).
cbor_minor_value(27, val(x8, V), B, C) :- numbytes_number(8,V,B,C).

Them test fails, but if you rewrite them as:

cbor_minor_value(24, val(x1, V), B, C) :- B=D, numbytes_number(1,V,D,C).
cbor_minor_value(25, val(x2, V), B, C) :- B=D, numbytes_number(2,V,D,C).
cbor_minor_value(26, val(x4, V), B, C) :- B=D, numbytes_number(4,V,D,C).
cbor_minor_value(27, val(x8, V), B, C) :- B=D, numbytes_number(8,V,D,C).

Then suddenly all tests pass. 🤔

@UWN
Copy link

UWN commented Feb 3, 2025

Please do narrow down the problem to the very smallest program possible. Here is what I obtained by stepwise reducing your program, removing everything unnecessary:

:- use_module(library(freeze)).

main1 :-
  freeze(Minor,true),
  cbor_minor_value1(Minor, []).

main2 :-
  freeze(Minor,true),
  cbor_minor_value2(Minor, []).

cbor_minor_value1(24, S0) :- numbytes_number(1, S0).

cbor_minor_value2(24, S0) :- S0=S1, numbytes_number(1, S1).

numbytes_number(_, []).

?- main1.
   false, unexpected.
   true. % expected, but not found
?- main2.
   true. % expected

So it is unrelated to clpz.

@Kiyoshi364
Copy link
Author

Thanks!

I'm adding 3 tests more.
I hope they help.

main3 :-
  freeze(Minor,true),
  cbor_minor_value3(Minor, []).

main4 :-
  freeze(Minor,true),
  cbor_minor_value4(Minor, []).

main5 :-
  freeze(Minor,true),
  cbor_minor_value5(Minor, []).

cbor_minor_value3(24, S0) :- numbytes_number(1, S1), S0=S1.

cbor_minor_value4(24, S0) :- true, numbytes_number(1, S0).

cbor_minor_value5(24, S0) :- numbytes_number(1, S0), true.

numbytes_number(_, []).

/*
?- main3.
   true. % expected
?- main4.
   true. % expected
?- main5.
   false, unexpected.
   true. % expected, but not found
*/

@UWN
Copy link

UWN commented Feb 3, 2025

Another version that shows that the module name of the attribute is involved:

:- use_module(library(freeze)).
   
main :-
  freeze(Minor,true),
  cbor_minor_value(Minor, 1, []).

cbor_minor_value(24, One, S) :- numbytes_number(1, One, S).

numbytes_number(_, One, _) :- arg(One,f(200),200).

?- main.
   error(type_error(integer,freeze),arg/3), unexpected.
   type_error(integer,freeze), unexpected. % no matter what the 2nd arg looks like
   true. % expected, but not found

@bakaq
Copy link
Contributor

bakaq commented Feb 4, 2025

I just confirmed that this is the same problem as #2706.

@bakaq bakaq linked a pull request Feb 4, 2025 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants