* Re: [Emacs-diffs] trunk r117002: Correctly treat progn contents as toplevel forms when byte compiling
[not found] <E1WcAcP-0006zy-MJ@vcs.savannah.gnu.org>
@ 2014-04-21 15:09 ` Stefan Monnier
2014-04-21 17:44 ` Daniel Colascione
0 siblings, 1 reply; 23+ messages in thread
From: Stefan Monnier @ 2014-04-21 15:09 UTC (permalink / raw)
To: Daniel Colascione; +Cc: emacs-devel
> Correctly treat progn contents as toplevel forms when byte compiling
Your commit messages should be copies of the ChangeLog entry.
Could you describe the case(s) that this fixes?
> + ;; Macroexpand (not macroexpand-all!)
That could be a problem.
> form at toplevel in case it
> + ;; expands into a toplevel-equivalent `progn'. See CLHS section
> + ;; 3.2.3.1, "Processing of Top Level Forms".
Note that Elisp is not Common-Lisp, so we don't always follow
Common-Lisp's design decisions (although, we often do, as well).
> The semantics are very
> + ;; subtle: see test/automated/bytecomp-tests.el for interesting
> + ;; cases.
> + (setf form (macroexpand form byte-compile-macro-environment))
> + (if (eq (car-safe form) 'progn)
> + (cons 'progn
> + (mapcar (lambda (subform)
> + (byte-compile-recurse-toplevel
> + subform non-toplevel-case))
> + (cdr form)))
> + (funcall non-toplevel-case form)))
`non-toplevel-case' is declared as optional, but here you call it
without ensuring it's non-nil. IOW it shouldn't be optional.
> (defconst byte-compile-initial-macro-environment
> '(
> ;; (byte-compiler-options . (lambda (&rest forms)
> ;; (apply 'byte-compiler-options-handler forms)))
> (declare-function . byte-compile-macroexpand-declare-function)
> (eval-when-compile . (lambda (&rest body)
Oops, we have a bug here. We should be using `(... ,(lambda ...
Stefan
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [Emacs-diffs] trunk r117002: Correctly treat progn contents as toplevel forms when byte compiling
2014-04-21 15:09 ` [Emacs-diffs] trunk r117002: Correctly treat progn contents as toplevel forms when byte compiling Stefan Monnier
@ 2014-04-21 17:44 ` Daniel Colascione
2014-04-21 22:09 ` Stefan Monnier
0 siblings, 1 reply; 23+ messages in thread
From: Daniel Colascione @ 2014-04-21 17:44 UTC (permalink / raw)
To: Stefan Monnier; +Cc: emacs-devel
[-- Attachment #1: Type: text/plain, Size: 2161 bytes --]
On 04/21/2014 08:09 AM, Stefan Monnier wrote:
>> Correctly treat progn contents as toplevel forms when byte compiling
>
> Your commit messages should be copies of the ChangeLog entry.
>
> Could you describe the case(s) that this fixes?
See the testcases. Generally speaking, this change fixes situations
where the byte-compiler miscompiles code that contains (or generates)
top-level progns that define macros, then use them.
>> + ;; Macroexpand (not macroexpand-all!)
>
> That could be a problem.
Why? We macroexpand-all forms later when we actually compile or eval them.
>> form at toplevel in case it
>> + ;; expands into a toplevel-equivalent `progn'. See CLHS section
>> + ;; 3.2.3.1, "Processing of Top Level Forms".
>
> Note that Elisp is not Common-Lisp, so we don't always follow
> Common-Lisp's design decisions (although, we often do, as well).
Unless there's a good reason to depart from CL, we should follow CL's
approach to things. CL in a good sane default, and in this case, CL
specifies exactly the right behavior.
>> The semantics are very
>> + ;; subtle: see test/automated/bytecomp-tests.el for interesting
>> + ;; cases.
>> + (setf form (macroexpand form byte-compile-macro-environment))
>> + (if (eq (car-safe form) 'progn)
>> + (cons 'progn
>> + (mapcar (lambda (subform)
>> + (byte-compile-recurse-toplevel
>> + subform non-toplevel-case))
>> + (cdr form)))
>> + (funcall non-toplevel-case form)))
>
> `non-toplevel-case' is declared as optional, but here you call it
> without ensuring it's non-nil. IOW it shouldn't be optional.
Err, yes.
>> (defconst byte-compile-initial-macro-environment
>> '(
>> ;; (byte-compiler-options . (lambda (&rest forms)
>> ;; (apply 'byte-compiler-options-handler forms)))
>> (declare-function . byte-compile-macroexpand-declare-function)
>> (eval-when-compile . (lambda (&rest body)
>
> Oops, we have a bug here. We should be using `(... ,(lambda ...
Well, a minor performance bug. Still worth fixing.
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 884 bytes --]
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [Emacs-diffs] trunk r117002: Correctly treat progn contents as toplevel forms when byte compiling
2014-04-21 17:44 ` Daniel Colascione
@ 2014-04-21 22:09 ` Stefan Monnier
2014-04-21 22:29 ` Daniel Colascione
0 siblings, 1 reply; 23+ messages in thread
From: Stefan Monnier @ 2014-04-21 22:09 UTC (permalink / raw)
To: Daniel Colascione; +Cc: emacs-devel
>>> Correctly treat progn contents as toplevel forms when byte compiling
>> Your commit messages should be copies of the ChangeLog entry.
>> Could you describe the case(s) that this fixes?
> See the testcases. Generally speaking, this change fixes situations
> where the byte-compiler miscompiles code that contains (or generates)
> top-level progns that define macros, then use them.
Can you show an example of a macro that does that?
>>> + ;; Macroexpand (not macroexpand-all!)
>> That could be a problem.
> Why? We macroexpand-all forms later when we actually compile or eval them.
Not sure why, exactly. It just feels like it could be a problem.
Usually, we assume it's safe to use macroexpand-all, and it's not 100%
crystal clear why we could be sure that macroexpand-all won't be used.
> Unless there's a good reason to depart from CL, we should follow CL's
> approach to things. CL in a good sane default, and in this case, CL
> specifies exactly the right behavior.
Yes. But Elisp's design constraints, especially w.r.t macro expansion,
are slightly different, partly for historical reasons, partly for
technical reasons. It might not be relevant here, but I just want to
make double sure.
Stefan
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [Emacs-diffs] trunk r117002: Correctly treat progn contents as toplevel forms when byte compiling
2014-04-21 22:09 ` Stefan Monnier
@ 2014-04-21 22:29 ` Daniel Colascione
2014-04-22 2:09 ` Stefan Monnier
0 siblings, 1 reply; 23+ messages in thread
From: Daniel Colascione @ 2014-04-21 22:29 UTC (permalink / raw)
To: Stefan Monnier; +Cc: emacs-devel
[-- Attachment #1: Type: text/plain, Size: 2054 bytes --]
On 04/21/2014 03:09 PM, Stefan Monnier wrote:
>>>> Correctly treat progn contents as toplevel forms when byte compiling
>>> Your commit messages should be copies of the ChangeLog entry.
>>> Could you describe the case(s) that this fixes?
>> See the testcases. Generally speaking, this change fixes situations
>> where the byte-compiler miscompiles code that contains (or generates)
>> top-level progns that define macros, then use them.
>
> Can you show an example of a macro that does that?
Any macro that expands to something like this:
(progn (defmacro abc (arg) 1) (defun def () (abc 2)))
Some of the iface stuff I was working on used this functionality. The
comments in bytecomp.el suggest that EIEIO has similar stuff. In any
case, it's a reasonable thing to want to do, so we should support it.
>>>> + ;; Macroexpand (not macroexpand-all!)
>>> That could be a problem.
>> Why? We macroexpand-all forms later when we actually compile or eval them.
>
> Not sure why, exactly. It just feels like it could be a problem.
> Usually, we assume it's safe to use macroexpand-all, and it's not 100%
> crystal clear why we could be sure that macroexpand-all won't be used.
We only want to expand the top-level macro to see whether it expands
into a progn. If it does, we treat each form in the progn as its own
top-level form, recursively. If we called macroexpand-all, we'd expand
the subforms too soon, before we'd compiled defmacro forms that might be
inside the progn body.
>> Unless there's a good reason to depart from CL, we should follow CL's
>> approach to things. CL in a good sane default, and in this case, CL
>> specifies exactly the right behavior.
>
> Yes. But Elisp's design constraints, especially w.r.t macro expansion,
> are slightly different, partly for historical reasons, partly for
> technical reasons. It might not be relevant here, but I just want to
> make double sure.
It's not relevant here. I also still want to make those macro-expansion
changes I proposed last year.
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 884 bytes --]
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [Emacs-diffs] trunk r117002: Correctly treat progn contents as toplevel forms when byte compiling
2014-04-21 22:29 ` Daniel Colascione
@ 2014-04-22 2:09 ` Stefan Monnier
2014-04-22 2:21 ` Daniel Colascione
0 siblings, 1 reply; 23+ messages in thread
From: Stefan Monnier @ 2014-04-22 2:09 UTC (permalink / raw)
To: Daniel Colascione; +Cc: emacs-devel
> Any macro that expands to something like this:
> (progn (defmacro abc (arg) 1) (defun def () (abc 2)))
That's not the kind of example I was thinking if. Do you have a real
example, maybe?
> Some of the iface stuff I was working on used this functionality.
> The comments in bytecomp.el suggest that EIEIO has similar stuff.
No, that comment is about eieio.el using eval-and-compile over large
swaths of code, which is very unusual, so I made eval-and-compile behave
more like the usual top-level (before that eval-and-compile expanded
all its macros in a single pass).
> In any case, it's a reasonable thing to want to do, so we should
> support it.
I'm not sure I want to impose myself this level of detail.
Especially since it'll also have to be ported to the eager
macro-expansion code.
And OTOH your macro could expand calls to `abc' "manually" in the code
it returns, and hence avoid this need.
Stefan
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [Emacs-diffs] trunk r117002: Correctly treat progn contents as toplevel forms when byte compiling
2014-04-22 2:09 ` Stefan Monnier
@ 2014-04-22 2:21 ` Daniel Colascione
2014-04-22 4:25 ` Stefan Monnier
0 siblings, 1 reply; 23+ messages in thread
From: Daniel Colascione @ 2014-04-22 2:21 UTC (permalink / raw)
To: Stefan Monnier; +Cc: emacs-devel
[-- Attachment #1: Type: text/plain, Size: 2392 bytes --]
On 04/21/2014 07:09 PM, Stefan Monnier wrote:
>> Any macro that expands to something like this:
>> (progn (defmacro abc (arg) 1) (defun def () (abc 2)))
>
> That's not the kind of example I was thinking if. Do you have a real
> example, maybe?
Try writing a macro that emits a defstruct, then a function that uses
cl-typep for that struct, all wrapped in the same toplevel progn.
>> Some of the iface stuff I was working on used this functionality.
>
>> The comments in bytecomp.el suggest that EIEIO has similar stuff.
>
> No, that comment is about eieio.el using eval-and-compile over large
> swaths of code, which is very unusual, so I made eval-and-compile behave
> more like the usual top-level (before that eval-and-compile expanded
> all its macros in a single pass).
Yes, eieio uses eval-and-compile, but there's no reason the same
toplevel semantics shouldn't apply to regular progn.
>> In any case, it's a reasonable thing to want to do, so we should
>> support it.
>
> I'm not sure I want to impose myself this level of detail.
> Especially since it'll also have to be ported to the eager
> macro-expansion code.
Other lisps provide the same functionality that my change does, and for
good reason. It's a simple, useful concept: macros can only generate one
form, so if they generate a progn, we treat each form in the progn as a
toplevel form. Not supporting this mode of operation makes elisp much
less useful.
The reason we have automated tests is to make sure we can maintain this
"level of detail". That it's not immediately useful to you isn't a
reason not to include it. I can't believe this issue is even
contentious: the current behavior is a clear bug.
> And OTOH your macro could expand calls to `abc' "manually" in the code
> it returns, and hence avoid this need.
How? By locally defining those macros in a temporary macrolet (which
we'd macroexpand-all?) in addition to emiting defmacros? What if the
macro generation is implicit, as it is with defstruct, so that the
top-level form doesn't even realize it has to employ this awful hack?
The need for this ridiculous and needless hack can be avoided if we just
have sane toplevel macro expansion semantics. Forcing people to rely on
tricks like what you propose instead of providing sane macro expansion
semantics will waste a lot of people's time.
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 884 bytes --]
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [Emacs-diffs] trunk r117002: Correctly treat progn contents as toplevel forms when byte compiling
2014-04-22 2:21 ` Daniel Colascione
@ 2014-04-22 4:25 ` Stefan Monnier
2014-04-22 4:46 ` Daniel Colascione
0 siblings, 1 reply; 23+ messages in thread
From: Stefan Monnier @ 2014-04-22 4:25 UTC (permalink / raw)
To: Daniel Colascione; +Cc: emacs-devel
>> That's not the kind of example I was thinking if. Do you have a real
>> example, maybe?
> Try writing a macro that emits a defstruct, then a function that uses
> cl-typep for that struct, all wrapped in the same toplevel progn.
That's getting closer to an actual example. I still can't think of
a case where you'd want to use cl-typep in this way, tho.
> The reason we have automated tests is to make sure we can maintain this
> "level of detail". That it's not immediately useful to you isn't a
> reason not to include it. I can't believe this issue is even
> contentious: the current behavior is a clear bug.
It's a clear bug if we assume Common-Lisp semantics. But in many cases,
Elisp chooses to provide simpler semantics, to allow a simpler and/or
more naive implementation.
I'm not yet convinced either way, but claiming it's a bug won't sway me.
We've lived with a "simpler" semantics for 30 years and you're the first
to complain about this limitation, so I'd really want to see clear
evidence that it's worth adding this complexity.
> we'd macroexpand-all?) in addition to emiting defmacros? What if the
> macro generation is implicit, as it is with defstruct, so that the
> top-level form doesn't even realize it has to employ this awful hack?
Yes, the defstruct+typep example above sounds like a good example where
my suggestion is not really workable.
Stefan
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [Emacs-diffs] trunk r117002: Correctly treat progn contents as toplevel forms when byte compiling
2014-04-22 4:25 ` Stefan Monnier
@ 2014-04-22 4:46 ` Daniel Colascione
2014-04-22 15:06 ` Stefan Monnier
2014-04-22 15:20 ` Stefan Monnier
0 siblings, 2 replies; 23+ messages in thread
From: Daniel Colascione @ 2014-04-22 4:46 UTC (permalink / raw)
To: Stefan Monnier; +Cc: emacs-devel
[-- Attachment #1: Type: text/plain, Size: 4286 bytes --]
On 04/21/2014 09:25 PM, Stefan Monnier wrote:
>>> That's not the kind of example I was thinking if. Do you have a real
>>> example, maybe?
>> Try writing a macro that emits a defstruct, then a function that uses
>> cl-typep for that struct, all wrapped in the same toplevel progn.
>
> That's getting closer to an actual example. I still can't think of
> a case where you'd want to use cl-typep in this way, tho.
cl-struct-slot-value uses typep It makes sense to do so given that
cl-struct-slot-value knows the name of the struct, but not necessarily
the name of its predicate function --- which might not even exist.
The chunk below is from the iface code I'm working on. This code isn't
even close to done --- it's just here to give you a sense of the
problem. You see that we declare a structure, then emit some functions
that use the structure. Some of these functions go on to do things with
values that are allegedly of the structure type, and they use typep to
check that these values are actually of the struct type. This approach
is a perfectly logical way to go about writing code, and we should
support it. Forcing users to do something else is especially pernicious
because the problem we're discussing only shows up when compiling (or
loading) files --- in normal interactive development, everything seems fine!
(eval-and-compile
(defun iface--make-member-wrapper (iface-name member)
"Create a lisp form defining an interface accessor.
IFACE-NAME is a symbol giving the name of the interface being
defined. MEMBER is an element of the MEMBERS parameter to
`iface-declare'."
(cl-destructuring-bind ((member-name inst-arg &rest xarglist)
&optional doc) member
(unless (and inst-arg
(symbolp inst-arg)
(not (eql (aref (symbol-name inst-arg) 0) ?\&)))
(error (concat "Interface members must accept an instance as"
" their first argument")))
`(defun ,member-name (,inst-arg &rest xargs)
,doc
(declare (advertised-calling-convention (,inst-arg ,@xarglist)
,emacs-version))
(apply (cl-struct-slot-value ',iface-name ',member-name ,inst-arg)
,inst-arg xargs)))))
(cl-defmacro iface-declare ((name base) &rest members)
"Create a new interface called NAME, inheriting from BASE.
MEMBERS is a list of member specifiers. Each is a list of the form
((NAME . ARGUMENTS) DOCUMENTATION), where NAME is a symbol
naming the interface member, ARGUMENTS is a cl-lib-style argument
list, and DOCUMENTATION is documentation to attach to that
function."
(let ((doc (and (stringp (car members)) (pop members)))
(prefix (concat (symbol-name name) "--iface-")))
`(progn
(cl-defstruct (,name (:include ,base)
(:conc-name ,(intern prefix))
(:copier nil))
,@(if doc (list doc))
,@(mapcar #'caar members))
,@(mapcar (lambda (member)
(iface--make-member-wrapper name member))
members)
',name)))
>> The reason we have automated tests is to make sure we can maintain this
>> "level of detail". That it's not immediately useful to you isn't a
>> reason not to include it. I can't believe this issue is even
>> contentious: the current behavior is a clear bug.
>
> It's a clear bug if we assume Common-Lisp semantics. But in many cases,
> Elisp chooses to provide simpler semantics, to allow a simpler and/or
> more naive implementation.
I don't care whether we diverge from CL in sets of supported features
and names of functions, but we should try hard to match CL's fundamental
execution semantics. Practically every possible bad lisp idea was tried
before Common Lisp came around. The CL people knew about the precise
problem we're discussing on this thread and codified the best solution
in the language. There are solutions in CL for problems that we haven't
even encountered yet. The less closely we follow CL, the less we benefit
from the experience baked into the specification and the harder it is to
fix problems that eventually do come up.
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 884 bytes --]
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [Emacs-diffs] trunk r117002: Correctly treat progn contents as toplevel forms when byte compiling
2014-04-22 4:46 ` Daniel Colascione
@ 2014-04-22 15:06 ` Stefan Monnier
2014-04-22 17:22 ` Daniel Colascione
2014-04-22 15:20 ` Stefan Monnier
1 sibling, 1 reply; 23+ messages in thread
From: Stefan Monnier @ 2014-04-22 15:06 UTC (permalink / raw)
To: Daniel Colascione; +Cc: emacs-devel
> (eval-and-compile
> (defun iface--make-member-wrapper (iface-name member)
> "Create a lisp form defining an interface accessor.
> IFACE-NAME is a symbol giving the name of the interface being
> defined. MEMBER is an element of the MEMBERS parameter to
> `iface-declare'."
> (cl-destructuring-bind ((member-name inst-arg &rest xarglist)
> &optional doc) member
> (unless (and inst-arg
> (symbolp inst-arg)
> (not (eql (aref (symbol-name inst-arg) 0) ?\&)))
> (error (concat "Interface members must accept an instance as"
> " their first argument")))
> `(defun ,member-name (,inst-arg &rest xargs)
> ,doc
> (declare (advertised-calling-convention (,inst-arg ,@xarglist)
> ,emacs-version))
> (apply (cl-struct-slot-value ',iface-name ',member-name ,inst-arg)
> ,inst-arg xargs)))))
> (cl-defmacro iface-declare ((name base) &rest members)
> "Create a new interface called NAME, inheriting from BASE.
> MEMBERS is a list of member specifiers. Each is a list of the form
> ((NAME . ARGUMENTS) DOCUMENTATION), where NAME is a symbol
> naming the interface member, ARGUMENTS is a cl-lib-style argument
> list, and DOCUMENTATION is documentation to attach to that
> function."
> (let ((doc (and (stringp (car members)) (pop members)))
> (prefix (concat (symbol-name name) "--iface-")))
> `(progn
> (cl-defstruct (,name (:include ,base)
> (:conc-name ,(intern prefix))
> (:copier nil))
> ,@(if doc (list doc))
> ,@(mapcar #'caar members))
> ,@(mapcar (lambda (member)
> (iface--make-member-wrapper name member))
> members)
> ',name)))
But here you really don't need cl-struct-slot-value since you know very
well the name of the accessor functions.
And if you insist on doing it this way, you can wrap the cl-defstruct
within an eval-and-compile.
The problem with relying on CL semantics, is that it means that your
iface-declare will only work at top-level, e.g. not within a `cl-letf'
or a `cl-flet' or ...
So while the current semantics bites you, CL's semantics will also bite
you in other cases. IOW They just try to avoid biting you in a couple
more cases, but they can't avoid the fundamental problem.
The above example doesn't convince me yet that the convenience of hiding
the fundamental problem in those few cases is worth the trouble.
Maybe to solve this problem right, we'd need to do it in
macroexpand-all: detect a "defmacro" and add the corresponding macro to
macroexpand-all-environment for the rest of the expansion. Not sure
it'd be worth the trouble, but at least it would fix this "toplevel
special case".
Stefan
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [Emacs-diffs] trunk r117002: Correctly treat progn contents as toplevel forms when byte compiling
2014-04-22 4:46 ` Daniel Colascione
2014-04-22 15:06 ` Stefan Monnier
@ 2014-04-22 15:20 ` Stefan Monnier
2014-04-22 17:04 ` Daniel Colascione
1 sibling, 1 reply; 23+ messages in thread
From: Stefan Monnier @ 2014-04-22 15:20 UTC (permalink / raw)
To: Daniel Colascione; +Cc: emacs-devel
> `(defun ,member-name (,inst-arg &rest xargs)
> ,doc
> (declare (advertised-calling-convention (,inst-arg ,@xarglist)
> ,emacs-version))
> (apply (cl-struct-slot-value ',iface-name ',member-name ,inst-arg)
> ,inst-arg xargs)))))
I think we'd be just as happy, with something like
(defun method-call (method inst &rest args)
(apply (funcall method inst) inst args))
instead of defining umpteen "method call wrappers".
Stefan
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [Emacs-diffs] trunk r117002: Correctly treat progn contents as toplevel forms when byte compiling
2014-04-22 15:20 ` Stefan Monnier
@ 2014-04-22 17:04 ` Daniel Colascione
0 siblings, 0 replies; 23+ messages in thread
From: Daniel Colascione @ 2014-04-22 17:04 UTC (permalink / raw)
To: Stefan Monnier; +Cc: emacs-devel
[-- Attachment #1: Type: text/plain, Size: 911 bytes --]
On 04/22/2014 08:20 AM, Stefan Monnier wrote:
>> `(defun ,member-name (,inst-arg &rest xargs)
>> ,doc
>> (declare (advertised-calling-convention (,inst-arg ,@xarglist)
>> ,emacs-version))
>> (apply (cl-struct-slot-value ',iface-name ',member-name ,inst-arg)
>> ,inst-arg xargs)))))
>
> I think we'd be just as happy, with something like
>
> (defun method-call (method inst &rest args)
> (apply (funcall method inst) inst args))
>
> instead of defining umpteen "method call wrappers".
That way, you don't get docstrings, parameter-number checking, eldoc,
and so on. And you have to be aware that you're using this odd calling
convention instead of just calling a function like you would any other.
I'd much rather have the wrappers, which we can inline and make
practically free.
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 884 bytes --]
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [Emacs-diffs] trunk r117002: Correctly treat progn contents as toplevel forms when byte compiling
2014-04-22 15:06 ` Stefan Monnier
@ 2014-04-22 17:22 ` Daniel Colascione
2014-04-22 18:13 ` Daniel Colascione
2014-04-22 18:29 ` Stefan Monnier
0 siblings, 2 replies; 23+ messages in thread
From: Daniel Colascione @ 2014-04-22 17:22 UTC (permalink / raw)
To: Stefan Monnier; +Cc: emacs-devel
[-- Attachment #1: Type: text/plain, Size: 1101 bytes --]
On 04/22/2014 08:06 AM, Stefan Monnier wrote:
> And if you insist on doing it this way, you can wrap the cl-defstruct
> within an eval-and-compile.
>
> The problem with relying on CL semantics, is that it means that your
> iface-declare will only work at top-level, e.g. not within a `cl-letf'
> or a `cl-flet' or ...
> a
> So while the current semantics bites you, CL's semantics will also bite
> you in other cases. IOW They just try to avoid biting you in a couple
> more cases, but they can't avoid the fundamental problem.
>
> The above example doesn't convince me yet that the convenience of hiding
> the fundamental problem in those few cases is worth the trouble.
>
> Maybe to solve this problem right, we'd need to do it in
> macroexpand-all: detect a "defmacro" and add the corresponding macro to
> macroexpand-all-environment for the rest of the expansion. Not sure
> it'd be worth the trouble, but at least it would fix this "toplevel
> special case".
That's fine too, provided we handle the toplevel case correctly. Would
you accept a change that did that?
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 884 bytes --]
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [Emacs-diffs] trunk r117002: Correctly treat progn contents as toplevel forms when byte compiling
2014-04-22 17:22 ` Daniel Colascione
@ 2014-04-22 18:13 ` Daniel Colascione
2014-04-22 18:37 ` Stefan Monnier
2014-04-22 18:44 ` Drew Adams
2014-04-22 18:29 ` Stefan Monnier
1 sibling, 2 replies; 23+ messages in thread
From: Daniel Colascione @ 2014-04-22 18:13 UTC (permalink / raw)
To: Stefan Monnier; +Cc: emacs-devel
[-- Attachment #1: Type: text/plain, Size: 1943 bytes --]
On 04/22/2014 10:22 AM, Daniel Colascione wrote:
> On 04/22/2014 08:06 AM, Stefan Monnier wrote:
>> And if you insist on doing it this way, you can wrap the cl-defstruct
>> within an eval-and-compile.
>>
>> The problem with relying on CL semantics, is that it means that your
>> iface-declare will only work at top-level, e.g. not within a `cl-letf'
>> or a `cl-flet' or ...
>> a
>> So while the current semantics bites you, CL's semantics will also bite
>> you in other cases. IOW They just try to avoid biting you in a couple
>> more cases, but they can't avoid the fundamental problem.
>>
>> The above example doesn't convince me yet that the convenience of hiding
>> the fundamental problem in those few cases is worth the trouble.
>>
>> Maybe to solve this problem right, we'd need to do it in
>> macroexpand-all: detect a "defmacro" and add the corresponding macro to
>> macroexpand-all-environment for the rest of the expansion. Not sure
>> it'd be worth the trouble, but at least it would fix this "toplevel
>> special case".
>
> That's fine too, provided we handle the toplevel case correctly. Would
> you accept a change that did that?
That said, the CL way is much better. It's conceptually simpler to say
that defmacro at toplevel is well-defined (progn contents being
considered "toplevel") and everything else is undefined than to try to
support this defmacro stuff in *all* contexts and run into the exciting
corner inherent in your approach: cases involving nested macroexpand-all
calls in particular would be interesting. You worried about the level of
"detail" required to maintain this stuff, yet you're talking about
greatly increasing, relative to my change, the number of situations in
which we have to define macro expansion semantics. The CL toplevel
semantics are required to support real code: yours are not. Nobody is
going to write a defmacro at toplevel inside a cl-letf.
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 884 bytes --]
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [Emacs-diffs] trunk r117002: Correctly treat progn contents as toplevel forms when byte compiling
2014-04-22 17:22 ` Daniel Colascione
2014-04-22 18:13 ` Daniel Colascione
@ 2014-04-22 18:29 ` Stefan Monnier
1 sibling, 0 replies; 23+ messages in thread
From: Stefan Monnier @ 2014-04-22 18:29 UTC (permalink / raw)
To: Daniel Colascione; +Cc: emacs-devel
> That's fine too, provided we handle the toplevel case correctly.
> Would you accept a change that did that?
Depends on what ends up being needed for it. But if it's not too ugly, yes.
Stefan
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [Emacs-diffs] trunk r117002: Correctly treat progn contents as toplevel forms when byte compiling
2014-04-22 18:13 ` Daniel Colascione
@ 2014-04-22 18:37 ` Stefan Monnier
2014-04-22 19:08 ` Daniel Colascione
2014-04-22 18:44 ` Drew Adams
1 sibling, 1 reply; 23+ messages in thread
From: Stefan Monnier @ 2014-04-22 18:37 UTC (permalink / raw)
To: Daniel Colascione; +Cc: emacs-devel
> Nobody is going to write a defmacro at toplevel inside a cl-letf.
So far, nobody has written the kind of code you say you want to write.
In both cases it's trying to handle hypothetical cases, so indeed,
I prefer neither overall.
I'm OK with adding a bit of complexity if it removes special cases
(which my proposal might do, tho I have no experience with it, so maybe
it'll need horrendous hacks to implement and additionally it will
introduce new special cases), but the CL semantics adds complexity
without really removing special cases: it just moves the "special case
boundary" elsewhere. And I don't like it for that reason.
It's a question of taste, to a large extent, hence the bikeshedding.
I prefer you adding `eval-and-compile' at a few places to work around
the "buggy Elisp semantics" over imposing the CL semantics.
Stefan
^ permalink raw reply [flat|nested] 23+ messages in thread
* RE: [Emacs-diffs] trunk r117002: Correctly treat progn contents as toplevel forms when byte compiling
2014-04-22 18:13 ` Daniel Colascione
2014-04-22 18:37 ` Stefan Monnier
@ 2014-04-22 18:44 ` Drew Adams
2014-04-22 19:23 ` Daniel Colascione
1 sibling, 1 reply; 23+ messages in thread
From: Drew Adams @ 2014-04-22 18:44 UTC (permalink / raw)
To: Daniel Colascione, Stefan Monnier; +Cc: emacs-devel
> That said, the CL way is much better. It's conceptually simpler to say
> that defmacro at toplevel is well-defined (progn contents being
> considered "toplevel") and everything else is undefined than to try to
> support this defmacro stuff in *all* contexts and run into the exciting
> corner inherent in your approach...
Are you saying that in CL if defmacro is used elsewhere than at top level
it is not well-defined? That doesn't sound right to me.
(Apologies if I misunderstand. If so, or if irrelevant, please ignore.)
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [Emacs-diffs] trunk r117002: Correctly treat progn contents as toplevel forms when byte compiling
2014-04-22 18:37 ` Stefan Monnier
@ 2014-04-22 19:08 ` Daniel Colascione
0 siblings, 0 replies; 23+ messages in thread
From: Daniel Colascione @ 2014-04-22 19:08 UTC (permalink / raw)
To: Stefan Monnier; +Cc: emacs-devel
[-- Attachment #1: Type: text/plain, Size: 2479 bytes --]
On 04/22/2014 11:37 AM, Stefan Monnier wrote:
>> Nobody is going to write a defmacro at toplevel inside a cl-letf.
> I'm OK with adding a bit of complexity if it removes special cases
> (which my proposal might do, tho I have no experience with it, so maybe
> it'll need horrendous hacks to implement and additionally it will
> introduce new special cases),
I think it will need horrendous hacks (but maybe I'm wrong). We'd have
to expand macros step-by-step and check recursively for macro-defining
macros, and probably introduce some kind of special alternative defmacro
in the environment, since the normal `defmacro' is itself a macro and
would be hidden by macroexpand. (Imagine a macro that just expands to a
single defmacro --- we'd still want to add that macro to our temporary
environment.) To address this problem, we could merge macroexpand-1
instead, but that's an even bigger change. You also have to worry about
nested macroexpand-all calls, leakage between defuns, and so on. There
are interesting corner cases too: what about (progn (and nil (defmacro
foo () ...)) (foo))?
The current code works, solves a real problem, matches many other lisp
implementations, and has automated tests. It doesn't affect (and slow)
every macro expansion everywhere.
> but the CL semantics adds complexity
> without really removing special cases: it just moves the "special case
> boundary" elsewhere. And I don't like it for that reason.
> It's a question of taste, to a large extent, hence the bikeshedding.
Your proposal is equivalent to sucking all the forms "following" (in
some sense) a defmacro into an implicit macrolet that defines the same
macro that the defmacro does. Fine. But how do you decide how much code
is included in this implicit macrolet? All the remaining forms in the
current call to macroexpand-all? That's too broad: a macro defined in
one defun shouldn't affect forms in a completely different defun. The
forms following the defmacro in the same progn? That's too narrow ---
there's still a "special case boundary". I think that no matter where we
choose to put the implicit macrolet, it'll surprise someone. I'd rather
not try. Instead, we should address the case that's come up in practice
(and that came up 20 years ago in Common Lisp).
> I prefer you adding `eval-and-compile' at a few places to work around
> the "buggy Elisp semantics" over imposing the CL semantics.
I'm not going to do that.
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 884 bytes --]
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [Emacs-diffs] trunk r117002: Correctly treat progn contents as toplevel forms when byte compiling
2014-04-22 18:44 ` Drew Adams
@ 2014-04-22 19:23 ` Daniel Colascione
2014-04-22 19:59 ` Drew Adams
0 siblings, 1 reply; 23+ messages in thread
From: Daniel Colascione @ 2014-04-22 19:23 UTC (permalink / raw)
To: Drew Adams, Stefan Monnier; +Cc: emacs-devel
[-- Attachment #1: Type: text/plain, Size: 984 bytes --]
On 04/22/2014 11:44 AM, Drew Adams wrote:
>> That said, the CL way is much better. It's conceptually simpler to say
>> that defmacro at toplevel is well-defined (progn contents being
>> considered "toplevel") and everything else is undefined than to try to
>> support this defmacro stuff in *all* contexts and run into the exciting
>> corner inherent in your approach...
>
> Are you saying that in CL if defmacro is used elsewhere than at top level
> it is not well-defined? That doesn't sound right to me.
>
> (Apologies if I misunderstand. If so, or if irrelevant, please ignore.)
Compilers appear to differ. Consider the code below:
(defun foo ()
(defmacro bar () 1)
(bar))
(format t "~s" (foo))
SBCL and ECL both signal an error. CLISP compiles the file, substituting
(bar) with 1, then complains when calling foo that bar is redefined. The
SBCL and ECL behavior is what I'd expect from reading the spec, but
maybe I misunderstood something.
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 884 bytes --]
^ permalink raw reply [flat|nested] 23+ messages in thread
* RE: [Emacs-diffs] trunk r117002: Correctly treat progn contents as toplevel forms when byte compiling
2014-04-22 19:23 ` Daniel Colascione
@ 2014-04-22 19:59 ` Drew Adams
2014-04-22 20:10 ` Daniel Colascione
0 siblings, 1 reply; 23+ messages in thread
From: Drew Adams @ 2014-04-22 19:59 UTC (permalink / raw)
To: Daniel Colascione, Stefan Monnier; +Cc: emacs-devel
> >> That said, the CL way is much better. It's conceptually simpler to say
> >> that defmacro at toplevel is well-defined (progn contents being
> >> considered "toplevel") and everything else is undefined than to try to
> >> support this defmacro stuff in *all* contexts and run into the exciting
> >> corner inherent in your approach...
> >
> > Are you saying that in CL if defmacro is used elsewhere than at top level
> > it is not well-defined? That doesn't sound right to me.
> >
> > (Apologies if I misunderstand. If so, or if irrelevant, please ignore.)
>
> Compilers appear to differ. Consider the code below:
>
> (defun foo ()
> (defmacro bar () 1)
> (bar))
>
> (format t "~s" (foo))
>
> SBCL and ECL both signal an error. CLISP compiles the file, substituting
> (bar) with 1, then complains when calling foo that bar is redefined.
I see. But that does not imply that the standard says that the behavior
is undefined for `defmacro' at other than top level. That's what I
thought you were saying. Implementations do not always implement what
a standard says. ;-)
> The SBCL and ECL behavior is what I'd expect from reading the spec, but
> maybe I misunderstood something.
Hm. What part of the spec do you think gives the impression that
`defmacro' behavior is defined only at top level?
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [Emacs-diffs] trunk r117002: Correctly treat progn contents as toplevel forms when byte compiling
2014-04-22 19:59 ` Drew Adams
@ 2014-04-22 20:10 ` Daniel Colascione
2014-04-22 20:41 ` Drew Adams
0 siblings, 1 reply; 23+ messages in thread
From: Daniel Colascione @ 2014-04-22 20:10 UTC (permalink / raw)
To: Drew Adams, Stefan Monnier; +Cc: emacs-devel
[-- Attachment #1: Type: text/plain, Size: 1879 bytes --]
On 04/22/2014 12:59 PM, Drew Adams wrote:
>> The SBCL and ECL behavior is what I'd expect from reading the spec, but
>> maybe I misunderstood something.
>
> Hm. What part of the spec do you think gives the impression that
> `defmacro' behavior is defined only at top level?
defmacro is specced to "define[] name as a macro by associating a macro
function with that name in the global environment". Like any form, it's
supposed to do that when it's evaluated, and forms inside defuns aren't
evaluated when they're loaded or compiled: they're evaluated when the
defun is called. So you should expect a defmacro inside a defun to have
no effect unti lthe defun is called.
Likewise, if a defmacro appears at top level, it should ordinarily be
evaluated only when the file that contains it is loaded, just like any
other toplevel form. So, without special provisions, defmacro should not
be expanded inside forms that happen to be in the same file.
But this behavior isn't very useful, so as a special case, CL specifies
that "if a defmacro form appears as a top level form, the compiler must
store the macro definition at compile time, so that occurrences of the
macro later on in the file can be expanded correctly. Users must ensure
that the body of the macro can be evaluated at compile time if it is
referenced within the file being compiled."
It's because of this special case that a normal defmacro, not wrapped in
an eval-when, has any effect on compilation of forms in the same file. A
defmacro inside a defun isn't covered by this special case, so its
behavior should revert to the normal behavior for forms. SBCL and ECL
implement this model of evaluation. CLISP's behavior appears to be
incorrect here.
The behavior I'm proposing for Emacs is identical to what SBCL and ECL
do. Stefan is proposing that we adopt CLISP behavior.
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 884 bytes --]
^ permalink raw reply [flat|nested] 23+ messages in thread
* RE: [Emacs-diffs] trunk r117002: Correctly treat progn contents as toplevel forms when byte compiling
2014-04-22 20:10 ` Daniel Colascione
@ 2014-04-22 20:41 ` Drew Adams
2014-04-22 21:05 ` Daniel Colascione
2014-04-23 0:50 ` Stephen J. Turnbull
0 siblings, 2 replies; 23+ messages in thread
From: Drew Adams @ 2014-04-22 20:41 UTC (permalink / raw)
To: Daniel Colascione, Stefan Monnier; +Cc: emacs-devel
> >> The SBCL and ECL behavior is what I'd expect from reading the spec, but
> >> maybe I misunderstood something.
> >
> > Hm. What part of the spec do you think gives the impression that
> > `defmacro' behavior is defined only at top level?
>
> defmacro is specced to "define[] name as a macro by associating a macro
> function with that name in the global environment".
> Like any form, it's supposed to do that when it's evaluated,
Yes, anywhere and anywhen it's evaluated, including from a file at any
level. And including when invoked from running code. And including
`defmacro' forms that are generated and eval'd on the fly.
> and forms inside defuns aren't evaluated when they're loaded or
> compiled: they're evaluated when the defun is called. So you should
> expect a defmacro inside a defun to have no effect unti lthe defun is
> called.
Agreed, but when the defun is called and the `defmacro' is evaluated,
its behavior should be well-defined - it is not just up for grabs or
up to the implementation.
But I do see now that you allowed for `progn' contexts, at least.
I guess you meant any context, like progn, which evaluates the
`defmacro' at load or compile time.
> Likewise, if a defmacro appears at top level, it should ordinarily be
> evaluated only when the file that contains it is loaded, just like any
> other toplevel form. So, without special provisions, defmacro should not
> be expanded inside forms that happen to be in the same file.
>
> But this behavior isn't very useful, so as a special case, CL specifies
> that "if a defmacro form appears as a top level form, the compiler must
> store the macro definition at compile time, so that occurrences of the
> macro later on in the file can be expanded correctly. Users must ensure
> that the body of the macro can be evaluated at compile time if it is
> referenced within the file being compiled."
That was precisely the passage I was thinking of, BTW.
It does not say anything about `defmacro' inside a defun signaling a
compile-time error, as opposed to doing what you write above: "have no
effect until the defun is called". A priori, when the defun is called
the `defmacro' inside it should be evaluated, defining the macro
normally, no?
It says clearly that IF you expect the macro to be available to code
in the same file at compile time for that file, THEN you must ensure
that it gets evaluated at compile time. If not, then not.
> It's because of this special case that a normal defmacro, not wrapped in
> an eval-when, has any effect on compilation of forms in the same file. A
> defmacro inside a defun isn't covered by this special case, so its
> behavior should revert to the normal behavior for forms.
Which is what? Why isn't it that the embedded `defmacro' would, as you
said "have no effect until the defun is called"?
> SBCL and ECL implement this model of evaluation. CLISP's behavior
> appears to be incorrect here.
I don't see that either of those behaviors realizes the exclusive truth
here. All I see that passage saying is that you must not expect a
`defvar' embedded in a defun to have an effect, at compile time, on
subsequent code located in the same file. I don't see that as a call
to raise a compile-time error.
> The behavior I'm proposing for Emacs is identical to what SBCL and ECL
> do. Stefan is proposing that we adopt CLISP behavior.
I see. Anyway, I misunderstood your original comment about `defmacro'
behavior being undefined if not at top level - sorry.
(And I have no special opinion about the question you are deciding.
A priori, I prefer that Emacs Lisp be closer to CL, but I have no
opinion about this particular issue.)
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [Emacs-diffs] trunk r117002: Correctly treat progn contents as toplevel forms when byte compiling
2014-04-22 20:41 ` Drew Adams
@ 2014-04-22 21:05 ` Daniel Colascione
2014-04-23 0:50 ` Stephen J. Turnbull
1 sibling, 0 replies; 23+ messages in thread
From: Daniel Colascione @ 2014-04-22 21:05 UTC (permalink / raw)
To: Drew Adams, Stefan Monnier; +Cc: emacs-devel
[-- Attachment #1: Type: text/plain, Size: 2674 bytes --]
On 04/22/2014 01:41 PM, Drew Adams wrote:
>>>> The SBCL and ECL behavior is what I'd expect from reading the spec, but
>>>> maybe I misunderstood something.
>>>
>>> Hm. What part of the spec do you think gives the impression that
>>> `defmacro' behavior is defined only at top level?
>>
>> defmacro is specced to "define[] name as a macro by associating a macro
>> function with that name in the global environment".
>
>> Like any form, it's supposed to do that when it's evaluated,
>
> Yes, anywhere and anywhen it's evaluated, including from a file at any
> level. And including when invoked from running code. And including
> `defmacro' forms that are generated and eval'd on the fly.
That goes without saying.
> But I do see now that you allowed for `progn' contexts, at least.
> I guess you meant any context, like progn, which evaluates the
> `defmacro' at load or compile time.
>
> It does not say anything about `defmacro' inside a defun signaling a
> compile-time error, as opposed to doing what you write above: "have no
> effect until the defun is called". A priori, when the defun is called
> the `defmacro' inside it should be evaluated, defining the macro
> normally, no?
Neither did I. I was imprecise: the code I mentioned compiles without
error. It signals an error at runtime because there is no function
called `bar'. The function is trying to call `bar' because the macro
`bar' wasn't expanded during compilation.
> It says clearly that IF you expect the macro to be available to code
> in the same file at compile time for that file, THEN you must ensure
> that it gets evaluated at compile time. If not, then not.
>
>> It's because of this special case that a normal defmacro, not wrapped in
>> an eval-when, has any effect on compilation of forms in the same file. A
>> defmacro inside a defun isn't covered by this special case, so its
>> behavior should revert to the normal behavior for forms.
>
> Which is what? Why isn't it that the embedded `defmacro' would, as you
> said "have no effect until the defun is called"?
"No effect until the defun is called" is the correct behavior.
>> SBCL and ECL implement this model of evaluation. CLISP's behavior
>> appears to be incorrect here.
>
> I don't see that either of those behaviors realizes the exclusive truth
> here. All I see that passage saying is that you must not expect a
> `defvar' embedded in a defun to have an effect, at compile time, on
> subsequent code located in the same file. I don't see that as a call
> to raise a compile-time error.
There is no compile-time error; sorry for the misunderstanding.
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 884 bytes --]
^ permalink raw reply [flat|nested] 23+ messages in thread
* RE: [Emacs-diffs] trunk r117002: Correctly treat progn contents as toplevel forms when byte compiling
2014-04-22 20:41 ` Drew Adams
2014-04-22 21:05 ` Daniel Colascione
@ 2014-04-23 0:50 ` Stephen J. Turnbull
1 sibling, 0 replies; 23+ messages in thread
From: Stephen J. Turnbull @ 2014-04-23 0:50 UTC (permalink / raw)
To: Drew Adams; +Cc: Daniel Colascione, Stefan Monnier, emacs-devel
Drew Adams writes:
> Yes, anywhere and anywhen it's evaluated, including from a file at
> any level. And including when invoked from running code. And
> including `defmacro' forms that are generated and eval'd on the
> fly.
The point is that the list of cases you have above is correct
*because* it does not include "when compiling". The compiler does not
evaluate the forms it processes, with a very few exceptions. AFAIK
the only forms in the compiled text that cause evaluation at compile
time are `eval-when' and friends.
> But I do see now that you allowed for `progn' contexts, at least.
> I guess you meant any context, like progn, which evaluates the
> `defmacro' at load or compile time.
`progn' does not evaluate anything at compile time.
^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2014-04-23 0:50 UTC | newest]
Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <E1WcAcP-0006zy-MJ@vcs.savannah.gnu.org>
2014-04-21 15:09 ` [Emacs-diffs] trunk r117002: Correctly treat progn contents as toplevel forms when byte compiling Stefan Monnier
2014-04-21 17:44 ` Daniel Colascione
2014-04-21 22:09 ` Stefan Monnier
2014-04-21 22:29 ` Daniel Colascione
2014-04-22 2:09 ` Stefan Monnier
2014-04-22 2:21 ` Daniel Colascione
2014-04-22 4:25 ` Stefan Monnier
2014-04-22 4:46 ` Daniel Colascione
2014-04-22 15:06 ` Stefan Monnier
2014-04-22 17:22 ` Daniel Colascione
2014-04-22 18:13 ` Daniel Colascione
2014-04-22 18:37 ` Stefan Monnier
2014-04-22 19:08 ` Daniel Colascione
2014-04-22 18:44 ` Drew Adams
2014-04-22 19:23 ` Daniel Colascione
2014-04-22 19:59 ` Drew Adams
2014-04-22 20:10 ` Daniel Colascione
2014-04-22 20:41 ` Drew Adams
2014-04-22 21:05 ` Daniel Colascione
2014-04-23 0:50 ` Stephen J. Turnbull
2014-04-22 18:29 ` Stefan Monnier
2014-04-22 15:20 ` Stefan Monnier
2014-04-22 17:04 ` Daniel Colascione
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.