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

Possible issue regarding :-. #229

Open
enoperm opened this issue Jun 30, 2022 · 6 comments
Open

Possible issue regarding :-. #229

enoperm opened this issue Jun 30, 2022 · 6 comments

Comments

@enoperm
Copy link

enoperm commented Jun 30, 2022

I have been playing around with prolog recently, and I got a meta-interpreter running (mostly by going along with https://www.metalevel.at/acomip) that provides a reasoning as to how a goal was fulfilled, as well as allow for using a list provided as a parameter in place of the global database.

mi(+true, _Facts, true).
mi(+Conj, Facts, [ReasonA|ReasonB]) :- Conj = (A, B), mi(+A, Facts, ReasonA), mi(+B, Facts, ReasonB).
mi(+Disj, Facts, Reason) :- Disj = (A; B), (mi(+A, Facts, Reason); mi(+B, Facts, Reason)).
mi(+Fact, Facts, [fact(Fact)]) :- member(Fact, Facts).
mi(+R, Facts, [rule(R, Body) | Reason]) :- member(Rule, Facts), :-(R, Body) = Rule, mi(+Body, Facts, Reason).

This works fine in SWI Prolog:

?- [meta].
true.

?- mi(+mortal(X), [(mortal(X) :- man(X)), man(socrates)], Reasoning).
X = socrates,
Reasoning = [rule(mortal(socrates), man(socrates)), fact(man(socrates))] .

In a 1pl repl, however, I get an error.

Top level for ichiban/prolog v0.9.1
This is for testing purposes only!
See https://github.com/ichiban/prolog for more details.
Type Ctrl-C or 'halt.' to exit.
?- [meta].
true.
?- mi(+mortal(X), [(mortal(X) :- man(X)), man(socrates)], Reasoning).
2022/06/30 19:31:41 error(existence_error(procedure, :- /1), 'Unknown procedure.')

Which is odd, because I do not see :-/1 anywhere in the code, at most I'd expect to see an error about :-/2.
I have tried defining :-/1 as a dynamic predicate in the source file where the meta-interpreter lies, as below:

:- dynamic((:-)/1).

This line was accepted by both implementations, and the behaviour of SWIPL did not change.
With that addition, I do not receive an error message from 1pl anymore, but it still did not behave as I expected.

?- [meta].
true.
?- mi(+mortal(X), [(mortal(X) :- man(X)), man(socrates)], Reasoning).
false.

Curiously, if I replace my use of :-(Head, Body) with a custom predicate, such as rule(Head, Body), it behaves the same in both implementations:

?- [meta].
true.
?- mi(+mortal(X), [rule(mortal(X), man(X)), man(socrates)], Reasoning).
X = socrates,
Reasoning = [rule(mortal(socrates), man(socrates)), fact(man(socrates))].

I'm not quite sure what is going wrong, but I suspect :- may be receiving special treatment somewhere in Ichiban Prolog?

@ichiban
Copy link
Owner

ichiban commented Jul 1, 2022

Thank you very much for reporting this! I think this is because of a bug in the parser.

This implementation does special treatment to :- in a couple of places:

But none of them distinguish between Head :- Body and :-(Head, Body)- they're same after the parsing phase.

I'm working hard on the parser/lexer/writer right now and the next release, hopefully this weekend, will fix the most of syntax related bugs.

@ichiban
Copy link
Owner

ichiban commented Jul 17, 2022

@enoperm Could you try the latest release v0.10.1, please? I fixed all the syntax bugs known so far including the ones regarding operators. The problem you're seeing here might have been fixed as well.

@UWN
Copy link

UWN commented Jul 20, 2022

Defining a predicate (:-)/1 is quite problematic as it is easily confused with the principal functor of a directive. For this reason SICStus and IF produce a permission_error(modify,static_procedure,_). From a conformity standpoint they consider (:-)/1 an implementation specific built-in (5.5.9) that cannot be called (they produce there either an existence error or some implementation specific one). Same for (:-)/2, (?-)/1, and (-->)/2.

In SWI this kind of works, but note that it can be abused for code injection. Just try listing((:-)/1) to see why. Similarly GNU.

@enoperm
Copy link
Author

enoperm commented Jul 20, 2022

@enoperm Could you try the latest release v0.10.1, please? I fixed all the syntax bugs known so far including the ones regarding operators. The problem you're seeing here might have been fixed as well.

Seems to work, now.

Defining a predicate (:-)/1 is quite problematic as it is easily confused with the principal functor of a directive. For this reason SICStus and IF produce a permission_error(modify,static_procedure,_). From a conformity standpoint they consider (:-)/1 an implementation specific built-in (5.5.9) that cannot be called (they produce there either an existence error or some implementation specific one). Same for (:-)/2, (?-)/1, and (-->)/2.

In SWI this kind of works, but note that it can be abused for code injection. Just try listing((:-)/1) to see why. Similarly GNU.

I tried testing it with an SWI toplevel, but it raises an existience_error for both of listing((:-)/1) and listing((:-)/2) from either a clean state or after loading the current iteration of my metainterpreter.

GNU prolog simply yields yes, which is interesting, though I'm not quite sure how that leads to code injection, yet.

EDIT: I just realized I forgot to prepend :-, listing((:-)/1). does yield a result now.

@enoperm
Copy link
Author

enoperm commented Jul 20, 2022

Though I might add, I only included a definition for :-/1 to see whether it changes the behaviour of 1pl, it is neither needed nor wanted in the code.

@UWN
Copy link

UWN commented Jul 20, 2022

Maybe I was a bit too terse concerning SWI, so this I meant:

?- catch(asserta((:-a)),Error,true).
true.

?- listing(:-).
:- dynamic (:-)/1.

:-a.

true.

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

No branches or pull requests

3 participants