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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.