Re: Attempt at approximating Lisp's "macroexpansion"
Ian Tegebo <[email protected]>
| Newsgroups | gmane.comp.ai.prolog.swi |
|---|---|
| Message-ID | <CAFBOwCbSMZFzFNB=XFBPJXy3nn9CtV1yc+ccx71pef0GTXNmyQ@mail.gmail.com> |
Alan,
Unfortunately, I left out some details. First, I started the top-level:
$ swipl
...
1 ?- edit(file('arec_mod.pl')).
Then, I edited the file to look like:
arec_mod.pl:
:- module(arec_mod,[]).
:- use_module(library(record)).
:- record arec(afield:atom='').
Then, I compiled it from the editor with C-c, C-b. Back in the top-level:
2 ?- module(arec_mod).
true.
arec_mod: 3 ?- expand_term(:- record arec(afield:atom=''),Res).
ERROR: Syntax error: Operator expected
ERROR: expand_term(:- record
ERROR: ** here **
ERROR: arec(afield:atom=''),Res) .
Now, even if I consult library(record) from the default working module:
arec_mod: 4 ?- [library(record)].
The "record" atom is still not recognized as an operator:
arec_mod: 5 ?- current_op(1150,fx,record).
false.
And that was confusing because I expected the exported operator to be
available given that I'd changed the working module at the top-level. Now
let's do:
arec_mod: 6 ?- module(user).
true.
7 ?- [library(record)].
% library(record) compiled into record 0.01 sec, 59 clauses
true.
8 ?- current_op(1150,fx,record).
true.
9 ?- module(arec_mod).
true.
arec_mod: 10 ?- current_op(1150,fx,record).
true.
arec_mod: 11 ?- expand_term(:- record arec(afield:atom=''),Res).
Res = [default_arec(arec('')), ...
So, what does this mean? It appears that the operator table at the
top-level doesn't reflect the current working module. Is the user module's
operator table expected to be the only one in use while in the top-level?
If so, I feel like this somewhat weakens its usefulness for debugging
modules. I got into the habit of using module/1 at the top-level for the
convenience of atom completion.
On Wed, Jul 17, 2013 at 6:48 AM, Alan Baljeu <[email protected]> wrote:
> I think you're missing something in your understanding of Prolog.
>
> The Prolog compiler will read one line at a time from a source file and
> then compile that line. The first step of compiling is read/N. If the
> line can't be read and converted to a term, we have an error.
> term_expansion happens to the term after it's read.
> So when you see this:
>
> ?- expand_term(:- record arec(afield:atom=''),Res).
> ERROR: Syntax error: Operator expected
> ERROR: system:expand_term(:- record
> ERROR: ** here **
> ERROR: arec(afield:atom=''),Res) .
>
>
> It's because record is not a defined operator. And that's because you
> have not imported the module that defines it.
>
> 20 ?- [library(record)]
>
> 21 ?- expand_term(:- record arec(afield:atom=''),Res).
> Res = [ (:-record'<compiled>'), default_arec(arec('')),
> arec_afield(arec(_G620493), _G620493), arec_data(afield, arec(_G620510),
> _G620510), (set_afield_of_arec(_G620558, arec(_G620555),
> arec(_G620558)):-must_be(atom, _G620558)), (set_afield_of_arec(_G620558,
> _G620593):-must_be(atom, _G620558), setarg(1, _G620593, _G620558)),
> (nb_set_afield_of_arec(_G620558, _G620593):-must_be(..., ...),
> nb_setarg(..., ..., ...)), (set_arec_field(..., ..., ...):-must_be(...,
> ...)), (... :- ...)|...].
>
> Alan Baljeu
>
>
>
> ----- Original Message -----
> From: Ian Tegebo <[email protected]>
> To: "[email protected]" <[email protected]>
> Cc:
> Sent: Wednesday, July 17, 2013 12:30:00 AM
> Subject: [SWIPL] Attempt at approximating Lisp's "macroexpansion"
>
> Firstly, this email is longer than I'd like. I ask and answer some of my
> own questions. I didn't edit as much as I could because I think it helps
> explain my confusion and may be of some use to those seeking to improve
> docs or otherwise teach others.
>
> ----
>
> I was trying to use expand_term/2 like one might use "macroexpand" in a
> Lisp when I ran into trouble. Consider expanding an example using the
> library(record):
>
> ?- expand_term(:- record arec(afield:atom=''),Res).
> ERROR: Syntax error: Operator expected
> ERROR: system:expand_term(:- record
> ERROR: ** here **
> ERROR: arec(afield:atom=''),Res) .
>
> After much puzzling and eventually re-reading library/record.pl, I saw
> that
> the term_expansion definition didn't refer to "record" as an operator, but
> as a predicate. So,
>
> ?- expand_term(:- record(arec(afield:atom='')),Res).
> Res = [default_arec(arec('')), ...
>
> And then I got what I expected. But this left me with two questions:
>
> 1) At what point does "record" go from an operator to a predicate during
> compilation and/or execution as a directive?
> 2) What's the deal with the "system" module qualification in the definition
> of term_expansion? Here's the definition:
>
> system:term_expansion((:- record(Record)), Clauses) :-
> compile_records(Record, Clauses).
>
> The documentation for term_expansion doesn't mention the "system" module:
>
> http://www.swi-prolog.org/pldoc/man?predicate=term_expansion/2
>
> Assuming something special is going on, should it?
>
> Also, the issue surrounding "record" as operator is unsettling; at the
> top-level, I can query current_op while within my module to see that
> "record" is in fact an operator. Operator handling seems to happen before
> expand_term. If so, is there another predicate I should use before
> expanding it? In the Lisp world, I'd have thought "read" would do the job.
>
> After a bit of manual reading,
>
> arec_mod ?- open_chars_stream(":- record
> arec(afield:atom='').",S),read(S,T),expand_term(T,Res).
> ERROR: Stream <stream>(0x38db590):0:1 Syntax error: Operator expected
>
> More manual reading revealed read_term/3 accepts a module option but
> read_clause/3 is supposed to set it automatically based on the "current
> compilation module". Sadly, it didn't work whereas explicitly handing the
> module over to read_term/3 does:
>
> arec_mod ?- open_chars_stream(":- record
> arec(afield:atom='').",S),read_clause(S,T,[]),expand_term(T,Res).
> ERROR: Stream <stream>(0x3b702f0):0:1 Syntax error: Operator expected
>
> arec_mod ?- open_chars_stream(":- record
>
> arec(afield:atom='').",S),read_term(S,T,[module(arec_mod)]),expand_term(T,Res).
> (this one worked as expected)
>
> Okay, let's follow the manual to see what the "current compilation module"
> is supposed to be:
>
> arec_mod ?- prolog_load_context(module,V).
> V = user.
>
> This is surprising because I'd already done "?- module(arec_mod)". Looking
> around for more "context", I found,
>
> arec_mod: ?- context_module(M).
> M = arec_mod.
>
> At this point, I have something that seems to work for my use case. That
> said, I think I've only scratched the surface of all the issues at play.
> Here's what I have so far:
>
> :- meta_predicate expand_chars_term(:,-).
> expand_chars_term(Mod:Chars,Term) :- expand_chars_term(Chars,Mod,Term).
> expand_chars_term(Chars,Module,Term) :-
> open_chars_stream(Chars,S),
> read_term(S,T,[module(Module)]),
> expand_term(T,Term).
>
> Where the following is my pretty-printer:
>
> :- meta_predicate portray_expansion(:).
> portray_expansion(Mod:Chars) :-
> expand_chars_term(Chars,Mod,Term),
> is_list(Term) -> maplist(portray_clause,Term)
> ; portray_clause(Term).
>
> Now I can see a pretty-printed expansion:
>
> arec_mod ?- portray_expansion(":- record arec(afield:atom='').").
>
> I'm assuming the caller is at the top-level, "inside" the module where
> predicates/operators that may occur in Chars have already been loaded. I
> can imagine a few improvements, but I'd like some feedback given that I'm
> still a Prolog newbie.
>
> Thanks,
> --
> Ian Tegebo
> -------------- next part --------------
> HTML attachment scrubbed and removed
> _______________________________________________
> SWI-Prolog mailing list
> [email protected]
> https://lists.iai.uni-bonn.de/mailman/listinfo.cgi/swi-prolog
>
>
--
Ian Tegebo
-------------- next part --------------
HTML attachment scrubbed and removed