⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eval.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
  Lisp_Object funcar;  int numargs = nargs - 1;  Lisp_Object lisp_numargs;  Lisp_Object val;  struct backtrace backtrace;  struct gcpro gcpro1;  register Lisp_Object *internal_args;  register int i;  QUIT;  if (consing_since_gc > gc_cons_threshold)    {      GCPRO1 (*args);      gcpro1.nvars = nargs;      Fgarbage_collect ();      UNGCPRO;    }  if (++lisp_eval_depth > max_lisp_eval_depth)    {      if (max_lisp_eval_depth < 100)	max_lisp_eval_depth = 100;      if (lisp_eval_depth > max_lisp_eval_depth)	error ("Lisp nesting exceeds max-lisp-eval-depth");    }  backtrace.next = backtrace_list;  backtrace_list = &backtrace;  backtrace.function = &args[0];  backtrace.args = &args[1];  backtrace.nargs = nargs - 1;  backtrace.evalargs = 0;  backtrace.debug_on_exit = 0;  if (debug_on_next_call)    do_debug_on_call (Qlambda); retry:  fun = args[0];  while (XTYPE (fun) == Lisp_Symbol)    {      QUIT;      val = XSYMBOL (fun)->function;      if (EQ (val, Qunbound))	Fsymbol_function (fun);	/* Get the right kind of error! */      fun = val;    }  if (XTYPE (fun) == Lisp_Subr)    {      if (numargs < XSUBR (fun)->min_args ||	  (XSUBR (fun)->max_args >= 0 && XSUBR (fun)->max_args < numargs))	{	  XFASTINT (lisp_numargs) = numargs;	  return Fsignal (Qwrong_number_of_arguments, Fcons (fun, Fcons (lisp_numargs, Qnil)));	}      if (XSUBR (fun)->max_args == UNEVALLED)	return Fsignal (Qinvalid_function, Fcons (fun, Qnil));      if (XSUBR (fun)->max_args == MANY)	{	  val = (*XSUBR (fun)->function) (numargs, args + 1);	  goto done;	}      if (XSUBR (fun)->max_args > numargs)	{	  internal_args = (Lisp_Object *) alloca (XSUBR (fun)->max_args * sizeof (Lisp_Object));	  bcopy (args + 1, internal_args, 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) ();	  goto done;	case 1:	  val = (*XSUBR (fun)->function) (internal_args[0]);	  goto done;	case 2:	  val = (*XSUBR (fun)->function) (internal_args[0],					  internal_args[1]);	  goto done;	case 3:	  val = (*XSUBR (fun)->function) (internal_args[0], internal_args[1],					  internal_args[2]);	  goto done;	case 4:	  val = (*XSUBR (fun)->function) (internal_args[0], internal_args[1],					  internal_args[2],					  internal_args[3]);	  goto done;	case 5:	  val = (*XSUBR (fun)->function) (internal_args[0], internal_args[1],					  internal_args[2], internal_args[3],					  internal_args[4]);	  goto done;	}    }  if (!CONSP (fun))    return Fsignal (Qinvalid_function, Fcons (fun, Qnil));  funcar = Fcar (fun);  if (XTYPE (funcar) != Lisp_Symbol)    return Fsignal (Qinvalid_function, Fcons (fun, Qnil));  if (EQ (funcar, Qlambda))    val = funcall_lambda (fun, numargs, args + 1);  else if (EQ (funcar, Qmocklisp))    val = ml_apply (fun, Flist (numargs, args + 1));  else if (EQ (funcar, Qautoload))    {      do_autoload (fun, args[0]);      goto retry;    }  else    return Fsignal (Qinvalid_function, Fcons (fun, Qnil)); done:  lisp_eval_depth--;  if (backtrace.debug_on_exit)    val = call_debugger (Fcons (Qexit, Fcons (val, Qnil)));  backtrace_list = backtrace.next;  return val;}Lisp_Objectapply_lambda (fun, args, eval_flag)     Lisp_Object fun, args;     int eval_flag;{  Lisp_Object args_left;  Lisp_Object numargs;  register Lisp_Object *arg_vector;  struct gcpro gcpro1, gcpro2, gcpro3;  register int i;  register Lisp_Object tem;  numargs = Flength (args);  arg_vector = (Lisp_Object *) alloca (XINT (numargs) * sizeof (Lisp_Object));  args_left = args;  GCPRO3 (*arg_vector, args_left, fun);  gcpro1.nvars = 0;  for (i = 0; i < XINT (numargs);)    {      tem = Fcar (args_left), args_left = Fcdr (args_left);      if (eval_flag) tem = Feval (tem);      arg_vector[i++] = tem;      gcpro1.nvars = i;    }  UNGCPRO;  if (eval_flag)    {      backtrace_list->args = arg_vector;      backtrace_list->nargs = i;    }  backtrace_list->evalargs = 0;  tem = funcall_lambda (fun, XINT (numargs), arg_vector);  /* Do the debug-on-exit now, while arg_vector still exists.  */  if (backtrace_list->debug_on_exit)    tem = call_debugger (Fcons (Qexit, Fcons (tem, Qnil)));  /* Don't do it again when we return to eval.  */  backtrace_list->debug_on_exit = 0;  return tem;}Lisp_Objectfuncall_lambda (fun, nargs, arg_vector)     Lisp_Object fun;     int nargs;     register Lisp_Object *arg_vector;{  Lisp_Object val, tem;  register Lisp_Object syms_left;  Lisp_Object numargs;  register Lisp_Object next;  int count = specpdl_ptr - specpdl;  register int i;  int optional = 0, rest = 0;  specbind (Qmocklisp_arguments, Qt);   /* t means NOT mocklisp! */  XFASTINT (numargs) = nargs;  i = 0;  for (syms_left = Fcar (Fcdr (fun)); !NULL (syms_left); syms_left = Fcdr (syms_left))    {      QUIT;      next = Fcar (syms_left);      if (EQ (next, Qand_rest))	rest = 1;      else if (EQ (next, Qand_optional))	optional = 1;      else if (rest)	{	  specbind (Fcar (syms_left), Flist (nargs - i, &arg_vector[i]));	  i = nargs;	}      else if (i < nargs)	{	  tem = arg_vector[i++];	  specbind (next, tem);	}      else if (!optional)	return Fsignal (Qwrong_number_of_arguments, Fcons (fun, Fcons (numargs, Qnil)));      else	specbind (next, Qnil);    }  if (i < nargs)    return Fsignal (Qwrong_number_of_arguments, Fcons (fun, Fcons (numargs, Qnil)));  val = Fprogn (Fcdr (Fcdr (fun)));  unbind_to (count);  return val;}voidgrow_specpdl (){  register int count = specpdl_ptr - specpdl;  if (specpdl_size >= max_specpdl_size)    {      if (max_specpdl_size < 400)	max_specpdl_size = 400;      if (specpdl_size >= max_specpdl_size)	{	  Fsignal (Qerror,		   Fcons (build_string ("Variable binding depth exceeds max-specpdl-size"), Qnil));	  max_specpdl_size *= 2;	}    }  specpdl_size *= 2;  if (specpdl_size > max_specpdl_size)    specpdl_size = max_specpdl_size;  specpdl = (struct specbinding *) xrealloc (specpdl, specpdl_size * sizeof (struct specbinding));  specpdl_ptr = specpdl + count;}voidspecbind (symbol, value)     Lisp_Object symbol, value;{  extern void store_symval_forwarding (); /* in eval.c */  Lisp_Object ovalue;  if (specpdl_ptr == specpdl + specpdl_size)    grow_specpdl ();  specpdl_ptr->symbol = symbol;  specpdl_ptr->func = 0;  ovalue = XSYMBOL (symbol)->value;  specpdl_ptr->old_value = EQ (ovalue, Qunbound) ? Qunbound : Fsymbol_value (symbol);  specpdl_ptr++;  if (XTYPE (ovalue) == Lisp_Buffer_Objfwd)    store_symval_forwarding (symbol, ovalue, value);  else    Fset (symbol, value);}voidrecord_unwind_protect (function, arg)     Lisp_Object (*function)();     Lisp_Object arg;{  if (specpdl_ptr == specpdl + specpdl_size)    grow_specpdl ();  specpdl_ptr->func = function;  specpdl_ptr->symbol = Qnil;  specpdl_ptr->old_value = arg;  specpdl_ptr++;}voidunbind_to (count)     int count;{  int quitf = !NULL (Vquit_flag);  Vquit_flag = Qnil;  while (specpdl_ptr != specpdl + count)    {      --specpdl_ptr;      if (specpdl_ptr->func != 0)	(*specpdl_ptr->func) (specpdl_ptr->old_value);      /* Note that a "binding" of nil is really an unwind protect,	so in that case the "old value" is a list of forms to evaluate.  */      else if (NULL (specpdl_ptr->symbol))	Fprogn (specpdl_ptr->old_value);      else        Fset (specpdl_ptr->symbol, specpdl_ptr->old_value);    }  if (NULL (Vquit_flag) && quitf) Vquit_flag = Qt;}#if 0/* Get the value of symbol's global binding, even if that binding is not now dynamically visible.  */Lisp_Objecttop_level_value (symbol)     Lisp_Object symbol;{  register struct specbinding *ptr = specpdl;  CHECK_SYMBOL (symbol, 0);  for (; ptr != specpdl_ptr; ptr++)    {      if (EQ (ptr->symbol, symbol))	return ptr->old_value;    }  return Fsymbol_value (symbol);}Lisp_Objecttop_level_set (symbol, newval)     Lisp_Object symbol, newval;{  register struct specbinding *ptr = specpdl;  CHECK_SYMBOL (symbol, 0);  for (; ptr != specpdl_ptr; ptr++)    {      if (EQ (ptr->symbol, symbol))	{	  ptr->old_value = newval;	  return newval;	}    }  return Fset (symbol, newval);}  #endif /* 0 */DEFUN ("backtrace-debug", Fbacktrace_debug, Sbacktrace_debug, 2, 2, 0,  "Set the debug-on-exit flag of eval frame LEVEL levels down to FLAG.\n\The debugger is entered when that frame exits, if the flag is non-nil.")  (level, flag)     Lisp_Object level, flag;{  register struct backtrace *backlist = backtrace_list;  register int i;  CHECK_NUMBER (level, 0);  for (i = 0; backlist && i < XINT (level); i++)    {      backlist = backlist->next;    }  if (backlist)    backlist->debug_on_exit = !NULL (flag);  return flag;}DEFUN ("backtrace", Fbacktrace, Sbacktrace, 0, 0, "",  "Print a trace of Lisp function calls currently active.\n\Output stream used is value of standard-output.")  (){  register struct backtrace *backlist = backtrace_list;  register int i;  Lisp_Object tail;  Lisp_Object tem;  struct gcpro gcpro1;  tail = Qnil;  GCPRO1 (tail);  while (backlist)    {      write_string (backlist->debug_on_exit ? "* " : "  ", 2);      if (backlist->nargs == UNEVALLED)        write_string ("(", -1);      tem = *backlist->function;      Fprin1 (tem, Qnil);	/* This can QUIT */      if (backlist->nargs == UNEVALLED)	{	  if (backlist->evalargs)	    write_string (" ...computing arguments...", -1);	  else	    write_string (" ...", -1);	}      else if (backlist->nargs == MANY)	{	  write_string ("(", -1);	  for (tail = *backlist->args, i = 0; !NULL (tail); tail = Fcdr (tail), i++)	    {	      if (i) write_string (" ", -1);	      Fprin1 (Fcar (tail), Qnil);	    }	}      else	{	  write_string ("(", -1);	  for (i = 0; i < backlist->nargs; i++)	    {	      if (i) write_string (" ", -1);	      Fprin1 (backlist->args[i], Qnil);	    }	}      write_string (")\n", -1);      backlist = backlist->next;    }  UNGCPRO;  return Qnil;}syms_of_eval (){  DEFVAR_INT ("max-specpdl-size", &max_specpdl_size,    "Limit on number of Lisp variable bindings & unwind-protects before error.");  DEFVAR_INT ("max-lisp-eval-depth", &max_lisp_eval_depth,    "Limit on depth in eval, apply and funcall before error.");  DEFVAR_LISP ("quit-flag", &Vquit_flag,    "Non-nil causes  eval  to abort, unless  inhibit-quit  is non-nil.\n\Typing C-G sets  quit-flag  non-nil, regardless of  inhibit-quit.");  Vquit_flag = Qnil;  Qinhibit_quit = intern ("inhibit-quit");  staticpro (&Qinhibit_quit);  DEFVAR_LISP ("inhibit-quit", &Vinhibit_quit,    "Non-nil inhibits C-g quitting from happening immediately.\n\Note that  quit-flag  will still be set by typing C-g,\n\so a quit will be signalled as soon as  inhibit-quit  is nil.\n\To prevent this happening, set  quit-flag  to nil\n\before making  inhibit-quit  nil.");  Vinhibit_quit = Qnil;  Qautoload = intern ("autoload");  staticpro (&Qautoload);  Qmacro = intern ("macro");  staticpro (&Qmacro);  Qexit = intern ("exit");  staticpro (&Qexit);  Qinteractive = intern ("interactive");  staticpro (&Qinteractive);  Qcommandp = intern ("commandp");  staticpro (&Qcommandp);  Qdefun = intern ("defun");  staticpro (&Qdefun);  Qand_rest = intern ("&rest");  staticpro (&Qand_rest);  Qand_optional = intern ("&optional");  staticpro (&Qand_optional);  DEFVAR_BOOL ("stack-trace-on-error", &stack_trace_on_error,    "*Non-nil means automatically display a backtrace buffer\n\after any error that is handled by the editor command loop.");  stack_trace_on_error = 0;  DEFVAR_BOOL ("debug-on-error", &debug_on_error,    "*Non-nil means enter debugger if an error is signaled.\n\Does not apply to errors handled by condition-case.\n\See also variable debug-on-quit.");  debug_on_error = 0;  DEFVAR_BOOL ("debug-on-quit", &debug_on_quit,    "*Non-nil means enter debugger if quit is signaled (C-G, for example).\n\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,    "Non-nil means enter debugger before next eval, apply or funcall.");  DEFVAR_LISP ("debugger", &Vdebugger,    "Function to call to invoke debugger.\n\If due to frame exit, args are 'exit and value being returned;\n\ this function's value will be returned instead of that.\n\If due to error, args are 'error and list of signal's args.\n\If due to apply or funcall entry, one arg, 'lambda.\n\If due to eval entry, one arg, 't.");  Vdebugger = Qnil;  Qmocklisp_arguments = intern ("mocklisp-arguments");  staticpro (&Qmocklisp_arguments);  DEFVAR_LISP ("mocklisp-arguments", &Vmocklisp_arguments,    "While in a mocklisp function, the list of its unevaluated args.");  Vmocklisp_arguments = Qt;  staticpro (&Vautoload_queue);  Vautoload_queue = Qnil;  defsubr (&Sor);  defsubr (&Sand);  defsubr (&Sif);  defsubr (&Scond);  defsubr (&Sprogn);  defsubr (&Sprog1);  defsubr (&Sprog2);  defsubr (&Ssetq);  defsubr (&Squote);  defsubr (&Sfunction);  defsubr (&Sdefun);  defsubr (&Sdefmacro);  defsubr (&Sdefvar);  defsubr (&Sdefconst);  defsubr (&Suser_variable_p);  defsubr (&Slet);  defsubr (&SletX);  defsubr (&Swhile);  defsubr (&Smacroexpand);  defsubr (&Scatch);  defsubr (&Sthrow);  defsubr (&Sunwind_protect);  defsubr (&Scondition_case);  defsubr (&Ssignal);  defsubr (&Sinteractive_p);  defsubr (&Scommandp);  defsubr (&Sautoload);  defsubr (&Seval);  defsubr (&Sapply);  defsubr (&Sfuncall);  defsubr (&Sbacktrace_debug);  defsubr (&Sbacktrace);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -