trealla-prolog / trealla

A compact, efficient Prolog interpreter written in plain-old C.
MIT License
273 stars 13 forks source link

Optionally allow for clause/2,3 to grab non-dynamic predicates #372

Closed guregu closed 1 year ago

guregu commented 1 year ago

I'm not sure if there's an ISO-friendly way to accomplish this, but it would be nice if clause/2,3 could work for non-dynamic predicates. My use case is making a LSP, which will require predicates like SWI's xref_called/5. I'm thinking it will be easy to prototype something if we can reason about the whole program using Prolog, although we may want to write some of the predicates in C later.

Proposal: relax the requirement for dynamic predicates when the flag strict_iso is off.

I have implemented this in my experimental fork and it seems to work nicely. I can send a PR if it sounds good; it's a pretty small change.

I would also be happy to use an alternative if anyone has a better idea. We could make the :- public directive do something, but even with that I think an LSP would be tricky. Another alternative could be a system predicate that ignores the restrictions.

infradig commented 1 year ago

I have no problems with your proposal re strict_iso and clause/2,3 so please go ahead with a PR.

On Tue, Oct 17, 2023 at 2:41 PM guregu @.***> wrote:

I'm not sure if there's an ISO-friendly way to accomplish this, but it would be nice if clause/2,3 could work for non-dynamic predicates. My use case is making a LSP, which will require predicates like SWI's xref_called/5 https://www.swi-prolog.org/pldoc/doc_for?object=xref_called/3. I'm thinking it will be easy to prototype something if we can reason about the whole program using Prolog, although we may want to write some of the predicates in C later.

Proposal: relax the requirement for dynamic predicates when the flag strict_iso is off.

I have implemented this in my experimental fork and it seems to work nicely. I can send a PR if it sounds good; it's a pretty small change.

I would also be happy to use an alternative if anyone has a better idea. We could make the :- public directive do something, but even with that I think an LSP would be tricky. Another alternative could be a system predicate that ignores the restrictions.

— Reply to this email directly, view it on GitHub https://github.com/trealla-prolog/trealla/issues/372, or unsubscribe https://github.com/notifications/unsubscribe-auth/AFNKSETQBG442UZXBV252SLX7YEAXAVCNFSM6AAAAAA6DGCYA2VHI2DSMVQWIX3LMV43ASLTON2WKOZRHE2DMNJSHA3DQOI . You are receiving this because you are subscribed to this thread.Message ID: @.***>

infradig commented 1 year ago

Oh, and i just merged a whole bunch of accumulated small changes. Please update first and work against the latest.

On Tue, Oct 17, 2023 at 2:41 PM guregu @.***> wrote:

I'm not sure if there's an ISO-friendly way to accomplish this, but it would be nice if clause/2,3 could work for non-dynamic predicates. My use case is making a LSP, which will require predicates like SWI's xref_called/5 https://www.swi-prolog.org/pldoc/doc_for?object=xref_called/3. I'm thinking it will be easy to prototype something if we can reason about the whole program using Prolog, although we may want to write some of the predicates in C later.

Proposal: relax the requirement for dynamic predicates when the flag strict_iso is off.

I have implemented this in my experimental fork and it seems to work nicely. I can send a PR if it sounds good; it's a pretty small change.

I would also be happy to use an alternative if anyone has a better idea. We could make the :- public directive do something, but even with that I think an LSP would be tricky. Another alternative could be a system predicate that ignores the restrictions.

— Reply to this email directly, view it on GitHub https://github.com/trealla-prolog/trealla/issues/372, or unsubscribe https://github.com/notifications/unsubscribe-auth/AFNKSETQBG442UZXBV252SLX7YEAXAVCNFSM6AAAAAA6DGCYA2VHI2DSMVQWIX3LMV43ASLTON2WKOZRHE2DMNJSHA3DQOI . You are receiving this because you are subscribed to this thread.Message ID: @.***>

guregu commented 1 year ago

Awesome, will do. Thanks!

guregu commented 1 year ago

Much appreciated. It'll probably take a while but when I make some progress with the LSP I'll write something in the discussions page.

