summaryrefslogtreecommitdiff
path: root/src/data.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/data.c')
-rw-r--r--src/data.c231
1 files changed, 190 insertions, 41 deletions
diff --git a/src/data.c b/src/data.c
index 9bf9d605cf1..1526cc0c737 100644
--- a/src/data.c
+++ b/src/data.c
@@ -216,6 +216,7 @@ for example, (type-of 1) returns `integer'. */)
case PVEC_NORMAL_VECTOR: return Qvector;
case PVEC_BIGNUM: return Qinteger;
case PVEC_MARKER: return Qmarker;
+ case PVEC_SYMBOL_WITH_POS: return Qsymbol_with_pos;
case PVEC_OVERLAY: return Qoverlay;
case PVEC_FINALIZER: return Qfinalizer;
case PVEC_USER_PTR: return Quser_ptr;
@@ -259,6 +260,8 @@ for example, (type-of 1) returns `integer'. */)
return Qxwidget;
case PVEC_XWIDGET_VIEW:
return Qxwidget_view;
+ case PVEC_SQLITE:
+ return Qsqlite;
/* "Impossible" cases. */
case PVEC_MISC_PTR:
case PVEC_OTHER:
@@ -316,6 +319,26 @@ DEFUN ("nlistp", Fnlistp, Snlistp, 1, 1, 0,
return Qt;
}
+DEFUN ("bare-symbol-p", Fbare_symbol_p, Sbare_symbol_p, 1, 1, 0,
+ doc: /* Return t if OBJECT is a symbol, but not a symbol together with position. */
+ attributes: const)
+ (Lisp_Object object)
+{
+ if (BARE_SYMBOL_P (object))
+ return Qt;
+ return Qnil;
+}
+
+DEFUN ("symbol-with-pos-p", Fsymbol_with_pos_p, Ssymbol_with_pos_p, 1, 1, 0,
+ doc: /* Return t if OBJECT is a symbol together with position. */
+ attributes: const)
+ (Lisp_Object object)
+{
+ if (SYMBOL_WITH_POS_P (object))
+ return Qt;
+ return Qnil;
+}
+
DEFUN ("symbolp", Fsymbolp, Ssymbolp, 1, 1, 0,
doc: /* Return t if OBJECT is a symbol. */
attributes: const)
@@ -753,11 +776,66 @@ DEFUN ("symbol-name", Fsymbol_name, Ssymbol_name, 1, 1, 0,
return name;
}
+DEFUN ("bare-symbol", Fbare_symbol, Sbare_symbol, 1, 1, 0,
+ doc: /* Extract, if need be, the bare symbol from SYM, a symbol. */)
+ (register Lisp_Object sym)
+{
+ if (BARE_SYMBOL_P (sym))
+ return sym;
+ /* Type checking is done in the following macro. */
+ return SYMBOL_WITH_POS_SYM (sym);
+}
+
+DEFUN ("symbol-with-pos-pos", Fsymbol_with_pos_pos, Ssymbol_with_pos_pos, 1, 1, 0,
+ doc: /* Extract the position from a symbol with position. */)
+ (register Lisp_Object ls)
+{
+ /* Type checking is done in the following macro. */
+ return SYMBOL_WITH_POS_POS (ls);
+}
+
+DEFUN ("remove-pos-from-symbol", Fremove_pos_from_symbol,
+ Sremove_pos_from_symbol, 1, 1, 0,
+ doc: /* If ARG is a symbol with position, return it without the position.
+Otherwise, return ARG unchanged. Compare with `bare-symbol'. */)
+ (register Lisp_Object arg)
+{
+ if (SYMBOL_WITH_POS_P (arg))
+ return (SYMBOL_WITH_POS_SYM (arg));
+ return arg;
+}
+
+DEFUN ("position-symbol", Fposition_symbol, Sposition_symbol, 2, 2, 0,
+ doc: /* Create a new symbol with position.
+SYM is a symbol, with or without position, the symbol to position.
+POS, the position, is either a fixnum or a symbol with position from which
+the position will be taken. */)
+ (register Lisp_Object sym, register Lisp_Object pos)
+{
+ Lisp_Object bare;
+ Lisp_Object position;
+
+ if (BARE_SYMBOL_P (sym))
+ bare = sym;
+ else if (SYMBOL_WITH_POS_P (sym))
+ bare = XSYMBOL_WITH_POS (sym)->sym;
+ else
+ wrong_type_argument (Qsymbolp, sym);
+
+ if (FIXNUMP (pos))
+ position = pos;
+ else if (SYMBOL_WITH_POS_P (pos))
+ position = XSYMBOL_WITH_POS (pos)->pos;
+ else
+ wrong_type_argument (Qfixnum_or_symbol_with_pos_p, pos);
+
+ return build_symbol_with_pos (bare, position);
+}
+
DEFUN ("fset", Ffset, Sfset, 2, 2, 0,
doc: /* Set SYMBOL's function definition to DEFINITION, and return DEFINITION. */)
(register Lisp_Object symbol, Lisp_Object definition)
{
- register Lisp_Object function;
CHECK_SYMBOL (symbol);
/* Perhaps not quite the right error signal, but seems good enough. */
if (NILP (symbol) && !NILP (definition))
@@ -765,17 +843,11 @@ DEFUN ("fset", Ffset, Sfset, 2, 2, 0,
think this one little sanity check is worth its cost, but anyway. */
xsignal1 (Qsetting_constant, symbol);
- function = XSYMBOL (symbol)->u.s.function;
-
- if (!NILP (Vautoload_queue) && !NILP (function))
- Vautoload_queue = Fcons (Fcons (symbol, function), Vautoload_queue);
-
- if (AUTOLOADP (function))
- Fput (symbol, Qautoload, XCDR (function));
-
eassert (valid_lisp_object_p (definition));
#ifdef HAVE_NATIVE_COMP
+ register Lisp_Object function = XSYMBOL (symbol)->u.s.function;
+
if (comp_enable_subr_trampolines
&& SUBRP (function)
&& !SUBR_NATIVE_COMPILEDP (function))
@@ -787,6 +859,75 @@ DEFUN ("fset", Ffset, Sfset, 2, 2, 0,
return definition;
}
+static void
+add_to_function_history (Lisp_Object symbol, Lisp_Object olddef)
+{
+ eassert (!NILP (olddef));
+
+ Lisp_Object past = Fget (symbol, Qfunction_history);
+ Lisp_Object file = Qnil;
+ /* FIXME: Sadly, `Vload_file_name` gives less precise information
+ (it's sometimes non-nil when it shoujld be nil). */
+ Lisp_Object tail = Vcurrent_load_list;
+ FOR_EACH_TAIL_SAFE (tail)
+ if (NILP (XCDR (tail)) && STRINGP (XCAR (tail)))
+ file = XCAR (tail);
+
+ Lisp_Object tem = Fplist_member (past, file);
+ if (!NILP (tem))
+ { /* New def from a file used before.
+ Overwrite the previous record associated with this file. */
+ if (EQ (tem, past))
+ /* The new def is from the same file as the last change, so
+ there's nothing to do: unloading the file should revert to
+ the status before the last change rather than before this load. */
+ return;
+ Lisp_Object pastlen = Flength (past);
+ Lisp_Object temlen = Flength (tem);
+ EMACS_INT tempos = XFIXNUM (pastlen) - XFIXNUM (temlen);
+ eassert (tempos > 1);
+ Lisp_Object prev = Fnthcdr (make_fixnum (tempos - 2), past);
+ /* Remove the previous info for this file.
+ E.g. change `hist` from (... OTHERFILE DEF3 THISFILE DEF2 ...)
+ to (... OTHERFILE DEF2). */
+ XSETCDR (prev, XCDR (tem));
+ }
+ /* Push new def from new file. */
+ Fput (symbol, Qfunction_history, Fcons (file, Fcons (olddef, past)));
+}
+
+void
+defalias (Lisp_Object symbol, Lisp_Object definition)
+{
+ {
+ bool autoload = AUTOLOADP (definition);
+ if (!will_dump_p () || !autoload)
+ { /* Only add autoload entries after dumping, because the ones before are
+ not useful and else we get loads of them from the loaddefs.el.
+ That saves us about 110KB in the pdmp file (Jan 2022). */
+ LOADHIST_ATTACH (Fcons (Qdefun, symbol));
+ }
+ }
+
+ {
+ Lisp_Object olddef = XSYMBOL (symbol)->u.s.function;
+ if (!NILP (olddef))
+ {
+ if (!NILP (Vautoload_queue))
+ Vautoload_queue = Fcons (symbol, Vautoload_queue);
+ add_to_function_history (symbol, olddef);
+ }
+ }
+
+ { /* Handle automatic advice activation. */
+ Lisp_Object hook = Fget (symbol, Qdefalias_fset_function);
+ if (!NILP (hook))
+ call2 (hook, symbol, definition);
+ else
+ Ffset (symbol, definition);
+ }
+}
+
DEFUN ("defalias", Fdefalias, Sdefalias, 2, 3, 0,
doc: /* Set SYMBOL's function definition to DEFINITION.
Associates the function with the current load file, if any.
@@ -806,26 +947,7 @@ The return value is undefined. */)
&& !KEYMAPP (definition))
definition = Fpurecopy (definition);
- {
- bool autoload = AUTOLOADP (definition);
- if (!will_dump_p () || !autoload)
- { /* Only add autoload entries after dumping, because the ones before are
- not useful and else we get loads of them from the loaddefs.el. */
-
- if (AUTOLOADP (XSYMBOL (symbol)->u.s.function))
- /* Remember that the function was already an autoload. */
- LOADHIST_ATTACH (Fcons (Qt, symbol));
- LOADHIST_ATTACH (Fcons (autoload ? Qautoload : Qdefun, symbol));
- }
- }
-
- { /* Handle automatic advice activation. */
- Lisp_Object hook = Fget (symbol, Qdefalias_fset_function);
- if (!NILP (hook))
- call2 (hook, symbol, definition);
- else
- Ffset (symbol, definition);
- }
+ defalias (symbol, definition);
maybe_defer_native_compilation (symbol, definition);
@@ -1715,7 +1837,7 @@ notify_variable_watchers (Lisp_Object symbol,
{
symbol = Findirect_variable (symbol);
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
record_unwind_protect (restore_symbol_trapped_write, symbol);
/* Avoid recursion. */
set_symbol_trapped_write (symbol, SYMBOL_UNTRAPPED_WRITE);
@@ -2101,7 +2223,7 @@ Instead, use `add-hook' and specify t for the LOCAL argument. */)
/* Make sure this buffer has its own value of symbol. */
XSETSYMBOL (variable, sym); /* Update in case of aliasing. */
- tem = Fassq (variable, BVAR (current_buffer, local_var_alist));
+ tem = assq_no_quit (variable, BVAR (current_buffer, local_var_alist));
if (NILP (tem))
{
if (let_shadows_buffer_binding_p (sym))
@@ -2181,7 +2303,7 @@ From now on the default value will apply in this buffer. Return VARIABLE. */)
/* Get rid of this buffer's alist element, if any. */
XSETSYMBOL (variable, sym); /* Propagate variable indirection. */
- tem = Fassq (variable, BVAR (current_buffer, local_var_alist));
+ tem = assq_no_quit (variable, BVAR (current_buffer, local_var_alist));
if (!NILP (tem))
bset_local_var_alist
(current_buffer,
@@ -2222,7 +2344,7 @@ Also see `buffer-local-boundp'.*/)
case SYMBOL_PLAINVAL: return Qnil;
case SYMBOL_LOCALIZED:
{
- Lisp_Object tail, elt, tmp;
+ Lisp_Object tmp;
struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym);
XSETBUFFER (tmp, buf);
XSETSYMBOL (variable, sym); /* Update in case of aliasing. */
@@ -2230,13 +2352,9 @@ Also see `buffer-local-boundp'.*/)
if (EQ (blv->where, tmp)) /* The binding is already loaded. */
return blv_found (blv) ? Qt : Qnil;
else
- for (tail = BVAR (buf, local_var_alist); CONSP (tail); tail = XCDR (tail))
- {
- elt = XCAR (tail);
- if (EQ (variable, XCAR (elt)))
- return Qt;
- }
- return Qnil;
+ return NILP (assq_no_quit (variable, BVAR (buf, local_var_alist)))
+ ? Qnil
+ : Qt;
}
case SYMBOL_FORWARDED:
{
@@ -3894,7 +4012,7 @@ A is a bool vector, B is t or nil, and I is an index into A. */)
void
syms_of_data (void)
{
- Lisp_Object error_tail, arith_tail;
+ Lisp_Object error_tail, arith_tail, recursion_tail;
DEFSYM (Qquote, "quote");
DEFSYM (Qlambda, "lambda");
@@ -3929,8 +4047,14 @@ syms_of_data (void)
DEFSYM (Qmark_inactive, "mark-inactive");
DEFSYM (Qinhibited_interaction, "inhibited-interaction");
+ DEFSYM (Qrecursion_error, "recursion-error");
+ DEFSYM (Qexcessive_variable_binding, "excessive-variable-binding");
+ DEFSYM (Qexcessive_lisp_nesting, "excessive-lisp-nesting");
+
DEFSYM (Qlistp, "listp");
DEFSYM (Qconsp, "consp");
+ DEFSYM (Qbare_symbol_p, "bare-symbol-p");
+ DEFSYM (Qsymbol_with_pos_p, "symbol-with-pos-p");
DEFSYM (Qsymbolp, "symbolp");
DEFSYM (Qfixnump, "fixnump");
DEFSYM (Qintegerp, "integerp");
@@ -3956,6 +4080,7 @@ syms_of_data (void)
DEFSYM (Qchar_table_p, "char-table-p");
DEFSYM (Qvector_or_char_table_p, "vector-or-char-table-p");
+ DEFSYM (Qfixnum_or_symbol_with_pos_p, "fixnum-or-symbol-with-pos-p");
DEFSYM (Qsubrp, "subrp");
DEFSYM (Qunevalled, "unevalled");
@@ -4034,12 +4159,23 @@ syms_of_data (void)
PUT_ERROR (Qunderflow_error, Fcons (Qrange_error, arith_tail),
"Arithmetic underflow error");
+ recursion_tail = pure_cons (Qrecursion_error, error_tail);
+ Fput (Qrecursion_error, Qerror_conditions, recursion_tail);
+ Fput (Qrecursion_error, Qerror_message, build_pure_c_string
+ ("Excessive recursive calling error"));
+
+ PUT_ERROR (Qexcessive_variable_binding, recursion_tail,
+ "Variable binding depth exceeds max-specpdl-size");
+ PUT_ERROR (Qexcessive_lisp_nesting, recursion_tail,
+ "Lisp nesting exceeds `max-lisp-eval-depth'");
+
/* Types that type-of returns. */
DEFSYM (Qinteger, "integer");
DEFSYM (Qsymbol, "symbol");
DEFSYM (Qstring, "string");
DEFSYM (Qcons, "cons");
DEFSYM (Qmarker, "marker");
+ DEFSYM (Qsymbol_with_pos, "symbol-with-pos");
DEFSYM (Qoverlay, "overlay");
DEFSYM (Qfinalizer, "finalizer");
DEFSYM (Qmodule_function, "module-function");
@@ -4072,6 +4208,7 @@ syms_of_data (void)
DEFSYM (Qinteractive_form, "interactive-form");
DEFSYM (Qdefalias_fset_function, "defalias-fset-function");
+ DEFSYM (Qfunction_history, "function-history");
DEFSYM (Qbyte_code_function_p, "byte-code-function-p");
@@ -4091,6 +4228,8 @@ syms_of_data (void)
defsubr (&Snumber_or_marker_p);
defsubr (&Sfloatp);
defsubr (&Snatnump);
+ defsubr (&Sbare_symbol_p);
+ defsubr (&Ssymbol_with_pos_p);
defsubr (&Ssymbolp);
defsubr (&Skeywordp);
defsubr (&Sstringp);
@@ -4121,6 +4260,10 @@ syms_of_data (void)
defsubr (&Sindirect_function);
defsubr (&Ssymbol_plist);
defsubr (&Ssymbol_name);
+ defsubr (&Sbare_symbol);
+ defsubr (&Ssymbol_with_pos_pos);
+ defsubr (&Sremove_pos_from_symbol);
+ defsubr (&Sposition_symbol);
defsubr (&Smakunbound);
defsubr (&Sfmakunbound);
defsubr (&Sboundp);
@@ -4203,6 +4346,12 @@ This variable cannot be set; trying to do so will signal an error. */);
Vmost_negative_fixnum = make_fixnum (MOST_NEGATIVE_FIXNUM);
make_symbol_constant (intern_c_string ("most-negative-fixnum"));
+ DEFSYM (Qsymbols_with_pos_enabled, "symbols-with-pos-enabled");
+ DEFVAR_BOOL ("symbols-with-pos-enabled", symbols_with_pos_enabled,
+ doc: /* Non-nil when "symbols with position" can be used as symbols.
+Bind this to non-nil in applications such as the byte compiler. */);
+ symbols_with_pos_enabled = false;
+
DEFSYM (Qwatchers, "watchers");
DEFSYM (Qmakunbound, "makunbound");
DEFSYM (Qunlet, "unlet");