/* Evaluator for GNU Emacs Lisp interpreter.
- Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1999, 2000, 2001,
- 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
- Free Software Foundation, Inc.
+ Copyright (C) 1985-1987, 1993-1995, 1999-2011 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#endif
Lisp_Object Qautoload, Qmacro, Qexit, Qinteractive, Qcommandp, Qdefun;
-Lisp_Object Qinhibit_quit, Vinhibit_quit, Vquit_flag;
+Lisp_Object Qinhibit_quit;
Lisp_Object Qand_rest, Qand_optional;
Lisp_Object Qdebug_on_error;
Lisp_Object Qdeclare;
+Lisp_Object Qinternal_interpreter_environment, Qclosure;
+
Lisp_Object Qdebug;
-extern Lisp_Object Qinteractive_form;
/* This holds either the symbol `run-hooks' or nil.
It is nil at an early stage of startup, and when Emacs
/* Current number of specbindings allocated in specpdl. */
-int specpdl_size;
+EMACS_INT specpdl_size;
/* Pointer to beginning of specpdl. */
struct specbinding *specpdl_ptr;
-/* Maximum size allowed for specpdl allocation */
-
-EMACS_INT max_specpdl_size;
-
/* Depth in Lisp evaluations and function calls. */
-int lisp_eval_depth;
-
-/* Maximum allowed depth in Lisp evaluations and function calls. */
-
-EMACS_INT max_lisp_eval_depth;
-
-/* Nonzero means enter debugger before next function call */
-
-int debug_on_next_call;
-
-/* Non-zero means debugger may continue. This is zero when the
- debugger is called during redisplay, where it might not be safe to
- continue the interrupted redisplay. */
-
-int debugger_may_continue;
-
-/* List of conditions (non-nil atom means all) which cause a backtrace
- if an error is handled by the command loop's error handler. */
-
-Lisp_Object Vstack_trace_on_error;
-
-/* List of conditions (non-nil atom means all) which enter the debugger
- if an error is handled by the command loop's error handler. */
-
-Lisp_Object Vdebug_on_error;
-
-/* List of conditions and regexps specifying error messages which
- do not enter the debugger even if Vdebug_on_error says they should. */
-
-Lisp_Object Vdebug_ignored_errors;
-
-/* Non-nil means call the debugger even if the error will be handled. */
-
-Lisp_Object Vdebug_on_signal;
-
-/* Hook for edebug to use. */
-
-Lisp_Object Vsignal_hook_function;
-
-/* Nonzero means enter debugger if a quit signal
- is handled by the command loop's error handler. */
-
-int debug_on_quit;
+EMACS_INT lisp_eval_depth;
/* The value of num_nonmacro_input_events as of the last time we
started to enter the debugger. If we decide to enter the debugger
int when_entered_debugger;
-Lisp_Object Vdebugger;
-
/* The function from which the last `signal' was called. Set in
Fsignal. */
int handling_signal;
-/* Function to process declarations in defmacro forms. */
-
-Lisp_Object Vmacro_declaration_function;
-
-extern Lisp_Object Qrisky_local_variable;
-
-extern Lisp_Object Qfunction;
-
-static Lisp_Object funcall_lambda (Lisp_Object, int, Lisp_Object*);
+static Lisp_Object apply_lambda (Lisp_Object fun, Lisp_Object args);
+static Lisp_Object funcall_lambda (Lisp_Object, int, Lisp_Object *);
static void unwind_to_catch (struct catchtag *, Lisp_Object) NO_RETURN;
-
-#if __GNUC__
-/* "gcc -O3" enables automatic function inlining, which optimizes out
- the arguments for the invocations of these functions, whereas they
- expect these values on the stack. */
-Lisp_Object apply1 (Lisp_Object fn, Lisp_Object arg) __attribute__((noinline));
-Lisp_Object call2 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2) __attribute__((noinline));
-#endif
+static int interactive_p (int);
\f
void
init_eval_once (void)
specpdl = (struct specbinding *) xmalloc (specpdl_size * sizeof (struct specbinding));
specpdl_ptr = specpdl;
/* Don't forget to update docs (lispref node "Local Variables"). */
- max_specpdl_size = 1000;
- max_lisp_eval_depth = 500;
+ max_specpdl_size = 1300; /* 1000 is not enough for CEDET's c-by.el. */
+ max_lisp_eval_depth = 600;
Vrun_hooks = Qnil;
}
int debug_while_redisplaying;
int count = SPECPDL_INDEX ();
Lisp_Object val;
- int old_max = max_specpdl_size;
+ EMACS_INT old_max = max_specpdl_size;
/* Temporarily bump up the stack limits,
so the debugger won't run out of stack. */
The remaining args are not evalled at all.
If all args return nil, return nil.
usage: (or CONDITIONS...) */)
- (args)
- Lisp_Object args;
+ (Lisp_Object args)
{
register Lisp_Object val = Qnil;
struct gcpro gcpro1;
while (CONSP (args))
{
- val = Feval (XCAR (args));
+ val = eval_sub (XCAR (args));
if (!NILP (val))
break;
args = XCDR (args);
The remaining args are not evalled at all.
If no arg yields nil, return the last arg's value.
usage: (and CONDITIONS...) */)
- (args)
- Lisp_Object args;
+ (Lisp_Object args)
{
register Lisp_Object val = Qt;
struct gcpro gcpro1;
while (CONSP (args))
{
- val = Feval (XCAR (args));
+ val = eval_sub (XCAR (args));
if (NILP (val))
break;
args = XCDR (args);
THEN must be one expression, but ELSE... can be zero or more expressions.
If COND yields nil, and there are no ELSE's, the value is nil.
usage: (if COND THEN ELSE...) */)
- (args)
- Lisp_Object args;
+ (Lisp_Object args)
{
register Lisp_Object cond;
struct gcpro gcpro1;
GCPRO1 (args);
- cond = Feval (Fcar (args));
+ cond = eval_sub (Fcar (args));
UNGCPRO;
if (!NILP (cond))
- return Feval (Fcar (Fcdr (args)));
+ return eval_sub (Fcar (Fcdr (args)));
return Fprogn (Fcdr (Fcdr (args)));
}
If a clause has one element, as in (CONDITION),
CONDITION's value if non-nil is returned from the cond-form.
usage: (cond CLAUSES...) */)
- (args)
- Lisp_Object args;
+ (Lisp_Object args)
{
register Lisp_Object clause, val;
struct gcpro gcpro1;
while (!NILP (args))
{
clause = Fcar (args);
- val = Feval (Fcar (clause));
+ val = eval_sub (Fcar (clause));
if (!NILP (val))
{
if (!EQ (XCDR (clause), Qnil))
DEFUN ("progn", Fprogn, Sprogn, 0, UNEVALLED, 0,
doc: /* Eval BODY forms sequentially and return value of last one.
usage: (progn BODY...) */)
- (args)
- Lisp_Object args;
+ (Lisp_Object args)
{
register Lisp_Object val = Qnil;
struct gcpro gcpro1;
while (CONSP (args))
{
- val = Feval (XCAR (args));
+ val = eval_sub (XCAR (args));
args = XCDR (args);
}
The value of FIRST is saved during the evaluation of the remaining args,
whose values are discarded.
usage: (prog1 FIRST BODY...) */)
- (args)
- Lisp_Object args;
+ (Lisp_Object args)
{
Lisp_Object val;
register Lisp_Object args_left;
do
{
if (!(argnum++))
- val = Feval (Fcar (args_left));
+ val = eval_sub (Fcar (args_left));
else
- Feval (Fcar (args_left));
+ eval_sub (Fcar (args_left));
args_left = Fcdr (args_left);
}
while (!NILP(args_left));
The value of FORM2 is saved during the evaluation of the
remaining args, whose values are discarded.
usage: (prog2 FORM1 FORM2 BODY...) */)
- (args)
- Lisp_Object args;
+ (Lisp_Object args)
{
Lisp_Object val;
register Lisp_Object args_left;
do
{
if (!(argnum++))
- val = Feval (Fcar (args_left));
+ val = eval_sub (Fcar (args_left));
else
- Feval (Fcar (args_left));
+ eval_sub (Fcar (args_left));
args_left = Fcdr (args_left);
}
while (!NILP (args_left));
each VAL can use the new value of variables set earlier in the `setq'.
The return value of the `setq' form is the value of the last VAL.
usage: (setq [SYM VAL]...) */)
- (args)
- Lisp_Object args;
+ (Lisp_Object args)
{
register Lisp_Object args_left;
- register Lisp_Object val, sym;
+ register Lisp_Object val, sym, lex_binding;
struct gcpro gcpro1;
if (NILP (args))
do
{
- val = Feval (Fcar (Fcdr (args_left)));
+ val = eval_sub (Fcar (Fcdr (args_left)));
sym = Fcar (args_left);
- Fset (sym, val);
+
+ /* Like for eval_sub, we do not check declared_special here since
+ it's been done when let-binding. */
+ if (!NILP (Vinternal_interpreter_environment) /* Mere optimization! */
+ && SYMBOLP (sym)
+ && !NILP (lex_binding
+ = Fassq (sym, Vinternal_interpreter_environment)))
+ XSETCDR (lex_binding, val); /* SYM is lexically bound. */
+ else
+ Fset (sym, val); /* SYM is dynamically bound. */
+
args_left = Fcdr (Fcdr (args_left));
}
while (!NILP(args_left));
DEFUN ("quote", Fquote, Squote, 1, UNEVALLED, 0,
doc: /* Return the argument, without evaluating it. `(quote x)' yields `x'.
usage: (quote ARG) */)
- (args)
- Lisp_Object args;
+ (Lisp_Object args)
{
if (!NILP (Fcdr (args)))
xsignal2 (Qwrong_number_of_arguments, Qquote, Flength (args));
In byte compilation, `function' causes its argument to be compiled.
`quote' cannot do that.
usage: (function ARG) */)
- (args)
- Lisp_Object args;
+ (Lisp_Object args)
{
+ Lisp_Object quoted = XCAR (args);
+
if (!NILP (Fcdr (args)))
xsignal2 (Qwrong_number_of_arguments, Qfunction, Flength (args));
- return Fcar (args);
+
+ if (!NILP (Vinternal_interpreter_environment)
+ && CONSP (quoted)
+ && EQ (XCAR (quoted), Qlambda))
+ /* This is a lambda expression within a lexical environment;
+ return an interpreted closure instead of a simple lambda. */
+ return Fcons (Qclosure, Fcons (Vinternal_interpreter_environment, quoted));
+ else
+ /* Simply quote the argument. */
+ return quoted;
}
either (i) add an extra optional argument and give it an `interactive'
spec that specifies non-nil unconditionally (such as \"p\"); or (ii)
use `called-interactively-p'. */)
- ()
+ (void)
{
- return (INTERACTIVE && interactive_p (1)) ? Qt : Qnil;
+ return interactive_p (1) ? Qt : Qnil;
}
cleaner to give your function an extra optional argument whose
`interactive' spec specifies non-nil unconditionally (\"p\" is a good
way to do this), or via (not (or executing-kbd-macro noninteractive)). */)
- (kind)
- Lisp_Object kind;
+ (Lisp_Object kind)
{
return ((INTERACTIVE || !EQ (kind, intern ("interactive")))
&& interactive_p (1)) ? Qt : Qnil;
EXCLUDE_SUBRS_P non-zero means always return 0 if the function
called is a built-in. */
-int
+static int
interactive_p (int exclude_subrs_p)
{
struct backtrace *btp;
The definition is (lambda ARGLIST [DOCSTRING] BODY...).
See also the function `interactive'.
usage: (defun NAME ARGLIST [DOCSTRING] BODY...) */)
- (args)
- Lisp_Object args;
+ (Lisp_Object args)
{
register Lisp_Object fn_name;
register Lisp_Object defn;
fn_name = Fcar (args);
CHECK_SYMBOL (fn_name);
defn = Fcons (Qlambda, Fcdr (args));
+ if (!NILP (Vinternal_interpreter_environment)) /* Mere optimization! */
+ defn = Ffunction (Fcons (defn, Qnil));
if (!NILP (Vpurify_flag))
defn = Fpurecopy (defn);
if (CONSP (XSYMBOL (fn_name)->function)
Set NAME's `doc-string-elt' property to ELT.
usage: (defmacro NAME ARGLIST [DOCSTRING] [DECL] BODY...) */)
- (args)
- Lisp_Object args;
+ (Lisp_Object args)
{
register Lisp_Object fn_name;
register Lisp_Object defn;
tail = XCDR (tail);
}
- while (CONSP (Fcar (tail))
- && EQ (Fcar (Fcar (tail)), Qdeclare))
+ if (CONSP (Fcar (tail))
+ && EQ (Fcar (Fcar (tail)), Qdeclare))
{
if (!NILP (Vmacro_declaration_function))
{
tail = Fcons (lambda_list, tail);
else
tail = Fcons (lambda_list, Fcons (doc, tail));
- defn = Fcons (Qmacro, Fcons (Qlambda, tail));
+
+ defn = Fcons (Qlambda, tail);
+ if (!NILP (Vinternal_interpreter_environment)) /* Mere optimization! */
+ defn = Ffunction (Fcons (defn, Qnil));
+ defn = Fcons (Qmacro, defn);
if (!NILP (Vpurify_flag))
defn = Fpurecopy (defn);
itself an alias. If NEW-ALIAS is bound, and BASE-VARIABLE is not,
then the value of BASE-VARIABLE is set to that of NEW-ALIAS.
The return value is BASE-VARIABLE. */)
- (new_alias, base_variable, docstring)
- Lisp_Object new_alias, base_variable, docstring;
+ (Lisp_Object new_alias, Lisp_Object base_variable, Lisp_Object docstring)
{
struct Lisp_Symbol *sym;
error ("Don't know how to make a let-bound variable an alias");
}
+ sym->declared_special = 1;
sym->redirect = SYMBOL_VARALIAS;
SET_SYMBOL_ALIAS (sym, XSYMBOL (base_variable));
sym->constant = SYMBOL_CONSTANT_P (base_variable);
for these variables. \(`defconst' and `defcustom' behave similarly in
this respect.)
usage: (defvar SYMBOL &optional INITVALUE DOCSTRING) */)
- (args)
- Lisp_Object args;
+ (Lisp_Object args)
{
register Lisp_Object sym, tem, tail;
tem = Fdefault_boundp (sym);
if (!NILP (tail))
{
+ if (SYMBOLP (sym))
+ /* Do it before evaluating the initial value, for self-references. */
+ XSYMBOL (sym)->declared_special = 1;
+
if (SYMBOL_CONSTANT_P (sym))
{
/* For upward compatibility, allow (defvar :foo (quote :foo)). */
}
if (NILP (tem))
- Fset_default (sym, Feval (Fcar (tail)));
+ Fset_default (sym, eval_sub (Fcar (tail)));
else
{ /* Check if there is really a global binding rather than just a let
binding that shadows the global unboundness of the var. */
}
LOADHIST_ATTACH (sym);
}
+ else if (!NILP (Vinternal_interpreter_environment)
+ && !XSYMBOL (sym)->declared_special)
+ /* A simple (defvar foo) with lexical scoping does "nothing" except
+ declare that var to be dynamically scoped *locally* (i.e. within
+ the current file or let-block). */
+ Vinternal_interpreter_environment =
+ Fcons (sym, Vinternal_interpreter_environment);
else
/* Simple (defvar <var>) should not count as a definition at all.
It could get in the way of other definitions, and unloading this
package could try to make the variable unbound. */
;
-
+
return sym;
}
value. However, you should normally not make local bindings for
variables defined with this form.
usage: (defconst SYMBOL INITVALUE [DOCSTRING]) */)
- (args)
- Lisp_Object args;
+ (Lisp_Object args)
{
register Lisp_Object sym, tem;
if (!NILP (Fcdr (Fcdr (Fcdr (args)))))
error ("Too many arguments");
- tem = Feval (Fcar (Fcdr (args)));
+ tem = eval_sub (Fcar (Fcdr (args)));
if (!NILP (Vpurify_flag))
tem = Fpurecopy (tem);
Fset_default (sym, tem);
+ XSYMBOL (sym)->declared_special = 1;
tem = Fcar (Fcdr (Fcdr (args)));
if (!NILP (tem))
{
\(3) it is an alias for another user variable.
Return nil if VARIABLE is an alias and there is a loop in the
chain of symbols. */)
- (variable)
- Lisp_Object variable;
+ (Lisp_Object variable)
{
Lisp_Object documentation;
/* If indirect and there's an alias loop, don't check anything else. */
if (XSYMBOL (variable)->redirect == SYMBOL_VARALIAS
&& NILP (internal_condition_case_1 (lisp_indirect_variable, variable,
- Qt, user_variable_p_eh)))
+ Qt, user_variable_p_eh)))
return Qnil;
while (1)
{
documentation = Fget (variable, Qvariable_documentation);
if (INTEGERP (documentation) && XINT (documentation) < 0)
- return Qt;
+ return Qt;
if (STRINGP (documentation)
- && ((unsigned char) SREF (documentation, 0) == '*'))
- return Qt;
+ && ((unsigned char) SREF (documentation, 0) == '*'))
+ return Qt;
/* If it is (STRING . INTEGER), a negative integer means a user variable. */
if (CONSP (documentation)
- && STRINGP (XCAR (documentation))
- && INTEGERP (XCDR (documentation))
- && XINT (XCDR (documentation)) < 0)
- return Qt;
+ && STRINGP (XCAR (documentation))
+ && INTEGERP (XCDR (documentation))
+ && XINT (XCDR (documentation)) < 0)
+ return Qt;
/* Customizable? See `custom-variable-p'. */
if ((!NILP (Fget (variable, intern ("standard-value"))))
- || (!NILP (Fget (variable, intern ("custom-autoload")))))
- return Qt;
+ || (!NILP (Fget (variable, intern ("custom-autoload")))))
+ return Qt;
if (!(XSYMBOL (variable)->redirect == SYMBOL_VARALIAS))
- return Qnil;
+ return Qnil;
/* An indirect variable? Let's follow the chain. */
XSETSYMBOL (variable, SYMBOL_ALIAS (XSYMBOL (variable)));
or a list (SYMBOL VALUEFORM) (which binds SYMBOL to the value of VALUEFORM).
Each VALUEFORM can refer to the symbols already bound by this VARLIST.
usage: (let* VARLIST BODY...) */)
- (args)
- Lisp_Object args;
+ (Lisp_Object args)
{
- Lisp_Object varlist, val, elt;
+ Lisp_Object varlist, var, val, elt, lexenv;
int count = SPECPDL_INDEX ();
struct gcpro gcpro1, gcpro2, gcpro3;
GCPRO3 (args, elt, varlist);
+ lexenv = Vinternal_interpreter_environment;
+
varlist = Fcar (args);
- while (!NILP (varlist))
+ while (CONSP (varlist))
{
QUIT;
- elt = Fcar (varlist);
+
+ elt = XCAR (varlist);
if (SYMBOLP (elt))
- specbind (elt, Qnil);
+ {
+ var = elt;
+ val = Qnil;
+ }
else if (! NILP (Fcdr (Fcdr (elt))))
signal_error ("`let' bindings can have only one value-form", elt);
else
{
- val = Feval (Fcar (Fcdr (elt)));
- specbind (Fcar (elt), val);
+ var = Fcar (elt);
+ val = eval_sub (Fcar (Fcdr (elt)));
}
- varlist = Fcdr (varlist);
+
+ if (!NILP (lexenv) && SYMBOLP (var)
+ && !XSYMBOL (var)->declared_special
+ && NILP (Fmemq (var, Vinternal_interpreter_environment)))
+ /* Lexically bind VAR by adding it to the interpreter's binding
+ alist. */
+ {
+ Lisp_Object newenv
+ = Fcons (Fcons (var, val), Vinternal_interpreter_environment);
+ if (EQ (Vinternal_interpreter_environment, lexenv))
+ /* Save the old lexical environment on the specpdl stack,
+ but only for the first lexical binding, since we'll never
+ need to revert to one of the intermediate ones. */
+ specbind (Qinternal_interpreter_environment, newenv);
+ else
+ Vinternal_interpreter_environment = newenv;
+ }
+ else
+ specbind (var, val);
+
+ varlist = XCDR (varlist);
}
+
UNGCPRO;
+
val = Fprogn (Fcdr (args));
+
return unbind_to (count, val);
}
or a list (SYMBOL VALUEFORM) (which binds SYMBOL to the value of VALUEFORM).
All the VALUEFORMs are evalled before any symbols are bound.
usage: (let VARLIST BODY...) */)
- (args)
- Lisp_Object args;
+ (Lisp_Object args)
{
- Lisp_Object *temps, tem;
+ Lisp_Object *temps, tem, lexenv;
register Lisp_Object elt, varlist;
int count = SPECPDL_INDEX ();
register int argnum;
struct gcpro gcpro1, gcpro2;
+ USE_SAFE_ALLOCA;
varlist = Fcar (args);
/* Make space to hold the values to give the bound variables */
elt = Flength (varlist);
- temps = (Lisp_Object *) alloca (XFASTINT (elt) * sizeof (Lisp_Object));
+ SAFE_ALLOCA_LISP (temps, XFASTINT (elt));
/* Compute the values and store them in `temps' */
else if (! NILP (Fcdr (Fcdr (elt))))
signal_error ("`let' bindings can have only one value-form", elt);
else
- temps [argnum++] = Feval (Fcar (Fcdr (elt)));
+ temps [argnum++] = eval_sub (Fcar (Fcdr (elt)));
gcpro2.nvars = argnum;
}
UNGCPRO;
+ lexenv = Vinternal_interpreter_environment;
+
varlist = Fcar (args);
for (argnum = 0; CONSP (varlist); varlist = XCDR (varlist))
{
+ Lisp_Object var;
+
elt = XCAR (varlist);
+ var = SYMBOLP (elt) ? elt : Fcar (elt);
tem = temps[argnum++];
- if (SYMBOLP (elt))
- specbind (elt, tem);
+
+ if (!NILP (lexenv) && SYMBOLP (var)
+ && !XSYMBOL (var)->declared_special
+ && NILP (Fmemq (var, Vinternal_interpreter_environment)))
+ /* Lexically bind VAR by adding it to the lexenv alist. */
+ lexenv = Fcons (Fcons (var, tem), lexenv);
else
- specbind (Fcar (elt), tem);
+ /* Dynamically bind VAR. */
+ specbind (var, tem);
}
+ if (!EQ (lexenv, Vinternal_interpreter_environment))
+ /* Instantiate a new lexical environment. */
+ specbind (Qinternal_interpreter_environment, lexenv);
+
elt = Fprogn (Fcdr (args));
+ SAFE_FREE ();
return unbind_to (count, elt);
}
The order of execution is thus TEST, BODY, TEST, BODY and so on
until TEST returns nil.
usage: (while TEST BODY...) */)
- (args)
- Lisp_Object args;
+ (Lisp_Object args)
{
Lisp_Object test, body;
struct gcpro gcpro1, gcpro2;
test = Fcar (args);
body = Fcdr (args);
- while (!NILP (Feval (test)))
+ while (!NILP (eval_sub (test)))
{
QUIT;
Fprogn (body);
The second optional arg ENVIRONMENT specifies an environment of macro
definitions to shadow the loaded ones for use in file byte-compilation. */)
- (form, environment)
- Lisp_Object form;
- Lisp_Object environment;
+ (Lisp_Object form, Lisp_Object environment)
{
/* With cleanups from Hallvard Furuseth. */
register Lisp_Object expander, sym, def, tem;
If no throw happens, `catch' returns the value of the last BODY form.
If a throw happens, it specifies the value to return from `catch'.
usage: (catch TAG BODY...) */)
- (args)
- Lisp_Object args;
+ (Lisp_Object args)
{
register Lisp_Object tag;
struct gcpro gcpro1;
GCPRO1 (args);
- tag = Feval (Fcar (args));
+ tag = eval_sub (Fcar (args));
UNGCPRO;
return internal_catch (tag, Fprogn, Fcdr (args));
}
last_time = catchlist == catch;
/* Unwind the specpdl stack, and then restore the proper set of
- handlers. */
+ handlers. */
unbind_to (catchlist->pdlcount, Qnil);
handlerlist = catchlist->handlerlist;
catchlist = catchlist->next;
/* If x_catch_errors was done, turn it off now.
(First we give unbind_to a chance to do that.) */
#if 0 /* This would disable x_catch_errors after x_connection_closed.
- * The catch must remain in effect during that delicate
- * state. --lorentey */
+ The catch must remain in effect during that delicate
+ state. --lorentey */
x_fully_uncatch_errors ();
#endif
#endif
DEFUN ("throw", Fthrow, Sthrow, 2, 2, 0,
doc: /* Throw to the catch for TAG and return VALUE from it.
Both TAG and VALUE are evalled. */)
- (tag, value)
- register Lisp_Object tag, value;
+ (register Lisp_Object tag, Lisp_Object value)
{
register struct catchtag *c;
after executing the UNWINDFORMS.
If BODYFORM exits nonlocally, the UNWINDFORMS are executed anyway.
usage: (unwind-protect BODYFORM UNWINDFORMS...) */)
- (args)
- Lisp_Object args;
+ (Lisp_Object args)
{
Lisp_Object val;
int count = SPECPDL_INDEX ();
record_unwind_protect (Fprogn, Fcdr (args));
- val = Feval (Fcar (args));
+ val = eval_sub (Fcar (args));
return unbind_to (count, val);
}
\f
When a handler handles an error, control returns to the `condition-case'
and it executes the handler's BODY...
with VAR bound to (ERROR-SYMBOL . SIGNAL-DATA) from the error.
-(If VAR is nil, the handler can't access that information.)
+\(If VAR is nil, the handler can't access that information.)
Then the value of the last BODY form is returned from the `condition-case'
expression.
See also the function `signal' for more info.
usage: (condition-case VAR BODYFORM &rest HANDLERS) */)
- (args)
- Lisp_Object args;
+ (Lisp_Object args)
{
register Lisp_Object bodyform, handlers;
volatile Lisp_Object var;
if (_setjmp (c.jmp))
{
if (!NILP (h.var))
- specbind (h.var, c.val);
+ specbind (h.var, c.val);
val = Fprogn (Fcdr (h.chosen_clause));
/* Note that this just undoes the binding of h.var; whoever
h.tag = &c;
handlerlist = &h;
- val = Feval (bodyform);
+ val = eval_sub (bodyform);
catchlist = c.next;
handlerlist = h.next;
return val;
\f
static Lisp_Object find_handler_clause (Lisp_Object, Lisp_Object,
- Lisp_Object, Lisp_Object);
+ Lisp_Object, Lisp_Object);
+static int maybe_call_debugger (Lisp_Object conditions, Lisp_Object sig,
+ Lisp_Object data);
DEFUN ("signal", Fsignal, Ssignal, 2, 2, 0,
doc: /* Signal an error. Args are ERROR-SYMBOL and associated DATA.
error message is constructed.
If the signal is handled, DATA is made available to the handler.
See also the function `condition-case'. */)
- (error_symbol, data)
- Lisp_Object error_symbol, data;
+ (Lisp_Object error_symbol, Lisp_Object data)
{
/* When memory is full, ERROR-SYMBOL is nil,
and DATA is (REAL-ERROR-SYMBOL . REAL-DATA).
That is a special case--don't do this in other situations. */
- register struct handler *allhandlers = handlerlist;
Lisp_Object conditions;
- extern int gc_in_progress;
- extern int waiting_for_input;
Lisp_Object string;
- Lisp_Object real_error_symbol;
+ Lisp_Object real_error_symbol
+ = (NILP (error_symbol) ? Fcar (data) : error_symbol);
+ register Lisp_Object clause = Qnil;
+ struct handler *h;
struct backtrace *bp;
immediate_quit = handling_signal = 0;
if (gc_in_progress || waiting_for_input)
abort ();
- if (NILP (error_symbol))
- real_error_symbol = Fcar (data);
- else
- real_error_symbol = error_symbol;
-
#if 0 /* rms: I don't know why this was here,
but it is surely wrong for an error that is handled. */
#ifdef HAVE_WINDOW_SYSTEM
Vsignaling_function = *bp->function;
}
- for (; handlerlist; handlerlist = handlerlist->next)
+ for (h = handlerlist; h; h = h->next)
{
- register Lisp_Object clause;
-
- clause = find_handler_clause (handlerlist->handler, conditions,
+ clause = find_handler_clause (h->handler, conditions,
error_symbol, data);
-
- if (EQ (clause, Qlambda))
- {
- /* We can't return values to code which signaled an error, but we
- can continue code which has signaled a quit. */
- if (EQ (real_error_symbol, Qquit))
- return Qnil;
- else
- error ("Cannot return from the debugger in an error");
- }
-
if (!NILP (clause))
- {
- Lisp_Object unwind_data;
- struct handler *h = handlerlist;
-
- handlerlist = allhandlers;
-
- if (NILP (error_symbol))
- unwind_data = data;
- else
- unwind_data = Fcons (error_symbol, data);
- h->chosen_clause = clause;
- unwind_to_catch (h->tag, unwind_data);
- }
+ break;
+ }
+
+ if (/* Don't run the debugger for a memory-full error.
+ (There is no room in memory to do that!) */
+ !NILP (error_symbol)
+ && (!NILP (Vdebug_on_signal)
+ /* If no handler is present now, try to run the debugger. */
+ || NILP (clause)
+ /* Special handler that means "print a message and run debugger
+ if requested". */
+ || EQ (h->handler, Qerror)))
+ {
+ int debugger_called
+ = maybe_call_debugger (conditions, error_symbol, data);
+ /* We can't return values to code which signaled an error, but we
+ can continue code which has signaled a quit. */
+ if (debugger_called && EQ (real_error_symbol, Qquit))
+ return Qnil;
+ }
+
+ if (!NILP (clause))
+ {
+ Lisp_Object unwind_data
+ = (NILP (error_symbol) ? data : Fcons (error_symbol, data));
+
+ h->chosen_clause = clause;
+ unwind_to_catch (h->tag, unwind_data);
+ }
+ else
+ {
+ if (catchlist != 0)
+ Fthrow (Qtop_level, Qt);
}
-
- handlerlist = allhandlers;
- /* If no handler is present now, try to run the debugger,
- and if that fails, throw to top level. */
- find_handler_clause (Qerror, conditions, error_symbol, data);
- if (catchlist != 0)
- Fthrow (Qtop_level, Qt);
if (! NILP (error_symbol))
data = Fcons (error_symbol, data);
-
+
string = Ferror_message_string (data);
fatal ("%s", SDATA (string), 0);
}
If ARG is not a genuine list, make it a one-element list. */
void
-signal_error (char *s, Lisp_Object arg)
+signal_error (const char *s, Lisp_Object arg)
{
Lisp_Object tortoise, hare;
Lisp_Object sig, Lisp_Object data)
{
register Lisp_Object h;
- register Lisp_Object tem;
- int debugger_called = 0;
- int debugger_considered = 0;
/* t is used by handlers for all conditions, set up by C code. */
if (EQ (handlers, Qt))
return Qt;
- /* Don't run the debugger for a memory-full error.
- (There is no room in memory to do that!) */
- if (NILP (sig))
- debugger_considered = 1;
-
/* error is used similarly, but means print an error message
and run the debugger if that is enabled. */
- if (EQ (handlers, Qerror)
- || !NILP (Vdebug_on_signal)) /* This says call debugger even if
- there is a handler. */
- {
- if (!NILP (sig) && wants_debugger (Vstack_trace_on_error, conditions))
- {
- max_lisp_eval_depth += 15;
- max_specpdl_size++;
- if (noninteractive)
- Fbacktrace ();
- else
- internal_with_output_to_temp_buffer
- ("*Backtrace*",
- (Lisp_Object (*) (Lisp_Object)) Fbacktrace,
- Qnil);
- max_specpdl_size--;
- max_lisp_eval_depth -= 15;
- }
-
- if (!debugger_considered)
- {
- debugger_considered = 1;
- debugger_called = maybe_call_debugger (conditions, sig, data);
- }
-
- /* If there is no handler, return saying whether we ran the debugger. */
- if (EQ (handlers, Qerror))
- {
- if (debugger_called)
- return Qlambda;
- return Qt;
- }
- }
+ if (EQ (handlers, Qerror))
+ return Qt;
- for (h = handlers; CONSP (h); h = Fcdr (h))
+ for (h = handlers; CONSP (h); h = XCDR (h))
{
- Lisp_Object handler, condit;
+ Lisp_Object handler = XCAR (h);
+ Lisp_Object condit, tem;
- handler = Fcar (h);
if (!CONSP (handler))
continue;
- condit = Fcar (handler);
+ condit = XCAR (handler);
/* Handle a single condition name in handler HANDLER. */
if (SYMBOLP (condit))
{
Lisp_Object tail;
for (tail = condit; CONSP (tail); tail = XCDR (tail))
{
- tem = Fmemq (Fcar (tail), conditions);
+ tem = Fmemq (XCAR (tail), conditions);
if (!NILP (tem))
- {
- /* This handler is going to apply.
- Does it allow the debugger to run first? */
- if (! debugger_considered && !NILP (Fmemq (Qdebug, condit)))
- maybe_call_debugger (conditions, sig, data);
- return handler;
- }
+ return handler;
}
}
}
return Qnil;
}
-/* dump an error message; called like printf */
-/* VARARGS 1 */
+/* dump an error message; called like vprintf */
void
-error (m, a1, a2, a3)
- char *m;
- char *a1, *a2, *a3;
+verror (const char *m, va_list ap)
{
char buf[200];
- int size = 200;
+ EMACS_INT size = 200;
int mlen;
char *buffer = buf;
- char *args[3];
int allocated = 0;
Lisp_Object string;
- args[0] = a1;
- args[1] = a2;
- args[2] = a3;
-
mlen = strlen (m);
while (1)
{
- int used = doprnt (buffer, size, m, m + mlen, 3, args);
+ EMACS_INT used;
+ used = doprnt (buffer, size, m, m + mlen, ap);
if (used < size)
break;
size *= 2;
xsignal1 (Qerror, string);
}
+
+
+/* dump an error message; called like printf */
+
+/* VARARGS 1 */
+void
+error (const char *m, ...)
+{
+ va_list ap;
+ va_start (ap, m);
+ verror (m, ap);
+ va_end (ap);
+}
\f
DEFUN ("commandp", Fcommandp, Scommandp, 1, 2, 0,
doc: /* Non-nil if FUNCTION makes provisions for interactive calling.
If the optional argument FOR-CALL-INTERACTIVELY is non-nil,
then strings and vectors are not accepted. */)
- (function, for_call_interactively)
- Lisp_Object function, for_call_interactively;
+ (Lisp_Object function, Lisp_Object for_call_interactively)
{
register Lisp_Object fun;
register Lisp_Object funcar;
if (!CONSP (fun))
return Qnil;
funcar = XCAR (fun);
+ if (EQ (funcar, Qclosure))
+ fun = Fcdr (XCDR (fun)), funcar = Fcar (fun);
if (EQ (funcar, Qlambda))
return !NILP (Fassq (Qinteractive, Fcdr (XCDR (fun)))) ? Qt : if_prop;
- if (EQ (funcar, Qautoload))
+ else if (EQ (funcar, Qautoload))
return !NILP (Fcar (Fcdr (Fcdr (XCDR (fun))))) ? Qt : if_prop;
else
return Qnil;
They default to nil.
If FUNCTION is already defined other than as an autoload,
this does nothing and returns nil. */)
- (function, file, docstring, interactive, type)
- Lisp_Object function, file, docstring, interactive, type;
+ (Lisp_Object function, Lisp_Object file, Lisp_Object docstring, Lisp_Object interactive, Lisp_Object type)
{
CHECK_SYMBOL (function);
CHECK_STRING (file);
}
\f
-DEFUN ("eval", Feval, Seval, 1, 1, 0,
- doc: /* Evaluate FORM and return its value. */)
- (form)
- Lisp_Object form;
+DEFUN ("eval", Feval, Seval, 1, 2, 0,
+ doc: /* Evaluate FORM and return its value.
+If LEXICAL is t, evaluate using lexical scoping. */)
+ (Lisp_Object form, Lisp_Object lexical)
+{
+ int count = SPECPDL_INDEX ();
+ specbind (Qinternal_interpreter_environment,
+ NILP (lexical) ? Qnil : Fcons (Qt, Qnil));
+ return unbind_to (count, eval_sub (form));
+}
+
+/* Eval a sub-expression of the current expression (i.e. in the same
+ lexical scope). */
+Lisp_Object
+eval_sub (Lisp_Object form)
{
Lisp_Object fun, val, original_fun, original_args;
Lisp_Object funcar;
abort ();
if (SYMBOLP (form))
- return Fsymbol_value (form);
+ {
+ /* Look up its binding in the lexical environment.
+ We do not pay attention to the declared_special flag here, since we
+ already did that when let-binding the variable. */
+ Lisp_Object lex_binding
+ = !NILP (Vinternal_interpreter_environment) /* Mere optimization! */
+ ? Fassq (form, Vinternal_interpreter_environment)
+ : Qnil;
+ if (CONSP (lex_binding))
+ return XCDR (lex_binding);
+ else
+ return Fsymbol_value (form);
+ }
+
if (!CONSP (form))
return form;
(XSUBR (fun)->max_args >= 0 && XSUBR (fun)->max_args < XINT (numargs)))
xsignal2 (Qwrong_number_of_arguments, original_fun, numargs);
- if (XSUBR (fun)->max_args == UNEVALLED)
+ else if (XSUBR (fun)->max_args == UNEVALLED)
{
backtrace.evalargs = 0;
- val = (XSUBR (fun)->function.a1) (args_left);
- goto done;
+ val = (XSUBR (fun)->function.aUNEVALLED) (args_left);
}
-
- if (XSUBR (fun)->max_args == MANY)
+ else if (XSUBR (fun)->max_args == MANY)
{
/* Pass a vector of evaluated arguments */
Lisp_Object *vals;
register int argnum = 0;
+ USE_SAFE_ALLOCA;
- vals = (Lisp_Object *) alloca (XINT (numargs) * sizeof (Lisp_Object));
+ SAFE_ALLOCA_LISP (vals, XINT (numargs));
GCPRO3 (args_left, fun, fun);
gcpro3.var = vals;
while (!NILP (args_left))
{
- vals[argnum++] = Feval (Fcar (args_left));
+ vals[argnum++] = eval_sub (Fcar (args_left));
args_left = Fcdr (args_left);
gcpro3.nvars = argnum;
}
backtrace.args = vals;
backtrace.nargs = XINT (numargs);
- val = (XSUBR (fun)->function.am) (XINT (numargs), vals);
+ val = (XSUBR (fun)->function.aMANY) (XINT (numargs), vals);
UNGCPRO;
- goto done;
+ SAFE_FREE ();
}
-
- GCPRO3 (args_left, fun, fun);
- gcpro3.var = argvals;
- gcpro3.nvars = 0;
-
- maxargs = XSUBR (fun)->max_args;
- for (i = 0; i < maxargs; args_left = Fcdr (args_left))
+ else
{
- argvals[i] = Feval (Fcar (args_left));
- gcpro3.nvars = ++i;
- }
+ GCPRO3 (args_left, fun, fun);
+ gcpro3.var = argvals;
+ gcpro3.nvars = 0;
- UNGCPRO;
+ maxargs = XSUBR (fun)->max_args;
+ for (i = 0; i < maxargs; args_left = Fcdr (args_left))
+ {
+ argvals[i] = eval_sub (Fcar (args_left));
+ gcpro3.nvars = ++i;
+ }
+
+ UNGCPRO;
- backtrace.args = argvals;
- backtrace.nargs = XINT (numargs);
+ backtrace.args = argvals;
+ backtrace.nargs = XINT (numargs);
- switch (i)
- {
- case 0:
- val = (XSUBR (fun)->function.a0) ();
- goto done;
- case 1:
- val = (XSUBR (fun)->function.a1) (argvals[0]);
- goto done;
- case 2:
- val = (XSUBR (fun)->function.a2) (argvals[0], argvals[1]);
- goto done;
- case 3:
- val = (XSUBR (fun)->function.a3) (argvals[0], argvals[1],
- argvals[2]);
- goto done;
- case 4:
- val = (XSUBR (fun)->function.a4) (argvals[0], argvals[1],
- argvals[2], argvals[3]);
- goto done;
- case 5:
- val = (XSUBR (fun)->function.a5) (argvals[0], argvals[1], argvals[2],
- argvals[3], argvals[4]);
- goto done;
- case 6:
- val = (XSUBR (fun)->function.a6) (argvals[0], argvals[1], argvals[2],
- argvals[3], argvals[4], argvals[5]);
- goto done;
- case 7:
- val = (XSUBR (fun)->function.a7) (argvals[0], argvals[1], argvals[2],
- argvals[3], argvals[4], argvals[5],
- argvals[6]);
- goto done;
-
- case 8:
- val = (XSUBR (fun)->function.a8) (argvals[0], argvals[1], argvals[2],
- argvals[3], argvals[4], argvals[5],
- argvals[6], argvals[7]);
- goto done;
-
- default:
- /* Someone has created a subr that takes more arguments than
- is supported by this code. We need to either rewrite the
- subr to use a different argument protocol, or add more
- cases to this switch. */
- abort ();
+ switch (i)
+ {
+ case 0:
+ val = (XSUBR (fun)->function.a0 ());
+ break;
+ case 1:
+ val = (XSUBR (fun)->function.a1 (argvals[0]));
+ break;
+ case 2:
+ val = (XSUBR (fun)->function.a2 (argvals[0], argvals[1]));
+ break;
+ case 3:
+ val = (XSUBR (fun)->function.a3
+ (argvals[0], argvals[1], argvals[2]));
+ break;
+ case 4:
+ val = (XSUBR (fun)->function.a4
+ (argvals[0], argvals[1], argvals[2], argvals[3]));
+ break;
+ case 5:
+ val = (XSUBR (fun)->function.a5
+ (argvals[0], argvals[1], argvals[2], argvals[3],
+ argvals[4]));
+ break;
+ case 6:
+ val = (XSUBR (fun)->function.a6
+ (argvals[0], argvals[1], argvals[2], argvals[3],
+ argvals[4], argvals[5]));
+ break;
+ case 7:
+ val = (XSUBR (fun)->function.a7
+ (argvals[0], argvals[1], argvals[2], argvals[3],
+ argvals[4], argvals[5], argvals[6]));
+ break;
+
+ case 8:
+ val = (XSUBR (fun)->function.a8
+ (argvals[0], argvals[1], argvals[2], argvals[3],
+ argvals[4], argvals[5], argvals[6], argvals[7]));
+ break;
+
+ default:
+ /* Someone has created a subr that takes more arguments than
+ is supported by this code. We need to either rewrite the
+ subr to use a different argument protocol, or add more
+ cases to this switch. */
+ abort ();
+ }
}
}
- if (COMPILEDP (fun))
- val = apply_lambda (fun, original_args, 1);
+ else if (COMPILEDP (fun))
+ val = apply_lambda (fun, original_args);
else
{
if (EQ (fun, Qunbound))
goto retry;
}
if (EQ (funcar, Qmacro))
- val = Feval (apply1 (Fcdr (fun), original_args));
- else if (EQ (funcar, Qlambda))
- val = apply_lambda (fun, original_args, 1);
+ val = eval_sub (apply1 (Fcdr (fun), original_args));
+ else if (EQ (funcar, Qlambda)
+ || EQ (funcar, Qclosure))
+ val = apply_lambda (fun, original_args);
else
xsignal1 (Qinvalid_function, original_fun);
}
- done:
CHECK_CONS_LIST ();
lisp_eval_depth--;
Then return the value FUNCTION returns.
Thus, (apply '+ 1 2 '(3 4)) returns 10.
usage: (apply FUNCTION &rest ARGUMENTS) */)
- (nargs, args)
- int nargs;
- Lisp_Object *args;
+ (int nargs, Lisp_Object *args)
{
register int i, numargs;
register Lisp_Object spread_arg;
register Lisp_Object *funcall_args;
- Lisp_Object fun;
+ Lisp_Object fun, retval;
struct gcpro gcpro1;
+ USE_SAFE_ALLOCA;
fun = args [0];
funcall_args = 0;
{
/* Avoid making funcall cons up a yet another new vector of arguments
by explicitly supplying nil's for optional values */
- funcall_args = (Lisp_Object *) alloca ((1 + XSUBR (fun)->max_args)
- * sizeof (Lisp_Object));
+ SAFE_ALLOCA_LISP (funcall_args, 1 + XSUBR (fun)->max_args);
for (i = numargs; i < XSUBR (fun)->max_args;)
funcall_args[++i] = Qnil;
GCPRO1 (*funcall_args);
function itself as well as its arguments. */
if (!funcall_args)
{
- funcall_args = (Lisp_Object *) alloca ((1 + numargs)
- * sizeof (Lisp_Object));
+ SAFE_ALLOCA_LISP (funcall_args, 1 + numargs);
GCPRO1 (*funcall_args);
gcpro1.nvars = 1 + numargs;
}
}
/* By convention, the caller needs to gcpro Ffuncall's args. */
- RETURN_UNGCPRO (Ffuncall (gcpro1.nvars, funcall_args));
+ retval = Ffuncall (gcpro1.nvars, funcall_args);
+ UNGCPRO;
+ SAFE_FREE ();
+
+ return retval;
}
\f
/* Run hook variables in various ways. */
enum run_hooks_condition {to_completion, until_success, until_failure};
static Lisp_Object run_hook_with_args (int, Lisp_Object *,
- enum run_hooks_condition);
+ enum run_hooks_condition);
DEFUN ("run-hooks", Frun_hooks, Srun_hooks, 0, MANY, 0,
doc: /* Run each hook in HOOKS.
Do not use `make-local-variable' to make a hook variable buffer-local.
Instead, use `add-hook' and specify t for the LOCAL argument.
usage: (run-hooks &rest HOOKS) */)
- (nargs, args)
- int nargs;
- Lisp_Object *args;
+ (int nargs, Lisp_Object *args)
{
Lisp_Object hook[1];
register int i;
Do not use `make-local-variable' to make a hook variable buffer-local.
Instead, use `add-hook' and specify t for the LOCAL argument.
usage: (run-hook-with-args HOOK &rest ARGS) */)
- (nargs, args)
- int nargs;
- Lisp_Object *args;
+ (int nargs, Lisp_Object *args)
{
return run_hook_with_args (nargs, args, to_completion);
}
Do not use `make-local-variable' to make a hook variable buffer-local.
Instead, use `add-hook' and specify t for the LOCAL argument.
usage: (run-hook-with-args-until-success HOOK &rest ARGS) */)
- (nargs, args)
- int nargs;
- Lisp_Object *args;
+ (int nargs, Lisp_Object *args)
{
return run_hook_with_args (nargs, args, until_success);
}
Do not use `make-local-variable' to make a hook variable buffer-local.
Instead, use `add-hook' and specify t for the LOCAL argument.
usage: (run-hook-with-args-until-failure HOOK &rest ARGS) */)
- (nargs, args)
- int nargs;
- Lisp_Object *args;
+ (int nargs, Lisp_Object *args)
{
return run_hook_with_args (nargs, args, until_failure);
}
}
}
-/* Run a hook symbol ARGS[0], but use FUNLIST instead of the actual
- present value of that symbol.
- Call each element of FUNLIST,
- passing each of them the rest of ARGS.
- The caller (or its caller, etc) must gcpro all of ARGS,
- except that it isn't necessary to gcpro ARGS[0]. */
-
-Lisp_Object
-run_hook_list_with_args (Lisp_Object funlist, int nargs, Lisp_Object *args)
-{
- Lisp_Object sym;
- Lisp_Object val;
- Lisp_Object globals;
- struct gcpro gcpro1, gcpro2, gcpro3;
-
- sym = args[0];
- globals = Qnil;
- GCPRO3 (sym, val, globals);
-
- for (val = funlist; CONSP (val); val = XCDR (val))
- {
- if (EQ (XCAR (val), Qt))
- {
- /* t indicates this hook has a local binding;
- it means to run the global binding too. */
-
- for (globals = Fdefault_value (sym);
- CONSP (globals);
- globals = XCDR (globals))
- {
- args[0] = XCAR (globals);
- /* In a global value, t should not occur. If it does, we
- must ignore it to avoid an endless loop. */
- if (!EQ (args[0], Qt))
- Ffuncall (nargs, args);
- }
- }
- else
- {
- args[0] = XCAR (val);
- Ffuncall (nargs, args);
- }
- }
- UNGCPRO;
- return Qnil;
-}
-
/* Run the hook HOOK, giving each function the two args ARG1 and ARG2. */
void
/* The caller should GCPRO all the elements of ARGS. */
+DEFUN ("functionp", Ffunctionp, Sfunctionp, 1, 1, 0,
+ doc: /* Return non-nil if OBJECT is a type of object that can be called as a function. */)
+ (Lisp_Object object)
+{
+ if (SYMBOLP (object) && !NILP (Ffboundp (object)))
+ {
+ object = Findirect_function (object, Qnil);
+
+ if (CONSP (object) && EQ (XCAR (object), Qautoload))
+ {
+ /* Autoloaded symbols are functions, except if they load
+ macros or keymaps. */
+ int i;
+ for (i = 0; i < 4 && CONSP (object); i++)
+ object = XCDR (object);
+
+ return (CONSP (object) && !NILP (XCAR (object))) ? Qnil : Qt;
+ }
+ }
+
+ if (SUBRP (object))
+ return (XSUBR (object)->max_args != UNEVALLED) ? Qt : Qnil;
+ else if (COMPILEDP (object))
+ return Qt;
+ else if (CONSP (object))
+ {
+ Lisp_Object car = XCAR (object);
+ return (EQ (car, Qlambda) || EQ (car, Qclosure)) ? Qt : Qnil;
+ }
+ else
+ return Qnil;
+}
+
DEFUN ("funcall", Ffuncall, Sfuncall, 1, MANY, 0,
doc: /* Call first argument as a function, passing remaining arguments to it.
Return the value that function returns.
Thus, (funcall 'cons 'x 'y) returns (x . y).
usage: (funcall FUNCTION &rest ARGUMENTS) */)
- (nargs, args)
- int nargs;
- Lisp_Object *args;
+ (int nargs, Lisp_Object *args)
{
Lisp_Object fun, original_fun;
Lisp_Object funcar;
if (SUBRP (fun))
{
- if (numargs < XSUBR (fun)->min_args
+ if (numargs < XSUBR (fun)->min_args
|| (XSUBR (fun)->max_args >= 0 && XSUBR (fun)->max_args < numargs))
{
XSETFASTINT (lisp_numargs, numargs);
xsignal2 (Qwrong_number_of_arguments, original_fun, lisp_numargs);
}
- if (XSUBR (fun)->max_args == UNEVALLED)
+ else if (XSUBR (fun)->max_args == UNEVALLED)
xsignal1 (Qinvalid_function, original_fun);
- if (XSUBR (fun)->max_args == MANY)
- {
- val = (XSUBR (fun)->function.am) (numargs, args + 1);
- goto done;
- }
-
- if (XSUBR (fun)->max_args > numargs)
- {
- internal_args = (Lisp_Object *) alloca (XSUBR (fun)->max_args * sizeof (Lisp_Object));
- memcpy (internal_args, args + 1, numargs * sizeof (Lisp_Object));
- for (i = numargs; i < XSUBR (fun)->max_args; i++)
- internal_args[i] = Qnil;
- }
+ else if (XSUBR (fun)->max_args == MANY)
+ val = (XSUBR (fun)->function.aMANY) (numargs, args + 1);
else
- internal_args = args + 1;
- switch (XSUBR (fun)->max_args)
{
- case 0:
- val = (XSUBR (fun)->function.a0) ();
- goto done;
- case 1:
- val = (XSUBR (fun)->function.a1) (internal_args[0]);
- goto done;
- case 2:
- val = (XSUBR (fun)->function.a2) (internal_args[0], internal_args[1]);
- goto done;
- case 3:
- val = (XSUBR (fun)->function.a3) (internal_args[0], internal_args[1],
- internal_args[2]);
- goto done;
- case 4:
- val = (XSUBR (fun)->function.a4) (internal_args[0], internal_args[1],
- internal_args[2], internal_args[3]);
- goto done;
- case 5:
- val = (XSUBR (fun)->function.a5) (internal_args[0], internal_args[1],
- internal_args[2], internal_args[3],
- internal_args[4]);
- goto done;
- case 6:
- val = (XSUBR (fun)->function.a6) (internal_args[0], internal_args[1],
- internal_args[2], internal_args[3],
- internal_args[4], internal_args[5]);
- goto done;
- case 7:
- val = (XSUBR (fun)->function.a7) (internal_args[0], internal_args[1],
- internal_args[2], internal_args[3],
- internal_args[4], internal_args[5],
- internal_args[6]);
- goto done;
-
- case 8:
- val = (XSUBR (fun)->function.a8) (internal_args[0], internal_args[1],
- internal_args[2], internal_args[3],
- internal_args[4], internal_args[5],
- internal_args[6], internal_args[7]);
- goto done;
-
- default:
-
- /* If a subr takes more than 8 arguments without using MANY
- or UNEVALLED, we need to extend this function to support it.
- Until this is done, there is no way to call the function. */
- abort ();
+ if (XSUBR (fun)->max_args > numargs)
+ {
+ internal_args = (Lisp_Object *) alloca (XSUBR (fun)->max_args * sizeof (Lisp_Object));
+ memcpy (internal_args, args + 1, numargs * sizeof (Lisp_Object));
+ for (i = numargs; i < XSUBR (fun)->max_args; i++)
+ internal_args[i] = Qnil;
+ }
+ else
+ internal_args = args + 1;
+ switch (XSUBR (fun)->max_args)
+ {
+ case 0:
+ val = (XSUBR (fun)->function.a0 ());
+ break;
+ case 1:
+ val = (XSUBR (fun)->function.a1 (internal_args[0]));
+ break;
+ case 2:
+ val = (XSUBR (fun)->function.a2
+ (internal_args[0], internal_args[1]));
+ break;
+ case 3:
+ val = (XSUBR (fun)->function.a3
+ (internal_args[0], internal_args[1], internal_args[2]));
+ break;
+ case 4:
+ val = (XSUBR (fun)->function.a4
+ (internal_args[0], internal_args[1], internal_args[2],
+ internal_args[3]));
+ break;
+ case 5:
+ val = (XSUBR (fun)->function.a5
+ (internal_args[0], internal_args[1], internal_args[2],
+ internal_args[3], internal_args[4]));
+ break;
+ case 6:
+ val = (XSUBR (fun)->function.a6
+ (internal_args[0], internal_args[1], internal_args[2],
+ internal_args[3], internal_args[4], internal_args[5]));
+ break;
+ case 7:
+ val = (XSUBR (fun)->function.a7
+ (internal_args[0], internal_args[1], internal_args[2],
+ internal_args[3], internal_args[4], internal_args[5],
+ internal_args[6]));
+ break;
+
+ case 8:
+ val = (XSUBR (fun)->function.a8
+ (internal_args[0], internal_args[1], internal_args[2],
+ internal_args[3], internal_args[4], internal_args[5],
+ internal_args[6], internal_args[7]));
+ break;
+
+ default:
+
+ /* If a subr takes more than 8 arguments without using MANY
+ or UNEVALLED, we need to extend this function to support it.
+ Until this is done, there is no way to call the function. */
+ abort ();
+ }
}
}
- if (COMPILEDP (fun))
+ else if (COMPILEDP (fun))
val = funcall_lambda (fun, numargs, args + 1);
else
{
funcar = XCAR (fun);
if (!SYMBOLP (funcar))
xsignal1 (Qinvalid_function, original_fun);
- if (EQ (funcar, Qlambda))
+ if (EQ (funcar, Qlambda)
+ || EQ (funcar, Qclosure))
val = funcall_lambda (fun, numargs, args + 1);
else if (EQ (funcar, Qautoload))
{
else
xsignal1 (Qinvalid_function, original_fun);
}
- done:
CHECK_CONS_LIST ();
lisp_eval_depth--;
if (backtrace.debug_on_exit)
return val;
}
\f
-Lisp_Object
-apply_lambda (Lisp_Object fun, Lisp_Object args, int eval_flag)
+static Lisp_Object
+apply_lambda (Lisp_Object fun, Lisp_Object args)
{
Lisp_Object args_left;
Lisp_Object numargs;
struct gcpro gcpro1, gcpro2, gcpro3;
register int i;
register Lisp_Object tem;
+ USE_SAFE_ALLOCA;
numargs = Flength (args);
- arg_vector = (Lisp_Object *) alloca (XINT (numargs) * sizeof (Lisp_Object));
+ SAFE_ALLOCA_LISP (arg_vector, XINT (numargs));
args_left = args;
GCPRO3 (*arg_vector, args_left, fun);
for (i = 0; i < XINT (numargs);)
{
tem = Fcar (args_left), args_left = Fcdr (args_left);
- if (eval_flag) tem = Feval (tem);
+ tem = eval_sub (tem);
arg_vector[i++] = tem;
gcpro1.nvars = i;
}
UNGCPRO;
- if (eval_flag)
- {
- backtrace_list->args = arg_vector;
- backtrace_list->nargs = i;
- }
+ backtrace_list->args = arg_vector;
+ backtrace_list->nargs = i;
backtrace_list->evalargs = 0;
tem = funcall_lambda (fun, XINT (numargs), arg_vector);
tem = call_debugger (Fcons (Qexit, Fcons (tem, Qnil)));
/* Don't do it again when we return to eval. */
backtrace_list->debug_on_exit = 0;
+ SAFE_FREE ();
return tem;
}
FUN must be either a lambda-expression or a compiled-code object. */
static Lisp_Object
-funcall_lambda (Lisp_Object fun, int nargs, register Lisp_Object *arg_vector)
+funcall_lambda (Lisp_Object fun, int nargs,
+ register Lisp_Object *arg_vector)
{
- Lisp_Object val, syms_left, next;
+ Lisp_Object val, syms_left, next, lexenv;
int count = SPECPDL_INDEX ();
int i, optional, rest;
if (CONSP (fun))
{
+ if (EQ (XCAR (fun), Qclosure))
+ {
+ fun = XCDR (fun); /* Drop `closure'. */
+ lexenv = XCAR (fun);
+ fun = XCDR (fun); /* Drop the lexical environment. */
+ }
+ else
+ lexenv = Qnil;
syms_left = XCDR (fun);
if (CONSP (syms_left))
syms_left = XCAR (syms_left);
xsignal1 (Qinvalid_function, fun);
}
else if (COMPILEDP (fun))
- syms_left = AREF (fun, COMPILED_ARGLIST);
+ {
+ if ((ASIZE (fun) & PSEUDOVECTOR_SIZE_MASK) > COMPILED_PUSH_ARGS
+ && ! NILP (XVECTOR (fun)->contents[COMPILED_PUSH_ARGS]))
+ /* A byte-code object with a non-nil `push args' slot means we
+ shouldn't bind any arguments, instead just call the byte-code
+ interpreter directly; it will push arguments as necessary.
+
+ Byte-code objects with either a non-existant, or a nil value for
+ the `push args' slot (the default), have dynamically-bound
+ arguments, and use the argument-binding code below instead (as do
+ all interpreted functions, even lexically bound ones). */
+ {
+ /* If we have not actually read the bytecode string
+ and constants vector yet, fetch them from the file. */
+ if (CONSP (AREF (fun, COMPILED_BYTECODE)))
+ Ffetch_bytecode (fun);
+ return exec_byte_code (AREF (fun, COMPILED_BYTECODE),
+ AREF (fun, COMPILED_CONSTANTS),
+ AREF (fun, COMPILED_STACK_DEPTH),
+ AREF (fun, COMPILED_ARGLIST),
+ nargs, arg_vector);
+ }
+ syms_left = AREF (fun, COMPILED_ARGLIST);
+ lexenv = Qnil;
+ }
else
abort ();
rest = 1;
else if (EQ (next, Qand_optional))
optional = 1;
- else if (rest)
+ else
{
- specbind (next, Flist (nargs - i, &arg_vector[i]));
- i = nargs;
+ Lisp_Object val;
+ if (rest)
+ {
+ val = Flist (nargs - i, &arg_vector[i]);
+ i = nargs;
+ }
+ else if (i < nargs)
+ val = arg_vector[i++];
+ else if (!optional)
+ xsignal2 (Qwrong_number_of_arguments, fun, make_number (nargs));
+ else
+ val = Qnil;
+
+ /* Bind the argument. */
+ if (!NILP (lexenv) && SYMBOLP (next))
+ /* Lexically bind NEXT by adding it to the lexenv alist. */
+ lexenv = Fcons (Fcons (next, val), lexenv);
+ else
+ /* Dynamically bind NEXT. */
+ specbind (next, val);
}
- else if (i < nargs)
- specbind (next, arg_vector[i++]);
- else if (!optional)
- xsignal2 (Qwrong_number_of_arguments, fun, make_number (nargs));
- else
- specbind (next, Qnil);
}
if (!NILP (syms_left))
else if (i < nargs)
xsignal2 (Qwrong_number_of_arguments, fun, make_number (nargs));
+ if (!EQ (lexenv, Vinternal_interpreter_environment))
+ /* Instantiate a new lexical environment. */
+ specbind (Qinternal_interpreter_environment, lexenv);
+
if (CONSP (fun))
val = Fprogn (XCDR (XCDR (fun)));
else
and constants vector yet, fetch them from the file. */
if (CONSP (AREF (fun, COMPILED_BYTECODE)))
Ffetch_bytecode (fun);
- val = Fbyte_code (AREF (fun, COMPILED_BYTECODE),
- AREF (fun, COMPILED_CONSTANTS),
- AREF (fun, COMPILED_STACK_DEPTH));
+ val = exec_byte_code (AREF (fun, COMPILED_BYTECODE),
+ AREF (fun, COMPILED_CONSTANTS),
+ AREF (fun, COMPILED_STACK_DEPTH),
+ Qnil, 0, 0);
}
return unbind_to (count, val);
DEFUN ("fetch-bytecode", Ffetch_bytecode, Sfetch_bytecode,
1, 1, 0,
doc: /* If byte-compiled OBJECT is lazy-loaded, fetch it now. */)
- (object)
- Lisp_Object object;
+ (Lisp_Object object)
{
Lisp_Object tem;
case SYMBOL_VARALIAS:
sym = indirect_variable (sym); XSETSYMBOL (symbol, sym); goto start;
case SYMBOL_PLAINVAL:
- { /* The most common case is that of a non-constant symbol with a
- trivial value. Make that as fast as we can. */
- specpdl_ptr->symbol = symbol;
- specpdl_ptr->old_value = SYMBOL_VAL (sym);
- specpdl_ptr->func = NULL;
- ++specpdl_ptr;
- if (!sym->constant)
- SET_SYMBOL_VAL (sym, value);
- else
- set_internal (symbol, value, Qnil, 1);
- break;
- }
+ /* The most common case is that of a non-constant symbol with a
+ trivial value. Make that as fast as we can. */
+ specpdl_ptr->symbol = symbol;
+ specpdl_ptr->old_value = SYMBOL_VAL (sym);
+ specpdl_ptr->func = NULL;
+ ++specpdl_ptr;
+ if (!sym->constant)
+ SET_SYMBOL_VAL (sym, value);
+ else
+ set_internal (symbol, value, Qnil, 1);
+ break;
case SYMBOL_LOCALIZED:
if (SYMBOL_BLV (sym)->frame_local)
error ("Frame-local vars cannot be let-bound");
bound a variable that had a buffer-local or frame-local
binding. WHERE nil means that the variable had the default
value when it was bound. CURRENT-BUFFER is the buffer that
- was current when the variable was bound. */
+ was current when the variable was bound. */
else if (CONSP (this_binding.symbol))
{
Lisp_Object symbol, where;
UNGCPRO;
return value;
}
+
\f
+
+DEFUN ("special-variable-p", Fspecial_variable_p, Sspecial_variable_p, 1, 1, 0,
+ doc: /* Return non-nil if SYMBOL's global binding has been declared special.
+A special variable is one that will be bound dynamically, even in a
+context where binding is lexical by default. */)
+ (Lisp_Object symbol)
+{
+ CHECK_SYMBOL (symbol);
+ return XSYMBOL (symbol)->declared_special ? Qt : Qnil;
+}
+
+\f
+
DEFUN ("backtrace-debug", Fbacktrace_debug, Sbacktrace_debug, 2, 2, 0,
doc: /* Set the debug-on-exit flag of eval frame LEVEL levels down to FLAG.
The debugger is entered when that frame exits, if the flag is non-nil. */)
- (level, flag)
- Lisp_Object level, flag;
+ (Lisp_Object level, Lisp_Object flag)
{
register struct backtrace *backlist = backtrace_list;
register int i;
DEFUN ("backtrace", Fbacktrace, Sbacktrace, 0, 0, "",
doc: /* Print a trace of Lisp function calls currently active.
Output stream used is value of `standard-output'. */)
- ()
+ (void)
{
register struct backtrace *backlist = backtrace_list;
register int i;
Lisp_Object tail;
Lisp_Object tem;
- extern Lisp_Object Vprint_level;
struct gcpro gcpro1;
+ Lisp_Object old_print_level = Vprint_level;
- XSETFASTINT (Vprint_level, 3);
+ if (NILP (Vprint_level))
+ XSETFASTINT (Vprint_level, 8);
tail = Qnil;
GCPRO1 (tail);
backlist = backlist->next;
}
- Vprint_level = Qnil;
+ Vprint_level = old_print_level;
UNGCPRO;
return Qnil;
}
FUNCTION is whatever was supplied as car of evaluated list,
or a lambda expression for macro calls.
If NFRAMES is more than the number of frames, the value is nil. */)
- (nframes)
- Lisp_Object nframes;
+ (Lisp_Object nframes)
{
register struct backtrace *backlist = backtrace_list;
register int i;
}
}
+EXFUN (Funintern, 2);
+
void
syms_of_eval (void)
{
- DEFVAR_INT ("max-specpdl-size", &max_specpdl_size,
+ DEFVAR_INT ("max-specpdl-size", max_specpdl_size,
doc: /* *Limit on number of Lisp variable bindings and `unwind-protect's.
If Lisp code tries to increase the total number past this amount,
an error is signaled.
if that proves inconveniently small. However, if you increase it too far,
Emacs could run out of memory trying to make the stack bigger. */);
- DEFVAR_INT ("max-lisp-eval-depth", &max_lisp_eval_depth,
+ DEFVAR_INT ("max-lisp-eval-depth", max_lisp_eval_depth,
doc: /* *Limit on depth in `eval', `apply' and `funcall' before error.
This limit serves to catch infinite recursions for you before they cause
if that proves inconveniently small. However, if you increase it too far,
Emacs could overflow the real C stack, and crash. */);
- DEFVAR_LISP ("quit-flag", &Vquit_flag,
+ DEFVAR_LISP ("quit-flag", Vquit_flag,
doc: /* Non-nil causes `eval' to abort, unless `inhibit-quit' is non-nil.
If the value is t, that means do an ordinary quit.
If the value equals `throw-on-input', that means quit by throwing
but `inhibit-quit' non-nil prevents anything from taking notice of that. */);
Vquit_flag = Qnil;
- DEFVAR_LISP ("inhibit-quit", &Vinhibit_quit,
+ DEFVAR_LISP ("inhibit-quit", Vinhibit_quit,
doc: /* Non-nil inhibits C-g quitting from happening immediately.
Note that `quit-flag' will still be set by typing C-g,
so a quit will be signaled as soon as `inhibit-quit' is nil.
Qand_optional = intern_c_string ("&optional");
staticpro (&Qand_optional);
+ Qclosure = intern_c_string ("closure");
+ staticpro (&Qclosure);
+
Qdebug = intern_c_string ("debug");
staticpro (&Qdebug);
- DEFVAR_LISP ("stack-trace-on-error", &Vstack_trace_on_error,
- doc: /* *Non-nil means errors display a backtrace buffer.
-More precisely, this happens for any error that is handled
-by the editor command loop.
-If the value is a list, an error only means to display a backtrace
-if one of its condition symbols appears in the list. */);
- Vstack_trace_on_error = Qnil;
-
- DEFVAR_LISP ("debug-on-error", &Vdebug_on_error,
+ DEFVAR_LISP ("debug-on-error", Vdebug_on_error,
doc: /* *Non-nil means enter debugger if an error is signaled.
Does not apply to errors handled by `condition-case' or those
matched by `debug-ignored-errors'.
See also the variable `debug-on-quit'. */);
Vdebug_on_error = Qnil;
- DEFVAR_LISP ("debug-ignored-errors", &Vdebug_ignored_errors,
+ DEFVAR_LISP ("debug-ignored-errors", Vdebug_ignored_errors,
doc: /* *List of errors for which the debugger should not be called.
Each element may be a condition-name or a regexp that matches error messages.
If any element applies to a given error, that error skips the debugger
It does not apply to errors handled by `condition-case'. */);
Vdebug_ignored_errors = Qnil;
- DEFVAR_BOOL ("debug-on-quit", &debug_on_quit,
+ DEFVAR_BOOL ("debug-on-quit", debug_on_quit,
doc: /* *Non-nil means enter debugger if quit is signaled (C-g, for example).
Does not apply if quit is handled by a `condition-case'. */);
debug_on_quit = 0;
- DEFVAR_BOOL ("debug-on-next-call", &debug_on_next_call,
+ DEFVAR_BOOL ("debug-on-next-call", debug_on_next_call,
doc: /* Non-nil means enter debugger before next `eval', `apply' or `funcall'. */);
- DEFVAR_BOOL ("debugger-may-continue", &debugger_may_continue,
+ DEFVAR_BOOL ("debugger-may-continue", debugger_may_continue,
doc: /* Non-nil means debugger may continue execution.
This is nil when the debugger is called under circumstances where it
might not be safe to continue. */);
debugger_may_continue = 1;
- DEFVAR_LISP ("debugger", &Vdebugger,
+ DEFVAR_LISP ("debugger", Vdebugger,
doc: /* Function to call to invoke debugger.
If due to frame exit, args are `exit' and the value being returned;
this function's value will be returned instead of that.
If due to `eval' entry, one arg, t. */);
Vdebugger = Qnil;
- DEFVAR_LISP ("signal-hook-function", &Vsignal_hook_function,
+ DEFVAR_LISP ("signal-hook-function", Vsignal_hook_function,
doc: /* If non-nil, this is a function for `signal' to call.
It receives the same arguments that `signal' was given.
The Edebug package uses this to regain control. */);
Vsignal_hook_function = Qnil;
- DEFVAR_LISP ("debug-on-signal", &Vdebug_on_signal,
+ DEFVAR_LISP ("debug-on-signal", Vdebug_on_signal,
doc: /* *Non-nil means call the debugger regardless of condition handlers.
Note that `debug-on-error', `debug-on-quit' and friends
still determine whether to handle the particular condition. */);
Vdebug_on_signal = Qnil;
- DEFVAR_LISP ("macro-declaration-function", &Vmacro_declaration_function,
+ DEFVAR_LISP ("macro-declaration-function", Vmacro_declaration_function,
doc: /* Function to process declarations in a macro definition.
The function will be called with two args MACRO and DECL.
MACRO is the name of the macro being defined.
The value the function returns is not used. */);
Vmacro_declaration_function = Qnil;
+ /* When lexical binding is being used,
+ vinternal_interpreter_environment is non-nil, and contains an alist
+ of lexically-bound variable, or (t), indicating an empty
+ environment. The lisp name of this variable would be
+ `internal-interpreter-environment' if it weren't hidden.
+ Every element of this list can be either a cons (VAR . VAL)
+ specifying a lexical binding, or a single symbol VAR indicating
+ that this variable should use dynamic scoping. */
+ Qinternal_interpreter_environment
+ = intern_c_string ("internal-interpreter-environment");
+ staticpro (&Qinternal_interpreter_environment);
+ DEFVAR_LISP ("internal-interpreter-environment",
+ Vinternal_interpreter_environment,
+ doc: /* If non-nil, the current lexical environment of the lisp interpreter.
+When lexical binding is not being used, this variable is nil.
+A value of `(t)' indicates an empty environment, otherwise it is an
+alist of active lexical bindings. */);
+ Vinternal_interpreter_environment = Qnil;
+ /* Don't export this variable to Elisp, so noone can mess with it
+ (Just imagine if someone makes it buffer-local). */
+ Funintern (Qinternal_interpreter_environment, Qnil);
+
Vrun_hooks = intern_c_string ("run-hooks");
staticpro (&Vrun_hooks);
defsubr (&Sbacktrace_debug);
defsubr (&Sbacktrace);
defsubr (&Sbacktrace_frame);
+ defsubr (&Sspecial_variable_p);
+ defsubr (&Sfunctionp);
}
-/* arch-tag: 014a07aa-33ab-4a8f-a3d2-ee8a4a9ff7fb
- (do not change this comment) */