How to tell xref/pceemacs about my module

So I’m playing with a very simplified CHR/rewrite thing.
I hope to declare rewrites with code like
this, that ~~> something, else.

Then expect step([this, that | Rest], [something, else | Rest])

So far the code does what I hope, but I can’t seem to appease pceemacs that a ~~> b. is valid code.

Working with Claude/ChatGPT and trying to learn from yall/chr has simply resulted in many failed attempts. Any help is appreciated. Actual code starts at % ACTUAL CODE and the rest is the current attempt at the proper incantations.

:- module(steps,
          [ steps/2,
            op(1150, xfx, '~~>')
          ]).

% ATTEMPTS at syntax handling/coloring in PceEmacs

:- meta_predicate
    transformation(?,0,?),
    steps(:, ?).

:- dynamic transformation/3.
:- multifile transformation/3.

:- op(1150, xfx, '~~>').

% Additional CHR-style declarations
:- multifile prolog:called_by/4.
:- multifile prolog:called_by_1/4.
:- multifile prolog_colour:term_colours/2.

% Tell Prolog how to analyze calls to the operator
prolog:called_by('~~>'(_,_), [], _, []).
prolog:called_by_1('~~>'(_,_), [], _, []).

% Tell PceEmacs how to color the terms
prolog_colour:term_colours((Head ~~> Body), expanded - [classify, classify]).

% Define how the operator should be treated in analysis
:- multifile prolog:hook/1.
prolog:hook('~~>'(_,_)).

% END ATTEMPTS at syntax handling/coloring in PceEmacs

% ACTUAL CODE
user:term_expansion(T, G) :-
    \+ var(T),
    ~~>(A,B) = T,
    prolog_load_context(module, Module),
    (  B = '|'(GoalB, BodyB)
    -> G = Module:transformation(A, GoalB, BodyB)
    ;  G = Module:transformation(A, true, B)
    ).

steps(M:In, Final) :-
    (  M:transformation(A, G, B),
       remove_terms(A, In, Intermediate),
       (   call(G)
       *-> add_terms(B, Intermediate, Next),
           steps(M:Next, Final)
       ;   fail
       )
    -> true
    ;  Final = In
    ).

remove_terms(NonVar, In, Out) :-
    \+ var(NonVar),
    (  functor(NonVar, ',', 2)
    -> (A,R) = NonVar,
       (  ground(A)
       -> selectchk(A, In, Next)
       ;  select(A, In, Next)
       ),
       remove_terms(R, Next, Out)
    ;  select(NonVar, In, Out)
    ).

add_terms(NonVar, In, Final) :-
    \+ var(NonVar),
    (  functor(NonVar, ',', 2)
    -> (A,R) = NonVar,
       add_terms(R, [A|In], Final)
    ;  Final = [NonVar|In]
    ).


I have little clue what you are trying to do. Smells a bit like my attempts yesterday in taming the mathlife JavaScript library using ChatGPT: lots of convincingly looking advice that touches what needs to be done, but is all just plain wrong :frowning: It seems that is the current state of the art when you try these tools outside the mainstream domain.

surely, called_by/4 is wrong (see docs in prolog_xref.pl). called_by_1/4 does not exist at all. Declaring something as a hook is intended for predicates that are called “spontaneously”. I don’t think your ~~~> operator is called like that, but I have little clue what it is supposed to do.

1 Like

To add additional emphasis to what @Jan notes, using any general LLM to learn or create SWI-Prolog code for CHR will most likely fail, I have yet to get any CHR to be created by an LLM to work as given and no longer attempt such.

My advice would be to avoid using the LLMs for this as they will just eat your time, maybe in the future things will get better or someone may finetune a model for just CHR. :slightly_smiling_face:

New basic example.
Let’s suppose I want to write a module horn.pl that allows me to write Prolog clauses with a syntax something like a, b ===> ab.

I can do that:

:- module(horn,
          [ op(1200, xfx, '===>')
          ]).

term_expansion(Term, G) :-
    \+ var(Term),
    Term = ===>(T, H),
    G = (H :- T).

a.
b.

a, b ===> ab.

The code works within this file, but PceEmacs will say ===>, and a and b are not loaded/unreferenced.
How do I remedy that?

How do I modify horn.pl so that I can import it and have the new syntax in the imported file and have PceEmacs understand what is happening?

Guess this comes from an LLM? term_expansion/2 is never called with an unbound first argument.

I guess you need to add a term_colours rule that flips the colouring of the head and body. Possibly you also have to extend the cross referencer. It might pick it up through term expansion, but I’m not sure. If it needs adjusting, there is no hook to deal with this.