# Converting a term into executable emacs-lisp expression

**URL:** <https://swi-prolog.discourse.group/t/converting-a-term-into-executable-emacs-lisp-expression/6586>\
**Category:** General\
**Tags:** emacs-lisp\
**Created:** [May 29, 2023, 7:46am UTC](https://swi-prolog.discourse.group/t/converting-a-term-into-executable-emacs-lisp-expression/6586 "2023-05-29T07:46:23Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![kuniaki.mukai](https://avatars.discourse-cdn.com/v4/letter/k/c67d28/32.png) [@kuniaki.mukai](https://swi-prolog.discourse.group/u/kuniaki.mukai)\
**Post date:** [May 29, 2023, 7:46am UTC](https://swi-prolog.discourse.group/t/converting-a-term-into-executable-emacs-lisp-expression/6586/1 "2023-05-29T07:46:23Z")

</div>

I made a small revision on an old codes of mine, which converts a prolog term into an executable emacs-lisp expression. Here is some self-explanatory sample queries:

```prolog
% ?- elisp:term_to_lisp_string(f(), X).
%@ X = "(f )" .
% ?- elisp:term_to_lisp_string(list(1,2,3), X).
%@ X = "(list 1 2 3 )" .
% ?- elisp:term_to_lisp_string(progn(a, b, c), X).
%@ X = "(progn a b c )" .
% ?- elisp:term_to_lisp_string(cond([a,b],[b,c]), X).
%@ X = "(cond (a b )(b c ))" .
% ?- elisp:term_to_lisp_string(defun(f, [a,b], +(a, b)), X).
%@ X = "(defun f (a b )(+ a b ))" .

```

This converter is used in my “emacs-prolog” on top of emacs-lisp, which works fine for basic editing region of emacs buffer.

It is straightforward to use this converter for handling emacs buffer by calling functions in emacs-lisp. Details is lengthy, so should be omitted here.

```prolog
% ?- elisp:lisp(sort(list(4, 8, 21, 17, 33, 7, 21, 7), #(>)), V).
['V'=[33,21,21,17,8,7,7,4]]

% ?- elisp:lisp(+(1, 2, 3), Y).
['Y'=6]

% ?- elisp:lisp(setq(uuu, +(1,2,3)), V).
['V'=6]

% ?- elisp:lisp(progn(setq(uuu, +(1,2,3)), *(uuu, uuu)), V).
['V'=36]

# is for `quote`.
% ?- elisp:lisp(append(cons(#(x),#([a,b])), #([u,v])), R).
['R'=[x,a,b,u,v]]

```

```prolog
% # is reserved for quote.
term_to_tokens(X, ['('|Y], Z):- is_list(X), !,
		  term_to_tokens_with_closing(X, Y, Z).
term_to_tokens(X, [X0|Y], Y):- atom(X), !, atom_string(X, X0).
term_to_tokens(X, [X0|Y], Y):- atomic(X), !, term_string(X, X0).
term_to_tokens(#(X), Y, Z) :- term_to_tokens([quote, X], Y, Z).
term_to_tokens(X, Y, Z) :-
	compound_name_arguments(X, F, Args),
	term_to_tokens([F|Args], Y, Z).

term_to_tokens_with_closing([], [')'|Y], Y).
term_to_tokens_with_closing([A|B], X, Y):- term_to_tokens(A, X, Z),
	term_to_tokens_with_closing(B, Z, Y).

```

I am afraid that at this time of modern technology, “emacs-prolog” is obsolete or deprecated. Although Pcemacs sounds close to the emacs-prolog. Unfortunately it seems not work  
on GnuEmacs.

---

<div class="post-metadata">

**Author:** ![oskardrums](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/oskardrums/32/3594_2.png) [@oskardrums](https://swi-prolog.discourse.group/u/oskardrums)\
**Post date:** [May 29, 2023, 9:25am UTC](https://swi-prolog.discourse.group/t/converting-a-term-into-executable-emacs-lisp-expression/6586/2 "2023-05-29T09:25:02Z")

</div>

> [@kuniaki.mukai](#):
>
> I am afraid that at this time of modern technology, “emacs-prolog” is obsolete or deprecated

I’m not sure but it sounds like Sweep can be of help here. For one, [it allows Prolog to invoke Elisp](https://eshelyaron.com/sweep.html#funcall-from-prolog).  
(It also allows Elisp to call Prolog, which can in turn call Elisp, and so on.)

Could you shed some more light on “emacs-prolog” and what it does?

---

<div class="post-metadata">

**Author:** ![kuniaki.mukai](https://avatars.discourse-cdn.com/v4/letter/k/c67d28/32.png) [@kuniaki.mukai](https://swi-prolog.discourse.group/u/kuniaki.mukai)\
**Post date:** [May 29, 2023, 10:27am UTC](https://swi-prolog.discourse.group/t/converting-a-term-into-executable-emacs-lisp-expression/6586/3 "2023-05-29T10:27:53Z")

</div>

> [@oskardrums](#):
>
> [it allows Prolog to invoke Elisp](https://eshelyaron.com/sweep.html#funcall-from-prolog).

Sound great! Which makes me sure my work is really obsolete.

I hope the following two simple examples will help you what I have in mind for emacs-prolog on top of emacs-lisp.

```prolog
handle([choose, files]) -->
	{choose_files(X), insert("\n", X, X0) },
	 peek(X0).
handle([enum]) --> region,
	snippets:environment(enumerate),
	overwrite.

```

The first region handler displays POSiX file paths which are choosen by the user via osacscript.

The second one is to edit latex enumerate environment for items in the region.

```prolog
% region
a

b

c

```

Output in the region.

```prolog
\begin{enumerate}
\item a
\item b
\item c
\end{enumerate}

```

Emacs shortcut “C-l” is prepared to invoke handlers with completing arguments.

---

<div class="post-metadata">

**Author:** ![kuniaki.mukai](https://avatars.discourse-cdn.com/v4/letter/k/c67d28/32.png) [@kuniaki.mukai](https://swi-prolog.discourse.group/u/kuniaki.mukai)\
**Post date:** [May 30, 2023, 5:41am UTC](https://swi-prolog.discourse.group/t/converting-a-term-into-executable-emacs-lisp-expression/6586/4 "2023-05-30T05:41:24Z")

</div>

> [@oskardrums](#):
>
> [it allows Prolog to invoke Elisp](https://eshelyaron.com/sweep.html#funcall-from-prolog).

I have skimmed the doc. It may take time for me to digest it so that I can move my “emacs handlers” to Sweep. Sorry for my poor reading. I am a user of Ediprolog mode, which I never read the doc about ediprolog.el, which is still a blackbox for me. So far it’s DWIM facility was enough for my using the mode. Do you have some advice for those who are (too much ) familiar  
with Ediprolog mode to move to Sweep ?

**EDIT**

Afer installing sweeprolog by M-x package-list-packages and inserting the two lines in init.el:  
(require 'sweeprolog)  
(setq sweeprolog-swipl-path “/usr/local/bin/swipl”)

with ediprolog lines commenting out.

I put a new file test.pl  
test.pl:

```prolog
test:- writeln("hello world.\n").

```

My first question is how to compile the test.pl by sweep, and then  
how to run the query `?- test.`

Thanks.

---

<div class="post-metadata">

**Author:** ![oskardrums](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/oskardrums/32/3594_2.png) [@oskardrums](https://swi-prolog.discourse.group/u/oskardrums)\
**Post date:** [May 30, 2023, 8:31am UTC](https://swi-prolog.discourse.group/t/converting-a-term-into-executable-emacs-lisp-expression/6586/5 "2023-05-30T08:31:05Z")

</div>

> [@kuniaki.mukai](#):
>
> My first question is how to compile the test.pl by sweep, and then  
> how to run the query `?- test.`

First, make sure that `sweeprolog-mode` is enabled in the `test.pl` buffer. You can have Emacs use this mode for Prolog buffers automatically by adding something like the following to your config:

```prolog
(add-to-list 'auto-mode-alist '("\\.plt?\\'" . sweeprolog-mode))

```

In `sweeprolog-mode`, you can use `C-c C-l` to [load the current buffer](https://eshelyaron.com/sweep.html#loading-buffers).  
To run your code, use [the integrated top-level](https://eshelyaron.com/sweep.html#prolog-top-level). The simplest way to do that is to type `C-c C-t` in the source code buffer, that’ll pop up the top-level where you can then type `test.` and hit enter just like you would in a regular top-level.

---

<div class="post-metadata">

**Author:** ![kuniaki.mukai](https://avatars.discourse-cdn.com/v4/letter/k/c67d28/32.png) [@kuniaki.mukai](https://swi-prolog.discourse.group/u/kuniaki.mukai)\
**Post date:** [May 30, 2023, 10:38am UTC](https://swi-prolog.discourse.group/t/converting-a-term-into-executable-emacs-lisp-expression/6586/6 "2023-05-30T10:38:39Z")

</div>

> [@oskardrums](#):
>
> ```prolog
> (add-to-list 'auto-mode-alist '("\\.plt?\\'" . sweeprolog-mode))
> 
> ```

Thanks. “Hello World.\n” runs !

However, it runs in a different way from Ediprolog mode, which runs queries in the buffer with typing C-c C-e. Has Sweep a switch for mode for running dierectly the query in the buffer like Ediprolog mode ? I guess it seems out of design principle of Sweep.

Anyway thanks. Sweep is impressive. now I want read more the Sweep doc.

---

<div class="post-metadata">

**Author:** ![oskardrums](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/oskardrums/32/3594_2.png) [@oskardrums](https://swi-prolog.discourse.group/u/oskardrums)\
**Post date:** [May 30, 2023, 11:24am UTC](https://swi-prolog.discourse.group/t/converting-a-term-into-executable-emacs-lisp-expression/6586/7 "2023-05-30T11:24:11Z")

</div>

> [@kuniaki.mukai](#):
>
> However, it runs in a different way from Ediprolog mode, which runs queries in the buffer with typing C-c C-e. Has Sweep a switch for mode for running dierectly the query in the buffer like Ediprolog mode ?

Indeed, in Sweep we use separate buffers for writing and evaluating code.  
BTW if you find this as a limitation, I’d be interested to hear why. It shouldn’t be too hard to extend Sweep with a way of evaluating example queries that appear in comments similarly to what `ediprolog` provides, but I’m not sure I fully understand the motivation.

> [@kuniaki.mukai](#):
>
> Anyway thanks. Sweep is impressive. now I want read more the Sweep doc.

Thank you!

---

<div class="post-metadata">

**Author:** ![kuniaki.mukai](https://avatars.discourse-cdn.com/v4/letter/k/c67d28/32.png) [@kuniaki.mukai](https://swi-prolog.discourse.group/u/kuniaki.mukai)\
**Post date:** [May 30, 2023, 11:51am UTC](https://swi-prolog.discourse.group/t/converting-a-term-into-executable-emacs-lisp-expression/6586/8 "2023-05-30T11:51:18Z")

</div>

> [@oskardrums](#):
>
> but I’m not sure I fully understand the motivation.

It’s my custom to add sample queries before predicate definitions like this, which is useful to remind me of functions later and by running the query.

```prolog
% ?- elisp:term_to_lisp_string(f(), X).
%@ X = "(f )" .
% ?- elisp:term_to_lisp_string(list(1,2,3), X).
%@ X = "(list 1 2 3 )" .
% ?- elisp:term_to_lisp_string(prog(a, b, c), X).
%@ X = "(prog a b c )" .
% ?- elisp:term_to_lisp_string(cond([a,b],[b,c]), X).
%@ X = "(cond (a b )(b c ))" .
% ?- elisp:term_to_lisp_string(defun(f, [a,b], +(a, b)), X).
%@ X = "(defun f (a b )(+ a b ))" .
term_to_lisp_string(X, Y):- term_to_tokens(X, Y0, []),
	tokens_to_string(Y0, Y).

```

Ediprolog mode has a merit to dispense cut and paste typing between two buffers (source and toplevel ones).

I would appreciate if such “minor request” of a lazy person could be accepted.

---

<div class="post-metadata">

**Author:** ![kuniaki.mukai](https://avatars.discourse-cdn.com/v4/letter/k/c67d28/32.png) [@kuniaki.mukai](https://swi-prolog.discourse.group/u/kuniaki.mukai)\
**Post date:** [May 30, 2023, 5:13pm UTC](https://swi-prolog.discourse.group/t/converting-a-term-into-executable-emacs-lisp-expression/6586/9 "2023-05-30T17:13:16Z")

</div>

What is the exclamation symbol (!) displayed at the beginning of predicate definition,  
which is in green color ?

I use key-chord package, and jj,bb,ii, MM,for example are defined to do special actions on the buffer in Ediprolog mode. For instance, bb is defined to do qcompile the current buffer and  
make it current module looking at the directive at the beginning line (:- module(–)).  
I gives module name often at random, and often forget it easily.

When I move finally to Sweep in the future, I have to update prolog-mode to sweeprolog-mode.

Thus there may be small things to ask and to be updated for this transition, which take some time.  
At this moment, I can only hope it is as short time as negligible to solve by myself.

To be honest, I am quite new to webassembly technology, which is a half of the motivation  
for this transition to learn.

---

<div class="post-metadata">

**Author:** ![oskardrums](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/oskardrums/32/3594_2.png) [@oskardrums](https://swi-prolog.discourse.group/u/oskardrums)\
**Post date:** [May 30, 2023, 8:14pm UTC](https://swi-prolog.discourse.group/t/converting-a-term-into-executable-emacs-lisp-expression/6586/10 "2023-05-30T20:14:12Z")

</div>

> [@kuniaki.mukai](#):
>
> It’s my custom to add sample queries before predicate definitions like this, which is useful to remind me of functions later and by running the query.
> 
> Ediprolog mode has a merit to dispense cut and paste typing between two buffers (source and toplevel ones).

I can see how having such comments (along with a convenient way to create them) may be useful.  
I’ve pushed a new version of Sweep that includes a command for that. (Note that It usually takes about a day for the Emacs package archive to pick up and publish the new version.)  
This new command lets you create such example usage comments without having to copy-paste and format top-level transcripts manually.  
See [the accompanying manual section](https://eshelyaron.com/sweep.html#usage-comments) for full details.

---

<div class="post-metadata">

**Author:** ![oskardrums](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/oskardrums/32/3594_2.png) [@oskardrums](https://swi-prolog.discourse.group/u/oskardrums)\
**Post date:** [May 30, 2023, 8:27pm UTC](https://swi-prolog.discourse.group/t/converting-a-term-into-executable-emacs-lisp-expression/6586/11 "2023-05-30T20:27:47Z")

</div>

> [@kuniaki.mukai](#):
>
> What is the exclamation symbol (!) displayed at the beginning of predicate definition,  
> which is in green color ?

These are [Flymake](https://www.gnu.org/software/emacs/manual/html_node/flymake/index.html#Top) diagnostic indicators. They indicate that there’s a diagnostic (error, warning or note) for some part of that line. Sweep enables these by default, you can change that by customizing `sweeprolog-enable-flymake`.

> [@kuniaki.mukai](#):
>
> To be honest, I am quite new to webassembly technology, which is a half of the motivation  
> for this transition to learn.

I’m not sure I understand the connection to WebAssembly, is this regarding Sweep? FWIW Sweep is not implemented with WebAssembly, it loads the regular SWI-Prolog (binary) shared library as an Emacs dynamic module and integrates the two through their C APIs.

---

<div class="post-metadata">

**Author:** ![kuniaki.mukai](https://avatars.discourse-cdn.com/v4/letter/k/c67d28/32.png) [@kuniaki.mukai](https://swi-prolog.discourse.group/u/kuniaki.mukai)\
**Post date:** [May 30, 2023, 10:17pm UTC](https://swi-prolog.discourse.group/t/converting-a-term-into-executable-emacs-lisp-expression/6586/12 "2023-05-30T22:17:09Z")

</div>

> [@oskardrums](#):
>
> See [the accompanying manual section](https://eshelyaron.com/sweep.html#usage-comments) for full details.

Thanks. It seems that any possible questions of mine is answered in the manual.  
From now on, I shoud keep silent before consulting it.

---

<div class="post-metadata">

**Author:** ![kuniaki.mukai](https://avatars.discourse-cdn.com/v4/letter/k/c67d28/32.png) [@kuniaki.mukai](https://swi-prolog.discourse.group/u/kuniaki.mukai)\
**Post date:** [May 30, 2023, 10:37pm UTC](https://swi-prolog.discourse.group/t/converting-a-term-into-executable-emacs-lisp-expression/6586/13 "2023-05-30T22:37:48Z")

</div>

> [@oskardrums](#):
>
> I’m not sure I understand the connection to WebAssembly, is this regarding Sweep?

Sorry, it’s my fault, which perhaps comes from my confusion with webassmbly on browsers.

BTW, transition from the current emacs handlers of mine based on start-process of emacs-lisp  
to that on Sweep should be easy, because basic idea of the handler is to send prolog goal to prolog from emacs-lisp, and S-expression from prolog to emacs-lisp. According to your related comment, such send/receive should be easy, though I am slow in rewriting codes on  
what looks clear and easy in my mind.

---

<div class="post-metadata">

**Author:** ![kuniaki.mukai](https://avatars.discourse-cdn.com/v4/letter/k/c67d28/32.png) [@kuniaki.mukai](https://swi-prolog.discourse.group/u/kuniaki.mukai)\
**Post date:** [May 31, 2023, 7:08am UTC](https://swi-prolog.discourse.group/t/converting-a-term-into-executable-emacs-lisp-expression/6586/14 "2023-05-31T07:08:36Z")

</div>

> [@oskardrums](#):
>
> This new command lets you create such example usage comments without having to copy-paste and format top-level transcripts manually.  
> See [the accompanying manual section](https://eshelyaron.com/sweep.html#usage-comments) for full details.

Thank you for really quick push.

BTW, is the toplevel window always necessary?

As for Ediprolog mode, it is not, but the current buffer works also as the toplevel window,  
which is covenient, for example, particularly when the query is long and complex with multiple lines, and the user wants to run the query multiple times with some experimental small changes.

Suppose ediprolog mode.  
A region (1) in a prolog-mode buffer with the cursor at some point in the first line. Hit dwim(do what I mean) key C-c C-e then the region updated to (2)

(1) Region

```prolog
% ?- writeln([somethinglong,
% somethinglong,
% somethinglong,
% somethinglong
% ]).

```

(2) updated Region with answer appended.

```prolog
% ?- writeln([somethinglong,
% somethinglong,
% somethinglong,
% somethinglong
% ]).
%@ [somethinglong,somethinglong,somethinglong,somethinglong]
%@ true.

```

I am afraid this feature is not easy for Sweep, but I thought it is better for Sweep to put a note  
on “toplevel window-less” Ediprolog mode.

Anyway thanks a lot.

**EDIT:**** What am I missing ?**

I put the sample elisp codes (1) in the manual on Emacs scratch buffer, and load the sweeprolog codes (2). Then I did `M-x eval-region` on the region (1), but to see nothing happen. I am surely missing something basic on how to use of Sweeprolog.

Any advice on what I am missing woul be appreciated. Thanks.

(1) This elisp codes is taken from the manual on sample query.

```prolog
     (sweeprolog-open-query "user" "lists" "permutation" '(1 2 3 4 5))
     (let ((num 0)
           (sol (sweeprolog-next-solution)))
       (while sol
         (setq num (1+ num))
         (setq sol (sweeprolog-next-solution)))
       (sweeprolog-close-query)
       num)

```

(2) I check this prolog codes works as ordinal prolog codes.

```prolog
% ?- permutation([a,b,c], X).
user:permutation([], []).
user:permutation([X|Xs], Ps):- permutation(Xs, Qs),
	insert_elem(X, Qs, Ps).
%
user:insert_elem(X, As, [X|As]).
user:insert_elem(X, [A|As], [A|Bs]):- insert_elem(X, As, Bs).

```
