diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/callint.c | 6 | ||||
| -rw-r--r-- | src/data.c | 46 | ||||
| -rw-r--r-- | src/eval.c | 148 | ||||
| -rw-r--r-- | src/lread.c | 35 | ||||
| -rw-r--r-- | src/profiler.c | 8 |
5 files changed, 149 insertions, 94 deletions
diff --git a/src/callint.c b/src/callint.c index b31faba8704..9d6f2ab2888 100644 --- a/src/callint.c +++ b/src/callint.c | |||
| @@ -319,10 +319,10 @@ invoke it (via an `interactive' spec that contains, for instance, an | |||
| 319 | { | 319 | { |
| 320 | Lisp_Object funval = Findirect_function (function, Qt); | 320 | Lisp_Object funval = Findirect_function (function, Qt); |
| 321 | uintmax_t events = num_input_events; | 321 | uintmax_t events = num_input_events; |
| 322 | Lisp_Object env = CLOSUREP (funval) && CONSP (AREF (funval, CLOSURE_CODE)) | ||
| 323 | ? AREF (funval, CLOSURE_CONSTANTS) : Qnil; | ||
| 322 | /* Compute the arg values using the user's expression. */ | 324 | /* Compute the arg values using the user's expression. */ |
| 323 | specs = Feval (specs, | 325 | specs = Feval (specs, env); |
| 324 | CONSP (funval) && EQ (Qclosure, XCAR (funval)) | ||
| 325 | ? CAR_SAFE (XCDR (funval)) : Qnil); | ||
| 326 | if (events != num_input_events || !NILP (record_flag)) | 326 | if (events != num_input_events || !NILP (record_flag)) |
| 327 | { | 327 | { |
| 328 | /* We should record this command on the command history. | 328 | /* We should record this command on the command history. |
diff --git a/src/data.c b/src/data.c index 681054ff8cb..ea611ad1abf 100644 --- a/src/data.c +++ b/src/data.c | |||
| @@ -248,7 +248,9 @@ a fixed set of types. */) | |||
| 248 | return XSUBR (object)->max_args == UNEVALLED ? Qspecial_form | 248 | return XSUBR (object)->max_args == UNEVALLED ? Qspecial_form |
| 249 | : SUBR_NATIVE_COMPILEDP (object) ? Qsubr_native_elisp | 249 | : SUBR_NATIVE_COMPILEDP (object) ? Qsubr_native_elisp |
| 250 | : Qprimitive_function; | 250 | : Qprimitive_function; |
| 251 | case PVEC_CLOSURE: return Qcompiled_function; | 251 | case PVEC_CLOSURE: |
| 252 | return CONSP (AREF (object, CLOSURE_CODE)) | ||
| 253 | ? Qinterpreted_function : Qbyte_code_function; | ||
| 252 | case PVEC_BUFFER: return Qbuffer; | 254 | case PVEC_BUFFER: return Qbuffer; |
| 253 | case PVEC_CHAR_TABLE: return Qchar_table; | 255 | case PVEC_CHAR_TABLE: return Qchar_table; |
| 254 | case PVEC_BOOL_VECTOR: return Qbool_vector; | 256 | case PVEC_BOOL_VECTOR: return Qbool_vector; |
| @@ -518,12 +520,32 @@ DEFUN ("subrp", Fsubrp, Ssubrp, 1, 1, 0, | |||
| 518 | return Qnil; | 520 | return Qnil; |
| 519 | } | 521 | } |
| 520 | 522 | ||
| 523 | DEFUN ("closurep", Fclosurep, Sclosurep, | ||
| 524 | 1, 1, 0, | ||
| 525 | doc: /* Return t if OBJECT is a function of type `closure'. */) | ||
| 526 | (Lisp_Object object) | ||
| 527 | { | ||
| 528 | if (CLOSUREP (object)) | ||
| 529 | return Qt; | ||
| 530 | return Qnil; | ||
| 531 | } | ||
| 532 | |||
| 521 | DEFUN ("byte-code-function-p", Fbyte_code_function_p, Sbyte_code_function_p, | 533 | DEFUN ("byte-code-function-p", Fbyte_code_function_p, Sbyte_code_function_p, |
| 522 | 1, 1, 0, | 534 | 1, 1, 0, |
| 523 | doc: /* Return t if OBJECT is a byte-compiled function object. */) | 535 | doc: /* Return t if OBJECT is a byte-compiled function object. */) |
| 524 | (Lisp_Object object) | 536 | (Lisp_Object object) |
| 525 | { | 537 | { |
| 526 | if (CLOSUREP (object)) | 538 | if (CLOSUREP (object) && STRINGP (AREF (object, CLOSURE_CODE))) |
| 539 | return Qt; | ||
| 540 | return Qnil; | ||
| 541 | } | ||
| 542 | |||
| 543 | DEFUN ("interpreted-function-p", Finterpreted_function_p, | ||
| 544 | Sinterpreted_function_p, 1, 1, 0, | ||
| 545 | doc: /* Return t if OBJECT is a function of type `interpreted-function'. */) | ||
| 546 | (Lisp_Object object) | ||
| 547 | { | ||
| 548 | if (CLOSUREP (object) && CONSP (AREF (object, CLOSURE_CODE))) | ||
| 527 | return Qt; | 549 | return Qt; |
| 528 | return Qnil; | 550 | return Qnil; |
| 529 | } | 551 | } |
| @@ -1174,17 +1196,11 @@ Value, if non-nil, is a list (interactive SPEC). */) | |||
| 1174 | else if (CONSP (fun)) | 1196 | else if (CONSP (fun)) |
| 1175 | { | 1197 | { |
| 1176 | Lisp_Object funcar = XCAR (fun); | 1198 | Lisp_Object funcar = XCAR (fun); |
| 1177 | if (EQ (funcar, Qclosure) | 1199 | if (EQ (funcar, Qlambda)) |
| 1178 | || EQ (funcar, Qlambda)) | ||
| 1179 | { | 1200 | { |
| 1180 | Lisp_Object form = Fcdr (XCDR (fun)); | 1201 | Lisp_Object form = Fcdr (XCDR (fun)); |
| 1181 | if (EQ (funcar, Qclosure)) | ||
| 1182 | form = Fcdr (form); | ||
| 1183 | Lisp_Object spec = Fassq (Qinteractive, form); | 1202 | Lisp_Object spec = Fassq (Qinteractive, form); |
| 1184 | if (NILP (spec) && VALID_DOCSTRING_P (CAR_SAFE (form))) | 1203 | if (NILP (Fcdr (Fcdr (spec)))) |
| 1185 | /* A "docstring" is a sign that we may have an OClosure. */ | ||
| 1186 | genfun = true; | ||
| 1187 | else if (NILP (Fcdr (Fcdr (spec)))) | ||
| 1188 | return spec; | 1204 | return spec; |
| 1189 | else | 1205 | else |
| 1190 | return list2 (Qinteractive, Fcar (Fcdr (spec))); | 1206 | return list2 (Qinteractive, Fcar (Fcdr (spec))); |
| @@ -1257,12 +1273,9 @@ The value, if non-nil, is a list of mode name symbols. */) | |||
| 1257 | else if (CONSP (fun)) | 1273 | else if (CONSP (fun)) |
| 1258 | { | 1274 | { |
| 1259 | Lisp_Object funcar = XCAR (fun); | 1275 | Lisp_Object funcar = XCAR (fun); |
| 1260 | if (EQ (funcar, Qclosure) | 1276 | if (EQ (funcar, Qlambda)) |
| 1261 | || EQ (funcar, Qlambda)) | ||
| 1262 | { | 1277 | { |
| 1263 | Lisp_Object form = Fcdr (XCDR (fun)); | 1278 | Lisp_Object form = Fcdr (XCDR (fun)); |
| 1264 | if (EQ (funcar, Qclosure)) | ||
| 1265 | form = Fcdr (form); | ||
| 1266 | return Fcdr (Fcdr (Fassq (Qinteractive, form))); | 1279 | return Fcdr (Fcdr (Fassq (Qinteractive, form))); |
| 1267 | } | 1280 | } |
| 1268 | } | 1281 | } |
| @@ -4224,7 +4237,8 @@ syms_of_data (void) | |||
| 4224 | DEFSYM (Qspecial_form, "special-form"); | 4237 | DEFSYM (Qspecial_form, "special-form"); |
| 4225 | DEFSYM (Qprimitive_function, "primitive-function"); | 4238 | DEFSYM (Qprimitive_function, "primitive-function"); |
| 4226 | DEFSYM (Qsubr_native_elisp, "subr-native-elisp"); | 4239 | DEFSYM (Qsubr_native_elisp, "subr-native-elisp"); |
| 4227 | DEFSYM (Qcompiled_function, "compiled-function"); | 4240 | DEFSYM (Qbyte_code_function, "byte-code-function"); |
| 4241 | DEFSYM (Qinterpreted_function, "interpreted-function"); | ||
| 4228 | DEFSYM (Qbuffer, "buffer"); | 4242 | DEFSYM (Qbuffer, "buffer"); |
| 4229 | DEFSYM (Qframe, "frame"); | 4243 | DEFSYM (Qframe, "frame"); |
| 4230 | DEFSYM (Qvector, "vector"); | 4244 | DEFSYM (Qvector, "vector"); |
| @@ -4289,6 +4303,8 @@ syms_of_data (void) | |||
| 4289 | defsubr (&Smarkerp); | 4303 | defsubr (&Smarkerp); |
| 4290 | defsubr (&Ssubrp); | 4304 | defsubr (&Ssubrp); |
| 4291 | defsubr (&Sbyte_code_function_p); | 4305 | defsubr (&Sbyte_code_function_p); |
| 4306 | defsubr (&Sinterpreted_function_p); | ||
| 4307 | defsubr (&Sclosurep); | ||
| 4292 | defsubr (&Smodule_function_p); | 4308 | defsubr (&Smodule_function_p); |
| 4293 | defsubr (&Schar_or_string_p); | 4309 | defsubr (&Schar_or_string_p); |
| 4294 | defsubr (&Sthreadp); | 4310 | defsubr (&Sthreadp); |
diff --git a/src/eval.c b/src/eval.c index a7d860114cf..fd388706108 100644 --- a/src/eval.c +++ b/src/eval.c | |||
| @@ -510,6 +510,33 @@ usage: (quote ARG) */) | |||
| 510 | return XCAR (args); | 510 | return XCAR (args); |
| 511 | } | 511 | } |
| 512 | 512 | ||
| 513 | DEFUN ("make-interpreted-closure", Fmake_interpreted_closure, | ||
| 514 | Smake_interpreted_closure, 3, 5, 0, | ||
| 515 | doc: /* Make an interpreted closure. | ||
| 516 | ARGS should be the list of formal arguments. | ||
| 517 | BODY should be a non-empty list of forms. | ||
| 518 | ENV should be a lexical environment, like the second argument of `eval'. | ||
| 519 | IFORM if non-nil should be of the form (interactive ...). */) | ||
| 520 | (Lisp_Object args, Lisp_Object body, Lisp_Object env, | ||
| 521 | Lisp_Object docstring, Lisp_Object iform) | ||
| 522 | { | ||
| 523 | CHECK_CONS (body); /* Make sure it's not confused with byte-code! */ | ||
| 524 | CHECK_LIST (args); | ||
| 525 | CHECK_LIST (iform); | ||
| 526 | Lisp_Object ifcdr = Fcdr (iform); | ||
| 527 | Lisp_Object slots[] = { args, body, env, Qnil, docstring, | ||
| 528 | NILP (Fcdr (ifcdr)) | ||
| 529 | ? Fcar (ifcdr) | ||
| 530 | : CALLN (Fvector, XCAR (ifcdr), XCDR (ifcdr)) }; | ||
| 531 | /* Adjusting the size is indispensable since, as for byte-code objects, | ||
| 532 | we distinguish interactive functions by the presence or absence of the | ||
| 533 | iform slot. */ | ||
| 534 | Lisp_Object val | ||
| 535 | = Fvector (!NILP (iform) ? 6 : !NILP (docstring) ? 5 : 3, slots); | ||
| 536 | XSETPVECTYPE (XVECTOR (val), PVEC_CLOSURE); | ||
| 537 | return val; | ||
| 538 | } | ||
| 539 | |||
| 513 | DEFUN ("function", Ffunction, Sfunction, 1, UNEVALLED, 0, | 540 | DEFUN ("function", Ffunction, Sfunction, 1, UNEVALLED, 0, |
| 514 | doc: /* Like `quote', but preferred for objects which are functions. | 541 | doc: /* Like `quote', but preferred for objects which are functions. |
| 515 | In byte compilation, `function' causes its argument to be handled by | 542 | In byte compilation, `function' causes its argument to be handled by |
| @@ -525,33 +552,55 @@ usage: (function ARG) */) | |||
| 525 | if (!NILP (XCDR (args))) | 552 | if (!NILP (XCDR (args))) |
| 526 | xsignal2 (Qwrong_number_of_arguments, Qfunction, Flength (args)); | 553 | xsignal2 (Qwrong_number_of_arguments, Qfunction, Flength (args)); |
| 527 | 554 | ||
| 528 | if (!NILP (Vinternal_interpreter_environment) | 555 | if (CONSP (quoted) |
| 529 | && CONSP (quoted) | ||
| 530 | && EQ (XCAR (quoted), Qlambda)) | 556 | && EQ (XCAR (quoted), Qlambda)) |
| 531 | { /* This is a lambda expression within a lexical environment; | 557 | { /* This is a lambda expression within a lexical environment; |
| 532 | return an interpreted closure instead of a simple lambda. */ | 558 | return an interpreted closure instead of a simple lambda. */ |
| 533 | Lisp_Object cdr = XCDR (quoted); | 559 | Lisp_Object cdr = XCDR (quoted); |
| 534 | Lisp_Object tmp = cdr; | 560 | Lisp_Object args = Fcar (cdr); |
| 535 | if (CONSP (tmp) | 561 | cdr = Fcdr (cdr); |
| 536 | && (tmp = XCDR (tmp), CONSP (tmp)) | 562 | Lisp_Object docstring = Qnil, iform = Qnil; |
| 537 | && (tmp = XCAR (tmp), CONSP (tmp)) | 563 | if (CONSP (cdr)) |
| 538 | && (EQ (QCdocumentation, XCAR (tmp)))) | 564 | { |
| 539 | { /* Handle the special (:documentation <form>) to build the docstring | 565 | docstring = XCAR (cdr); |
| 566 | if (STRINGP (docstring)) | ||
| 567 | { | ||
| 568 | Lisp_Object tmp = XCDR (cdr); | ||
| 569 | if (!NILP (tmp)) | ||
| 570 | cdr = tmp; | ||
| 571 | else /* It's not a docstring, it's a return value. */ | ||
| 572 | docstring = Qnil; | ||
| 573 | } | ||
| 574 | /* Handle the special (:documentation <form>) to build the docstring | ||
| 540 | dynamically. */ | 575 | dynamically. */ |
| 541 | Lisp_Object docstring = eval_sub (Fcar (XCDR (tmp))); | 576 | else if (CONSP (docstring) |
| 542 | if (SYMBOLP (docstring) && !NILP (docstring)) | 577 | && EQ (QCdocumentation, XCAR (docstring)) |
| 543 | /* Hack for OClosures: Allow the docstring to be a symbol | 578 | && (docstring = eval_sub (Fcar (XCDR (docstring))), |
| 544 | * (the OClosure's type). */ | 579 | true)) |
| 545 | docstring = Fsymbol_name (docstring); | 580 | cdr = XCDR (cdr); |
| 546 | CHECK_STRING (docstring); | 581 | else |
| 547 | cdr = Fcons (XCAR (cdr), Fcons (docstring, XCDR (XCDR (cdr)))); | 582 | docstring = Qnil; /* Not a docstring after all. */ |
| 548 | } | 583 | } |
| 549 | if (NILP (Vinternal_make_interpreted_closure_function)) | 584 | if (CONSP (cdr)) |
| 550 | return Fcons (Qclosure, Fcons (Vinternal_interpreter_environment, cdr)); | 585 | { |
| 586 | iform = XCAR (cdr); | ||
| 587 | if (CONSP (iform) | ||
| 588 | && EQ (Qinteractive, XCAR (iform))) | ||
| 589 | cdr = XCDR (cdr); | ||
| 590 | else | ||
| 591 | iform = Qnil; /* Not an interactive-form after all. */ | ||
| 592 | } | ||
| 593 | if (NILP (cdr)) | ||
| 594 | cdr = Fcons (Qnil, Qnil); /* Make sure the body is never empty! */ | ||
| 595 | |||
| 596 | if (NILP (Vinternal_interpreter_environment) | ||
| 597 | || NILP (Vinternal_make_interpreted_closure_function)) | ||
| 598 | return Fmake_interpreted_closure | ||
| 599 | (args, cdr, Vinternal_interpreter_environment, docstring, iform); | ||
| 551 | else | 600 | else |
| 552 | return call2 (Vinternal_make_interpreted_closure_function, | 601 | return call5 (Vinternal_make_interpreted_closure_function, |
| 553 | Fcons (Qlambda, cdr), | 602 | args, cdr, Vinternal_interpreter_environment, |
| 554 | Vinternal_interpreter_environment); | 603 | docstring, iform); |
| 555 | } | 604 | } |
| 556 | else | 605 | else |
| 557 | /* Simply quote the argument. */ | 606 | /* Simply quote the argument. */ |
| @@ -2193,15 +2242,12 @@ then strings and vectors are not accepted. */) | |||
| 2193 | else | 2242 | else |
| 2194 | { | 2243 | { |
| 2195 | Lisp_Object body = CDR_SAFE (XCDR (fun)); | 2244 | Lisp_Object body = CDR_SAFE (XCDR (fun)); |
| 2196 | if (EQ (funcar, Qclosure)) | 2245 | if (!EQ (funcar, Qlambda)) |
| 2197 | body = CDR_SAFE (body); | ||
| 2198 | else if (!EQ (funcar, Qlambda)) | ||
| 2199 | return Qnil; | 2246 | return Qnil; |
| 2200 | if (!NILP (Fassq (Qinteractive, body))) | 2247 | if (!NILP (Fassq (Qinteractive, body))) |
| 2201 | return Qt; | 2248 | return Qt; |
| 2202 | else if (VALID_DOCSTRING_P (CAR_SAFE (body))) | 2249 | else |
| 2203 | /* A "docstring" is a sign that we may have an OClosure. */ | 2250 | return Qnil; |
| 2204 | genfun = true; | ||
| 2205 | } | 2251 | } |
| 2206 | } | 2252 | } |
| 2207 | 2253 | ||
| @@ -2611,8 +2657,7 @@ eval_sub (Lisp_Object form) | |||
| 2611 | exp = unbind_to (count1, exp); | 2657 | exp = unbind_to (count1, exp); |
| 2612 | val = eval_sub (exp); | 2658 | val = eval_sub (exp); |
| 2613 | } | 2659 | } |
| 2614 | else if (EQ (funcar, Qlambda) | 2660 | else if (EQ (funcar, Qlambda)) |
| 2615 | || EQ (funcar, Qclosure)) | ||
| 2616 | return apply_lambda (fun, original_args, count); | 2661 | return apply_lambda (fun, original_args, count); |
| 2617 | else | 2662 | else |
| 2618 | xsignal1 (Qinvalid_function, original_fun); | 2663 | xsignal1 (Qinvalid_function, original_fun); |
| @@ -2950,7 +2995,7 @@ FUNCTIONP (Lisp_Object object) | |||
| 2950 | else if (CONSP (object)) | 2995 | else if (CONSP (object)) |
| 2951 | { | 2996 | { |
| 2952 | Lisp_Object car = XCAR (object); | 2997 | Lisp_Object car = XCAR (object); |
| 2953 | return EQ (car, Qlambda) || EQ (car, Qclosure); | 2998 | return EQ (car, Qlambda); |
| 2954 | } | 2999 | } |
| 2955 | else | 3000 | else |
| 2956 | return false; | 3001 | return false; |
| @@ -2980,8 +3025,7 @@ funcall_general (Lisp_Object fun, ptrdiff_t numargs, Lisp_Object *args) | |||
| 2980 | Lisp_Object funcar = XCAR (fun); | 3025 | Lisp_Object funcar = XCAR (fun); |
| 2981 | if (!SYMBOLP (funcar)) | 3026 | if (!SYMBOLP (funcar)) |
| 2982 | xsignal1 (Qinvalid_function, original_fun); | 3027 | xsignal1 (Qinvalid_function, original_fun); |
| 2983 | if (EQ (funcar, Qlambda) | 3028 | if (EQ (funcar, Qlambda)) |
| 2984 | || EQ (funcar, Qclosure)) | ||
| 2985 | return funcall_lambda (fun, numargs, args); | 3029 | return funcall_lambda (fun, numargs, args); |
| 2986 | else if (EQ (funcar, Qautoload)) | 3030 | else if (EQ (funcar, Qautoload)) |
| 2987 | { | 3031 | { |
| @@ -3165,16 +3209,7 @@ funcall_lambda (Lisp_Object fun, ptrdiff_t nargs, Lisp_Object *arg_vector) | |||
| 3165 | 3209 | ||
| 3166 | if (CONSP (fun)) | 3210 | if (CONSP (fun)) |
| 3167 | { | 3211 | { |
| 3168 | if (EQ (XCAR (fun), Qclosure)) | 3212 | lexenv = Qnil; |
| 3169 | { | ||
| 3170 | Lisp_Object cdr = XCDR (fun); /* Drop `closure'. */ | ||
| 3171 | if (! CONSP (cdr)) | ||
| 3172 | xsignal1 (Qinvalid_function, fun); | ||
| 3173 | fun = cdr; | ||
| 3174 | lexenv = XCAR (fun); | ||
| 3175 | } | ||
| 3176 | else | ||
| 3177 | lexenv = Qnil; | ||
| 3178 | syms_left = XCDR (fun); | 3213 | syms_left = XCDR (fun); |
| 3179 | if (CONSP (syms_left)) | 3214 | if (CONSP (syms_left)) |
| 3180 | syms_left = XCAR (syms_left); | 3215 | syms_left = XCAR (syms_left); |
| @@ -3189,10 +3224,12 @@ funcall_lambda (Lisp_Object fun, ptrdiff_t nargs, Lisp_Object *arg_vector) | |||
| 3189 | engine directly. */ | 3224 | engine directly. */ |
| 3190 | if (FIXNUMP (syms_left)) | 3225 | if (FIXNUMP (syms_left)) |
| 3191 | return exec_byte_code (fun, XFIXNUM (syms_left), nargs, arg_vector); | 3226 | return exec_byte_code (fun, XFIXNUM (syms_left), nargs, arg_vector); |
| 3192 | /* Otherwise the bytecode object uses dynamic binding and the | 3227 | /* Otherwise the closure either is interpreted |
| 3193 | ARGLIST slot contains a standard formal argument list whose | 3228 | or uses dynamic binding and the ARGLIST slot contains a standard |
| 3194 | variables are bound dynamically below. */ | 3229 | formal argument list whose variables are bound dynamically below. */ |
| 3195 | lexenv = Qnil; | 3230 | lexenv = CONSP (AREF (fun, CLOSURE_CODE)) |
| 3231 | ? AREF (fun, CLOSURE_CONSTANTS) | ||
| 3232 | : Qnil; | ||
| 3196 | } | 3233 | } |
| 3197 | #ifdef HAVE_MODULES | 3234 | #ifdef HAVE_MODULES |
| 3198 | else if (MODULE_FUNCTIONP (fun)) | 3235 | else if (MODULE_FUNCTIONP (fun)) |
| @@ -3280,7 +3317,14 @@ funcall_lambda (Lisp_Object fun, ptrdiff_t nargs, Lisp_Object *arg_vector) | |||
| 3280 | val = XSUBR (fun)->function.a0 (); | 3317 | val = XSUBR (fun)->function.a0 (); |
| 3281 | } | 3318 | } |
| 3282 | else | 3319 | else |
| 3283 | val = exec_byte_code (fun, 0, 0, NULL); | 3320 | { |
| 3321 | eassert (CLOSUREP (fun)); | ||
| 3322 | val = CONSP (AREF (fun, CLOSURE_CODE)) | ||
| 3323 | /* Interpreted function. */ | ||
| 3324 | ? Fprogn (AREF (fun, CLOSURE_CODE)) | ||
| 3325 | /* Dynbound bytecode. */ | ||
| 3326 | : exec_byte_code (fun, 0, 0, NULL); | ||
| 3327 | } | ||
| 3284 | 3328 | ||
| 3285 | return unbind_to (count, val); | 3329 | return unbind_to (count, val); |
| 3286 | } | 3330 | } |
| @@ -3330,8 +3374,7 @@ function with `&rest' args, or `unevalled' for a special form. */) | |||
| 3330 | funcar = XCAR (function); | 3374 | funcar = XCAR (function); |
| 3331 | if (!SYMBOLP (funcar)) | 3375 | if (!SYMBOLP (funcar)) |
| 3332 | xsignal1 (Qinvalid_function, original); | 3376 | xsignal1 (Qinvalid_function, original); |
| 3333 | if (EQ (funcar, Qlambda) | 3377 | if (EQ (funcar, Qlambda)) |
| 3334 | || EQ (funcar, Qclosure)) | ||
| 3335 | result = lambda_arity (function); | 3378 | result = lambda_arity (function); |
| 3336 | else if (EQ (funcar, Qautoload)) | 3379 | else if (EQ (funcar, Qautoload)) |
| 3337 | { | 3380 | { |
| @@ -3352,11 +3395,6 @@ lambda_arity (Lisp_Object fun) | |||
| 3352 | 3395 | ||
| 3353 | if (CONSP (fun)) | 3396 | if (CONSP (fun)) |
| 3354 | { | 3397 | { |
| 3355 | if (EQ (XCAR (fun), Qclosure)) | ||
| 3356 | { | ||
| 3357 | fun = XCDR (fun); /* Drop `closure'. */ | ||
| 3358 | CHECK_CONS (fun); | ||
| 3359 | } | ||
| 3360 | syms_left = XCDR (fun); | 3398 | syms_left = XCDR (fun); |
| 3361 | if (CONSP (syms_left)) | 3399 | if (CONSP (syms_left)) |
| 3362 | syms_left = XCAR (syms_left); | 3400 | syms_left = XCAR (syms_left); |
| @@ -4265,7 +4303,6 @@ before making `inhibit-quit' nil. */); | |||
| 4265 | DEFSYM (Qcommandp, "commandp"); | 4303 | DEFSYM (Qcommandp, "commandp"); |
| 4266 | DEFSYM (Qand_rest, "&rest"); | 4304 | DEFSYM (Qand_rest, "&rest"); |
| 4267 | DEFSYM (Qand_optional, "&optional"); | 4305 | DEFSYM (Qand_optional, "&optional"); |
| 4268 | DEFSYM (Qclosure, "closure"); | ||
| 4269 | DEFSYM (QCdocumentation, ":documentation"); | 4306 | DEFSYM (QCdocumentation, ":documentation"); |
| 4270 | DEFSYM (Qdebug, "debug"); | 4307 | DEFSYM (Qdebug, "debug"); |
| 4271 | DEFSYM (Qdebug_early, "debug-early"); | 4308 | DEFSYM (Qdebug_early, "debug-early"); |
| @@ -4423,6 +4460,7 @@ alist of active lexical bindings. */); | |||
| 4423 | defsubr (&Ssetq); | 4460 | defsubr (&Ssetq); |
| 4424 | defsubr (&Squote); | 4461 | defsubr (&Squote); |
| 4425 | defsubr (&Sfunction); | 4462 | defsubr (&Sfunction); |
| 4463 | defsubr (&Smake_interpreted_closure); | ||
| 4426 | defsubr (&Sdefault_toplevel_value); | 4464 | defsubr (&Sdefault_toplevel_value); |
| 4427 | defsubr (&Sset_default_toplevel_value); | 4465 | defsubr (&Sset_default_toplevel_value); |
| 4428 | defsubr (&Sdefvar); | 4466 | defsubr (&Sdefvar); |
diff --git a/src/lread.c b/src/lread.c index 8b614e6220e..983fdb883ff 100644 --- a/src/lread.c +++ b/src/lread.c | |||
| @@ -3523,25 +3523,32 @@ bytecode_from_rev_list (Lisp_Object elems, Lisp_Object readcharfun) | |||
| 3523 | } | 3523 | } |
| 3524 | } | 3524 | } |
| 3525 | 3525 | ||
| 3526 | if (!(size >= CLOSURE_STACK_DEPTH + 1 && size <= CLOSURE_INTERACTIVE + 1 | 3526 | if (!(size >= CLOSURE_STACK_DEPTH && size <= CLOSURE_INTERACTIVE + 1 |
| 3527 | && (FIXNUMP (vec[CLOSURE_ARGLIST]) | 3527 | && (FIXNUMP (vec[CLOSURE_ARGLIST]) |
| 3528 | || CONSP (vec[CLOSURE_ARGLIST]) | 3528 | || CONSP (vec[CLOSURE_ARGLIST]) |
| 3529 | || NILP (vec[CLOSURE_ARGLIST])) | 3529 | || NILP (vec[CLOSURE_ARGLIST])) |
| 3530 | && STRINGP (vec[CLOSURE_CODE]) | 3530 | && ((STRINGP (vec[CLOSURE_CODE]) /* Byte-code function. */ |
| 3531 | && VECTORP (vec[CLOSURE_CONSTANTS]) | 3531 | && VECTORP (vec[CLOSURE_CONSTANTS]) |
| 3532 | && FIXNATP (vec[CLOSURE_STACK_DEPTH]))) | 3532 | && size > CLOSURE_STACK_DEPTH |
| 3533 | && (FIXNATP (vec[CLOSURE_STACK_DEPTH]))) | ||
| 3534 | || (CONSP (vec[CLOSURE_CODE]) /* Interpreted function. */ | ||
| 3535 | && (CONSP (vec[CLOSURE_CONSTANTS]) | ||
| 3536 | || NILP (vec[CLOSURE_CONSTANTS])))))) | ||
| 3533 | invalid_syntax ("Invalid byte-code object", readcharfun); | 3537 | invalid_syntax ("Invalid byte-code object", readcharfun); |
| 3534 | 3538 | ||
| 3535 | if (STRING_MULTIBYTE (vec[CLOSURE_CODE])) | 3539 | if (STRINGP (vec[CLOSURE_CODE])) |
| 3536 | /* BYTESTR must have been produced by Emacs 20.2 or earlier | 3540 | { |
| 3537 | because it produced a raw 8-bit string for byte-code and | 3541 | if (STRING_MULTIBYTE (vec[CLOSURE_CODE])) |
| 3538 | now such a byte-code string is loaded as multibyte with | 3542 | /* BYTESTR must have been produced by Emacs 20.2 or earlier |
| 3539 | raw 8-bit characters converted to multibyte form. | 3543 | because it produced a raw 8-bit string for byte-code and |
| 3540 | Convert them back to the original unibyte form. */ | 3544 | now such a byte-code string is loaded as multibyte with |
| 3541 | vec[CLOSURE_CODE] = Fstring_as_unibyte (vec[CLOSURE_CODE]); | 3545 | raw 8-bit characters converted to multibyte form. |
| 3542 | 3546 | Convert them back to the original unibyte form. */ | |
| 3543 | /* Bytecode must be immovable. */ | 3547 | vec[CLOSURE_CODE] = Fstring_as_unibyte (vec[CLOSURE_CODE]); |
| 3544 | pin_string (vec[CLOSURE_CODE]); | 3548 | |
| 3549 | /* Bytecode must be immovable. */ | ||
| 3550 | pin_string (vec[CLOSURE_CODE]); | ||
| 3551 | } | ||
| 3545 | 3552 | ||
| 3546 | XSETPVECTYPE (XVECTOR (obj), PVEC_CLOSURE); | 3553 | XSETPVECTYPE (XVECTOR (obj), PVEC_CLOSURE); |
| 3547 | return obj; | 3554 | return obj; |
diff --git a/src/profiler.c b/src/profiler.c index ac23a97b672..6e1dc46abd3 100644 --- a/src/profiler.c +++ b/src/profiler.c | |||
| @@ -170,9 +170,7 @@ trace_hash (Lisp_Object *trace, int depth) | |||
| 170 | { | 170 | { |
| 171 | Lisp_Object f = trace[i]; | 171 | Lisp_Object f = trace[i]; |
| 172 | EMACS_UINT hash1 | 172 | EMACS_UINT hash1 |
| 173 | = (CLOSUREP (f) ? XHASH (AREF (f, CLOSURE_CODE)) | 173 | = (CLOSUREP (f) ? XHASH (AREF (f, CLOSURE_CODE)) : XHASH (f)); |
| 174 | : (CONSP (f) && CONSP (XCDR (f)) && BASE_EQ (Qclosure, XCAR (f))) | ||
| 175 | ? XHASH (XCDR (XCDR (f))) : XHASH (f)); | ||
| 176 | hash = sxhash_combine (hash, hash1); | 174 | hash = sxhash_combine (hash, hash1); |
| 177 | } | 175 | } |
| 178 | return hash; | 176 | return hash; |
| @@ -677,10 +675,6 @@ the same lambda expression, or are really unrelated function. */) | |||
| 677 | res = true; | 675 | res = true; |
| 678 | else if (CLOSUREP (f1) && CLOSUREP (f2)) | 676 | else if (CLOSUREP (f1) && CLOSUREP (f2)) |
| 679 | res = EQ (AREF (f1, CLOSURE_CODE), AREF (f2, CLOSURE_CODE)); | 677 | res = EQ (AREF (f1, CLOSURE_CODE), AREF (f2, CLOSURE_CODE)); |
| 680 | else if (CONSP (f1) && CONSP (f2) && CONSP (XCDR (f1)) && CONSP (XCDR (f2)) | ||
| 681 | && EQ (Qclosure, XCAR (f1)) | ||
| 682 | && EQ (Qclosure, XCAR (f2))) | ||
| 683 | res = EQ (XCDR (XCDR (f1)), XCDR (XCDR (f2))); | ||
| 684 | else | 678 | else |
| 685 | res = false; | 679 | res = false; |
| 686 | return res ? Qt : Qnil; | 680 | return res ? Qt : Qnil; |