let
code: eval.c
DEFUN ("let", Flet, Slet, 1, UNEVALLED, 0,
doc: /* Bind variables according to VARLIST then eval BODY.
The value of the last form in BODY is returned.
Each element of VARLIST is a symbol (which is bound to nil)
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...) */)
(Lisp_Object args)
{
Lisp_Object *temps, tem, lexenv;
Lisp_Object elt;
ptrdiff_t count = SPECPDL_INDEX ();
ptrdiff_t argnum;
USE_SAFE_ALLOCA;
Lisp_Object varlist = XCAR (args);
/* Make space to hold the values to give the bound variables. */
EMACS_INT varlist_len = list_length (varlist);
SAFE_ALLOCA_LISP (temps, varlist_len);
ptrdiff_t nvars = varlist_len;
/* Compute the values and store them in `temps'. */
for (argnum = 0; argnum < nvars && CONSP (varlist); argnum++)
{
maybe_quit ();
elt = XCAR (varlist);
varlist = XCDR (varlist);
if (SYMBOLP (elt))
else if (! NILP (Fcdr (Fcdr (elt))))
signal_error ("`let' bindings can have only one value-form", elt);
else
tempsargnum = eval_sub (Fcar (Fcdr (elt))); }
nvars = argnum;
lexenv = Vinternal_interpreter_environment;
varlist = XCAR (args);
for (argnum = 0; argnum < nvars && CONSP (varlist); argnum++)
{
Lisp_Object var;
elt = XCAR (varlist);
varlist = XCDR (varlist);
var = SYMBOLP (elt) ? elt : Fcar (elt);
if (!NILP (lexenv) && SYMBOLP (var)
&& !XSYMBOL (var)->u.s.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
/* Dynamically bind VAR. */
specbind (var, tem);
}
if (!EQ (lexenv, Vinternal_interpreter_environment))
/* Instantiate a new lexical environment. */
specbind (Qinternal_interpreter_environment, lexenv);
elt = Fprogn (XCDR (args));
return SAFE_FREE_UNBIND_TO (count, elt);
}