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 | |
| 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')
| -rw-r--r-- | src/ChangeLog.funvec | 37 | ||||
| -rw-r--r-- | src/ChangeLog.lexbind | 104 | ||||
| -rw-r--r-- | src/alloc.c | 76 | ||||
| -rw-r--r-- | src/buffer.c | 1 | ||||
| -rw-r--r-- | src/bytecode.c | 128 | ||||
| -rw-r--r-- | src/data.c | 28 | ||||
| -rw-r--r-- | src/doc.c | 11 | ||||
| -rw-r--r-- | src/eval.c | 377 | ||||
| -rw-r--r-- | src/fns.c | 25 | ||||
| -rw-r--r-- | src/image.c | 2 | ||||
| -rw-r--r-- | src/keyboard.c | 2 | ||||
| -rw-r--r-- | src/lisp.h | 44 | ||||
| -rw-r--r-- | src/lread.c | 194 | ||||
| -rw-r--r-- | src/print.c | 6 |
14 files changed, 945 insertions, 90 deletions
diff --git a/src/ChangeLog.funvec b/src/ChangeLog.funvec new file mode 100644 index 00000000000..098539f1dd9 --- /dev/null +++ b/src/ChangeLog.funvec | |||
| @@ -0,0 +1,37 @@ | |||
| 1 | 2004-05-20 Miles Bader <miles@gnu.org> | ||
| 2 | |||
| 3 | * lisp.h: Declare make_funvec and Ffunvec. | ||
| 4 | (enum pvec_type): Rename `PVEC_COMPILED' to `PVEC_FUNVEC'. | ||
| 5 | (XSETFUNVEC): Renamed from `XSETCOMPILED'. | ||
| 6 | (FUNVEC_SIZE, FUNVEC_COMPILED_TAG_P, FUNVEC_COMPILED_P): New macros. | ||
| 7 | (COMPILEDP): Define in terms of funvec macros. | ||
| 8 | (FUNVECP, GC_FUNVECP): Renamed from `COMPILEDP' & `GC_COMPILEDP'. | ||
| 9 | (FUNCTIONP): Use FUNVECP instead of COMPILEDP. | ||
| 10 | * alloc.c (make_funvec, funvec): New functions. | ||
| 11 | (Fmake_byte_code): Make sure the first element is a list. | ||
| 12 | |||
| 13 | * eval.c (Qcurry): New variable. | ||
| 14 | (funcall_funvec, Fcurry): New functions. | ||
| 15 | (syms_of_eval): Initialize them. | ||
| 16 | (funcall_lambda): Handle non-bytecode funvec objects by calling | ||
| 17 | funcall_funvec. | ||
| 18 | (Ffuncall, Feval): Use FUNVECP insetad of COMPILEDP. | ||
| 19 | * lread.c (read1): Return result of read_vector for `#[' syntax | ||
| 20 | directly; read_vector now does any extra work required. | ||
| 21 | (read_vector): Handle both funvec and byte-code objects, converting the | ||
| 22 | type as necessary. `bytecodeflag' argument is now called | ||
| 23 | `read_funvec'. | ||
| 24 | * data.c (Ffunvecp): New function. | ||
| 25 | * doc.c (Fdocumentation): Return nil for unknown funvecs. | ||
| 26 | * fns.c (mapcar1, Felt, concat): Allow funvecs. | ||
| 27 | |||
| 28 | * eval.c (Ffunctionp): Use `funvec' operators instead of `compiled' | ||
| 29 | operators. | ||
| 30 | * alloc.c (Fmake_byte_code, Fpurecopy, mark_object): Likewise. | ||
| 31 | * keyboard.c (Fcommand_execute): Likewise. | ||
| 32 | * image.c (parse_image_spec): Likewise. | ||
| 33 | * fns.c (Flength, concat, internal_equal): Likewise. | ||
| 34 | * data.c (Faref, Ftype_of): Likewise. | ||
| 35 | * print.c (print_preprocess, print_object): Likewise. | ||
| 36 | |||
| 37 | ;; arch-tag: f35a6a00-4a11-4739-a4b6-9cf98296f315 | ||
diff --git a/src/ChangeLog.lexbind b/src/ChangeLog.lexbind new file mode 100644 index 00000000000..c8336d12e9c --- /dev/null +++ b/src/ChangeLog.lexbind | |||
| @@ -0,0 +1,104 @@ | |||
| 1 | 2008-04-23 Miles Bader <miles@gnu.org> | ||
| 2 | |||
| 3 | * eval.c (Ffunctionp): Return nil for special forms. | ||
| 4 | (Qunevalled): New variable. | ||
| 5 | (syms_of_eval): Initialize it. | ||
| 6 | |||
| 7 | 2007-10-18 Miles Bader <miles@gnu.org> | ||
| 8 | |||
| 9 | * eval.c (FletX): Test the type of VARLIST rather than just !NILP. | ||
| 10 | (Flet): Use XCAR instead of Fcar. | ||
| 11 | |||
| 12 | 2007-10-16 Miles Bader <miles@gnu.org> | ||
| 13 | |||
| 14 | * alloc.c (make_funvec, Fpurecopy): Set the pseudo-vector type. | ||
| 15 | |||
| 16 | 2006-02-10 Miles Bader <miles@gnu.org> | ||
| 17 | |||
| 18 | * eval.c (Ffunctionp): Supply new 2nd arg to Findirect_function. | ||
| 19 | |||
| 20 | 2005-03-04 Miles Bader <miles@gnu.org> | ||
| 21 | |||
| 22 | * eval.c (FletX): Update Vinterpreter_lexical_environment for each | ||
| 23 | variable we bind, instead of all at once like `let'. | ||
| 24 | |||
| 25 | 2004-08-09 Miles Bader <miles@gnu.org> | ||
| 26 | |||
| 27 | Changes from merging the funvec patch: | ||
| 28 | |||
| 29 | * eval.c (Feval, Ffuncall): Don't special-case vectors. | ||
| 30 | (funcall_lambda): Use FUNVEC_SIZE. | ||
| 31 | (Fcurry): Remove function. | ||
| 32 | |||
| 33 | Merge funvec patch. | ||
| 34 | |||
| 35 | 2004-04-10 Miles Bader <miles@gnu.org> | ||
| 36 | |||
| 37 | * eval.c (Fspecialp): New function. | ||
| 38 | (syms_of_eval): Initialize it. | ||
| 39 | |||
| 40 | 2004-04-03 Miles Bader <miles@gnu.org> | ||
| 41 | |||
| 42 | * eval.c (Feval): If a variable isn't bound lexically, fall back | ||
| 43 | to looking it up dynamically even if it isn't declared special. | ||
| 44 | |||
| 45 | 2002-08-26 Miles Bader <miles@gnu.org> | ||
| 46 | |||
| 47 | * bytecode.c (Fbyte_code): Fsub1 can GC, so protect it. | ||
| 48 | |||
| 49 | 2002-06-12 Miles Bader <miles@gnu.org> | ||
| 50 | |||
| 51 | Lexical binding changes to the byte-code interpreter: | ||
| 52 | |||
| 53 | * bytecode.c (Bstack_ref, Bstack_set, Bstack_set2, Bvec_ref, Bvec_set) | ||
| 54 | (BdiscardN): New constants. | ||
| 55 | (exec_byte_code): Renamed from `Fbyte_code'. | ||
| 56 | Implement above new bytecodes. | ||
| 57 | Add ARGS-TEMPLATE, NARGS and ARGS parameters, and optionally use | ||
| 58 | them push initial args on the stack. | ||
| 59 | (Fbyte_code): New function, just call `exec_byte_code'. | ||
| 60 | Add additional optional arguments for `exec_byte_code'. | ||
| 61 | (Qand_optional, Qand_rest): New extern declarations. | ||
| 62 | * eval.c (Fcurry, Ffunctionp): New functions. | ||
| 63 | (syms_of_eval): Initialize them. | ||
| 64 | (funcall_lambda): Call `exec_byte_code' instead of Fbyte_code. | ||
| 65 | If a compiled-function object has a `push-args' slot, call the | ||
| 66 | byte-code interpreter without binding any arguments. | ||
| 67 | (Ffuncall): Add support for curried functions. | ||
| 68 | * lisp.h (Fbyte_code): Declare max-args as MANY. | ||
| 69 | (exec_byte_code): New declaration. | ||
| 70 | |||
| 71 | Lexical binding changes to the lisp interpreter: | ||
| 72 | |||
| 73 | * lisp.h (struct Lisp_Symbol): Add `declared_special' field. | ||
| 74 | (apply_lambda): Add new 3rd arg to decl. | ||
| 75 | * alloc.c (Fmake_symbol): Initialize `declared_special' field. | ||
| 76 | * eval.c (Vinterpreter_lexical_environment): New variable. | ||
| 77 | (syms_of_eval): Initialize it. | ||
| 78 | (Fsetq): Modify SYM's lexical binding if appropriate. | ||
| 79 | (Ffunction): Return a closure if within a lexical environment. | ||
| 80 | (Flet, FletX): Lexically bind non-defvar'd variables if inside a | ||
| 81 | lexical environment. | ||
| 82 | (Feval): Return lexical binding of variables, if they have one. | ||
| 83 | Pass current lexical environment to embedded lambdas. Handle closures. | ||
| 84 | (Ffuncall): Pass nil lexical environment to lambdas. Handle closures. | ||
| 85 | (funcall_lambda): Add new LEXENV argument, and lexically bind | ||
| 86 | arguments if it's non-nil. Bind `interpreter-lexenv' if it changed. | ||
| 87 | (apply_lambda): Add new LEXENV argument and pass it to funcall_lambda. | ||
| 88 | (Fdefvaralias, Fdefvar, Fdefconst): Mark the variable as special. | ||
| 89 | (Qinternal_interpreter_environment, Qclosure): New constants. | ||
| 90 | (syms_of_eval): Initialize them. | ||
| 91 | (Fdefun, Fdefmacro): Use a closure if lexical binding is active. | ||
| 92 | * lread.c (defvar_bool, defvar_lisp_nopro, defvar_per_buffer) | ||
| 93 | (defvar_kboard, defvar_int): Mark the variable as special. | ||
| 94 | (Vlexical_binding, Qlexical_binding): New variables. | ||
| 95 | (syms_of_lread): Initialize them. | ||
| 96 | (Fload): Bind `lexically-bound' to nil unless specified otherwise | ||
| 97 | in the file header. | ||
| 98 | (lisp_file_lexically_bound_p): New function. | ||
| 99 | (Qinternal_interpreter_environment): New variable. | ||
| 100 | * doc.c (Qclosure): New extern declaration. | ||
| 101 | (Fdocumentation, store_function_docstring): Handle interpreted | ||
| 102 | closures. | ||
| 103 | |||
| 104 | ;; arch-tag: 7cf884aa-6b48-40cb-bfca-265a1e99b3c5 | ||
diff --git a/src/alloc.c b/src/alloc.c index e0f07cc5f5a..a23c688043c 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -3042,6 +3042,39 @@ See also the function `vector'. */) | |||
| 3042 | } | 3042 | } |
| 3043 | 3043 | ||
| 3044 | 3044 | ||
| 3045 | /* Return a new `function vector' containing KIND as the first element, | ||
| 3046 | followed by NUM_NIL_SLOTS nil elements, and further elements copied from | ||
| 3047 | the vector PARAMS of length NUM_PARAMS (so the total length of the | ||
| 3048 | resulting vector is 1 + NUM_NIL_SLOTS + NUM_PARAMS). | ||
| 3049 | |||
| 3050 | If NUM_PARAMS is zero, then PARAMS may be NULL. | ||
| 3051 | |||
| 3052 | A `function vector', a.k.a. `funvec', is a funcallable vector in Emacs Lisp. | ||
| 3053 | See the function `funvec' for more detail. */ | ||
| 3054 | |||
| 3055 | Lisp_Object | ||
| 3056 | make_funvec (kind, num_nil_slots, num_params, params) | ||
| 3057 | Lisp_Object kind; | ||
| 3058 | int num_nil_slots, num_params; | ||
| 3059 | Lisp_Object *params; | ||
| 3060 | { | ||
| 3061 | int param_index; | ||
| 3062 | Lisp_Object funvec; | ||
| 3063 | |||
| 3064 | funvec = Fmake_vector (make_number (1 + num_nil_slots + num_params), Qnil); | ||
| 3065 | |||
| 3066 | ASET (funvec, 0, kind); | ||
| 3067 | |||
| 3068 | for (param_index = 0; param_index < num_params; param_index++) | ||
| 3069 | ASET (funvec, 1 + num_nil_slots + param_index, params[param_index]); | ||
| 3070 | |||
| 3071 | XSETPVECTYPE (XVECTOR (funvec), PVEC_FUNVEC); | ||
| 3072 | XSETFUNVEC (funvec, XVECTOR (funvec)); | ||
| 3073 | |||
| 3074 | return funvec; | ||
| 3075 | } | ||
| 3076 | |||
| 3077 | |||
| 3045 | DEFUN ("vector", Fvector, Svector, 0, MANY, 0, | 3078 | DEFUN ("vector", Fvector, Svector, 0, MANY, 0, |
| 3046 | doc: /* Return a newly created vector with specified arguments as elements. | 3079 | doc: /* Return a newly created vector with specified arguments as elements. |
| 3047 | Any number of arguments, even zero arguments, are allowed. | 3080 | Any number of arguments, even zero arguments, are allowed. |
| @@ -3063,6 +3096,29 @@ usage: (vector &rest OBJECTS) */) | |||
| 3063 | } | 3096 | } |
| 3064 | 3097 | ||
| 3065 | 3098 | ||
| 3099 | DEFUN ("funvec", Ffunvec, Sfunvec, 1, MANY, 0, | ||
| 3100 | doc: /* Return a newly created `function vector' of type KIND. | ||
| 3101 | A `function vector', a.k.a. `funvec', is a funcallable vector in Emacs Lisp. | ||
| 3102 | KIND indicates the kind of funvec, and determines its behavior when called. | ||
| 3103 | The meaning of the remaining arguments depends on KIND. Currently | ||
| 3104 | implemented values of KIND, and their meaning, are: | ||
| 3105 | |||
| 3106 | A list -- A byte-compiled function. See `make-byte-code' for the usual | ||
| 3107 | way to create byte-compiled functions. | ||
| 3108 | |||
| 3109 | `curry' -- A curried function. Remaining arguments are a function to | ||
| 3110 | call, and arguments to prepend to user arguments at the | ||
| 3111 | time of the call; see the `curry' function. | ||
| 3112 | |||
| 3113 | usage: (funvec KIND &rest PARAMS) */) | ||
| 3114 | (nargs, args) | ||
| 3115 | register int nargs; | ||
| 3116 | Lisp_Object *args; | ||
| 3117 | { | ||
| 3118 | return make_funvec (args[0], 0, nargs - 1, args + 1); | ||
| 3119 | } | ||
| 3120 | |||
| 3121 | |||
| 3066 | DEFUN ("make-byte-code", Fmake_byte_code, Smake_byte_code, 4, MANY, 0, | 3122 | DEFUN ("make-byte-code", Fmake_byte_code, Smake_byte_code, 4, MANY, 0, |
| 3067 | doc: /* Create a byte-code object with specified arguments as elements. | 3123 | doc: /* Create a byte-code object with specified arguments as elements. |
| 3068 | The arguments should be the arglist, bytecode-string, constant vector, | 3124 | The arguments should be the arglist, bytecode-string, constant vector, |
| @@ -3078,6 +3134,10 @@ usage: (make-byte-code ARGLIST BYTE-CODE CONSTANTS DEPTH &optional DOCSTRING INT | |||
| 3078 | register int index; | 3134 | register int index; |
| 3079 | register struct Lisp_Vector *p; | 3135 | register struct Lisp_Vector *p; |
| 3080 | 3136 | ||
| 3137 | /* Make sure the arg-list is really a list, as that's what's used to | ||
| 3138 | distinguish a byte-compiled object from other funvecs. */ | ||
| 3139 | CHECK_LIST (args[0]); | ||
| 3140 | |||
| 3081 | XSETFASTINT (len, nargs); | 3141 | XSETFASTINT (len, nargs); |
| 3082 | if (!NILP (Vpurify_flag)) | 3142 | if (!NILP (Vpurify_flag)) |
| 3083 | val = make_pure_vector ((EMACS_INT) nargs); | 3143 | val = make_pure_vector ((EMACS_INT) nargs); |
| @@ -3099,8 +3159,8 @@ usage: (make-byte-code ARGLIST BYTE-CODE CONSTANTS DEPTH &optional DOCSTRING INT | |||
| 3099 | args[index] = Fpurecopy (args[index]); | 3159 | args[index] = Fpurecopy (args[index]); |
| 3100 | p->contents[index] = args[index]; | 3160 | p->contents[index] = args[index]; |
| 3101 | } | 3161 | } |
| 3102 | XSETPVECTYPE (p, PVEC_COMPILED); | 3162 | XSETPVECTYPE (p, PVEC_FUNVEC); |
| 3103 | XSETCOMPILED (val, p); | 3163 | XSETFUNVEC (val, p); |
| 3104 | return val; | 3164 | return val; |
| 3105 | } | 3165 | } |
| 3106 | 3166 | ||
| @@ -3199,6 +3259,7 @@ Its value and function definition are void, and its property list is nil. */) | |||
| 3199 | p->gcmarkbit = 0; | 3259 | p->gcmarkbit = 0; |
| 3200 | p->interned = SYMBOL_UNINTERNED; | 3260 | p->interned = SYMBOL_UNINTERNED; |
| 3201 | p->constant = 0; | 3261 | p->constant = 0; |
| 3262 | p->declared_special = 0; | ||
| 3202 | consing_since_gc += sizeof (struct Lisp_Symbol); | 3263 | consing_since_gc += sizeof (struct Lisp_Symbol); |
| 3203 | symbols_consed++; | 3264 | symbols_consed++; |
| 3204 | return val; | 3265 | return val; |
| @@ -4907,7 +4968,7 @@ Does not copy symbols. Copies strings without text properties. */) | |||
| 4907 | obj = make_pure_string (SDATA (obj), SCHARS (obj), | 4968 | obj = make_pure_string (SDATA (obj), SCHARS (obj), |
| 4908 | SBYTES (obj), | 4969 | SBYTES (obj), |
| 4909 | STRING_MULTIBYTE (obj)); | 4970 | STRING_MULTIBYTE (obj)); |
| 4910 | else if (COMPILEDP (obj) || VECTORP (obj)) | 4971 | else if (FUNVECP (obj) || VECTORP (obj)) |
| 4911 | { | 4972 | { |
| 4912 | register struct Lisp_Vector *vec; | 4973 | register struct Lisp_Vector *vec; |
| 4913 | register int i; | 4974 | register int i; |
| @@ -4919,10 +4980,10 @@ Does not copy symbols. Copies strings without text properties. */) | |||
| 4919 | vec = XVECTOR (make_pure_vector (size)); | 4980 | vec = XVECTOR (make_pure_vector (size)); |
| 4920 | for (i = 0; i < size; i++) | 4981 | for (i = 0; i < size; i++) |
| 4921 | vec->contents[i] = Fpurecopy (XVECTOR (obj)->contents[i]); | 4982 | vec->contents[i] = Fpurecopy (XVECTOR (obj)->contents[i]); |
| 4922 | if (COMPILEDP (obj)) | 4983 | if (FUNVECP (obj)) |
| 4923 | { | 4984 | { |
| 4924 | XSETPVECTYPE (vec, PVEC_COMPILED); | 4985 | XSETPVECTYPE (vec, PVEC_FUNVEC); |
| 4925 | XSETCOMPILED (obj, vec); | 4986 | XSETFUNVEC (obj, vec); |
| 4926 | } | 4987 | } |
| 4927 | else | 4988 | else |
| 4928 | XSETVECTOR (obj, vec); | 4989 | XSETVECTOR (obj, vec); |
| @@ -5512,7 +5573,7 @@ mark_object (arg) | |||
| 5512 | } | 5573 | } |
| 5513 | else if (SUBRP (obj)) | 5574 | else if (SUBRP (obj)) |
| 5514 | break; | 5575 | break; |
| 5515 | else if (COMPILEDP (obj)) | 5576 | else if (FUNVECP (obj) && FUNVEC_COMPILED_P (obj)) |
| 5516 | /* We could treat this just like a vector, but it is better to | 5577 | /* We could treat this just like a vector, but it is better to |
| 5517 | save the COMPILED_CONSTANTS element for last and avoid | 5578 | save the COMPILED_CONSTANTS element for last and avoid |
| 5518 | recursion there. */ | 5579 | recursion there. */ |
| @@ -6423,6 +6484,7 @@ The time is in seconds as a floating point value. */); | |||
| 6423 | defsubr (&Scons); | 6484 | defsubr (&Scons); |
| 6424 | defsubr (&Slist); | 6485 | defsubr (&Slist); |
| 6425 | defsubr (&Svector); | 6486 | defsubr (&Svector); |
| 6487 | defsubr (&Sfunvec); | ||
| 6426 | defsubr (&Smake_byte_code); | 6488 | defsubr (&Smake_byte_code); |
| 6427 | defsubr (&Smake_list); | 6489 | defsubr (&Smake_list); |
| 6428 | defsubr (&Smake_vector); | 6490 | defsubr (&Smake_vector); |
diff --git a/src/buffer.c b/src/buffer.c index 589266f40e5..e907c295e8d 100644 --- a/src/buffer.c +++ b/src/buffer.c | |||
| @@ -5418,6 +5418,7 @@ defvar_per_buffer (bo_fwd, namestring, address, type, doc) | |||
| 5418 | bo_fwd->type = Lisp_Fwd_Buffer_Obj; | 5418 | bo_fwd->type = Lisp_Fwd_Buffer_Obj; |
| 5419 | bo_fwd->offset = offset; | 5419 | bo_fwd->offset = offset; |
| 5420 | bo_fwd->slottype = type; | 5420 | bo_fwd->slottype = type; |
| 5421 | sym->declared_special = 1; | ||
| 5421 | sym->redirect = SYMBOL_FORWARDED; | 5422 | sym->redirect = SYMBOL_FORWARDED; |
| 5422 | { | 5423 | { |
| 5423 | /* I tried to do the job without a cast, but it seems impossible. | 5424 | /* I tried to do the job without a cast, but it seems impossible. |
diff --git a/src/bytecode.c b/src/bytecode.c index c53c5acdbb3..fec855c0b83 100644 --- a/src/bytecode.c +++ b/src/bytecode.c | |||
| @@ -87,9 +87,11 @@ int byte_metering_on; | |||
| 87 | 87 | ||
| 88 | 88 | ||
| 89 | Lisp_Object Qbytecode; | 89 | Lisp_Object Qbytecode; |
| 90 | extern Lisp_Object Qand_optional, Qand_rest; | ||
| 90 | 91 | ||
| 91 | /* Byte codes: */ | 92 | /* Byte codes: */ |
| 92 | 93 | ||
| 94 | #define Bstack_ref 0 | ||
| 93 | #define Bvarref 010 | 95 | #define Bvarref 010 |
| 94 | #define Bvarset 020 | 96 | #define Bvarset 020 |
| 95 | #define Bvarbind 030 | 97 | #define Bvarbind 030 |
| @@ -229,6 +231,13 @@ Lisp_Object Qbytecode; | |||
| 229 | #define BconcatN 0260 | 231 | #define BconcatN 0260 |
| 230 | #define BinsertN 0261 | 232 | #define BinsertN 0261 |
| 231 | 233 | ||
| 234 | /* Bstack_ref is code 0. */ | ||
| 235 | #define Bstack_set 0262 | ||
| 236 | #define Bstack_set2 0263 | ||
| 237 | #define Bvec_ref 0264 | ||
| 238 | #define Bvec_set 0265 | ||
| 239 | #define BdiscardN 0266 | ||
| 240 | |||
| 232 | #define Bconstant 0300 | 241 | #define Bconstant 0300 |
| 233 | #define CONSTANTLIM 0100 | 242 | #define CONSTANTLIM 0100 |
| 234 | 243 | ||
| @@ -397,14 +406,41 @@ unmark_byte_stack () | |||
| 397 | } while (0) | 406 | } while (0) |
| 398 | 407 | ||
| 399 | 408 | ||
| 400 | DEFUN ("byte-code", Fbyte_code, Sbyte_code, 3, 3, 0, | 409 | DEFUN ("byte-code", Fbyte_code, Sbyte_code, 3, MANY, 0, |
| 401 | doc: /* Function used internally in byte-compiled code. | 410 | doc: /* Function used internally in byte-compiled code. |
| 402 | The first argument, BYTESTR, is a string of byte code; | 411 | The first argument, BYTESTR, is a string of byte code; |
| 403 | the second, VECTOR, a vector of constants; | 412 | the second, VECTOR, a vector of constants; |
| 404 | the third, MAXDEPTH, the maximum stack depth used in this function. | 413 | the third, MAXDEPTH, the maximum stack depth used in this function. |
| 405 | If the third argument is incorrect, Emacs may crash. */) | 414 | If the third argument is incorrect, Emacs may crash. |
| 406 | (bytestr, vector, maxdepth) | 415 | |
| 407 | Lisp_Object bytestr, vector, maxdepth; | 416 | If ARGS-TEMPLATE is specified, it is an argument list specification, |
| 417 | according to which any remaining arguments are pushed on the stack | ||
| 418 | before executing BYTESTR. | ||
| 419 | |||
| 420 | usage: (byte-code BYTESTR VECTOR MAXDEP &optional ARGS-TEMPLATE &rest ARGS) */) | ||
| 421 | (nargs, args) | ||
| 422 | int nargs; | ||
| 423 | Lisp_Object *args; | ||
| 424 | { | ||
| 425 | Lisp_Object args_tmpl = nargs >= 4 ? args[3] : Qnil; | ||
| 426 | int pnargs = nargs >= 4 ? nargs - 4 : 0; | ||
| 427 | Lisp_Object *pargs = nargs >= 4 ? args + 4 : 0; | ||
| 428 | return exec_byte_code (args[0], args[1], args[2], args_tmpl, pnargs, pargs); | ||
| 429 | } | ||
| 430 | |||
| 431 | /* Execute the byte-code in BYTESTR. VECTOR is the constant vector, and | ||
| 432 | MAXDEPTH is the maximum stack depth used (if MAXDEPTH is incorrect, | ||
| 433 | emacs may crash!). If ARGS_TEMPLATE is non-nil, it should be a lisp | ||
| 434 | argument list (including &rest, &optional, etc.), and ARGS, of size | ||
| 435 | NARGS, should be a vector of the actual arguments. The arguments in | ||
| 436 | ARGS are pushed on the stack according to ARGS_TEMPLATE before | ||
| 437 | executing BYTESTR. */ | ||
| 438 | |||
| 439 | Lisp_Object | ||
| 440 | exec_byte_code (bytestr, vector, maxdepth, args_template, nargs, args) | ||
| 441 | Lisp_Object bytestr, vector, maxdepth, args_template; | ||
| 442 | int nargs; | ||
| 443 | Lisp_Object *args; | ||
| 408 | { | 444 | { |
| 409 | int count = SPECPDL_INDEX (); | 445 | int count = SPECPDL_INDEX (); |
| 410 | #ifdef BYTE_CODE_METER | 446 | #ifdef BYTE_CODE_METER |
| @@ -462,6 +498,37 @@ If the third argument is incorrect, Emacs may crash. */) | |||
| 462 | stacke = stack.bottom - 1 + XFASTINT (maxdepth); | 498 | stacke = stack.bottom - 1 + XFASTINT (maxdepth); |
| 463 | #endif | 499 | #endif |
| 464 | 500 | ||
| 501 | if (! NILP (args_template)) | ||
| 502 | /* We should push some arguments on the stack. */ | ||
| 503 | { | ||
| 504 | Lisp_Object at; | ||
| 505 | int pushed = 0, optional = 0; | ||
| 506 | |||
| 507 | for (at = args_template; CONSP (at); at = XCDR (at)) | ||
| 508 | if (EQ (XCAR (at), Qand_optional)) | ||
| 509 | optional = 1; | ||
| 510 | else if (EQ (XCAR (at), Qand_rest)) | ||
| 511 | { | ||
| 512 | PUSH (Flist (nargs, args)); | ||
| 513 | pushed = nargs; | ||
| 514 | at = Qnil; | ||
| 515 | break; | ||
| 516 | } | ||
| 517 | else if (pushed < nargs) | ||
| 518 | { | ||
| 519 | PUSH (*args++); | ||
| 520 | pushed++; | ||
| 521 | } | ||
| 522 | else if (optional) | ||
| 523 | PUSH (Qnil); | ||
| 524 | else | ||
| 525 | break; | ||
| 526 | |||
| 527 | if (pushed != nargs || !NILP (at)) | ||
| 528 | Fsignal (Qwrong_number_of_arguments, | ||
| 529 | Fcons (args_template, Fcons (make_number (nargs), Qnil))); | ||
| 530 | } | ||
| 531 | |||
| 465 | while (1) | 532 | while (1) |
| 466 | { | 533 | { |
| 467 | #ifdef BYTE_CODE_SAFE | 534 | #ifdef BYTE_CODE_SAFE |
| @@ -1641,8 +1708,57 @@ If the third argument is incorrect, Emacs may crash. */) | |||
| 1641 | break; | 1708 | break; |
| 1642 | #endif | 1709 | #endif |
| 1643 | 1710 | ||
| 1644 | case 0: | 1711 | /* Handy byte-codes for lexical binding. */ |
| 1645 | abort (); | 1712 | case Bstack_ref: |
| 1713 | case Bstack_ref+1: | ||
| 1714 | case Bstack_ref+2: | ||
| 1715 | case Bstack_ref+3: | ||
| 1716 | case Bstack_ref+4: | ||
| 1717 | case Bstack_ref+5: | ||
| 1718 | PUSH (stack.bottom[op - Bstack_ref]); | ||
| 1719 | break; | ||
| 1720 | case Bstack_ref+6: | ||
| 1721 | PUSH (stack.bottom[FETCH]); | ||
| 1722 | break; | ||
| 1723 | case Bstack_ref+7: | ||
| 1724 | PUSH (stack.bottom[FETCH2]); | ||
| 1725 | break; | ||
| 1726 | case Bstack_set: | ||
| 1727 | stack.bottom[FETCH] = POP; | ||
| 1728 | break; | ||
| 1729 | case Bstack_set2: | ||
| 1730 | stack.bottom[FETCH2] = POP; | ||
| 1731 | break; | ||
| 1732 | case Bvec_ref: | ||
| 1733 | case Bvec_set: | ||
| 1734 | /* These byte-codes used mostly for variable references to | ||
| 1735 | lexically bound variables that are in an environment vector | ||
| 1736 | instead of on the byte-interpreter stack (generally those | ||
| 1737 | variables which might be shared with a closure). */ | ||
| 1738 | { | ||
| 1739 | int index = FETCH; | ||
| 1740 | Lisp_Object vec = POP; | ||
| 1741 | |||
| 1742 | if (! VECTORP (vec)) | ||
| 1743 | wrong_type_argument (Qvectorp, vec); | ||
| 1744 | else if (index < 0 || index >= XVECTOR (vec)->size) | ||
| 1745 | args_out_of_range (vec, index); | ||
| 1746 | |||
| 1747 | if (op == Bvec_ref) | ||
| 1748 | PUSH (XVECTOR (vec)->contents[index]); | ||
| 1749 | else | ||
| 1750 | XVECTOR (vec)->contents[index] = POP; | ||
| 1751 | } | ||
| 1752 | break; | ||
| 1753 | case BdiscardN: | ||
| 1754 | op = FETCH; | ||
| 1755 | if (op & 0x80) | ||
| 1756 | { | ||
| 1757 | op &= 0x7F; | ||
| 1758 | top[-op] = TOP; | ||
| 1759 | } | ||
| 1760 | DISCARD (op); | ||
| 1761 | break; | ||
| 1646 | 1762 | ||
| 1647 | case 255: | 1763 | case 255: |
| 1648 | default: | 1764 | default: |
diff --git a/src/data.c b/src/data.c index 93cc57e9f2c..6a21ad44720 100644 --- a/src/data.c +++ b/src/data.c | |||
| @@ -84,7 +84,7 @@ Lisp_Object Qinteger; | |||
| 84 | static Lisp_Object Qsymbol, Qstring, Qcons, Qmarker, Qoverlay; | 84 | static Lisp_Object Qsymbol, Qstring, Qcons, Qmarker, Qoverlay; |
| 85 | static Lisp_Object Qfloat, Qwindow_configuration, Qwindow; | 85 | static Lisp_Object Qfloat, Qwindow_configuration, Qwindow; |
| 86 | Lisp_Object Qprocess; | 86 | Lisp_Object Qprocess; |
| 87 | static Lisp_Object Qcompiled_function, Qbuffer, Qframe, Qvector; | 87 | static Lisp_Object Qcompiled_function, Qfunction_vector, Qbuffer, Qframe, Qvector; |
| 88 | static Lisp_Object Qchar_table, Qbool_vector, Qhash_table; | 88 | static Lisp_Object Qchar_table, Qbool_vector, Qhash_table; |
| 89 | static Lisp_Object Qsubrp, Qmany, Qunevalled; | 89 | static Lisp_Object Qsubrp, Qmany, Qunevalled; |
| 90 | Lisp_Object Qfont_spec, Qfont_entity, Qfont_object; | 90 | Lisp_Object Qfont_spec, Qfont_entity, Qfont_object; |
| @@ -219,8 +219,11 @@ for example, (type-of 1) returns `integer'. */) | |||
| 219 | return Qwindow; | 219 | return Qwindow; |
| 220 | if (SUBRP (object)) | 220 | if (SUBRP (object)) |
| 221 | return Qsubr; | 221 | return Qsubr; |
| 222 | if (COMPILEDP (object)) | 222 | if (FUNVECP (object)) |
| 223 | return Qcompiled_function; | 223 | if (FUNVEC_COMPILED_P (object)) |
| 224 | return Qcompiled_function; | ||
| 225 | else | ||
| 226 | return Qfunction_vector; | ||
| 224 | if (BUFFERP (object)) | 227 | if (BUFFERP (object)) |
| 225 | return Qbuffer; | 228 | return Qbuffer; |
| 226 | if (CHAR_TABLE_P (object)) | 229 | if (CHAR_TABLE_P (object)) |
| @@ -437,6 +440,14 @@ DEFUN ("byte-code-function-p", Fbyte_code_function_p, Sbyte_code_function_p, | |||
| 437 | return Qnil; | 440 | return Qnil; |
| 438 | } | 441 | } |
| 439 | 442 | ||
| 443 | DEFUN ("funvecp", Ffunvecp, Sfunvecp, 1, 1, 0, | ||
| 444 | doc: /* Return t if OBJECT is a `function vector' object. */) | ||
| 445 | (object) | ||
| 446 | Lisp_Object object; | ||
| 447 | { | ||
| 448 | return FUNVECP (object) ? Qt : Qnil; | ||
| 449 | } | ||
| 450 | |||
| 440 | DEFUN ("char-or-string-p", Fchar_or_string_p, Schar_or_string_p, 1, 1, 0, | 451 | DEFUN ("char-or-string-p", Fchar_or_string_p, Schar_or_string_p, 1, 1, 0, |
| 441 | doc: /* Return t if OBJECT is a character or a string. */) | 452 | doc: /* Return t if OBJECT is a character or a string. */) |
| 442 | (object) | 453 | (object) |
| @@ -2208,15 +2219,15 @@ or a byte-code object. IDX starts at 0. */) | |||
| 2208 | { | 2219 | { |
| 2209 | int size = 0; | 2220 | int size = 0; |
| 2210 | if (VECTORP (array)) | 2221 | if (VECTORP (array)) |
| 2211 | size = XVECTOR (array)->size; | 2222 | size = ASIZE (array); |
| 2212 | else if (COMPILEDP (array)) | 2223 | else if (FUNVECP (array)) |
| 2213 | size = XVECTOR (array)->size & PSEUDOVECTOR_SIZE_MASK; | 2224 | size = FUNVEC_SIZE (array); |
| 2214 | else | 2225 | else |
| 2215 | wrong_type_argument (Qarrayp, array); | 2226 | wrong_type_argument (Qarrayp, array); |
| 2216 | 2227 | ||
| 2217 | if (idxval < 0 || idxval >= size) | 2228 | if (idxval < 0 || idxval >= size) |
| 2218 | args_out_of_range (array, idx); | 2229 | args_out_of_range (array, idx); |
| 2219 | return XVECTOR (array)->contents[idxval]; | 2230 | return AREF (array, idxval); |
| 2220 | } | 2231 | } |
| 2221 | } | 2232 | } |
| 2222 | 2233 | ||
| @@ -3326,6 +3337,7 @@ syms_of_data () | |||
| 3326 | Qwindow = intern_c_string ("window"); | 3337 | Qwindow = intern_c_string ("window"); |
| 3327 | /* Qsubr = intern_c_string ("subr"); */ | 3338 | /* Qsubr = intern_c_string ("subr"); */ |
| 3328 | Qcompiled_function = intern_c_string ("compiled-function"); | 3339 | Qcompiled_function = intern_c_string ("compiled-function"); |
| 3340 | Qfunction_vector = intern_c_string ("function-vector"); | ||
| 3329 | Qbuffer = intern_c_string ("buffer"); | 3341 | Qbuffer = intern_c_string ("buffer"); |
| 3330 | Qframe = intern_c_string ("frame"); | 3342 | Qframe = intern_c_string ("frame"); |
| 3331 | Qvector = intern_c_string ("vector"); | 3343 | Qvector = intern_c_string ("vector"); |
| @@ -3351,6 +3363,7 @@ syms_of_data () | |||
| 3351 | staticpro (&Qwindow); | 3363 | staticpro (&Qwindow); |
| 3352 | /* staticpro (&Qsubr); */ | 3364 | /* staticpro (&Qsubr); */ |
| 3353 | staticpro (&Qcompiled_function); | 3365 | staticpro (&Qcompiled_function); |
| 3366 | staticpro (&Qfunction_vector); | ||
| 3354 | staticpro (&Qbuffer); | 3367 | staticpro (&Qbuffer); |
| 3355 | staticpro (&Qframe); | 3368 | staticpro (&Qframe); |
| 3356 | staticpro (&Qvector); | 3369 | staticpro (&Qvector); |
| @@ -3387,6 +3400,7 @@ syms_of_data () | |||
| 3387 | defsubr (&Smarkerp); | 3400 | defsubr (&Smarkerp); |
| 3388 | defsubr (&Ssubrp); | 3401 | defsubr (&Ssubrp); |
| 3389 | defsubr (&Sbyte_code_function_p); | 3402 | defsubr (&Sbyte_code_function_p); |
| 3403 | defsubr (&Sfunvecp); | ||
| 3390 | defsubr (&Schar_or_string_p); | 3404 | defsubr (&Schar_or_string_p); |
| 3391 | defsubr (&Scar); | 3405 | defsubr (&Scar); |
| 3392 | defsubr (&Scdr); | 3406 | defsubr (&Scdr); |
| @@ -56,7 +56,7 @@ Lisp_Object Qfunction_documentation; | |||
| 56 | /* A list of files used to build this Emacs binary. */ | 56 | /* A list of files used to build this Emacs binary. */ |
| 57 | static Lisp_Object Vbuild_files; | 57 | static Lisp_Object Vbuild_files; |
| 58 | 58 | ||
| 59 | extern Lisp_Object Voverriding_local_map; | 59 | extern Lisp_Object Voverriding_local_map, Qclosure; |
| 60 | 60 | ||
| 61 | extern Lisp_Object Qremap; | 61 | extern Lisp_Object Qremap; |
| 62 | 62 | ||
| @@ -385,6 +385,11 @@ string is passed through `substitute-command-keys'. */) | |||
| 385 | else | 385 | else |
| 386 | return Qnil; | 386 | return Qnil; |
| 387 | } | 387 | } |
| 388 | else if (FUNVECP (fun)) | ||
| 389 | { | ||
| 390 | /* Unless otherwise handled, funvecs have no documentation. */ | ||
| 391 | return Qnil; | ||
| 392 | } | ||
| 388 | else if (STRINGP (fun) || VECTORP (fun)) | 393 | else if (STRINGP (fun) || VECTORP (fun)) |
| 389 | { | 394 | { |
| 390 | return build_string ("Keyboard macro."); | 395 | return build_string ("Keyboard macro."); |
| @@ -412,6 +417,8 @@ string is passed through `substitute-command-keys'. */) | |||
| 412 | else | 417 | else |
| 413 | return Qnil; | 418 | return Qnil; |
| 414 | } | 419 | } |
| 420 | else if (EQ (funcar, Qclosure)) | ||
| 421 | return Fdocumentation (Fcdr (XCDR (fun)), raw); | ||
| 415 | else if (EQ (funcar, Qmacro)) | 422 | else if (EQ (funcar, Qmacro)) |
| 416 | return Fdocumentation (Fcdr (fun), raw); | 423 | return Fdocumentation (Fcdr (fun), raw); |
| 417 | else | 424 | else |
| @@ -542,6 +549,8 @@ store_function_docstring (fun, offset) | |||
| 542 | } | 549 | } |
| 543 | else if (EQ (tem, Qmacro)) | 550 | else if (EQ (tem, Qmacro)) |
| 544 | store_function_docstring (XCDR (fun), offset); | 551 | store_function_docstring (XCDR (fun), offset); |
| 552 | else if (EQ (tem, Qclosure)) | ||
| 553 | store_function_docstring (Fcdr (XCDR (fun)), offset); | ||
| 545 | } | 554 | } |
| 546 | 555 | ||
| 547 | /* Bytecode objects sometimes have slots for it. */ | 556 | /* Bytecode objects sometimes have slots for it. */ |
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 |
| @@ -149,8 +149,8 @@ To get the number of bytes, use `string-bytes'. */) | |||
| 149 | XSETFASTINT (val, MAX_CHAR); | 149 | XSETFASTINT (val, MAX_CHAR); |
| 150 | else if (BOOL_VECTOR_P (sequence)) | 150 | else if (BOOL_VECTOR_P (sequence)) |
| 151 | XSETFASTINT (val, XBOOL_VECTOR (sequence)->size); | 151 | XSETFASTINT (val, XBOOL_VECTOR (sequence)->size); |
| 152 | else if (COMPILEDP (sequence)) | 152 | else if (FUNVECP (sequence)) |
| 153 | XSETFASTINT (val, ASIZE (sequence) & PSEUDOVECTOR_SIZE_MASK); | 153 | XSETFASTINT (val, FUNVEC_SIZE (sequence)); |
| 154 | else if (CONSP (sequence)) | 154 | else if (CONSP (sequence)) |
| 155 | { | 155 | { |
| 156 | i = 0; | 156 | i = 0; |
| @@ -535,7 +535,7 @@ concat (nargs, args, target_type, last_special) | |||
| 535 | { | 535 | { |
| 536 | this = args[argnum]; | 536 | this = args[argnum]; |
| 537 | if (!(CONSP (this) || NILP (this) || VECTORP (this) || STRINGP (this) | 537 | if (!(CONSP (this) || NILP (this) || VECTORP (this) || STRINGP (this) |
| 538 | || COMPILEDP (this) || BOOL_VECTOR_P (this))) | 538 | || FUNVECP (this) || BOOL_VECTOR_P (this))) |
| 539 | wrong_type_argument (Qsequencep, this); | 539 | wrong_type_argument (Qsequencep, this); |
| 540 | } | 540 | } |
| 541 | 541 | ||
| @@ -559,7 +559,7 @@ concat (nargs, args, target_type, last_special) | |||
| 559 | Lisp_Object ch; | 559 | Lisp_Object ch; |
| 560 | int this_len_byte; | 560 | int this_len_byte; |
| 561 | 561 | ||
| 562 | if (VECTORP (this)) | 562 | if (VECTORP (this) || FUNVECP (this)) |
| 563 | for (i = 0; i < len; i++) | 563 | for (i = 0; i < len; i++) |
| 564 | { | 564 | { |
| 565 | ch = AREF (this, i); | 565 | ch = AREF (this, i); |
| @@ -1383,7 +1383,9 @@ DEFUN ("elt", Felt, Selt, 2, 2, 0, | |||
| 1383 | return Fcar (Fnthcdr (n, sequence)); | 1383 | return Fcar (Fnthcdr (n, sequence)); |
| 1384 | 1384 | ||
| 1385 | /* Faref signals a "not array" error, so check here. */ | 1385 | /* Faref signals a "not array" error, so check here. */ |
| 1386 | CHECK_ARRAY (sequence, Qsequencep); | 1386 | if (! FUNVECP (sequence)) |
| 1387 | CHECK_ARRAY (sequence, Qsequencep); | ||
| 1388 | |||
| 1387 | return Faref (sequence, n); | 1389 | return Faref (sequence, n); |
| 1388 | } | 1390 | } |
| 1389 | 1391 | ||
| @@ -2199,13 +2201,14 @@ internal_equal (o1, o2, depth, props) | |||
| 2199 | if (WINDOW_CONFIGURATIONP (o1)) | 2201 | if (WINDOW_CONFIGURATIONP (o1)) |
| 2200 | return compare_window_configurations (o1, o2, 0); | 2202 | return compare_window_configurations (o1, o2, 0); |
| 2201 | 2203 | ||
| 2202 | /* Aside from them, only true vectors, char-tables, compiled | 2204 | /* Aside from them, only true vectors, char-tables, function vectors, |
| 2203 | functions, and fonts (font-spec, font-entity, font-ojbect) | 2205 | and fonts (font-spec, font-entity, font-ojbect) are sensible to |
| 2204 | are sensible to compare, so eliminate the others now. */ | 2206 | compare, so eliminate the others now. */ |
| 2205 | if (size & PSEUDOVECTOR_FLAG) | 2207 | if (size & PSEUDOVECTOR_FLAG) |
| 2206 | { | 2208 | { |
| 2207 | if (!(size & (PVEC_COMPILED | 2209 | if (!(size & (PVEC_FUNVEC |
| 2208 | | PVEC_CHAR_TABLE | PVEC_SUB_CHAR_TABLE | PVEC_FONT))) | 2210 | | PVEC_CHAR_TABLE | PVEC_SUB_CHAR_TABLE |
| 2211 | | PVEC_FONT))) | ||
| 2209 | return 0; | 2212 | return 0; |
| 2210 | size &= PSEUDOVECTOR_SIZE_MASK; | 2213 | size &= PSEUDOVECTOR_SIZE_MASK; |
| 2211 | } | 2214 | } |
| @@ -2416,7 +2419,7 @@ mapcar1 (leni, vals, fn, seq) | |||
| 2416 | 1) lists are not relocated and 2) the list is marked via `seq' so will not | 2419 | 1) lists are not relocated and 2) the list is marked via `seq' so will not |
| 2417 | be freed */ | 2420 | be freed */ |
| 2418 | 2421 | ||
| 2419 | if (VECTORP (seq)) | 2422 | if (VECTORP (seq) || FUNVECP (seq)) |
| 2420 | { | 2423 | { |
| 2421 | for (i = 0; i < leni; i++) | 2424 | for (i = 0; i < leni; i++) |
| 2422 | { | 2425 | { |
diff --git a/src/image.c b/src/image.c index b9620e10948..67c228cbc7f 100644 --- a/src/image.c +++ b/src/image.c | |||
| @@ -885,7 +885,7 @@ parse_image_spec (spec, keywords, nkeywords, type) | |||
| 885 | case IMAGE_FUNCTION_VALUE: | 885 | case IMAGE_FUNCTION_VALUE: |
| 886 | value = indirect_function (value); | 886 | value = indirect_function (value); |
| 887 | if (SUBRP (value) | 887 | if (SUBRP (value) |
| 888 | || COMPILEDP (value) | 888 | || FUNVECP (value) |
| 889 | || (CONSP (value) && EQ (XCAR (value), Qlambda))) | 889 | || (CONSP (value) && EQ (XCAR (value), Qlambda))) |
| 890 | break; | 890 | break; |
| 891 | return 0; | 891 | return 0; |
diff --git a/src/keyboard.c b/src/keyboard.c index 63372d600e3..18d75f9b01c 100644 --- a/src/keyboard.c +++ b/src/keyboard.c | |||
| @@ -10390,7 +10390,7 @@ a special event, so ignore the prefix argument and don't clear it. */) | |||
| 10390 | return Fexecute_kbd_macro (final, prefixarg, Qnil); | 10390 | return Fexecute_kbd_macro (final, prefixarg, Qnil); |
| 10391 | } | 10391 | } |
| 10392 | 10392 | ||
| 10393 | if (CONSP (final) || SUBRP (final) || COMPILEDP (final)) | 10393 | if (CONSP (final) || SUBRP (final) || FUNVECP (final)) |
| 10394 | /* Don't call Fcall_interactively directly because we want to make | 10394 | /* Don't call Fcall_interactively directly because we want to make |
| 10395 | sure the backtrace has an entry for `call-interactively'. | 10395 | sure the backtrace has an entry for `call-interactively'. |
| 10396 | For the same reason, pass `cmd' rather than `final'. */ | 10396 | For the same reason, pass `cmd' rather than `final'. */ |
diff --git a/src/lisp.h b/src/lisp.h index 1941a2471a4..c7e8ea0fb8b 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -344,7 +344,7 @@ enum pvec_type | |||
| 344 | PVEC_NORMAL_VECTOR = 0, | 344 | PVEC_NORMAL_VECTOR = 0, |
| 345 | PVEC_PROCESS = 0x200, | 345 | PVEC_PROCESS = 0x200, |
| 346 | PVEC_FRAME = 0x400, | 346 | PVEC_FRAME = 0x400, |
| 347 | PVEC_COMPILED = 0x800, | 347 | PVEC_FUNVEC = 0x800, |
| 348 | PVEC_WINDOW = 0x1000, | 348 | PVEC_WINDOW = 0x1000, |
| 349 | PVEC_WINDOW_CONFIGURATION = 0x2000, | 349 | PVEC_WINDOW_CONFIGURATION = 0x2000, |
| 350 | PVEC_SUBR = 0x4000, | 350 | PVEC_SUBR = 0x4000, |
| @@ -623,7 +623,7 @@ extern size_t pure_size; | |||
| 623 | #define XSETWINDOW(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_WINDOW)) | 623 | #define XSETWINDOW(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_WINDOW)) |
| 624 | #define XSETTERMINAL(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_TERMINAL)) | 624 | #define XSETTERMINAL(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_TERMINAL)) |
| 625 | #define XSETSUBR(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_SUBR)) | 625 | #define XSETSUBR(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_SUBR)) |
| 626 | #define XSETCOMPILED(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_COMPILED)) | 626 | #define XSETFUNVEC(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_FUNVEC)) |
| 627 | #define XSETBUFFER(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_BUFFER)) | 627 | #define XSETBUFFER(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_BUFFER)) |
| 628 | #define XSETCHAR_TABLE(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_CHAR_TABLE)) | 628 | #define XSETCHAR_TABLE(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_CHAR_TABLE)) |
| 629 | #define XSETBOOL_VECTOR(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_BOOL_VECTOR)) | 629 | #define XSETBOOL_VECTOR(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_BOOL_VECTOR)) |
| @@ -639,6 +639,9 @@ extern size_t pure_size; | |||
| 639 | eassert ((IDX) >= 0 && (IDX) < ASIZE (ARRAY)), \ | 639 | eassert ((IDX) >= 0 && (IDX) < ASIZE (ARRAY)), \ |
| 640 | AREF ((ARRAY), (IDX)) = (VAL)) | 640 | AREF ((ARRAY), (IDX)) = (VAL)) |
| 641 | 641 | ||
| 642 | /* Return the size of the psuedo-vector object FUNVEC. */ | ||
| 643 | #define FUNVEC_SIZE(funvec) (ASIZE (funvec) & PSEUDOVECTOR_SIZE_MASK) | ||
| 644 | |||
| 642 | /* Convenience macros for dealing with Lisp strings. */ | 645 | /* Convenience macros for dealing with Lisp strings. */ |
| 643 | 646 | ||
| 644 | #define SDATA(string) (XSTRING (string)->data + 0) | 647 | #define SDATA(string) (XSTRING (string)->data + 0) |
| @@ -1020,6 +1023,10 @@ struct Lisp_Symbol | |||
| 1020 | /* Interned state of the symbol. This is an enumerator from | 1023 | /* Interned state of the symbol. This is an enumerator from |
| 1021 | enum symbol_interned. */ | 1024 | enum symbol_interned. */ |
| 1022 | unsigned interned : 2; | 1025 | unsigned interned : 2; |
| 1026 | |||
| 1027 | /* Non-zero means that this variable has been explicitly declared | ||
| 1028 | special (with `defvar' etc), and shouldn't be lexically bound. */ | ||
| 1029 | unsigned declared_special : 1; | ||
| 1023 | 1030 | ||
| 1024 | /* The symbol's name, as a Lisp string. | 1031 | /* The symbol's name, as a Lisp string. |
| 1025 | 1032 | ||
| @@ -1475,7 +1482,7 @@ struct Lisp_Float | |||
| 1475 | typedef unsigned char UCHAR; | 1482 | typedef unsigned char UCHAR; |
| 1476 | #endif | 1483 | #endif |
| 1477 | 1484 | ||
| 1478 | /* Meanings of slots in a Lisp_Compiled: */ | 1485 | /* Meanings of slots in a byte-compiled function vector: */ |
| 1479 | 1486 | ||
| 1480 | #define COMPILED_ARGLIST 0 | 1487 | #define COMPILED_ARGLIST 0 |
| 1481 | #define COMPILED_BYTECODE 1 | 1488 | #define COMPILED_BYTECODE 1 |
| @@ -1483,6 +1490,25 @@ typedef unsigned char UCHAR; | |||
| 1483 | #define COMPILED_STACK_DEPTH 3 | 1490 | #define COMPILED_STACK_DEPTH 3 |
| 1484 | #define COMPILED_DOC_STRING 4 | 1491 | #define COMPILED_DOC_STRING 4 |
| 1485 | #define COMPILED_INTERACTIVE 5 | 1492 | #define COMPILED_INTERACTIVE 5 |
| 1493 | #define COMPILED_PUSH_ARGS 6 | ||
| 1494 | |||
| 1495 | /* Return non-zero if TAG, the first element from a funvec object, refers | ||
| 1496 | to a byte-code object. Byte-code objects are distinguished from other | ||
| 1497 | `funvec' objects by having a (possibly empty) list as their first | ||
| 1498 | element -- other funvec types use a non-nil symbol there. */ | ||
| 1499 | #define FUNVEC_COMPILED_TAG_P(tag) \ | ||
| 1500 | (NILP (tag) || CONSP (tag)) | ||
| 1501 | |||
| 1502 | /* Return non-zero if FUNVEC, which should be a `funvec' object, is a | ||
| 1503 | byte-compiled function. Byte-compiled function are funvecs with the | ||
| 1504 | arglist as the first element (other funvec types will have a symbol | ||
| 1505 | identifying the type as the first object). */ | ||
| 1506 | #define FUNVEC_COMPILED_P(funvec) \ | ||
| 1507 | (FUNVEC_SIZE (funvec) > 0 && FUNVEC_COMPILED_TAG_P (AREF (funvec, 0))) | ||
| 1508 | |||
| 1509 | /* Return non-zero if OBJ is byte-compile function. */ | ||
| 1510 | #define COMPILEDP(obj) \ | ||
| 1511 | (FUNVECP (obj) && FUNVEC_COMPILED_P (obj)) | ||
| 1486 | 1512 | ||
| 1487 | /* Flag bits in a character. These also get used in termhooks.h. | 1513 | /* Flag bits in a character. These also get used in termhooks.h. |
| 1488 | Richard Stallman <rms@gnu.ai.mit.edu> thinks that MULE | 1514 | Richard Stallman <rms@gnu.ai.mit.edu> thinks that MULE |
| @@ -1604,7 +1630,7 @@ typedef struct { | |||
| 1604 | #define WINDOWP(x) PSEUDOVECTORP (x, PVEC_WINDOW) | 1630 | #define WINDOWP(x) PSEUDOVECTORP (x, PVEC_WINDOW) |
| 1605 | #define TERMINALP(x) PSEUDOVECTORP (x, PVEC_TERMINAL) | 1631 | #define TERMINALP(x) PSEUDOVECTORP (x, PVEC_TERMINAL) |
| 1606 | #define SUBRP(x) PSEUDOVECTORP (x, PVEC_SUBR) | 1632 | #define SUBRP(x) PSEUDOVECTORP (x, PVEC_SUBR) |
| 1607 | #define COMPILEDP(x) PSEUDOVECTORP (x, PVEC_COMPILED) | 1633 | #define FUNVECP(x) PSEUDOVECTORP (x, PVEC_FUNVEC) |
| 1608 | #define BUFFERP(x) PSEUDOVECTORP (x, PVEC_BUFFER) | 1634 | #define BUFFERP(x) PSEUDOVECTORP (x, PVEC_BUFFER) |
| 1609 | #define CHAR_TABLE_P(x) PSEUDOVECTORP (x, PVEC_CHAR_TABLE) | 1635 | #define CHAR_TABLE_P(x) PSEUDOVECTORP (x, PVEC_CHAR_TABLE) |
| 1610 | #define SUB_CHAR_TABLE_P(x) PSEUDOVECTORP (x, PVEC_SUB_CHAR_TABLE) | 1636 | #define SUB_CHAR_TABLE_P(x) PSEUDOVECTORP (x, PVEC_SUB_CHAR_TABLE) |
| @@ -1797,7 +1823,7 @@ typedef struct { | |||
| 1797 | #define FUNCTIONP(OBJ) \ | 1823 | #define FUNCTIONP(OBJ) \ |
| 1798 | ((CONSP (OBJ) && EQ (XCAR (OBJ), Qlambda)) \ | 1824 | ((CONSP (OBJ) && EQ (XCAR (OBJ), Qlambda)) \ |
| 1799 | || (SYMBOLP (OBJ) && !NILP (Ffboundp (OBJ))) \ | 1825 | || (SYMBOLP (OBJ) && !NILP (Ffboundp (OBJ))) \ |
| 1800 | || COMPILEDP (OBJ) \ | 1826 | || FUNVECP (OBJ) \ |
| 1801 | || SUBRP (OBJ)) | 1827 | || SUBRP (OBJ)) |
| 1802 | 1828 | ||
| 1803 | /* defsubr (Sname); | 1829 | /* defsubr (Sname); |
| @@ -2697,6 +2723,7 @@ EXFUN (Fmake_list, 2); | |||
| 2697 | extern Lisp_Object allocate_misc P_ ((void)); | 2723 | extern Lisp_Object allocate_misc P_ ((void)); |
| 2698 | EXFUN (Fmake_vector, 2); | 2724 | EXFUN (Fmake_vector, 2); |
| 2699 | EXFUN (Fvector, MANY); | 2725 | EXFUN (Fvector, MANY); |
| 2726 | EXFUN (Ffunvec, MANY); | ||
| 2700 | EXFUN (Fmake_symbol, 1); | 2727 | EXFUN (Fmake_symbol, 1); |
| 2701 | EXFUN (Fmake_marker, 0); | 2728 | EXFUN (Fmake_marker, 0); |
| 2702 | EXFUN (Fmake_string, 2); | 2729 | EXFUN (Fmake_string, 2); |
| @@ -2715,6 +2742,7 @@ extern Lisp_Object make_pure_c_string (const char *data); | |||
| 2715 | extern Lisp_Object pure_cons P_ ((Lisp_Object, Lisp_Object)); | 2742 | extern Lisp_Object pure_cons P_ ((Lisp_Object, Lisp_Object)); |
| 2716 | extern Lisp_Object make_pure_vector P_ ((EMACS_INT)); | 2743 | extern Lisp_Object make_pure_vector P_ ((EMACS_INT)); |
| 2717 | EXFUN (Fgarbage_collect, 0); | 2744 | EXFUN (Fgarbage_collect, 0); |
| 2745 | extern Lisp_Object make_funvec P_ ((Lisp_Object, int, int, Lisp_Object *)); | ||
| 2718 | EXFUN (Fmake_byte_code, MANY); | 2746 | EXFUN (Fmake_byte_code, MANY); |
| 2719 | EXFUN (Fmake_bool_vector, 2); | 2747 | EXFUN (Fmake_bool_vector, 2); |
| 2720 | extern Lisp_Object Qchar_table_extra_slots; | 2748 | extern Lisp_Object Qchar_table_extra_slots; |
| @@ -2894,7 +2922,7 @@ extern Lisp_Object call5 P_ ((Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object | |||
| 2894 | extern Lisp_Object call6 P_ ((Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object)); | 2922 | extern Lisp_Object call6 P_ ((Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object)); |
| 2895 | extern Lisp_Object call7 P_ ((Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object)); | 2923 | extern Lisp_Object call7 P_ ((Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object)); |
| 2896 | EXFUN (Fdo_auto_save, 2); | 2924 | EXFUN (Fdo_auto_save, 2); |
| 2897 | extern Lisp_Object apply_lambda P_ ((Lisp_Object, Lisp_Object, int)); | 2925 | extern Lisp_Object apply_lambda P_ ((Lisp_Object, Lisp_Object, int, Lisp_Object)); |
| 2898 | extern Lisp_Object internal_catch P_ ((Lisp_Object, Lisp_Object (*) (Lisp_Object), Lisp_Object)); | 2926 | extern Lisp_Object internal_catch P_ ((Lisp_Object, Lisp_Object (*) (Lisp_Object), Lisp_Object)); |
| 2899 | extern Lisp_Object internal_lisp_condition_case P_ ((Lisp_Object, Lisp_Object, Lisp_Object)); | 2927 | extern Lisp_Object internal_lisp_condition_case P_ ((Lisp_Object, Lisp_Object, Lisp_Object)); |
| 2900 | extern Lisp_Object internal_condition_case P_ ((Lisp_Object (*) (void), Lisp_Object, Lisp_Object (*) (Lisp_Object))); | 2928 | extern Lisp_Object internal_condition_case P_ ((Lisp_Object (*) (void), Lisp_Object, Lisp_Object (*) (Lisp_Object))); |
| @@ -3312,11 +3340,13 @@ extern int read_bytecode_char P_ ((int)); | |||
| 3312 | 3340 | ||
| 3313 | /* Defined in bytecode.c */ | 3341 | /* Defined in bytecode.c */ |
| 3314 | extern Lisp_Object Qbytecode; | 3342 | extern Lisp_Object Qbytecode; |
| 3315 | EXFUN (Fbyte_code, 3); | 3343 | EXFUN (Fbyte_code, MANY); |
| 3316 | extern void syms_of_bytecode P_ ((void)); | 3344 | extern void syms_of_bytecode P_ ((void)); |
| 3317 | extern struct byte_stack *byte_stack_list; | 3345 | extern struct byte_stack *byte_stack_list; |
| 3318 | extern void mark_byte_stack P_ ((void)); | 3346 | extern void mark_byte_stack P_ ((void)); |
| 3319 | extern void unmark_byte_stack P_ ((void)); | 3347 | extern void unmark_byte_stack P_ ((void)); |
| 3348 | extern Lisp_Object exec_byte_code P_ ((Lisp_Object, Lisp_Object, Lisp_Object, | ||
| 3349 | Lisp_Object, int, Lisp_Object *)); | ||
| 3320 | 3350 | ||
| 3321 | /* Defined in macros.c */ | 3351 | /* Defined in macros.c */ |
| 3322 | extern Lisp_Object Qexecute_kbd_macro; | 3352 | extern Lisp_Object Qexecute_kbd_macro; |
diff --git a/src/lread.c b/src/lread.c index 3a77a62b27f..53f26faea36 100644 --- a/src/lread.c +++ b/src/lread.c | |||
| @@ -83,6 +83,7 @@ Lisp_Object Qascii_character, Qload, Qload_file_name; | |||
| 83 | Lisp_Object Qbackquote, Qcomma, Qcomma_at, Qcomma_dot, Qfunction; | 83 | Lisp_Object Qbackquote, Qcomma, Qcomma_at, Qcomma_dot, Qfunction; |
| 84 | Lisp_Object Qinhibit_file_name_operation; | 84 | Lisp_Object Qinhibit_file_name_operation; |
| 85 | Lisp_Object Qeval_buffer_list, Veval_buffer_list; | 85 | Lisp_Object Qeval_buffer_list, Veval_buffer_list; |
| 86 | Lisp_Object Qlexical_binding; | ||
| 86 | Lisp_Object Qfile_truename, Qdo_after_load_evaluation; /* ACM 2006/5/16 */ | 87 | Lisp_Object Qfile_truename, Qdo_after_load_evaluation; /* ACM 2006/5/16 */ |
| 87 | 88 | ||
| 88 | /* Used instead of Qget_file_char while loading *.elc files compiled | 89 | /* Used instead of Qget_file_char while loading *.elc files compiled |
| @@ -93,6 +94,7 @@ static Lisp_Object Qload_force_doc_strings; | |||
| 93 | 94 | ||
| 94 | extern Lisp_Object Qevent_symbol_element_mask; | 95 | extern Lisp_Object Qevent_symbol_element_mask; |
| 95 | extern Lisp_Object Qfile_exists_p; | 96 | extern Lisp_Object Qfile_exists_p; |
| 97 | extern Lisp_Object Qinternal_interpreter_environment; | ||
| 96 | 98 | ||
| 97 | /* non-zero if inside `load' */ | 99 | /* non-zero if inside `load' */ |
| 98 | int load_in_progress; | 100 | int load_in_progress; |
| @@ -157,6 +159,9 @@ Lisp_Object Vread_with_symbol_positions; | |||
| 157 | /* List of (SYMBOL . POSITION) accumulated so far. */ | 159 | /* List of (SYMBOL . POSITION) accumulated so far. */ |
| 158 | Lisp_Object Vread_symbol_positions_list; | 160 | Lisp_Object Vread_symbol_positions_list; |
| 159 | 161 | ||
| 162 | /* If non-nil `readevalloop' evaluates code in a lexical environment. */ | ||
| 163 | Lisp_Object Vlexical_binding; | ||
| 164 | |||
| 160 | /* List of descriptors now open for Fload. */ | 165 | /* List of descriptors now open for Fload. */ |
| 161 | static Lisp_Object load_descriptor_list; | 166 | static Lisp_Object load_descriptor_list; |
| 162 | 167 | ||
| @@ -864,6 +869,118 @@ DEFUN ("get-file-char", Fget_file_char, Sget_file_char, 0, 0, 0, | |||
| 864 | 869 | ||
| 865 | 870 | ||
| 866 | 871 | ||
| 872 | |||
| 873 | /* Return true if the lisp code read using READCHARFUN defines a non-nil | ||
| 874 | `lexical-binding' file variable. After returning, the stream is | ||
| 875 | positioned following the first line, if it is a comment, otherwise | ||
| 876 | nothing is read. */ | ||
| 877 | |||
| 878 | static int | ||
| 879 | lisp_file_lexically_bound_p (readcharfun) | ||
| 880 | Lisp_Object readcharfun; | ||
| 881 | { | ||
| 882 | int ch = READCHAR; | ||
| 883 | if (ch != ';') | ||
| 884 | /* The first line isn't a comment, just give up. */ | ||
| 885 | { | ||
| 886 | UNREAD (ch); | ||
| 887 | return 0; | ||
| 888 | } | ||
| 889 | else | ||
| 890 | /* Look for an appropriate file-variable in the first line. */ | ||
| 891 | { | ||
| 892 | int rv = 0; | ||
| 893 | enum { | ||
| 894 | NOMINAL, AFTER_FIRST_DASH, AFTER_ASTERIX, | ||
| 895 | } beg_end_state = NOMINAL; | ||
| 896 | int in_file_vars = 0; | ||
| 897 | |||
| 898 | #define UPDATE_BEG_END_STATE(ch) \ | ||
| 899 | if (beg_end_state == NOMINAL) \ | ||
| 900 | beg_end_state = (ch == '-' ? AFTER_FIRST_DASH : NOMINAL); \ | ||
| 901 | else if (beg_end_state == AFTER_FIRST_DASH) \ | ||
| 902 | beg_end_state = (ch == '*' ? AFTER_ASTERIX : NOMINAL); \ | ||
| 903 | else if (beg_end_state == AFTER_ASTERIX) \ | ||
| 904 | { \ | ||
| 905 | if (ch == '-') \ | ||
| 906 | in_file_vars = !in_file_vars; \ | ||
| 907 | beg_end_state = NOMINAL; \ | ||
| 908 | } | ||
| 909 | |||
| 910 | /* Skip until we get to the file vars, if any. */ | ||
| 911 | do | ||
| 912 | { | ||
| 913 | ch = READCHAR; | ||
| 914 | UPDATE_BEG_END_STATE (ch); | ||
| 915 | } | ||
| 916 | while (!in_file_vars && ch != '\n' && ch != EOF); | ||
| 917 | |||
| 918 | while (in_file_vars) | ||
| 919 | { | ||
| 920 | char var[100], *var_end, val[100], *val_end; | ||
| 921 | |||
| 922 | ch = READCHAR; | ||
| 923 | |||
| 924 | /* Read a variable name. */ | ||
| 925 | while (ch == ' ' || ch == '\t') | ||
| 926 | ch = READCHAR; | ||
| 927 | |||
| 928 | var_end = var; | ||
| 929 | while (ch != ':' && ch != '\n' && ch != EOF) | ||
| 930 | { | ||
| 931 | if (var_end < var + sizeof var - 1) | ||
| 932 | *var_end++ = ch; | ||
| 933 | UPDATE_BEG_END_STATE (ch); | ||
| 934 | ch = READCHAR; | ||
| 935 | } | ||
| 936 | |||
| 937 | while (var_end > var | ||
| 938 | && (var_end[-1] == ' ' || var_end[-1] == '\t')) | ||
| 939 | var_end--; | ||
| 940 | *var_end = '\0'; | ||
| 941 | |||
| 942 | if (ch == ':') | ||
| 943 | { | ||
| 944 | /* Read a variable value. */ | ||
| 945 | ch = READCHAR; | ||
| 946 | |||
| 947 | while (ch == ' ' || ch == '\t') | ||
| 948 | ch = READCHAR; | ||
| 949 | |||
| 950 | val_end = val; | ||
| 951 | while (ch != ';' && ch != '\n' && ch != EOF && in_file_vars) | ||
| 952 | { | ||
| 953 | if (val_end < val + sizeof val - 1) | ||
| 954 | *val_end++ = ch; | ||
| 955 | UPDATE_BEG_END_STATE (ch); | ||
| 956 | ch = READCHAR; | ||
| 957 | } | ||
| 958 | if (! in_file_vars) | ||
| 959 | /* The value was terminated by an end-marker, which | ||
| 960 | remove. */ | ||
| 961 | val_end -= 3; | ||
| 962 | while (val_end > val | ||
| 963 | && (val_end[-1] == ' ' || val_end[-1] == '\t')) | ||
| 964 | val_end--; | ||
| 965 | *val_end = '\0'; | ||
| 966 | |||
| 967 | if (strcmp (var, "lexical-binding") == 0) | ||
| 968 | /* This is it... */ | ||
| 969 | { | ||
| 970 | rv = (strcmp (val, "nil") != 0); | ||
| 971 | break; | ||
| 972 | } | ||
| 973 | } | ||
| 974 | } | ||
| 975 | |||
| 976 | while (ch != '\n' && ch != EOF) | ||
| 977 | ch = READCHAR; | ||
| 978 | |||
| 979 | return rv; | ||
| 980 | } | ||
| 981 | } | ||
| 982 | |||
| 983 | |||
| 867 | /* Value is a version number of byte compiled code if the file | 984 | /* Value is a version number of byte compiled code if the file |
| 868 | associated with file descriptor FD is a compiled Lisp file that's | 985 | associated with file descriptor FD is a compiled Lisp file that's |
| 869 | safe to load. Only files compiled with Emacs are safe to load. | 986 | safe to load. Only files compiled with Emacs are safe to load. |
| @@ -1129,6 +1246,12 @@ Return t if the file exists and loads successfully. */) | |||
| 1129 | Vloads_in_progress = Fcons (found, Vloads_in_progress); | 1246 | Vloads_in_progress = Fcons (found, Vloads_in_progress); |
| 1130 | } | 1247 | } |
| 1131 | 1248 | ||
| 1249 | /* All loads are by default dynamic, unless the file itself specifies | ||
| 1250 | otherwise using a file-variable in the first line. This is bound here | ||
| 1251 | so that it takes effect whether or not we use | ||
| 1252 | Vload_source_file_function. */ | ||
| 1253 | specbind (Qlexical_binding, Qnil); | ||
| 1254 | |||
| 1132 | /* Get the name for load-history. */ | 1255 | /* Get the name for load-history. */ |
| 1133 | hist_file_name = (! NILP (Vpurify_flag) | 1256 | hist_file_name = (! NILP (Vpurify_flag) |
| 1134 | ? Fconcat (2, (tmp[0] = Ffile_name_directory (file), | 1257 | ? Fconcat (2, (tmp[0] = Ffile_name_directory (file), |
| @@ -1253,7 +1376,13 @@ Return t if the file exists and loads successfully. */) | |||
| 1253 | specbind (Qinhibit_file_name_operation, Qnil); | 1376 | specbind (Qinhibit_file_name_operation, Qnil); |
| 1254 | load_descriptor_list | 1377 | load_descriptor_list |
| 1255 | = Fcons (make_number (fileno (stream)), load_descriptor_list); | 1378 | = Fcons (make_number (fileno (stream)), load_descriptor_list); |
| 1379 | |||
| 1256 | specbind (Qload_in_progress, Qt); | 1380 | specbind (Qload_in_progress, Qt); |
| 1381 | |||
| 1382 | instream = stream; | ||
| 1383 | if (lisp_file_lexically_bound_p (Qget_file_char)) | ||
| 1384 | Fset (Qlexical_binding, Qt); | ||
| 1385 | |||
| 1257 | if (! version || version >= 22) | 1386 | if (! version || version >= 22) |
| 1258 | readevalloop (Qget_file_char, stream, hist_file_name, | 1387 | readevalloop (Qget_file_char, stream, hist_file_name, |
| 1259 | Feval, 0, Qnil, Qnil, Qnil, Qnil); | 1388 | Feval, 0, Qnil, Qnil, Qnil, Qnil); |
| @@ -1652,6 +1781,7 @@ readevalloop (readcharfun, stream, sourcename, evalfun, | |||
| 1652 | struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; | 1781 | struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; |
| 1653 | struct buffer *b = 0; | 1782 | struct buffer *b = 0; |
| 1654 | int continue_reading_p; | 1783 | int continue_reading_p; |
| 1784 | Lisp_Object lex_bound; | ||
| 1655 | /* Nonzero if reading an entire buffer. */ | 1785 | /* Nonzero if reading an entire buffer. */ |
| 1656 | int whole_buffer = 0; | 1786 | int whole_buffer = 0; |
| 1657 | /* 1 on the first time around. */ | 1787 | /* 1 on the first time around. */ |
| @@ -1677,6 +1807,15 @@ readevalloop (readcharfun, stream, sourcename, evalfun, | |||
| 1677 | record_unwind_protect (readevalloop_1, load_convert_to_unibyte ? Qt : Qnil); | 1807 | record_unwind_protect (readevalloop_1, load_convert_to_unibyte ? Qt : Qnil); |
| 1678 | load_convert_to_unibyte = !NILP (unibyte); | 1808 | load_convert_to_unibyte = !NILP (unibyte); |
| 1679 | 1809 | ||
| 1810 | /* If lexical binding is active (either because it was specified in | ||
| 1811 | the file's header, or via a buffer-local variable), create an empty | ||
| 1812 | lexical environment, otherwise, turn off lexical binding. */ | ||
| 1813 | lex_bound = find_symbol_value (Qlexical_binding); | ||
| 1814 | if (NILP (lex_bound) || EQ (lex_bound, Qunbound)) | ||
| 1815 | specbind (Qinternal_interpreter_environment, Qnil); | ||
| 1816 | else | ||
| 1817 | specbind (Qinternal_interpreter_environment, Fcons (Qt, Qnil)); | ||
| 1818 | |||
| 1680 | GCPRO4 (sourcename, readfun, start, end); | 1819 | GCPRO4 (sourcename, readfun, start, end); |
| 1681 | 1820 | ||
| 1682 | /* Try to ensure sourcename is a truename, except whilst preloading. */ | 1821 | /* Try to ensure sourcename is a truename, except whilst preloading. */ |
| @@ -1837,8 +1976,11 @@ This function preserves the position of point. */) | |||
| 1837 | 1976 | ||
| 1838 | specbind (Qeval_buffer_list, Fcons (buf, Veval_buffer_list)); | 1977 | specbind (Qeval_buffer_list, Fcons (buf, Veval_buffer_list)); |
| 1839 | specbind (Qstandard_output, tem); | 1978 | specbind (Qstandard_output, tem); |
| 1979 | specbind (Qlexical_binding, Qnil); | ||
| 1840 | record_unwind_protect (save_excursion_restore, save_excursion_save ()); | 1980 | record_unwind_protect (save_excursion_restore, save_excursion_save ()); |
| 1841 | BUF_TEMP_SET_PT (XBUFFER (buf), BUF_BEGV (XBUFFER (buf))); | 1981 | BUF_TEMP_SET_PT (XBUFFER (buf), BUF_BEGV (XBUFFER (buf))); |
| 1982 | if (lisp_file_lexically_bound_p (buf)) | ||
| 1983 | Fset (Qlexical_binding, Qt); | ||
| 1842 | readevalloop (buf, 0, filename, Feval, | 1984 | readevalloop (buf, 0, filename, Feval, |
| 1843 | !NILP (printflag), unibyte, Qnil, Qnil, Qnil); | 1985 | !NILP (printflag), unibyte, Qnil, Qnil, Qnil); |
| 1844 | unbind_to (count, Qnil); | 1986 | unbind_to (count, Qnil); |
| @@ -2481,14 +2623,8 @@ read1 (readcharfun, pch, first_in_list) | |||
| 2481 | invalid_syntax ("#&...", 5); | 2623 | invalid_syntax ("#&...", 5); |
| 2482 | } | 2624 | } |
| 2483 | if (c == '[') | 2625 | if (c == '[') |
| 2484 | { | 2626 | /* `function vector' objects, including byte-compiled functions. */ |
| 2485 | /* Accept compiled functions at read-time so that we don't have to | 2627 | return read_vector (readcharfun, 1); |
| 2486 | build them using function calls. */ | ||
| 2487 | Lisp_Object tmp; | ||
| 2488 | tmp = read_vector (readcharfun, 1); | ||
| 2489 | return Fmake_byte_code (XVECTOR (tmp)->size, | ||
| 2490 | XVECTOR (tmp)->contents); | ||
| 2491 | } | ||
| 2492 | if (c == '(') | 2628 | if (c == '(') |
| 2493 | { | 2629 | { |
| 2494 | Lisp_Object tmp; | 2630 | Lisp_Object tmp; |
| @@ -3300,9 +3436,9 @@ isfloat_string (cp, ignore_trailing) | |||
| 3300 | 3436 | ||
| 3301 | 3437 | ||
| 3302 | static Lisp_Object | 3438 | static Lisp_Object |
| 3303 | read_vector (readcharfun, bytecodeflag) | 3439 | read_vector (readcharfun, read_funvec) |
| 3304 | Lisp_Object readcharfun; | 3440 | Lisp_Object readcharfun; |
| 3305 | int bytecodeflag; | 3441 | int read_funvec; |
| 3306 | { | 3442 | { |
| 3307 | register int i; | 3443 | register int i; |
| 3308 | register int size; | 3444 | register int size; |
| @@ -3310,6 +3446,11 @@ read_vector (readcharfun, bytecodeflag) | |||
| 3310 | register Lisp_Object tem, item, vector; | 3446 | register Lisp_Object tem, item, vector; |
| 3311 | register struct Lisp_Cons *otem; | 3447 | register struct Lisp_Cons *otem; |
| 3312 | Lisp_Object len; | 3448 | Lisp_Object len; |
| 3449 | /* If we're reading a funvec object we start out assuming it's also a | ||
| 3450 | byte-code object (a subset of funvecs), so we can do any special | ||
| 3451 | processing needed. If it's just an ordinary funvec object, we'll | ||
| 3452 | realize that as soon as we've read the first element. */ | ||
| 3453 | int read_bytecode = read_funvec; | ||
| 3313 | 3454 | ||
| 3314 | tem = read_list (1, readcharfun); | 3455 | tem = read_list (1, readcharfun); |
| 3315 | len = Flength (tem); | 3456 | len = Flength (tem); |
| @@ -3320,11 +3461,19 @@ read_vector (readcharfun, bytecodeflag) | |||
| 3320 | for (i = 0; i < size; i++) | 3461 | for (i = 0; i < size; i++) |
| 3321 | { | 3462 | { |
| 3322 | item = Fcar (tem); | 3463 | item = Fcar (tem); |
| 3464 | |||
| 3465 | /* If READ_BYTECODE is set, check whether this is really a byte-code | ||
| 3466 | object, or just an ordinary `funvec' object -- non-byte-code | ||
| 3467 | funvec objects use the same reader syntax. We can tell from the | ||
| 3468 | first element which one it is. */ | ||
| 3469 | if (read_bytecode && i == 0 && ! FUNVEC_COMPILED_TAG_P (item)) | ||
| 3470 | read_bytecode = 0; /* Nope. */ | ||
| 3471 | |||
| 3323 | /* If `load-force-doc-strings' is t when reading a lazily-loaded | 3472 | /* If `load-force-doc-strings' is t when reading a lazily-loaded |
| 3324 | bytecode object, the docstring containing the bytecode and | 3473 | bytecode object, the docstring containing the bytecode and |
| 3325 | constants values must be treated as unibyte and passed to | 3474 | constants values must be treated as unibyte and passed to |
| 3326 | Fread, to get the actual bytecode string and constants vector. */ | 3475 | Fread, to get the actual bytecode string and constants vector. */ |
| 3327 | if (bytecodeflag && load_force_doc_strings) | 3476 | if (read_bytecode && load_force_doc_strings) |
| 3328 | { | 3477 | { |
| 3329 | if (i == COMPILED_BYTECODE) | 3478 | if (i == COMPILED_BYTECODE) |
| 3330 | { | 3479 | { |
| @@ -3377,6 +3526,14 @@ read_vector (readcharfun, bytecodeflag) | |||
| 3377 | tem = Fcdr (tem); | 3526 | tem = Fcdr (tem); |
| 3378 | free_cons (otem); | 3527 | free_cons (otem); |
| 3379 | } | 3528 | } |
| 3529 | |||
| 3530 | if (read_bytecode && size >= 4) | ||
| 3531 | /* Convert this vector to a bytecode object. */ | ||
| 3532 | vector = Fmake_byte_code (size, XVECTOR (vector)->contents); | ||
| 3533 | else if (read_funvec && size >= 1) | ||
| 3534 | /* Convert this vector to an ordinary funvec object. */ | ||
| 3535 | XSETFUNVEC (vector, XVECTOR (vector)); | ||
| 3536 | |||
| 3380 | return vector; | 3537 | return vector; |
| 3381 | } | 3538 | } |
| 3382 | 3539 | ||
| @@ -3979,6 +4136,7 @@ defvar_int (struct Lisp_Intfwd *i_fwd, | |||
| 3979 | sym = intern_c_string (namestring); | 4136 | sym = intern_c_string (namestring); |
| 3980 | i_fwd->type = Lisp_Fwd_Int; | 4137 | i_fwd->type = Lisp_Fwd_Int; |
| 3981 | i_fwd->intvar = address; | 4138 | i_fwd->intvar = address; |
| 4139 | XSYMBOL (sym)->declared_special = 1; | ||
| 3982 | XSYMBOL (sym)->redirect = SYMBOL_FORWARDED; | 4140 | XSYMBOL (sym)->redirect = SYMBOL_FORWARDED; |
| 3983 | SET_SYMBOL_FWD (XSYMBOL (sym), (union Lisp_Fwd *)i_fwd); | 4141 | SET_SYMBOL_FWD (XSYMBOL (sym), (union Lisp_Fwd *)i_fwd); |
| 3984 | } | 4142 | } |
| @@ -3993,6 +4151,7 @@ defvar_bool (struct Lisp_Boolfwd *b_fwd, | |||
| 3993 | sym = intern_c_string (namestring); | 4151 | sym = intern_c_string (namestring); |
| 3994 | b_fwd->type = Lisp_Fwd_Bool; | 4152 | b_fwd->type = Lisp_Fwd_Bool; |
| 3995 | b_fwd->boolvar = address; | 4153 | b_fwd->boolvar = address; |
| 4154 | XSYMBOL (sym)->declared_special = 1; | ||
| 3996 | XSYMBOL (sym)->redirect = SYMBOL_FORWARDED; | 4155 | XSYMBOL (sym)->redirect = SYMBOL_FORWARDED; |
| 3997 | SET_SYMBOL_FWD (XSYMBOL (sym), (union Lisp_Fwd *)b_fwd); | 4156 | SET_SYMBOL_FWD (XSYMBOL (sym), (union Lisp_Fwd *)b_fwd); |
| 3998 | Vbyte_boolean_vars = Fcons (sym, Vbyte_boolean_vars); | 4157 | Vbyte_boolean_vars = Fcons (sym, Vbyte_boolean_vars); |
| @@ -4011,6 +4170,7 @@ defvar_lisp_nopro (struct Lisp_Objfwd *o_fwd, | |||
| 4011 | sym = intern_c_string (namestring); | 4170 | sym = intern_c_string (namestring); |
| 4012 | o_fwd->type = Lisp_Fwd_Obj; | 4171 | o_fwd->type = Lisp_Fwd_Obj; |
| 4013 | o_fwd->objvar = address; | 4172 | o_fwd->objvar = address; |
| 4173 | XSYMBOL (sym)->declared_special = 1; | ||
| 4014 | XSYMBOL (sym)->redirect = SYMBOL_FORWARDED; | 4174 | XSYMBOL (sym)->redirect = SYMBOL_FORWARDED; |
| 4015 | SET_SYMBOL_FWD (XSYMBOL (sym), (union Lisp_Fwd *)o_fwd); | 4175 | SET_SYMBOL_FWD (XSYMBOL (sym), (union Lisp_Fwd *)o_fwd); |
| 4016 | } | 4176 | } |
| @@ -4023,6 +4183,7 @@ defvar_lisp (struct Lisp_Objfwd *o_fwd, | |||
| 4023 | staticpro (address); | 4183 | staticpro (address); |
| 4024 | } | 4184 | } |
| 4025 | 4185 | ||
| 4186 | |||
| 4026 | /* Similar but define a variable whose value is the Lisp Object stored | 4187 | /* Similar but define a variable whose value is the Lisp Object stored |
| 4027 | at a particular offset in the current kboard object. */ | 4188 | at a particular offset in the current kboard object. */ |
| 4028 | 4189 | ||
| @@ -4034,6 +4195,7 @@ defvar_kboard (struct Lisp_Kboard_Objfwd *ko_fwd, | |||
| 4034 | sym = intern_c_string (namestring); | 4195 | sym = intern_c_string (namestring); |
| 4035 | ko_fwd->type = Lisp_Fwd_Kboard_Obj; | 4196 | ko_fwd->type = Lisp_Fwd_Kboard_Obj; |
| 4036 | ko_fwd->offset = offset; | 4197 | ko_fwd->offset = offset; |
| 4198 | XSYMBOL (sym)->declared_special = 1; | ||
| 4037 | XSYMBOL (sym)->redirect = SYMBOL_FORWARDED; | 4199 | XSYMBOL (sym)->redirect = SYMBOL_FORWARDED; |
| 4038 | SET_SYMBOL_FWD (XSYMBOL (sym), (union Lisp_Fwd *)ko_fwd); | 4200 | SET_SYMBOL_FWD (XSYMBOL (sym), (union Lisp_Fwd *)ko_fwd); |
| 4039 | } | 4201 | } |
| @@ -4463,6 +4625,16 @@ to load. See also `load-dangerous-libraries'. */); | |||
| 4463 | Vbytecomp_version_regexp | 4625 | Vbytecomp_version_regexp |
| 4464 | = make_pure_c_string ("^;;;.\\(in Emacs version\\|bytecomp version FSF\\)"); | 4626 | = make_pure_c_string ("^;;;.\\(in Emacs version\\|bytecomp version FSF\\)"); |
| 4465 | 4627 | ||
| 4628 | Qlexical_binding = intern ("lexical-binding"); | ||
| 4629 | staticpro (&Qlexical_binding); | ||
| 4630 | DEFVAR_LISP ("lexical-binding", &Vlexical_binding, | ||
| 4631 | doc: /* If non-nil, use lexical binding when evaluating code. | ||
| 4632 | This only applies to code evaluated by `eval-buffer' and `eval-region'. | ||
| 4633 | This variable is automatically set from the file variables of an interpreted | ||
| 4634 | lisp file read using `load'. | ||
| 4635 | This variable automatically becomes buffer-local when set. */); | ||
| 4636 | Fmake_variable_buffer_local (Qlexical_binding); | ||
| 4637 | |||
| 4466 | DEFVAR_LISP ("eval-buffer-list", &Veval_buffer_list, | 4638 | DEFVAR_LISP ("eval-buffer-list", &Veval_buffer_list, |
| 4467 | doc: /* List of buffers being read from by calls to `eval-buffer' and `eval-region'. */); | 4639 | doc: /* List of buffers being read from by calls to `eval-buffer' and `eval-region'. */); |
| 4468 | Veval_buffer_list = Qnil; | 4640 | Veval_buffer_list = Qnil; |
diff --git a/src/print.c b/src/print.c index 6d403e00fe0..fb298233666 100644 --- a/src/print.c +++ b/src/print.c | |||
| @@ -1340,7 +1340,7 @@ print_preprocess (obj) | |||
| 1340 | 1340 | ||
| 1341 | loop: | 1341 | loop: |
| 1342 | if (STRINGP (obj) || CONSP (obj) || VECTORP (obj) | 1342 | if (STRINGP (obj) || CONSP (obj) || VECTORP (obj) |
| 1343 | || COMPILEDP (obj) || CHAR_TABLE_P (obj) || SUB_CHAR_TABLE_P (obj) | 1343 | || FUNVECP (obj) || CHAR_TABLE_P (obj) || SUB_CHAR_TABLE_P (obj) |
| 1344 | || HASH_TABLE_P (obj) | 1344 | || HASH_TABLE_P (obj) |
| 1345 | || (! NILP (Vprint_gensym) | 1345 | || (! NILP (Vprint_gensym) |
| 1346 | && SYMBOLP (obj) | 1346 | && SYMBOLP (obj) |
| @@ -1543,7 +1543,7 @@ print_object (obj, printcharfun, escapeflag) | |||
| 1543 | 1543 | ||
| 1544 | /* Detect circularities and truncate them. */ | 1544 | /* Detect circularities and truncate them. */ |
| 1545 | if (STRINGP (obj) || CONSP (obj) || VECTORP (obj) | 1545 | if (STRINGP (obj) || CONSP (obj) || VECTORP (obj) |
| 1546 | || COMPILEDP (obj) || CHAR_TABLE_P (obj) || SUB_CHAR_TABLE_P (obj) | 1546 | || FUNVECP (obj) || CHAR_TABLE_P (obj) || SUB_CHAR_TABLE_P (obj) |
| 1547 | || HASH_TABLE_P (obj) | 1547 | || HASH_TABLE_P (obj) |
| 1548 | || (! NILP (Vprint_gensym) | 1548 | || (! NILP (Vprint_gensym) |
| 1549 | && SYMBOLP (obj) | 1549 | && SYMBOLP (obj) |
| @@ -2175,7 +2175,7 @@ print_object (obj, printcharfun, escapeflag) | |||
| 2175 | else | 2175 | else |
| 2176 | { | 2176 | { |
| 2177 | EMACS_INT size = XVECTOR (obj)->size; | 2177 | EMACS_INT size = XVECTOR (obj)->size; |
| 2178 | if (COMPILEDP (obj)) | 2178 | if (FUNVECP (obj)) |
| 2179 | { | 2179 | { |
| 2180 | PRINTCHAR ('#'); | 2180 | PRINTCHAR ('#'); |
| 2181 | size &= PSEUDOVECTOR_SIZE_MASK; | 2181 | size &= PSEUDOVECTOR_SIZE_MASK; |