guregu commented 1 year ago

OK, @UWN has convinced me to do a proper implementation (see comments here: https://github.com/trealla-prolog/trealla/commit/a68b793edd1c98b0ae88669c17324765db0e8287#commitcomment-130290216). And now I own the standard (thank you INCITS).

Plan:

Now, the hard part: what to name this new flag? 🙂

Ideas:

I don't have any particularly strong opinions about what to call it, would be happy to implement anything that we can agree makes sense.

UWN commented 1 year ago

Something with public. No new notions.

A clause of a public procedure can be inspected, a clause
of a private procedure cannot be inspected.

infradig commented 1 year ago

I would revert everything, don't add a useless public directive or a new prolog flag. Just add '$clause'/2,3 that wraps clause/2,3 with an internal flag in the prolog structure enabled. This was probably your original idea Guregu. It's just an internal system predicate for use by the LSP.

On Wed, 18 Oct 2023, 22:57 guregu, @.***> wrote:

OK, @UWN https://github.com/UWN has convinced me to do a proper implementation (see comments here: a68b793#commitcomment-130290216 https://github.com/trealla-prolog/trealla/commit/a68b793edd1c98b0ae88669c17324765db0e8287#commitcomment-130290216). And now I own the standard (thank you INCITS).

Plan:

  • Implement public/1 directive as in other Prologs
  • Add a new flag, off by default, that changes the default permissions of clauses (i.e. bypasses the public check)
  • Revert changes to strict_iso flag

Now, the hard part: what to name this new flag? 🙂

Ideas:

  • set_prolog_flag(public_clauses, on) (off by default)
  • set_prolog_flag(default_clause_permissions, public) (private by default)
  • set_prolog_flag(clause_visibility, public) (private by default) ← it seems the ISO standard doesn't use the word 'visibility' anywhere so maybe a bad idea
  • set_prolog_flag(omniscient, on) ← joke? :-)

I don't have any particularly strong opinions about what to call it, would be happy to implement anything that we can agree makes sense.

— Reply to this email directly, view it on GitHub https://github.com/trealla-prolog/trealla/issues/372#issuecomment-1768398507, or unsubscribe https://github.com/notifications/unsubscribe-auth/AFNKSEXHIN3LTXMDBIQFUJ3X77G4HAVCNFSM6AAAAAA6DGCYA2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTONRYGM4TQNJQG4 . You are receiving this because you commented.Message ID: @.***>

infradig commented 1 year ago

Fyi: I did originally implement a public/1 directive but removed it a while back.

guregu commented 1 year ago

Yeah, that works for me (and was indeed my original intention). I'll cook up an alternative PR.

I think the public directive could be potentially useful for niche use cases (meta-interpreters that want to take advantage of clause indexing?), but a '$clause'/2,3 would be perfect for my LSP use case.

An aside but I wonder what the practical intention of public/private clauses in the standard is? I suppose that it gives runtimes the leeway to optimize private clauses by changing their internal contents and forgetting the original. But IMO it seems to unnecessarily hamper the usefulness of clause/2. (I'm not arguing that we should change the defaults, just trying to understand its original purpose).

UWN commented 1 year ago

it gives runtimes the leeway to optimize private clauses by changing their internal contents and forgetting the original.

Space is certainly a concern, some systems compiled directly to C. Some ran without any BIOS or other such amenities on the processors. Another concern was security, and in general access to the source code which clause effectively does.

But as is so often in such a context the rationale for a decision is often more controversial than the actual decision.

But IMO it seems to unnecessarily hamper the usefulness of clause/2.

Not clear what you mean by unnecessarily.

guregu commented 1 year ago

Thank you for humoring me @UWN, I appreciate the insight. That does make sense.

Unnecessary was a poor choice of words. clause/2, “code is data”, etc. are some of the coolest features of the language IMO. Being able to write queries against source code is super powerful and these kinds of introspection tools are lacking from most other languages. Indeed many LSPs end up writing their own ad-hoc query engine against the target language’s AST. From that perspective, it puzzled me a bit why private clauses are the default. But I think I understand it a bit better now.