diff --git a/etc/NEWS b/etc/NEWS index 63957628b98..c08b0052639 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1828,14 +1828,19 @@ Like 'static-if', these macros evaluate their condition at macro-expansion time and are useful for writing code that can work across different Emacs versions. +** Lexical binding + --- -** You can change the default value of 'lexical-binding'. +*** You can change the default value of 'lexical-binding'. While the default is still the use of dynamic binding dialect of Elisp in those places that don't explicitly set 'lexical-binding' you can change it globally with: (set-default-toplevel-value 'lexical-binding t) +--- +*** Loading a file displays a warning if there is no 'lexical-binding' cookie. + +++ ** New macros 'incf' and 'decf'. They increment or decrement the value stored in a variable (a symbol), diff --git a/lisp/files.el b/lisp/files.el index eb49f25ee27..7ba4079a650 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -4277,6 +4277,30 @@ all the specified local variables, but ignores any settings of \"mode:\"." (push elem file-local-variables-alist))) (hack-local-variables-apply)))))) +(defun internal--get-default-lexical-binding (from) + (let ((mib (lambda (node) (buttonize node (lambda (_) (info node)))))) + (or (and (bufferp from) (zerop (buffer-size from))) + (and (stringp from) + (eql 0 (file-attribute-size (file-attributes from)))) + (display-warning + '(files missing-lexbind-cookie) + (format-message "Missing `lexical-binding' cookie in %S. +You can add one with `M-x elisp-enable-lexical-binding RET'. +See `%s' and `%s' +for more information." + (if (not (and (bufferp from) + (equal (buffer-name from) " *load*") + load-file-name)) + from + (abbreviate-file-name load-file-name)) + (funcall mib "(elisp)Selecting Lisp Dialect") + (funcall mib "(elisp)Converting to Lexical Binding")) + :warning)) + (default-toplevel-value 'lexical-binding))) + +(setq internal--get-default-lexical-binding-function + #'internal--get-default-lexical-binding) + (defun hack-local-variables--find-variables (&optional handle-mode) "Return all local variables in the current buffer. If HANDLE-MODE is nil, we gather all the specified local diff --git a/src/lread.c b/src/lread.c index add8deb3954..445e5cd1fba 100644 --- a/src/lread.c +++ b/src/lread.c @@ -1271,6 +1271,18 @@ close_file_unwind_android_fd (void *ptr) #endif +static Lisp_Object +get_lexical_binding (Lisp_Object stream, Lisp_Object from) +{ + lexical_cookie_t lexc = lisp_file_lexical_cookie (stream); + return (lexc == Cookie_Lex ? Qt + : lexc == Cookie_Dyn ? Qnil + : (NILP (from) /* Loading a byte-compiled file. */ + || NILP (Vinternal__get_default_lexical_binding_function) + ? Fdefault_toplevel_value (Qlexical_binding) + : calln (Vinternal__get_default_lexical_binding_function, from))); +} + DEFUN ("load", Fload, Sload, 1, 5, 0, doc: /* Execute a file of Lisp code named FILE. First try FILE with `.elc' appended, then try with `.el', then try @@ -1720,11 +1732,8 @@ Return t if the file exists and loads successfully. */) } else { - lexical_cookie_t lexc = lisp_file_lexical_cookie (Qget_file_char); Fset (Qlexical_binding, - (lexc == Cookie_Lex ? Qt - : lexc == Cookie_Dyn ? Qnil - : Fdefault_toplevel_value (Qlexical_binding))); + get_lexical_binding (Qget_file_char, compiled ? Qnil : file)); if (! version || version >= 22) readevalloop (Qget_file_char, &input, hist_file_name, @@ -2609,11 +2618,7 @@ This function preserves the position of point. */) specbind (Qstandard_output, tem); record_unwind_protect_excursion (); BUF_TEMP_SET_PT (XBUFFER (buf), BUF_BEGV (XBUFFER (buf))); - lexical_cookie_t lexc = lisp_file_lexical_cookie (buf); - specbind (Qlexical_binding, - lexc == Cookie_Lex ? Qt - : lexc == Cookie_Dyn ? Qnil - : Fdefault_toplevel_value (Qlexical_binding)); + specbind (Qlexical_binding, get_lexical_binding (buf, buf)); BUF_TEMP_SET_PT (XBUFFER (buf), BUF_BEGV (XBUFFER (buf))); readevalloop (buf, 0, filename, !NILP (printflag), unibyte, Qnil, Qnil, Qnil); @@ -5169,7 +5174,7 @@ obarray_index (struct Lisp_Obarray *oa, const char *str, ptrdiff_t size_byte) return knuth_hash (reduce_emacs_uint_to_hash_hash (hash), oa->size_bits); } -/* Return the symbol in OBARRAY whose names matches the string +/* Return the symbol in OBARRAY whose name matches the string of SIZE characters (SIZE_BYTE bytes) at PTR. If there is no such symbol, return the integer bucket number of where the symbol would be if it were present. @@ -6145,6 +6150,11 @@ through `require'. */); DEFSYM (Qchar_from_name, "char-from-name"); + DEFVAR_LISP ("internal--get-default-lexical-binding-function", + Vinternal__get_default_lexical_binding_function, + doc: /* Function to decide default lexical-binding. */); + Vinternal__get_default_lexical_binding_function = Qnil; + DEFVAR_LISP ("read-symbol-shorthands", Vread_symbol_shorthands, doc: /* Alist of known symbol-name shorthands. This variable's value can only be set via file-local variables.