[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Emacs-diffs] trunk r117002: Correctly treat progn contents as tople

From: Stefan Monnier
Subject: Re: [Emacs-diffs] trunk r117002: Correctly treat progn contents as toplevel forms when byte compiling
Date: Tue, 22 Apr 2014 11:06:04 -0400
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.4.50 (gnu/linux)

> (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".


reply via email to

[Prev in Thread] Current Thread [Next in Thread]