emacs-devel
[Top][All Lists]
Advanced

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

Re: Can the byte-compiler check whether functions passed by name are def


From: Stefan Monnier
Subject: Re: Can the byte-compiler check whether functions passed by name are defined?
Date: Wed, 07 Aug 2013 13:34:41 -0400
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3.50 (gnu/linux)

>>>>> "Stefan" == Stefan Monnier <address@hidden> writes:

>> The patch only adds a single line of code to byte-compile-normal-call
>> which calls defun byte-compile--higher-order--check-arguments.

> But there's no normal call in (if a #'foo1 #'foo2), so how can this work?


>         Stefan

I installed the patch below which checks that #'foo refers to a function
that will exist.


        Stefan


=== modified file 'lisp/ChangeLog'
--- lisp/ChangeLog      2013-08-07 16:37:04 +0000
+++ lisp/ChangeLog      2013-08-07 17:33:11 +0000
@@ -1,3 +1,11 @@
+2013-08-07  Stefan Monnier  <address@hidden>
+
+       * emacs-lisp/bytecomp.el: Check existence of f in #'f.
+       (byte-compile-callargs-warn): Use `push'.
+       (byte-compile-arglist-warn): Ignore higher-order "calls".
+       (byte-compile-file-form-autoload): Use `pcase'.
+       (byte-compile-function-form): If quoting a symbol, check that it exists.
+
 2013-08-07  Eli Zaretskii  <address@hidden>
 
        * progmodes/dos.el (dos-font-lock-keywords): Rename LINUX to UNIX

=== modified file 'lisp/emacs-lisp/bytecomp.el'
--- lisp/emacs-lisp/bytecomp.el 2013-06-19 07:35:00 +0000
+++ lisp/emacs-lisp/bytecomp.el 2013-08-07 17:20:38 +0000
@@ -1364,7 +1364,10 @@
       ;; This is the first definition.  See if previous calls are compatible.
       (let ((calls (assq name byte-compile-unresolved-functions))
            nums sig min max)
-       (when calls
+        (setq byte-compile-unresolved-functions
+              (delq calls byte-compile-unresolved-functions))
+        (setq calls (delq t calls))  ;Ignore higher-order uses of the function.
+       (when (cdr calls)
           (when (and (symbolp name)
                      (eq (function-get name 'byte-optimizer)
                          'byte-compile-inline-expand))
@@ -1382,10 +1385,7 @@
              name
              (byte-compile-arglist-signature-string sig)
              (if (equal sig '(1 . 1)) " arg" " args")
-             (byte-compile-arglist-signature-string (cons min max))))
-
-          (setq byte-compile-unresolved-functions
-                (delq calls byte-compile-unresolved-functions)))))))
+             (byte-compile-arglist-signature-string (cons min max)))))))))
 
 (defvar byte-compile-cl-functions nil
   "List of functions defined in CL.")
@@ -3574,9 +3570,31 @@
 ;; and (funcall (function foo)) will lose with autoloads.
 
 (defun byte-compile-function-form (form)
-  (byte-compile-constant (if (eq 'lambda (car-safe (nth 1 form)))
-                             (byte-compile-lambda (nth 1 form))
-                           (nth 1 form))))
+  (let ((f (nth 1 form)))
+    (when (and (symbolp f)
+               (byte-compile-warning-enabled-p 'callargs))
+      (when (get f 'byte-obsolete-info)
+        (byte-compile-warn-obsolete (car form)))
+
+      ;; Check to see if the function will be available at runtime
+      ;; and/or remember its arity if it's unknown.
+      (or (and (or (fboundp f)          ; Might be a subr or autoload.
+                   (byte-compile-fdefinition (car form) nil))
+               (not (memq f byte-compile-noruntime-functions)))
+          (eq f byte-compile-current-form) ; ## This doesn't work
+                                           ; with recursion.
+          ;; It's a currently-undefined function.
+          ;; Remember number of args in call.
+          (let ((cons (assq f byte-compile-unresolved-functions)))
+            (if cons
+                (or (memq t (cdr cons))
+                    (push t (cdr cons)))
+              (push (list f t)
+                    byte-compile-unresolved-functions)))))
+
+    (byte-compile-constant (if (eq 'lambda (car-safe f))
+                               (byte-compile-lambda f)
+                             f))))
 
 (defun byte-compile-indent-to (form)
   (let ((len (length form)))




reply via email to

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