diff options
| author | Stefan Monnier | 2010-06-13 16:36:17 -0400 |
|---|---|---|
| committer | Stefan Monnier | 2010-06-13 16:36:17 -0400 |
| commit | b9598260f96ddc652cd82ab64bbe922ccfc48a29 (patch) | |
| tree | 2a692a8471de07f2578ea481c99971585def8eda /src/eval.c | |
| parent | a6e8d97c1414230e577d375c27da78c858a5fa75 (diff) | |
| download | emacs-b9598260f96ddc652cd82ab64bbe922ccfc48a29.tar.gz emacs-b9598260f96ddc652cd82ab64bbe922ccfc48a29.zip | |
New branch for lexbind, losing all history.
This initial patch is based on 2002-06-27T22:39:10Z!storm@cua.dk of the original
lexbind branch.
Diffstat (limited to 'src/eval.c')
| -rw-r--r-- | src/eval.c | 377 |
1 files changed, 342 insertions, 35 deletions
diff --git a/src/eval.c b/src/eval.c index 199c4705736..875b4498a61 100644 --- a/src/eval.c +++ b/src/eval.c | |||
| @@ -62,6 +62,9 @@ Lisp_Object Qinhibit_quit, Vinhibit_quit, Vquit_flag; | |||
| 62 | Lisp_Object Qand_rest, Qand_optional; | 62 | Lisp_Object Qand_rest, Qand_optional; |
| 63 | Lisp_Object Qdebug_on_error; | 63 | Lisp_Object Qdebug_on_error; |
| 64 | Lisp_Object Qdeclare; | 64 | Lisp_Object Qdeclare; |
| 65 | Lisp_Object Qcurry, Qunevalled; | ||
| 66 | Lisp_Object Qinternal_interpreter_environment, Qclosure; | ||
| 67 | |||
| 65 | Lisp_Object Qdebug; | 68 | Lisp_Object Qdebug; |
| 66 | extern Lisp_Object Qinteractive_form; | 69 | extern Lisp_Object Qinteractive_form; |
| 67 | 70 | ||
| @@ -78,6 +81,13 @@ Lisp_Object Vrun_hooks; | |||
| 78 | 81 | ||
| 79 | Lisp_Object Vautoload_queue; | 82 | Lisp_Object Vautoload_queue; |
| 80 | 83 | ||
| 84 | /* When lexical binding is being used, this is non-nil, and contains an | ||
| 85 | alist of lexically-bound variable, or t, indicating an empty | ||
| 86 | environment. The lisp name of this variable is | ||
| 87 | `internal-interpreter-lexical-environment'. */ | ||
| 88 | |||
| 89 | Lisp_Object Vinternal_interpreter_environment; | ||
| 90 | |||
| 81 | /* Current number of specbindings allocated in specpdl. */ | 91 | /* Current number of specbindings allocated in specpdl. */ |
| 82 | 92 | ||
| 83 | int specpdl_size; | 93 | int specpdl_size; |
| @@ -167,10 +177,11 @@ int handling_signal; | |||
| 167 | Lisp_Object Vmacro_declaration_function; | 177 | Lisp_Object Vmacro_declaration_function; |
| 168 | 178 | ||
| 169 | extern Lisp_Object Qrisky_local_variable; | 179 | extern Lisp_Object Qrisky_local_variable; |
| 170 | |||
| 171 | extern Lisp_Object Qfunction; | 180 | extern Lisp_Object Qfunction; |
| 172 | 181 | ||
| 173 | static Lisp_Object funcall_lambda P_ ((Lisp_Object, int, Lisp_Object*)); | 182 | static Lisp_Object funcall_lambda P_ ((Lisp_Object, int, Lisp_Object *, |
| 183 | Lisp_Object)); | ||
| 184 | |||
| 174 | static void unwind_to_catch P_ ((struct catchtag *, Lisp_Object)) NO_RETURN; | 185 | static void unwind_to_catch P_ ((struct catchtag *, Lisp_Object)) NO_RETURN; |
| 175 | 186 | ||
| 176 | #if __GNUC__ | 187 | #if __GNUC__ |
| @@ -504,7 +515,7 @@ usage: (setq [SYM VAL]...) */) | |||
| 504 | Lisp_Object args; | 515 | Lisp_Object args; |
| 505 | { | 516 | { |
| 506 | register Lisp_Object args_left; | 517 | register Lisp_Object args_left; |
| 507 | register Lisp_Object val, sym; | 518 | register Lisp_Object val, sym, lex_binding; |
| 508 | struct gcpro gcpro1; | 519 | struct gcpro gcpro1; |
| 509 | 520 | ||
| 510 | if (NILP (args)) | 521 | if (NILP (args)) |
| @@ -517,7 +528,15 @@ usage: (setq [SYM VAL]...) */) | |||
| 517 | { | 528 | { |
| 518 | val = Feval (Fcar (Fcdr (args_left))); | 529 | val = Feval (Fcar (Fcdr (args_left))); |
| 519 | sym = Fcar (args_left); | 530 | sym = Fcar (args_left); |
| 520 | Fset (sym, val); | 531 | |
| 532 | if (!NILP (Vinternal_interpreter_environment) | ||
| 533 | && SYMBOLP (sym) | ||
| 534 | && !XSYMBOL (sym)->declared_special | ||
| 535 | && !NILP (lex_binding = Fassq (sym, Vinternal_interpreter_environment))) | ||
| 536 | XSETCDR (lex_binding, val); /* SYM is lexically bound. */ | ||
| 537 | else | ||
| 538 | Fset (sym, val); /* SYM is dynamically bound. */ | ||
| 539 | |||
| 521 | args_left = Fcdr (Fcdr (args_left)); | 540 | args_left = Fcdr (Fcdr (args_left)); |
| 522 | } | 541 | } |
| 523 | while (!NILP(args_left)); | 542 | while (!NILP(args_left)); |
| @@ -545,9 +564,20 @@ usage: (function ARG) */) | |||
| 545 | (args) | 564 | (args) |
| 546 | Lisp_Object args; | 565 | Lisp_Object args; |
| 547 | { | 566 | { |
| 567 | Lisp_Object quoted = XCAR (args); | ||
| 568 | |||
| 548 | if (!NILP (Fcdr (args))) | 569 | if (!NILP (Fcdr (args))) |
| 549 | xsignal2 (Qwrong_number_of_arguments, Qfunction, Flength (args)); | 570 | xsignal2 (Qwrong_number_of_arguments, Qfunction, Flength (args)); |
| 550 | return Fcar (args); | 571 | |
| 572 | if (!NILP (Vinternal_interpreter_environment) | ||
| 573 | && CONSP (quoted) | ||
| 574 | && EQ (XCAR (quoted), Qlambda)) | ||
| 575 | /* This is a lambda expression within a lexical environment; | ||
| 576 | return an interpreted closure instead of a simple lambda. */ | ||
| 577 | return Fcons (Qclosure, Fcons (Vinternal_interpreter_environment, quoted)); | ||
| 578 | else | ||
| 579 | /* Simply quote the argument. */ | ||
| 580 | return quoted; | ||
| 551 | } | 581 | } |
| 552 | 582 | ||
| 553 | 583 | ||
| @@ -570,7 +600,7 @@ spec that specifies non-nil unconditionally (such as \"p\"); or (ii) | |||
| 570 | use `called-interactively-p'. */) | 600 | use `called-interactively-p'. */) |
| 571 | () | 601 | () |
| 572 | { | 602 | { |
| 573 | return (INTERACTIVE && interactive_p (1)) ? Qt : Qnil; | 603 | return interactive_p (1) ? Qt : Qnil; |
| 574 | } | 604 | } |
| 575 | 605 | ||
| 576 | 606 | ||
| @@ -666,6 +696,8 @@ usage: (defun NAME ARGLIST [DOCSTRING] BODY...) */) | |||
| 666 | fn_name = Fcar (args); | 696 | fn_name = Fcar (args); |
| 667 | CHECK_SYMBOL (fn_name); | 697 | CHECK_SYMBOL (fn_name); |
| 668 | defn = Fcons (Qlambda, Fcdr (args)); | 698 | defn = Fcons (Qlambda, Fcdr (args)); |
| 699 | if (! NILP (Vinternal_interpreter_environment)) | ||
| 700 | defn = Fcons (Qclosure, Fcons (Vinternal_interpreter_environment, defn)); | ||
| 669 | if (!NILP (Vpurify_flag)) | 701 | if (!NILP (Vpurify_flag)) |
| 670 | defn = Fpurecopy (defn); | 702 | defn = Fpurecopy (defn); |
| 671 | if (CONSP (XSYMBOL (fn_name)->function) | 703 | if (CONSP (XSYMBOL (fn_name)->function) |
| @@ -738,7 +770,11 @@ usage: (defmacro NAME ARGLIST [DOCSTRING] [DECL] BODY...) */) | |||
| 738 | tail = Fcons (lambda_list, tail); | 770 | tail = Fcons (lambda_list, tail); |
| 739 | else | 771 | else |
| 740 | tail = Fcons (lambda_list, Fcons (doc, tail)); | 772 | tail = Fcons (lambda_list, Fcons (doc, tail)); |
| 741 | defn = Fcons (Qmacro, Fcons (Qlambda, tail)); | 773 | |
| 774 | defn = Fcons (Qlambda, tail); | ||
| 775 | if (! NILP (Vinternal_interpreter_environment)) | ||
| 776 | defn = Fcons (Qclosure, Fcons (Vinternal_interpreter_environment, defn)); | ||
| 777 | defn = Fcons (Qmacro, defn); | ||
| 742 | 778 | ||
| 743 | if (!NILP (Vpurify_flag)) | 779 | if (!NILP (Vpurify_flag)) |
| 744 | defn = Fpurecopy (defn); | 780 | defn = Fpurecopy (defn); |
| @@ -799,6 +835,7 @@ The return value is BASE-VARIABLE. */) | |||
| 799 | error ("Don't know how to make a let-bound variable an alias"); | 835 | error ("Don't know how to make a let-bound variable an alias"); |
| 800 | } | 836 | } |
| 801 | 837 | ||
| 838 | sym->declared_special = 1; | ||
| 802 | sym->redirect = SYMBOL_VARALIAS; | 839 | sym->redirect = SYMBOL_VARALIAS; |
| 803 | SET_SYMBOL_ALIAS (sym, XSYMBOL (base_variable)); | 840 | SET_SYMBOL_ALIAS (sym, XSYMBOL (base_variable)); |
| 804 | sym->constant = SYMBOL_CONSTANT_P (base_variable); | 841 | sym->constant = SYMBOL_CONSTANT_P (base_variable); |
| @@ -889,6 +926,9 @@ usage: (defvar SYMBOL &optional INITVALUE DOCSTRING) */) | |||
| 889 | It could get in the way of other definitions, and unloading this | 926 | It could get in the way of other definitions, and unloading this |
| 890 | package could try to make the variable unbound. */ | 927 | package could try to make the variable unbound. */ |
| 891 | ; | 928 | ; |
| 929 | |||
| 930 | if (SYMBOLP (sym)) | ||
| 931 | XSYMBOL (sym)->declared_special = 1; | ||
| 892 | 932 | ||
| 893 | return sym; | 933 | return sym; |
| 894 | } | 934 | } |
| @@ -918,6 +958,7 @@ usage: (defconst SYMBOL INITVALUE [DOCSTRING]) */) | |||
| 918 | if (!NILP (Vpurify_flag)) | 958 | if (!NILP (Vpurify_flag)) |
| 919 | tem = Fpurecopy (tem); | 959 | tem = Fpurecopy (tem); |
| 920 | Fset_default (sym, tem); | 960 | Fset_default (sym, tem); |
| 961 | XSYMBOL (sym)->declared_special = 1; | ||
| 921 | tem = Fcar (Fcdr (Fcdr (args))); | 962 | tem = Fcar (Fcdr (Fcdr (args))); |
| 922 | if (!NILP (tem)) | 963 | if (!NILP (tem)) |
| 923 | { | 964 | { |
| @@ -1006,30 +1047,50 @@ usage: (let* VARLIST BODY...) */) | |||
| 1006 | (args) | 1047 | (args) |
| 1007 | Lisp_Object args; | 1048 | Lisp_Object args; |
| 1008 | { | 1049 | { |
| 1009 | Lisp_Object varlist, val, elt; | 1050 | Lisp_Object varlist, var, val, elt, lexenv; |
| 1010 | int count = SPECPDL_INDEX (); | 1051 | int count = SPECPDL_INDEX (); |
| 1011 | struct gcpro gcpro1, gcpro2, gcpro3; | 1052 | struct gcpro gcpro1, gcpro2, gcpro3; |
| 1012 | 1053 | ||
| 1013 | GCPRO3 (args, elt, varlist); | 1054 | GCPRO3 (args, elt, varlist); |
| 1014 | 1055 | ||
| 1056 | lexenv = Vinternal_interpreter_environment; | ||
| 1057 | |||
| 1015 | varlist = Fcar (args); | 1058 | varlist = Fcar (args); |
| 1016 | while (!NILP (varlist)) | 1059 | while (CONSP (varlist)) |
| 1017 | { | 1060 | { |
| 1018 | QUIT; | 1061 | QUIT; |
| 1019 | elt = Fcar (varlist); | 1062 | |
| 1063 | elt = XCAR (varlist); | ||
| 1020 | if (SYMBOLP (elt)) | 1064 | if (SYMBOLP (elt)) |
| 1021 | specbind (elt, Qnil); | 1065 | { |
| 1066 | var = elt; | ||
| 1067 | val = Qnil; | ||
| 1068 | } | ||
| 1022 | else if (! NILP (Fcdr (Fcdr (elt)))) | 1069 | else if (! NILP (Fcdr (Fcdr (elt)))) |
| 1023 | signal_error ("`let' bindings can have only one value-form", elt); | 1070 | signal_error ("`let' bindings can have only one value-form", elt); |
| 1024 | else | 1071 | else |
| 1025 | { | 1072 | { |
| 1073 | var = Fcar (elt); | ||
| 1026 | val = Feval (Fcar (Fcdr (elt))); | 1074 | val = Feval (Fcar (Fcdr (elt))); |
| 1027 | specbind (Fcar (elt), val); | ||
| 1028 | } | 1075 | } |
| 1029 | varlist = Fcdr (varlist); | 1076 | |
| 1077 | if (!NILP (lexenv) && SYMBOLP (var) && !XSYMBOL (var)->declared_special) | ||
| 1078 | /* Lexically bind VAR by adding it to the interpreter's binding | ||
| 1079 | alist. */ | ||
| 1080 | { | ||
| 1081 | lexenv = Fcons (Fcons (var, val), lexenv); | ||
| 1082 | specbind (Qinternal_interpreter_environment, lexenv); | ||
| 1083 | } | ||
| 1084 | else | ||
| 1085 | specbind (var, val); | ||
| 1086 | |||
| 1087 | varlist = XCDR (varlist); | ||
| 1030 | } | 1088 | } |
| 1089 | |||
| 1031 | UNGCPRO; | 1090 | UNGCPRO; |
| 1091 | |||
| 1032 | val = Fprogn (Fcdr (args)); | 1092 | val = Fprogn (Fcdr (args)); |
| 1093 | |||
| 1033 | return unbind_to (count, val); | 1094 | return unbind_to (count, val); |
| 1034 | } | 1095 | } |
| 1035 | 1096 | ||
| @@ -1043,7 +1104,7 @@ usage: (let VARLIST BODY...) */) | |||
| 1043 | (args) | 1104 | (args) |
| 1044 | Lisp_Object args; | 1105 | Lisp_Object args; |
| 1045 | { | 1106 | { |
| 1046 | Lisp_Object *temps, tem; | 1107 | Lisp_Object *temps, tem, lexenv; |
| 1047 | register Lisp_Object elt, varlist; | 1108 | register Lisp_Object elt, varlist; |
| 1048 | int count = SPECPDL_INDEX (); | 1109 | int count = SPECPDL_INDEX (); |
| 1049 | register int argnum; | 1110 | register int argnum; |
| @@ -1074,18 +1135,31 @@ usage: (let VARLIST BODY...) */) | |||
| 1074 | } | 1135 | } |
| 1075 | UNGCPRO; | 1136 | UNGCPRO; |
| 1076 | 1137 | ||
| 1138 | lexenv = Vinternal_interpreter_environment; | ||
| 1139 | |||
| 1077 | varlist = Fcar (args); | 1140 | varlist = Fcar (args); |
| 1078 | for (argnum = 0; CONSP (varlist); varlist = XCDR (varlist)) | 1141 | for (argnum = 0; CONSP (varlist); varlist = XCDR (varlist)) |
| 1079 | { | 1142 | { |
| 1143 | Lisp_Object var; | ||
| 1144 | |||
| 1080 | elt = XCAR (varlist); | 1145 | elt = XCAR (varlist); |
| 1146 | var = SYMBOLP (elt) ? elt : Fcar (elt); | ||
| 1081 | tem = temps[argnum++]; | 1147 | tem = temps[argnum++]; |
| 1082 | if (SYMBOLP (elt)) | 1148 | |
| 1083 | specbind (elt, tem); | 1149 | if (!NILP (lexenv) && SYMBOLP (var) && !XSYMBOL (var)->declared_special) |
| 1150 | /* Lexically bind VAR by adding it to the lexenv alist. */ | ||
| 1151 | lexenv = Fcons (Fcons (var, tem), lexenv); | ||
| 1084 | else | 1152 | else |
| 1085 | specbind (Fcar (elt), tem); | 1153 | /* Dynamically bind VAR. */ |
| 1154 | specbind (var, tem); | ||
| 1086 | } | 1155 | } |
| 1087 | 1156 | ||
| 1157 | if (!EQ (lexenv, Vinternal_interpreter_environment)) | ||
| 1158 | /* Instantiate a new lexical environment. */ | ||
| 1159 | specbind (Qinternal_interpreter_environment, lexenv); | ||
| 1160 | |||
| 1088 | elt = Fprogn (Fcdr (args)); | 1161 | elt = Fprogn (Fcdr (args)); |
| 1162 | |||
| 1089 | return unbind_to (count, elt); | 1163 | return unbind_to (count, elt); |
| 1090 | } | 1164 | } |
| 1091 | 1165 | ||
| @@ -2292,7 +2366,28 @@ DEFUN ("eval", Feval, Seval, 1, 1, 0, | |||
| 2292 | abort (); | 2366 | abort (); |
| 2293 | 2367 | ||
| 2294 | if (SYMBOLP (form)) | 2368 | if (SYMBOLP (form)) |
| 2295 | return Fsymbol_value (form); | 2369 | { |
| 2370 | /* If there's an active lexical environment, and the variable | ||
| 2371 | isn't declared special, look up its binding in the lexical | ||
| 2372 | environment. */ | ||
| 2373 | if (!NILP (Vinternal_interpreter_environment) | ||
| 2374 | && !XSYMBOL (form)->declared_special) | ||
| 2375 | { | ||
| 2376 | Lisp_Object lex_binding | ||
| 2377 | = Fassq (form, Vinternal_interpreter_environment); | ||
| 2378 | |||
| 2379 | /* If we found a lexical binding for FORM, return the value. | ||
| 2380 | Otherwise, we just drop through and look for a dynamic | ||
| 2381 | binding -- the variable isn't declared special, but there's | ||
| 2382 | not much else we can do, and Fsymbol_value will take care | ||
| 2383 | of signaling an error if there is no binding at all. */ | ||
| 2384 | if (CONSP (lex_binding)) | ||
| 2385 | return XCDR (lex_binding); | ||
| 2386 | } | ||
| 2387 | |||
| 2388 | return Fsymbol_value (form); | ||
| 2389 | } | ||
| 2390 | |||
| 2296 | if (!CONSP (form)) | 2391 | if (!CONSP (form)) |
| 2297 | return form; | 2392 | return form; |
| 2298 | 2393 | ||
| @@ -2452,8 +2547,8 @@ DEFUN ("eval", Feval, Seval, 1, 1, 0, | |||
| 2452 | abort (); | 2547 | abort (); |
| 2453 | } | 2548 | } |
| 2454 | } | 2549 | } |
| 2455 | if (COMPILEDP (fun)) | 2550 | if (FUNVECP (fun)) |
| 2456 | val = apply_lambda (fun, original_args, 1); | 2551 | val = apply_lambda (fun, original_args, 1, Qnil); |
| 2457 | else | 2552 | else |
| 2458 | { | 2553 | { |
| 2459 | if (EQ (fun, Qunbound)) | 2554 | if (EQ (fun, Qunbound)) |
| @@ -2471,7 +2566,18 @@ DEFUN ("eval", Feval, Seval, 1, 1, 0, | |||
| 2471 | if (EQ (funcar, Qmacro)) | 2566 | if (EQ (funcar, Qmacro)) |
| 2472 | val = Feval (apply1 (Fcdr (fun), original_args)); | 2567 | val = Feval (apply1 (Fcdr (fun), original_args)); |
| 2473 | else if (EQ (funcar, Qlambda)) | 2568 | else if (EQ (funcar, Qlambda)) |
| 2474 | val = apply_lambda (fun, original_args, 1); | 2569 | val = apply_lambda (fun, original_args, 1, |
| 2570 | /* Only pass down the current lexical environment | ||
| 2571 | if FUN is lexically embedded in FORM. */ | ||
| 2572 | (CONSP (original_fun) | ||
| 2573 | ? Vinternal_interpreter_environment | ||
| 2574 | : Qnil)); | ||
| 2575 | else if (EQ (funcar, Qclosure) | ||
| 2576 | && CONSP (XCDR (fun)) | ||
| 2577 | && CONSP (XCDR (XCDR (fun))) | ||
| 2578 | && EQ (XCAR (XCDR (XCDR (fun))), Qlambda)) | ||
| 2579 | val = apply_lambda (XCDR (XCDR (fun)), original_args, 1, | ||
| 2580 | XCAR (XCDR (fun))); | ||
| 2475 | else | 2581 | else |
| 2476 | xsignal1 (Qinvalid_function, original_fun); | 2582 | xsignal1 (Qinvalid_function, original_fun); |
| 2477 | } | 2583 | } |
| @@ -2981,6 +3087,40 @@ call7 (fn, arg1, arg2, arg3, arg4, arg5, arg6, arg7) | |||
| 2981 | 3087 | ||
| 2982 | /* The caller should GCPRO all the elements of ARGS. */ | 3088 | /* The caller should GCPRO all the elements of ARGS. */ |
| 2983 | 3089 | ||
| 3090 | DEFUN ("functionp", Ffunctionp, Sfunctionp, 1, 1, 0, | ||
| 3091 | doc: /* Return non-nil if OBJECT is a type of object that can be called as a function. */) | ||
| 3092 | (object) | ||
| 3093 | Lisp_Object object; | ||
| 3094 | { | ||
| 3095 | if (SYMBOLP (object) && !NILP (Ffboundp (object))) | ||
| 3096 | { | ||
| 3097 | object = Findirect_function (object, Qnil); | ||
| 3098 | |||
| 3099 | if (CONSP (object) && EQ (XCAR (object), Qautoload)) | ||
| 3100 | { | ||
| 3101 | /* Autoloaded symbols are functions, except if they load | ||
| 3102 | macros or keymaps. */ | ||
| 3103 | int i; | ||
| 3104 | for (i = 0; i < 4 && CONSP (object); i++) | ||
| 3105 | object = XCDR (object); | ||
| 3106 | |||
| 3107 | return (CONSP (object) && !NILP (XCAR (object))) ? Qnil : Qt; | ||
| 3108 | } | ||
| 3109 | } | ||
| 3110 | |||
| 3111 | if (SUBRP (object)) | ||
| 3112 | return (XSUBR (object)->max_args != Qunevalled) ? Qt : Qnil; | ||
| 3113 | else if (FUNVECP (object)) | ||
| 3114 | return Qt; | ||
| 3115 | else if (CONSP (object)) | ||
| 3116 | { | ||
| 3117 | Lisp_Object car = XCAR (object); | ||
| 3118 | return (EQ (car, Qlambda) || EQ (car, Qclosure)) ? Qt : Qnil; | ||
| 3119 | } | ||
| 3120 | else | ||
| 3121 | return Qnil; | ||
| 3122 | } | ||
| 3123 | |||
| 2984 | DEFUN ("funcall", Ffuncall, Sfuncall, 1, MANY, 0, | 3124 | DEFUN ("funcall", Ffuncall, Sfuncall, 1, MANY, 0, |
| 2985 | doc: /* Call first argument as a function, passing remaining arguments to it. | 3125 | doc: /* Call first argument as a function, passing remaining arguments to it. |
| 2986 | Return the value that function returns. | 3126 | Return the value that function returns. |
| @@ -3115,8 +3255,9 @@ usage: (funcall FUNCTION &rest ARGUMENTS) */) | |||
| 3115 | abort (); | 3255 | abort (); |
| 3116 | } | 3256 | } |
| 3117 | } | 3257 | } |
| 3118 | if (COMPILEDP (fun)) | 3258 | |
| 3119 | val = funcall_lambda (fun, numargs, args + 1); | 3259 | if (FUNVECP (fun)) |
| 3260 | val = funcall_lambda (fun, numargs, args + 1, Qnil); | ||
| 3120 | else | 3261 | else |
| 3121 | { | 3262 | { |
| 3122 | if (EQ (fun, Qunbound)) | 3263 | if (EQ (fun, Qunbound)) |
| @@ -3127,7 +3268,13 @@ usage: (funcall FUNCTION &rest ARGUMENTS) */) | |||
| 3127 | if (!SYMBOLP (funcar)) | 3268 | if (!SYMBOLP (funcar)) |
| 3128 | xsignal1 (Qinvalid_function, original_fun); | 3269 | xsignal1 (Qinvalid_function, original_fun); |
| 3129 | if (EQ (funcar, Qlambda)) | 3270 | if (EQ (funcar, Qlambda)) |
| 3130 | val = funcall_lambda (fun, numargs, args + 1); | 3271 | val = funcall_lambda (fun, numargs, args + 1, Qnil); |
| 3272 | else if (EQ (funcar, Qclosure) | ||
| 3273 | && CONSP (XCDR (fun)) | ||
| 3274 | && CONSP (XCDR (XCDR (fun))) | ||
| 3275 | && EQ (XCAR (XCDR (XCDR (fun))), Qlambda)) | ||
| 3276 | val = funcall_lambda (XCDR (XCDR (fun)), numargs, args + 1, | ||
| 3277 | XCAR (XCDR (fun))); | ||
| 3131 | else if (EQ (funcar, Qautoload)) | 3278 | else if (EQ (funcar, Qautoload)) |
| 3132 | { | 3279 | { |
| 3133 | do_autoload (fun, original_fun); | 3280 | do_autoload (fun, original_fun); |
| @@ -3147,9 +3294,10 @@ usage: (funcall FUNCTION &rest ARGUMENTS) */) | |||
| 3147 | } | 3294 | } |
| 3148 | 3295 | ||
| 3149 | Lisp_Object | 3296 | Lisp_Object |
| 3150 | apply_lambda (fun, args, eval_flag) | 3297 | apply_lambda (fun, args, eval_flag, lexenv) |
| 3151 | Lisp_Object fun, args; | 3298 | Lisp_Object fun, args; |
| 3152 | int eval_flag; | 3299 | int eval_flag; |
| 3300 | Lisp_Object lexenv; | ||
| 3153 | { | 3301 | { |
| 3154 | Lisp_Object args_left; | 3302 | Lisp_Object args_left; |
| 3155 | Lisp_Object numargs; | 3303 | Lisp_Object numargs; |
| @@ -3181,7 +3329,7 @@ apply_lambda (fun, args, eval_flag) | |||
| 3181 | backtrace_list->nargs = i; | 3329 | backtrace_list->nargs = i; |
| 3182 | } | 3330 | } |
| 3183 | backtrace_list->evalargs = 0; | 3331 | backtrace_list->evalargs = 0; |
| 3184 | tem = funcall_lambda (fun, XINT (numargs), arg_vector); | 3332 | tem = funcall_lambda (fun, XINT (numargs), arg_vector, lexenv); |
| 3185 | 3333 | ||
| 3186 | /* Do the debug-on-exit now, while arg_vector still exists. */ | 3334 | /* Do the debug-on-exit now, while arg_vector still exists. */ |
| 3187 | if (backtrace_list->debug_on_exit) | 3335 | if (backtrace_list->debug_on_exit) |
| @@ -3191,20 +3339,100 @@ apply_lambda (fun, args, eval_flag) | |||
| 3191 | return tem; | 3339 | return tem; |
| 3192 | } | 3340 | } |
| 3193 | 3341 | ||
| 3342 | |||
| 3343 | /* Call a non-bytecode funvec object FUN, on the argments in ARGS (of | ||
| 3344 | length NARGS). */ | ||
| 3345 | |||
| 3346 | static Lisp_Object | ||
| 3347 | funcall_funvec (fun, nargs, args) | ||
| 3348 | Lisp_Object fun; | ||
| 3349 | int nargs; | ||
| 3350 | Lisp_Object *args; | ||
| 3351 | { | ||
| 3352 | int size = FUNVEC_SIZE (fun); | ||
| 3353 | Lisp_Object tag = (size > 0 ? AREF (fun, 0) : Qnil); | ||
| 3354 | |||
| 3355 | if (EQ (tag, Qcurry)) | ||
| 3356 | { | ||
| 3357 | /* A curried function is a way to attach arguments to a another | ||
| 3358 | function. The first element of the vector is the identifier | ||
| 3359 | `curry', the second is the wrapped function, and remaining | ||
| 3360 | elements are the attached arguments. */ | ||
| 3361 | int num_curried_args = size - 2; | ||
| 3362 | /* Offset of the curried and user args in the final arglist. Curried | ||
| 3363 | args are first in the new arg vector, after the function. User | ||
| 3364 | args follow. */ | ||
| 3365 | int curried_args_offs = 1; | ||
| 3366 | int user_args_offs = curried_args_offs + num_curried_args; | ||
| 3367 | /* The curried function and arguments. */ | ||
| 3368 | Lisp_Object *curry_params = XVECTOR (fun)->contents + 1; | ||
| 3369 | /* The arguments in the curry vector. */ | ||
| 3370 | Lisp_Object *curried_args = curry_params + 1; | ||
| 3371 | /* The number of arguments with which we'll call funcall, and the | ||
| 3372 | arguments themselves. */ | ||
| 3373 | int num_funcall_args = 1 + num_curried_args + nargs; | ||
| 3374 | Lisp_Object *funcall_args | ||
| 3375 | = (Lisp_Object *) alloca (num_funcall_args * sizeof (Lisp_Object)); | ||
| 3376 | |||
| 3377 | /* First comes the real function. */ | ||
| 3378 | funcall_args[0] = curry_params[0]; | ||
| 3379 | |||
| 3380 | /* Then the arguments in the appropriate order. */ | ||
| 3381 | bcopy (curried_args, funcall_args + curried_args_offs, | ||
| 3382 | num_curried_args * sizeof (Lisp_Object)); | ||
| 3383 | bcopy (args, funcall_args + user_args_offs, | ||
| 3384 | nargs * sizeof (Lisp_Object)); | ||
| 3385 | |||
| 3386 | return Ffuncall (num_funcall_args, funcall_args); | ||
| 3387 | } | ||
| 3388 | else | ||
| 3389 | xsignal1 (Qinvalid_function, fun); | ||
| 3390 | } | ||
| 3391 | |||
| 3392 | |||
| 3194 | /* Apply a Lisp function FUN to the NARGS evaluated arguments in ARG_VECTOR | 3393 | /* Apply a Lisp function FUN to the NARGS evaluated arguments in ARG_VECTOR |
| 3195 | and return the result of evaluation. | 3394 | and return the result of evaluation. |
| 3196 | FUN must be either a lambda-expression or a compiled-code object. */ | 3395 | FUN must be either a lambda-expression or a compiled-code object. */ |
| 3197 | 3396 | ||
| 3198 | static Lisp_Object | 3397 | static Lisp_Object |
| 3199 | funcall_lambda (fun, nargs, arg_vector) | 3398 | funcall_lambda (fun, nargs, arg_vector, lexenv) |
| 3200 | Lisp_Object fun; | 3399 | Lisp_Object fun; |
| 3201 | int nargs; | 3400 | int nargs; |
| 3202 | register Lisp_Object *arg_vector; | 3401 | register Lisp_Object *arg_vector; |
| 3402 | Lisp_Object lexenv; | ||
| 3203 | { | 3403 | { |
| 3204 | Lisp_Object val, syms_left, next; | 3404 | Lisp_Object val, syms_left, next; |
| 3205 | int count = SPECPDL_INDEX (); | 3405 | int count = SPECPDL_INDEX (); |
| 3206 | int i, optional, rest; | 3406 | int i, optional, rest; |
| 3207 | 3407 | ||
| 3408 | if (COMPILEDP (fun) | ||
| 3409 | && FUNVEC_SIZE (fun) > COMPILED_PUSH_ARGS | ||
| 3410 | && ! NILP (XVECTOR (fun)->contents[COMPILED_PUSH_ARGS])) | ||
| 3411 | /* A byte-code object with a non-nil `push args' slot means we | ||
| 3412 | shouldn't bind any arguments, instead just call the byte-code | ||
| 3413 | interpreter directly; it will push arguments as necessary. | ||
| 3414 | |||
| 3415 | Byte-code objects with either a non-existant, or a nil value for | ||
| 3416 | the `push args' slot (the default), have dynamically-bound | ||
| 3417 | arguments, and use the argument-binding code below instead (as do | ||
| 3418 | all interpreted functions, even lexically bound ones). */ | ||
| 3419 | { | ||
| 3420 | /* If we have not actually read the bytecode string | ||
| 3421 | and constants vector yet, fetch them from the file. */ | ||
| 3422 | if (CONSP (AREF (fun, COMPILED_BYTECODE))) | ||
| 3423 | Ffetch_bytecode (fun); | ||
| 3424 | return exec_byte_code (AREF (fun, COMPILED_BYTECODE), | ||
| 3425 | AREF (fun, COMPILED_CONSTANTS), | ||
| 3426 | AREF (fun, COMPILED_STACK_DEPTH), | ||
| 3427 | AREF (fun, COMPILED_ARGLIST), | ||
| 3428 | nargs, arg_vector); | ||
| 3429 | } | ||
| 3430 | |||
| 3431 | if (FUNVECP (fun) && !FUNVEC_COMPILED_P (fun)) | ||
| 3432 | /* Byte-compiled functions are handled directly below, but we | ||
| 3433 | call other funvec types via funcall_funvec. */ | ||
| 3434 | return funcall_funvec (fun, nargs, arg_vector); | ||
| 3435 | |||
| 3208 | if (CONSP (fun)) | 3436 | if (CONSP (fun)) |
| 3209 | { | 3437 | { |
| 3210 | syms_left = XCDR (fun); | 3438 | syms_left = XCDR (fun); |
| @@ -3236,12 +3464,27 @@ funcall_lambda (fun, nargs, arg_vector) | |||
| 3236 | specbind (next, Flist (nargs - i, &arg_vector[i])); | 3464 | specbind (next, Flist (nargs - i, &arg_vector[i])); |
| 3237 | i = nargs; | 3465 | i = nargs; |
| 3238 | } | 3466 | } |
| 3239 | else if (i < nargs) | ||
| 3240 | specbind (next, arg_vector[i++]); | ||
| 3241 | else if (!optional) | ||
| 3242 | xsignal2 (Qwrong_number_of_arguments, fun, make_number (nargs)); | ||
| 3243 | else | 3467 | else |
| 3244 | specbind (next, Qnil); | 3468 | { |
| 3469 | Lisp_Object val; | ||
| 3470 | |||
| 3471 | /* Get the argument's actual value. */ | ||
| 3472 | if (i < nargs) | ||
| 3473 | val = arg_vector[i++]; | ||
| 3474 | else if (!optional) | ||
| 3475 | xsignal2 (Qwrong_number_of_arguments, fun, make_number (nargs)); | ||
| 3476 | else | ||
| 3477 | val = Qnil; | ||
| 3478 | |||
| 3479 | /* Bind the argument. */ | ||
| 3480 | if (!NILP (lexenv) | ||
| 3481 | && SYMBOLP (next) && !XSYMBOL (next)->declared_special) | ||
| 3482 | /* Lexically bind NEXT by adding it to the lexenv alist. */ | ||
| 3483 | lexenv = Fcons (Fcons (next, val), lexenv); | ||
| 3484 | else | ||
| 3485 | /* Dynamically bind NEXT. */ | ||
| 3486 | specbind (next, val); | ||
| 3487 | } | ||
| 3245 | } | 3488 | } |
| 3246 | 3489 | ||
| 3247 | if (!NILP (syms_left)) | 3490 | if (!NILP (syms_left)) |
| @@ -3249,6 +3492,10 @@ funcall_lambda (fun, nargs, arg_vector) | |||
| 3249 | else if (i < nargs) | 3492 | else if (i < nargs) |
| 3250 | xsignal2 (Qwrong_number_of_arguments, fun, make_number (nargs)); | 3493 | xsignal2 (Qwrong_number_of_arguments, fun, make_number (nargs)); |
| 3251 | 3494 | ||
| 3495 | if (!EQ (lexenv, Vinternal_interpreter_environment)) | ||
| 3496 | /* Instantiate a new lexical environment. */ | ||
| 3497 | specbind (Qinternal_interpreter_environment, lexenv); | ||
| 3498 | |||
| 3252 | if (CONSP (fun)) | 3499 | if (CONSP (fun)) |
| 3253 | val = Fprogn (XCDR (XCDR (fun))); | 3500 | val = Fprogn (XCDR (XCDR (fun))); |
| 3254 | else | 3501 | else |
| @@ -3257,9 +3504,10 @@ funcall_lambda (fun, nargs, arg_vector) | |||
| 3257 | and constants vector yet, fetch them from the file. */ | 3504 | and constants vector yet, fetch them from the file. */ |
| 3258 | if (CONSP (AREF (fun, COMPILED_BYTECODE))) | 3505 | if (CONSP (AREF (fun, COMPILED_BYTECODE))) |
| 3259 | Ffetch_bytecode (fun); | 3506 | Ffetch_bytecode (fun); |
| 3260 | val = Fbyte_code (AREF (fun, COMPILED_BYTECODE), | 3507 | val = exec_byte_code (AREF (fun, COMPILED_BYTECODE), |
| 3261 | AREF (fun, COMPILED_CONSTANTS), | 3508 | AREF (fun, COMPILED_CONSTANTS), |
| 3262 | AREF (fun, COMPILED_STACK_DEPTH)); | 3509 | AREF (fun, COMPILED_STACK_DEPTH), |
| 3510 | Qnil, 0, 0); | ||
| 3263 | } | 3511 | } |
| 3264 | 3512 | ||
| 3265 | return unbind_to (count, val); | 3513 | return unbind_to (count, val); |
| @@ -3502,7 +3750,42 @@ unbind_to (count, value) | |||
| 3502 | UNGCPRO; | 3750 | UNGCPRO; |
| 3503 | return value; | 3751 | return value; |
| 3504 | } | 3752 | } |
| 3753 | |||
| 3505 | 3754 | ||
| 3755 | |||
| 3756 | DEFUN ("specialp", Fspecialp, Sspecialp, 1, 1, 0, | ||
| 3757 | doc: /* Return non-nil if SYMBOL's global binding has been declared special. | ||
| 3758 | A special variable is one that will be bound dynamically, even in a | ||
| 3759 | context where binding is lexical by default. */) | ||
| 3760 | (symbol) | ||
| 3761 | Lisp_Object symbol; | ||
| 3762 | { | ||
| 3763 | CHECK_SYMBOL (symbol); | ||
| 3764 | return XSYMBOL (symbol)->declared_special ? Qt : Qnil; | ||
| 3765 | } | ||
| 3766 | |||
| 3767 | |||
| 3768 | |||
| 3769 | DEFUN ("curry", Fcurry, Scurry, 1, MANY, 0, | ||
| 3770 | doc: /* Return FUN curried with ARGS. | ||
| 3771 | The result is a function-like object that will append any arguments it | ||
| 3772 | is called with to ARGS, and call FUN with the resulting list of arguments. | ||
| 3773 | |||
| 3774 | For instance: | ||
| 3775 | (funcall (curry '+ 3 4 5) 2) is the same as (funcall '+ 3 4 5 2) | ||
| 3776 | and: | ||
| 3777 | (mapcar (curry 'concat "The ") '("a" "b" "c")) | ||
| 3778 | => ("The a" "The b" "The c") | ||
| 3779 | |||
| 3780 | usage: (curry FUN &rest ARGS) */) | ||
| 3781 | (nargs, args) | ||
| 3782 | register int nargs; | ||
| 3783 | Lisp_Object *args; | ||
| 3784 | { | ||
| 3785 | return make_funvec (Qcurry, 0, nargs, args); | ||
| 3786 | } | ||
| 3787 | |||
| 3788 | |||
| 3506 | DEFUN ("backtrace-debug", Fbacktrace_debug, Sbacktrace_debug, 2, 2, 0, | 3789 | DEFUN ("backtrace-debug", Fbacktrace_debug, Sbacktrace_debug, 2, 2, 0, |
| 3507 | doc: /* Set the debug-on-exit flag of eval frame LEVEL levels down to FLAG. | 3790 | doc: /* Set the debug-on-exit flag of eval frame LEVEL levels down to FLAG. |
| 3508 | The debugger is entered when that frame exits, if the flag is non-nil. */) | 3791 | The debugger is entered when that frame exits, if the flag is non-nil. */) |
| @@ -3713,6 +3996,15 @@ before making `inhibit-quit' nil. */); | |||
| 3713 | Qand_optional = intern_c_string ("&optional"); | 3996 | Qand_optional = intern_c_string ("&optional"); |
| 3714 | staticpro (&Qand_optional); | 3997 | staticpro (&Qand_optional); |
| 3715 | 3998 | ||
| 3999 | Qclosure = intern_c_string ("closure"); | ||
| 4000 | staticpro (&Qclosure); | ||
| 4001 | |||
| 4002 | Qcurry = intern_c_string ("curry"); | ||
| 4003 | staticpro (&Qcurry); | ||
| 4004 | |||
| 4005 | Qunevalled = intern_c_string ("unevalled"); | ||
| 4006 | staticpro (&Qunevalled); | ||
| 4007 | |||
| 3716 | Qdebug = intern_c_string ("debug"); | 4008 | Qdebug = intern_c_string ("debug"); |
| 3717 | staticpro (&Qdebug); | 4009 | staticpro (&Qdebug); |
| 3718 | 4010 | ||
| @@ -3788,6 +4080,17 @@ DECL is a list `(declare ...)' containing the declarations. | |||
| 3788 | The value the function returns is not used. */); | 4080 | The value the function returns is not used. */); |
| 3789 | Vmacro_declaration_function = Qnil; | 4081 | Vmacro_declaration_function = Qnil; |
| 3790 | 4082 | ||
| 4083 | Qinternal_interpreter_environment | ||
| 4084 | = intern_c_string ("internal-interpreter-environment"); | ||
| 4085 | staticpro (&Qinternal_interpreter_environment); | ||
| 4086 | DEFVAR_LISP ("internal-interpreter-environment", | ||
| 4087 | &Vinternal_interpreter_environment, | ||
| 4088 | doc: /* If non-nil, the current lexical environment of the lisp interpreter. | ||
| 4089 | When lexical binding is not being used, this variable is nil. | ||
| 4090 | A value of `(t)' indicates an empty environment, otherwise it is an | ||
| 4091 | alist of active lexical bindings. */); | ||
| 4092 | Vinternal_interpreter_environment = Qnil; | ||
| 4093 | |||
| 3791 | Vrun_hooks = intern_c_string ("run-hooks"); | 4094 | Vrun_hooks = intern_c_string ("run-hooks"); |
| 3792 | staticpro (&Vrun_hooks); | 4095 | staticpro (&Vrun_hooks); |
| 3793 | 4096 | ||
| @@ -3833,9 +4136,13 @@ The value the function returns is not used. */); | |||
| 3833 | defsubr (&Srun_hook_with_args_until_success); | 4136 | defsubr (&Srun_hook_with_args_until_success); |
| 3834 | defsubr (&Srun_hook_with_args_until_failure); | 4137 | defsubr (&Srun_hook_with_args_until_failure); |
| 3835 | defsubr (&Sfetch_bytecode); | 4138 | defsubr (&Sfetch_bytecode); |
| 4139 | defsubr (&Scurry); | ||
| 3836 | defsubr (&Sbacktrace_debug); | 4140 | defsubr (&Sbacktrace_debug); |
| 3837 | defsubr (&Sbacktrace); | 4141 | defsubr (&Sbacktrace); |
| 3838 | defsubr (&Sbacktrace_frame); | 4142 | defsubr (&Sbacktrace_frame); |
| 4143 | defsubr (&Scurry); | ||
| 4144 | defsubr (&Sspecialp); | ||
| 4145 | defsubr (&Sfunctionp); | ||
| 3839 | } | 4146 | } |
| 3840 | 4147 | ||
| 3841 | /* arch-tag: 014a07aa-33ab-4a8f-a3d2-ee8a4a9ff7fb | 4148 | /* arch-tag: 014a07aa-33ab-4a8f-a3d2-ee8a4a9ff7fb |