all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* 'Compiler' functionality for Emacs Lisp
@ 2010-07-29  3:46 Cecil Westerhof
  2010-07-29  4:47 ` Fren Zeee
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Cecil Westerhof @ 2010-07-29  3:46 UTC (permalink / raw)
  To: help-gnu-emacs

When using for example C++ the compiler does a lot of checks for you.
For example it checks if all your variables are declared or used and
it does even find potential memory leaks. Is there something like this
for Emacs Lisp? I am writing bigger functions nowadays. Yesterday I
found out that not all my variables where declared in a let block and
I had forgotten to remove a few I where not using anymore. Is there
something that could do these checks for me?

I am using: GNU Emacs 23.1.1.

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: 'Compiler' functionality for Emacs Lisp
  2010-07-29  3:46 'Compiler' functionality for Emacs Lisp Cecil Westerhof
@ 2010-07-29  4:47 ` Fren Zeee
  2010-07-29  7:55 ` Pascal J. Bourguignon
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Fren Zeee @ 2010-07-29  4:47 UTC (permalink / raw)
  To: help-gnu-emacs

On Jul 28, 8:46 pm, Cecil Westerhof <Ce...@decebal.nl> wrote:
> When using for example C++ the compiler does a lot of checks for you.
> For example it checks if all your variables are declared or used and
> it does even find potential memory leaks. Is there something like this
> for Emacs Lisp? I am writing bigger functions nowadays. Yesterday I
> found out that not all my variables where declared in a let block and
> I had forgotten to remove a few I where not using anymore. Is there
> something that could do these checks for me?
>
> I am using: GNU Emacs 23.1.1.
>
> --
> Cecil Westerhof
> Senior Software Engineer
> LinkedIn:http://www.linkedin.com/in/cecilwesterhof

You could add a lint like primitive function (necessary for speed)
once you figure out how the C code in emacs works. Be sure to share on
this group what you find on this matter.


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: 'Compiler' functionality for Emacs Lisp
  2010-07-29  3:46 'Compiler' functionality for Emacs Lisp Cecil Westerhof
  2010-07-29  4:47 ` Fren Zeee
@ 2010-07-29  7:55 ` Pascal J. Bourguignon
  2010-07-29  9:54 ` Stefan Monnier
  2010-07-29 11:47 ` Elena
  3 siblings, 0 replies; 5+ messages in thread
From: Pascal J. Bourguignon @ 2010-07-29  7:55 UTC (permalink / raw)
  To: help-gnu-emacs

Cecil Westerhof <Cecil@decebal.nl> writes:

> When using for example C++ the compiler does a lot of checks for you.
> For example it checks if all your variables are declared or used and
> it does even find potential memory leaks. Is there something like this
> for Emacs Lisp? I am writing bigger functions nowadays. Yesterday I
> found out that not all my variables where declared in a let block and
> I had forgotten to remove a few I where not using anymore. Is there
> something that could do these checks for me?

Lisp is fundamentally different from C++.

Perhaps you haven't noticed, but when you compile your lisp function,
you don't have to recompile the whole emacs!

This is something you would have to do with C++, to allow these global
checks.


About variables, again, emacs lisp variables are totally different
from C++ variables.  In C++, variables are lexical variables.  In
emacs lisp, all the variables are dynamic variables.  This means that
it is not an error to use a free variable in a function, or to define
(with let) a variable that doesn't seem to be used in the let body.
Because the variable may be defined in a different function that calls
yours, or used in a different function that you call.


(defun f ()
  (let ((x 1))
    ;; isn't x used?
    (g)))

(defun g ()
  (let ((y 2))
    ;; isn't y used?
    (list x ; x is used here!
          (h))))

(defun h ()
  y) ; y is used here!

(f)
;;  --> (1 2)


Of course, it's up to the caller to fulfil the contract of function
such as h, and to define their free variables:

(h)
;; --> Debugger entered--Lisp error: (void-variable y)

(let ((y 42)) (h))
;; --> 42


Now, even more:

(defun hh ()
  (list y x)) ; yet other free variables.

(defvar *hook* 'h)

(defun g ()
  (let ((y 2))
  (message "ghh %S" *hook*)
  (list x (funcall *hook*))))

(f)
;; --> (1 2)

(require 'cl)
(setf *hook* 'hh)
(f)
;; --> (1 (2 1))

which show that when this new g calls the function in *hook*, nobody
can know in advance what function will be called.  The emacs user may
at any time change the value of the variable *hook*, to call another
function.  Therefore there is absolutely no way to do a comprenhesive
and general compilation-time check of the use of emacs lisp variables.

You're in a dynamic world!  Anything can change at any time!




Now, if you want (as we all should in most cases, really) to use a
sublanguage where variables are used as if they were lexical
variables, you can easily enough write static analysis tools for emacs
lisp code.  For example, here is a function that extracts the free
variables from a lambda expression:

(require 'cl)
(defun* free-variables (expression &optional (bound-variables '()))
  (cond
    ((symbolp expression) (if (member expression bound-variables)
                             '()
                             (list expression)))
    ((atom expression)   '())
    ((eq 'lambda (car expression))
     (let ((bound-variables (append (cadr expression) bound-variables)))
       (mapcan (lambda (subexpr) (free-variables subexpr bound-variables))
               (cddr expression))))
    (t (mapcan (lambda (subexpr) (free-variables subexpr bound-variables))
               expression))))


(free-variables '((lambda (b) (+ ((lambda (x) (* 2 x)) a) b)) 3) '())
;; --> (+ * a)

(free-variables '(lambda () a) '())
;; --> (a)


Of course, you would have to process let, let*, macros, etc, etc, to
make it complete.

Other functions like this may be written to check that all variables
are used in their lexical scope, and you may also check that any
variable defined in a function f, that are visible in the scope of the
call to a function g, are not free variables in the function g (or any
function called from g).  If you ever see f calling a hook, for which
you cannot determine the set of functions that may be called at
run-time, then you would have to further check that the variables of f
are not free variables in all the functions in emacs lisp.
Well, apart from the cases where you do want to use a special variable.

For example, case-fold-search is a dynamic variable that is used by
some emacs lisp functions as a global parameter:

(defun f (cf)
  (let ((case-fold-search cf))
    (string-match "abc" "toto ABC abc toto")))

(list (f nil) (f t)) 
;; --> (9 5)


In Common Lisp, we would use a declaration to indicate that we want a
special variable (dynamic) instead of a normal variable (lexical):

#+common-lisp (defun f (cf)
                 (let ((case-fold-search cf))
                    (declare (special case-fold-search))
                    (do-something)))

Of course, in Common Lisp  since the default is lexical variables, the
compiler may check more easily when you're using a free variable, or
when you're not using a defined variable.  Perhaps you may want to use
emacs-cl, which is a Common Lisp implementation written in emacs-lisp,
and which would allow you to write your emacs functions in Common Lisp
instead of emacs lisp?


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: 'Compiler' functionality for Emacs Lisp
  2010-07-29  3:46 'Compiler' functionality for Emacs Lisp Cecil Westerhof
  2010-07-29  4:47 ` Fren Zeee
  2010-07-29  7:55 ` Pascal J. Bourguignon
@ 2010-07-29  9:54 ` Stefan Monnier
  2010-07-29 11:47 ` Elena
  3 siblings, 0 replies; 5+ messages in thread
From: Stefan Monnier @ 2010-07-29  9:54 UTC (permalink / raw)
  To: help-gnu-emacs

> When using for example C++ the compiler does a lot of checks for you.
> For example it checks if all your variables are declared or used and
> it does even find potential memory leaks. Is there something like this
> for Emacs Lisp? I am writing bigger functions nowadays. Yesterday I
> found out that not all my variables where declared in a let block and
> I had forgotten to remove a few I where not using anymore. Is there
> something that could do these checks for me?

The byte-compiler's warnings are pretty much the "best" there
is currently.


        Stefan


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: 'Compiler' functionality for Emacs Lisp
  2010-07-29  3:46 'Compiler' functionality for Emacs Lisp Cecil Westerhof
                   ` (2 preceding siblings ...)
  2010-07-29  9:54 ` Stefan Monnier
@ 2010-07-29 11:47 ` Elena
  3 siblings, 0 replies; 5+ messages in thread
From: Elena @ 2010-07-29 11:47 UTC (permalink / raw)
  To: help-gnu-emacs

Check out Emacs' standard package "elint".


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2010-07-29 11:47 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-07-29  3:46 'Compiler' functionality for Emacs Lisp Cecil Westerhof
2010-07-29  4:47 ` Fren Zeee
2010-07-29  7:55 ` Pascal J. Bourguignon
2010-07-29  9:54 ` Stefan Monnier
2010-07-29 11:47 ` Elena

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.