Mercurial > hg > xemacs-beta
comparison src/fns.c @ 4995:8431b52e43b1
Move the various map* functions to C; add #'map-into.
src/ChangeLog addition:
2010-01-31 Aidan Kehoe <kehoea@parhasard.net>
Move #'mapcar*, #'mapcan, #'mapc, #'map, #'mapl, #'mapcon to C;
extend #'mapvector, #'mapconcat, #'mapcar to support more
SEQUENCES; have them all error with circular lists.
* fns.c (Fsubseq): Call CHECK_SEQUENCE here; Flength can return
from the debugger if it errors with a non-sequence, leading to a
crash in Fsubseq if sequence really is *not* a sequence.
(mapcarX): Rename mapcar1 to mapcarX; rework it comprehensively to
take an optional lisp output argument, and a varying number of
sequences.
Special-case a single list argument, as we used to, saving its
elements in the stack space for the results before calling
FUNCTION, so FUNCTION can corrupt the list all it
wants. dead_wrong_type_argument() in the other cases if we
encounter a non-cons where we expected a cons.
(Fmapconcat):
Accept further SEQUENCES after separator here. Special-case
the idiom (mapconcat 'identity SEQUENCE), don't even funcall.
(FmapcarX): Rename this from Fmapcar. Accept optional SEQUENCES.
(Fmapvector): Accept optional SEQUENCES.
(Fmapcan, Fmapc, Fmap): Move these here from cl-extra.el.
(Fmap_into): New function, as specified by Common Lisp.
(maplist): New function, the guts of the implementation of
Fmaplist and Fmapl.
(Fmaplist, Fmapl, Fmapcon): Move these from cl-extra.el.
(syms_of_fns):
Add a few needed symbols here, for the type tests
used by #'map. Add the new subrs, with aliases for #'mapc-internal
and #'mapcar.
* general-slots.h: Declare Qcoerce here, now it's used in both
indent.c and fns.c
* indent.c (syms_of_indent): Qcoerce is gone from here.
* lisp.h: Add ARRAYP(), SEQUENCEP(), and the corresponding CHECK_*
macros. Declare Fbit_vector, Fstring, FmapcarX, now other files
need to use them.
* data.c (Farrayp, Fsequencep): Use ARRAYP and SEQUENCEP, just
added to lisp.h
* buffer.c (Fbuffer_list): Now Fmapcar has been renamed FmapcarX
and takes MANY arguments, update this function to reflect that.
lisp/ChangeLog addition:
2010-01-31 Aidan Kehoe <kehoea@parhasard.net>
* cl.el (mapcar*): Delete; this is now in fns.c.
Use #'mapc, not #'mapc-internal in a couple of places.
* cl-macs.el (mapc, mapcar*, map): Delete these compiler macros
now the corresponding functions are in fns.c; there's no run-time
advantage to the macros.
* cl-extra.el (coerce): Extend the possible conversions here a
little; it's not remotely comprehensive yet, though it does allow
running slightly more Common Lisp code than previously.
(cl-mapcar-many): Delete.
(map, maplist, mapc, mapl, mapcan, mapcon): Move these to fns.c.
* bytecomp.el (byte-compile-maybe-mapc):
Use #'mapc itself, not #'mapc-internal, now the former is in C.
(mapcar*): Use #'byte-compile-maybe-mapc as this function's
byte-compile method, now a #'mapc that can take more than one
sequence is in C.
* obsolete.el (cl-mapc): Move this compatibility alias to this file.
* update-elc.el (do-autoload-commands): Use #'mapc, not
#'mapc-internal here.
author | Aidan Kehoe <kehoea@parhasard.net> |
---|---|
date | Sun, 31 Jan 2010 18:29:48 +0000 |
parents | a5eca70cf401 |
children | c17c857e20bf |
comparison
equal
deleted
inserted
replaced
4904:e91e3e353805 | 4995:8431b52e43b1 |
---|---|
54 /* NOTE: This symbol is also used in lread.c */ | 54 /* NOTE: This symbol is also used in lread.c */ |
55 #define FEATUREP_SYNTAX | 55 #define FEATUREP_SYNTAX |
56 | 56 |
57 Lisp_Object Qstring_lessp; | 57 Lisp_Object Qstring_lessp; |
58 Lisp_Object Qidentity; | 58 Lisp_Object Qidentity; |
59 Lisp_Object Qvector, Qarray, Qstring, Qlist, Qbit_vector; | |
59 | 60 |
60 Lisp_Object Qbase64_conversion_error; | 61 Lisp_Object Qbase64_conversion_error; |
61 | 62 |
62 Lisp_Object Vpath_separator; | 63 Lisp_Object Vpath_separator; |
63 | 64 |
979 */ | 980 */ |
980 (sequence, start, end)) | 981 (sequence, start, end)) |
981 { | 982 { |
982 EMACS_INT len, s, e; | 983 EMACS_INT len, s, e; |
983 | 984 |
985 CHECK_SEQUENCE (sequence); | |
986 | |
984 if (STRINGP (sequence)) | 987 if (STRINGP (sequence)) |
985 return Fsubstring (sequence, start, end); | 988 return Fsubstring (sequence, start, end); |
986 | 989 |
987 len = XINT (Flength (sequence)); | 990 len = XINT (Flength (sequence)); |
988 | 991 |
1040 bit_vector_bit (XBIT_VECTOR (sequence), i)); | 1043 bit_vector_bit (XBIT_VECTOR (sequence), i)); |
1041 return result; | 1044 return result; |
1042 } | 1045 } |
1043 else | 1046 else |
1044 { | 1047 { |
1045 ABORT (); /* unreachable, since Flength (sequence) did not get | 1048 ABORT (); /* unreachable, since CHECK_SEQUENCE (sequence) did not |
1046 an error */ | 1049 error */ |
1047 return Qnil; | 1050 return Qnil; |
1048 } | 1051 } |
1049 } | 1052 } |
1050 | 1053 |
1051 /* Split STRING into a list of substrings. The substrings are the | 1054 /* Split STRING into a list of substrings. The substrings are the |
3152 RETURN_UNGCPRO (Qnil); /* No non-nil args provided. */ | 3155 RETURN_UNGCPRO (Qnil); /* No non-nil args provided. */ |
3153 } | 3156 } |
3154 | 3157 |
3155 | 3158 |
3156 /* This is the guts of several mapping functions. | 3159 /* This is the guts of several mapping functions. |
3157 Apply FUNCTION to each element of SEQUENCE, one by one, | 3160 |
3158 storing the results into elements of VALS, a C vector of Lisp_Objects. | 3161 Call FUNCTION CALL_COUNT times, with NSEQUENCES arguments each time, |
3159 LENI is the length of VALS, which should also be the length of SEQUENCE. | 3162 taking the elements from SEQUENCES. If VALS is non-NULL, store the |
3160 | 3163 results into VALS, a C array of Lisp_Objects; else, if LISP_VALS is |
3161 If VALS is a null pointer, do not accumulate the results. */ | 3164 non-nil, store the results into LISP_VALS, a sequence with sufficient |
3165 room for CALL_COUNT results. Else, do not accumulate any result. | |
3166 | |
3167 If VALS is non-NULL, NSEQUENCES is one, and SEQUENCES[0] is a cons, | |
3168 mapcarX will store the elements of SEQUENCES[0] in stack and GCPRO them, | |
3169 so FUNCTION cannot insert a non-cons into SEQUENCES[0] and throw off | |
3170 mapcarX. | |
3171 | |
3172 Otherwise, mapcarX signals a wrong-type-error if it encounters a | |
3173 non-cons, non-array when traversing SEQUENCES. Common Lisp specifies in | |
3174 MAPPING-DESTRUCTIVE-INTERACTION that it is an error when FUNCTION | |
3175 destructively modifies SEQUENCES in a way that might affect the ongoing | |
3176 traversal operation. */ | |
3162 | 3177 |
3163 static void | 3178 static void |
3164 mapcar1 (Elemcount leni, Lisp_Object *vals, | 3179 mapcarX (Elemcount call_count, Lisp_Object *vals, Lisp_Object lisp_vals, |
3165 Lisp_Object function, Lisp_Object sequence) | 3180 Lisp_Object function, int nsequences, Lisp_Object *sequences) |
3166 { | 3181 { |
3167 Lisp_Object result; | 3182 Lisp_Object called, *args; |
3168 Lisp_Object args[2]; | 3183 struct gcpro gcpro1, gcpro2; |
3169 struct gcpro gcpro1; | 3184 int i, j; |
3170 | 3185 enum lrecord_type lisp_vals_type; |
3171 if (vals) | 3186 |
3172 { | 3187 assert (LRECORDP (lisp_vals)); |
3173 GCPRO1 (vals[0]); | 3188 lisp_vals_type = XRECORD_LHEADER (lisp_vals)->type; |
3174 gcpro1.nvars = 0; | 3189 |
3175 } | 3190 args = alloca_array (Lisp_Object, nsequences + 1); |
3176 | |
3177 args[0] = function; | 3191 args[0] = function; |
3178 | 3192 for (i = 1; i <= nsequences; ++i) |
3179 if (LISTP (sequence)) | 3193 { |
3180 { | 3194 args[i] = Qnil; |
3181 /* A devious `function' could either: | 3195 } |
3182 - insert garbage into the list in front of us, causing XCDR to crash | 3196 |
3183 - amputate the list behind us using (setcdr), causing the remaining | 3197 if (vals != NULL) |
3184 elts to lose their GCPRO status. | 3198 { |
3185 | 3199 GCPRO2 (args[0], vals[0]); |
3186 if (vals != 0) we avoid this by copying the elts into the | 3200 gcpro1.nvars = nsequences + 1; |
3187 `vals' array. By a stroke of luck, `vals' is exactly large | 3201 gcpro2.nvars = 0; |
3188 enough to hold the elts left to be traversed as well as the | 3202 } |
3189 results computed so far. | 3203 else |
3190 | 3204 { |
3191 if (vals == 0) we don't have any free space available and | 3205 GCPRO1 (args[0]); |
3192 don't want to eat up any more stack with ALLOCA (). | 3206 gcpro1.nvars = nsequences + 1; |
3193 So we use EXTERNAL_LIST_LOOP_3_NO_DECLARE and GCPRO the tail. */ | 3207 } |
3194 | 3208 |
3195 if (vals) | 3209 /* Be extra nice in the event that we've been handed one list and one |
3196 { | 3210 only; make it possible for FUNCTION to set cdrs not yet processed to |
3197 Lisp_Object *val = vals; | 3211 non-cons, non-nil objects without ill-effect, if we have been handed |
3198 Elemcount i; | 3212 the stack space to do that. */ |
3199 | 3213 if (vals != NULL && 1 == nsequences && CONSP (sequences[0])) |
3200 LIST_LOOP_2 (elt, sequence) | 3214 { |
3201 *val++ = elt; | 3215 Lisp_Object lst = sequences[0]; |
3202 | 3216 Lisp_Object *val = vals; |
3203 gcpro1.nvars = leni; | 3217 for (i = 0; i < call_count; ++i) |
3204 | 3218 { |
3205 for (i = 0; i < leni; i++) | 3219 *val++ = XCAR (lst); |
3220 lst = XCDR (lst); | |
3221 } | |
3222 gcpro2.nvars = call_count; | |
3223 | |
3224 for (i = 0; i < call_count; ++i) | |
3225 { | |
3226 args[1] = vals[i]; | |
3227 vals[i] = Ffuncall (nsequences + 1, args); | |
3228 } | |
3229 } | |
3230 else | |
3231 { | |
3232 Binbyte *sequence_types = alloca_array (Binbyte, nsequences); | |
3233 for (j = 0; j < nsequences; ++j) | |
3234 { | |
3235 sequence_types[j] = XRECORD_LHEADER (sequences[j])->type; | |
3236 } | |
3237 | |
3238 for (i = 0; i < call_count; ++i) | |
3239 { | |
3240 for (j = 0; j < nsequences; ++j) | |
3206 { | 3241 { |
3207 args[1] = vals[i]; | 3242 switch (sequence_types[j]) |
3208 vals[i] = Ffuncall (2, args); | 3243 { |
3244 case lrecord_type_cons: | |
3245 { | |
3246 if (!CONSP (sequences[j])) | |
3247 { | |
3248 /* This means FUNCTION has probably messed | |
3249 around with a cons in one of the sequences, | |
3250 since we checked the type | |
3251 (CHECK_SEQUENCE()) and the length and | |
3252 structure (with Flength()) correctly in our | |
3253 callers. */ | |
3254 dead_wrong_type_argument (Qconsp, sequences[j]); | |
3255 } | |
3256 args[j + 1] = XCAR (sequences[j]); | |
3257 sequences[j] = XCDR (sequences[j]); | |
3258 break; | |
3259 } | |
3260 case lrecord_type_vector: | |
3261 { | |
3262 args[j + 1] = XVECTOR_DATA (sequences[j])[i]; | |
3263 break; | |
3264 } | |
3265 case lrecord_type_string: | |
3266 { | |
3267 args[j + 1] = make_char (string_ichar (sequences[j], i)); | |
3268 break; | |
3269 } | |
3270 case lrecord_type_bit_vector: | |
3271 { | |
3272 args[j + 1] | |
3273 = make_int (bit_vector_bit (XBIT_VECTOR (sequences[j]), | |
3274 i)); | |
3275 break; | |
3276 } | |
3277 default: | |
3278 ABORT(); | |
3279 } | |
3209 } | 3280 } |
3210 } | 3281 called = Ffuncall (nsequences + 1, args); |
3211 else | 3282 if (vals != NULL) |
3212 { | 3283 { |
3213 Lisp_Object elt, tail; | 3284 vals[i] = called; |
3214 EMACS_INT len_unused; | 3285 gcpro2.nvars += 1; |
3215 struct gcpro ngcpro1; | 3286 } |
3216 | 3287 else |
3217 NGCPRO1 (tail); | 3288 { |
3218 | 3289 switch (lisp_vals_type) |
3219 { | 3290 { |
3220 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tail, len_unused) | 3291 case lrecord_type_symbol: |
3221 { | 3292 break; |
3222 args[1] = elt; | 3293 case lrecord_type_cons: |
3223 Ffuncall (2, args); | 3294 { |
3224 } | 3295 if (!CONSP (lisp_vals)) |
3225 } | 3296 { |
3226 | 3297 /* If FUNCTION has inserted a non-cons non-nil cdr |
3227 NUNGCPRO; | 3298 into the list before we've processed the relevant |
3228 } | 3299 part, error. */ |
3229 } | 3300 dead_wrong_type_argument (Qconsp, lisp_vals); |
3230 else if (VECTORP (sequence)) | 3301 } |
3231 { | 3302 |
3232 Lisp_Object *objs = XVECTOR_DATA (sequence); | 3303 XSETCAR (lisp_vals, called); |
3233 Elemcount i; | 3304 lisp_vals = XCDR (lisp_vals); |
3234 for (i = 0; i < leni; i++) | 3305 break; |
3235 { | 3306 } |
3236 args[1] = *objs++; | 3307 case lrecord_type_vector: |
3237 result = Ffuncall (2, args); | 3308 { |
3238 if (vals) vals[gcpro1.nvars++] = result; | 3309 i < XVECTOR_LENGTH (lisp_vals) ? |
3239 } | 3310 (XVECTOR_DATA (lisp_vals)[i] = called) : |
3240 } | 3311 /* Let #'aset error. */ |
3241 else if (STRINGP (sequence)) | 3312 Faset (lisp_vals, make_int (i), called); |
3242 { | 3313 break; |
3243 /* The string data of `sequence' might be relocated during GC. */ | 3314 } |
3244 Bytecount slen = XSTRING_LENGTH (sequence); | 3315 case lrecord_type_string: |
3245 Ibyte *p = alloca_ibytes (slen); | 3316 { |
3246 Ibyte *end = p + slen; | 3317 /* If this ever becomes a code hotspot, we can keep |
3247 | 3318 around pointers into the data of the string, checking |
3248 memcpy (p, XSTRING_DATA (sequence), slen); | 3319 each time that it hasn't been relocated. */ |
3249 | 3320 Faset (lisp_vals, make_int (i), called); |
3250 while (p < end) | 3321 break; |
3251 { | 3322 } |
3252 args[1] = make_char (itext_ichar (p)); | 3323 case lrecord_type_bit_vector: |
3253 INC_IBYTEPTR (p); | 3324 { |
3254 result = Ffuncall (2, args); | 3325 (BITP (called) && |
3255 if (vals) vals[gcpro1.nvars++] = result; | 3326 i < bit_vector_length (XBIT_VECTOR (lisp_vals))) ? |
3256 } | 3327 set_bit_vector_bit (XBIT_VECTOR (lisp_vals), i, |
3257 } | 3328 XINT (called)) : |
3258 else if (BIT_VECTORP (sequence)) | 3329 Faset (lisp_vals, make_int (i), called); |
3259 { | 3330 break; |
3260 Lisp_Bit_Vector *v = XBIT_VECTOR (sequence); | 3331 } |
3261 Elemcount i; | 3332 default: |
3262 for (i = 0; i < leni; i++) | 3333 { |
3263 { | 3334 ABORT(); |
3264 args[1] = make_int (bit_vector_bit (v, i)); | 3335 break; |
3265 result = Ffuncall (2, args); | 3336 } |
3266 if (vals) vals[gcpro1.nvars++] = result; | 3337 } |
3267 } | 3338 } |
3268 } | 3339 } |
3269 else | 3340 } |
3270 ABORT (); /* unreachable, since Flength (sequence) did not get an error */ | 3341 UNGCPRO; |
3271 | 3342 } |
3272 if (vals) | 3343 |
3273 UNGCPRO; | 3344 DEFUN ("mapconcat", Fmapconcat, 3, MANY, 0, /* |
3274 } | 3345 Call FUNCTION on each element of SEQUENCE, and concat results to a string. |
3275 | |
3276 DEFUN ("mapconcat", Fmapconcat, 3, 3, 0, /* | |
3277 Apply FUNCTION to each element of SEQUENCE, and concat the results to a string. | |
3278 Between each pair of results, insert SEPARATOR. | 3346 Between each pair of results, insert SEPARATOR. |
3279 | 3347 |
3280 Each result, and SEPARATOR, should be strings. Thus, using " " as SEPARATOR | 3348 Each result, and SEPARATOR, should be strings. Thus, using " " as SEPARATOR |
3281 results in spaces between the values returned by FUNCTION. SEQUENCE itself | 3349 results in spaces between the values returned by FUNCTION. SEQUENCE itself |
3282 may be a list, a vector, a bit vector, or a string. | 3350 may be a list, a vector, a bit vector, or a string. |
3283 */ | 3351 |
3284 (function, sequence, separator)) | 3352 With optional SEQUENCES, call FUNCTION each time with as many arguments as |
3285 { | 3353 there are SEQUENCES, plus one for the element from SEQUENCE. One element |
3286 EMACS_INT len = XINT (Flength (sequence)); | 3354 from each sequence will be used each time FUNCTION is called, and |
3287 Lisp_Object *args; | 3355 `mapconcat' will give up once the shortest sequence is exhausted. |
3288 EMACS_INT i; | 3356 |
3289 EMACS_INT nargs = len + len - 1; | 3357 arguments: (FUNCTION SEQUENCE SEPARATOR &rest SEQUENCES) |
3358 */ | |
3359 (int nargs, Lisp_Object *args)) | |
3360 { | |
3361 Lisp_Object function = args[0]; | |
3362 Lisp_Object sequence = args[1]; | |
3363 Lisp_Object separator = args[2]; | |
3364 Elemcount len = EMACS_INT_MAX; | |
3365 Lisp_Object *args0; | |
3366 EMACS_INT i, nargs0; | |
3367 | |
3368 args[2] = sequence; | |
3369 args[1] = separator; | |
3370 | |
3371 for (i = 2; i < nargs; ++i) | |
3372 { | |
3373 CHECK_SEQUENCE (args[i]); | |
3374 len = min (len, XINT (Flength (args[i]))); | |
3375 } | |
3290 | 3376 |
3291 if (len == 0) return build_string (""); | 3377 if (len == 0) return build_string (""); |
3292 | 3378 |
3293 args = alloca_array (Lisp_Object, nargs); | 3379 nargs0 = len + len - 1; |
3294 | 3380 args0 = alloca_array (Lisp_Object, nargs0); |
3295 mapcar1 (len, args, function, sequence); | 3381 |
3382 /* Special-case this, it's very common and doesn't require any | |
3383 funcalls. Upside of doing it here, instead of cl-macs.el: no consing, | |
3384 apart from the final string, we allocate everything on the stack. */ | |
3385 if (EQ (function, Qidentity) && 3 == nargs && CONSP (sequence)) | |
3386 { | |
3387 for (i = 0; i < len; ++i) | |
3388 { | |
3389 args0[i] = XCAR (sequence); | |
3390 sequence = XCDR (sequence); | |
3391 } | |
3392 } | |
3393 else | |
3394 { | |
3395 mapcarX (len, args0, Qnil, function, nargs - 2, args + 2); | |
3396 } | |
3296 | 3397 |
3297 for (i = len - 1; i >= 0; i--) | 3398 for (i = len - 1; i >= 0; i--) |
3298 args[i + i] = args[i]; | 3399 args0[i + i] = args0[i]; |
3299 | 3400 |
3300 for (i = 1; i < nargs; i += 2) | 3401 for (i = 1; i < nargs0; i += 2) |
3301 args[i] = separator; | 3402 args0[i] = separator; |
3302 | 3403 |
3303 return Fconcat (nargs, args); | 3404 return Fconcat (nargs0, args0); |
3304 } | 3405 } |
3305 | 3406 |
3306 DEFUN ("mapcar", Fmapcar, 2, 2, 0, /* | 3407 DEFUN ("mapcar*", FmapcarX, 2, MANY, 0, /* |
3307 Apply FUNCTION to each element of SEQUENCE; return a list of the results. | 3408 Call FUNCTION on each element of SEQUENCE; return a list of the results. |
3308 The result is a list of the same length as SEQUENCE. | 3409 The result is a list of the same length as SEQUENCE. |
3309 SEQUENCE may be a list, a vector, a bit vector, or a string. | 3410 SEQUENCE may be a list, a vector, a bit vector, or a string. |
3310 */ | 3411 |
3311 (function, sequence)) | 3412 With optional SEQUENCES, call FUNCTION each time with as many arguments as |
3312 { | 3413 there are SEQUENCES, plus one for the element from SEQUENCE. One element |
3313 Elemcount len = XINT (Flength (sequence)); | 3414 from each sequence will be used each time FUNCTION is called, and `mapcar' |
3314 Lisp_Object *args = alloca_array (Lisp_Object, len); | 3415 stops calling FUNCTION once the shortest sequence is exhausted. |
3315 | 3416 |
3316 mapcar1 (len, args, function, sequence); | 3417 arguments: (FUNCTION SEQUENCE &rest SEQUENCES) |
3317 | 3418 */ |
3318 return Flist ((int) len, args); | 3419 (int nargs, Lisp_Object *args)) |
3319 } | 3420 { |
3320 | 3421 Lisp_Object function = args[0]; |
3321 DEFUN ("mapvector", Fmapvector, 2, 2, 0, /* | 3422 Elemcount len = EMACS_INT_MAX; |
3322 Apply FUNCTION to each element of SEQUENCE; return a vector of the results. | 3423 Lisp_Object *args0; |
3424 int i; | |
3425 | |
3426 for (i = 1; i < nargs; ++i) | |
3427 { | |
3428 CHECK_SEQUENCE (args[i]); | |
3429 len = min (len, XINT (Flength (args[i]))); | |
3430 } | |
3431 | |
3432 args0 = alloca_array (Lisp_Object, len); | |
3433 mapcarX (len, args0, Qnil, function, nargs - 1, args + 1); | |
3434 | |
3435 return Flist ((int) len, args0); | |
3436 } | |
3437 | |
3438 DEFUN ("mapvector", Fmapvector, 2, MANY, 0, /* | |
3439 Call FUNCTION on each element of SEQUENCE; return a vector of the results. | |
3323 The result is a vector of the same length as SEQUENCE. | 3440 The result is a vector of the same length as SEQUENCE. |
3324 SEQUENCE may be a list, a vector, a bit vector, or a string. | 3441 SEQUENCE may be a list, a vector, a bit vector, or a string. |
3325 */ | 3442 |
3326 (function, sequence)) | 3443 With optional SEQUENCES, call FUNCTION each time with as many arguments as |
3327 { | 3444 there are SEQUENCES, plus one for the element from SEQUENCE. One element |
3328 Elemcount len = XINT (Flength (sequence)); | 3445 from each sequence will be used each time FUNCTION is called, and |
3329 Lisp_Object result = make_vector (len, Qnil); | 3446 `mapvector' stops calling FUNCTION once the shortest sequence is exhausted. |
3447 | |
3448 arguments: (FUNCTION SEQUENCE &rest SEQUENCES) | |
3449 */ | |
3450 (int nargs, Lisp_Object *args)) | |
3451 { | |
3452 Lisp_Object function = args[0]; | |
3453 Elemcount len = EMACS_INT_MAX; | |
3454 Lisp_Object result; | |
3330 struct gcpro gcpro1; | 3455 struct gcpro gcpro1; |
3331 | 3456 int i; |
3457 | |
3458 for (i = 1; i < nargs; ++i) | |
3459 { | |
3460 CHECK_SEQUENCE (args[i]); | |
3461 len = min (len, XINT (Flength (args[i]))); | |
3462 } | |
3463 | |
3464 result = make_vector (len, Qnil); | |
3332 GCPRO1 (result); | 3465 GCPRO1 (result); |
3333 mapcar1 (len, XVECTOR_DATA (result), function, sequence); | 3466 /* Don't pass result as the lisp_object argument, we want mapcarX to protect |
3467 a single list argument's elements from being garbage-collected. */ | |
3468 mapcarX (len, XVECTOR_DATA (result), Qnil, function, nargs - 1, args +1); | |
3334 UNGCPRO; | 3469 UNGCPRO; |
3335 | 3470 |
3336 return result; | 3471 return result; |
3337 } | 3472 } |
3338 | 3473 |
3339 DEFUN ("mapc-internal", Fmapc_internal, 2, 2, 0, /* | 3474 DEFUN ("mapcan", Fmapcan, 2, MANY, 0, /* |
3340 Apply FUNCTION to each element of SEQUENCE. | 3475 Call FUNCTION on each element of SEQUENCE; chain the results together. |
3476 | |
3477 FUNCTION must normally return a list; the results will be concatenated | |
3478 together using `nconc'. | |
3479 | |
3480 With optional SEQUENCES, call FUNCTION each time with as many arguments as | |
3481 there are SEQUENCES, plus one for the element from SEQUENCE. One element | |
3482 from each sequence will be used each time FUNCTION is called, and | |
3483 `mapcan' stops calling FUNCTION once the shortest sequence is exhausted. | |
3484 | |
3485 arguments: (FUNCTION SEQUENCE &rest SEQUENCES) | |
3486 */ | |
3487 (int nargs, Lisp_Object *args)) | |
3488 { | |
3489 Lisp_Object function = args[0], nconcing; | |
3490 Elemcount len = EMACS_INT_MAX; | |
3491 Lisp_Object *args0; | |
3492 struct gcpro gcpro1; | |
3493 int i; | |
3494 | |
3495 for (i = 1; i < nargs; ++i) | |
3496 { | |
3497 CHECK_SEQUENCE (args[i]); | |
3498 len = min (len, XINT (Flength (args[i]))); | |
3499 } | |
3500 | |
3501 args0 = alloca_array (Lisp_Object, len + 1); | |
3502 mapcarX (len, args0 + 1, Qnil, function, nargs - 1, args + 1); | |
3503 | |
3504 if (len < 2) | |
3505 { | |
3506 return len ? args0[1] : Qnil; | |
3507 } | |
3508 | |
3509 /* bytecode_nconc2 can signal and return, we need to GCPRO the args, since | |
3510 mapcarX is no longer doing this for us. */ | |
3511 args0[0] = Fcons (Qnil, Qnil); | |
3512 GCPRO1 (args0[0]); | |
3513 gcpro1.nvars = len + 1; | |
3514 | |
3515 for (i = 0; i < len; ++i) | |
3516 { | |
3517 nconcing = bytecode_nconc2 (args0 + i); | |
3518 args0[i + 1] = nconcing; | |
3519 } | |
3520 | |
3521 RETURN_UNGCPRO (XCDR (nconcing)); | |
3522 } | |
3523 | |
3524 DEFUN ("mapc", Fmapc, 2, MANY, 0, /* | |
3525 Call FUNCTION on each element of SEQUENCE. | |
3526 | |
3341 SEQUENCE may be a list, a vector, a bit vector, or a string. | 3527 SEQUENCE may be a list, a vector, a bit vector, or a string. |
3342 This function is like `mapcar' but does not accumulate the results, | 3528 This function is like `mapcar' but does not accumulate the results, |
3343 which is more efficient if you do not use the results. | 3529 which is more efficient if you do not use the results. |
3344 | 3530 |
3345 The difference between this and `mapc' is that `mapc' supports all | 3531 With optional SEQUENCES, call FUNCTION each time with as many arguments as |
3346 the spiffy Common Lisp arguments. You should normally use `mapc'. | 3532 there are SEQUENCES, plus one for the elements from SEQUENCE. One element |
3347 */ | 3533 from each sequence will be used each time FUNCTION is called, and |
3348 (function, sequence)) | 3534 `mapc' stops calling FUNCTION once the shortest sequence is exhausted. |
3349 { | 3535 |
3350 mapcar1 (XINT (Flength (sequence)), 0, function, sequence); | 3536 Return SEQUENCE. |
3351 | 3537 |
3352 return sequence; | 3538 arguments: (FUNCTION SEQUENCE &rest SEQUENCES) |
3353 } | 3539 */ |
3354 | 3540 (int nargs, Lisp_Object *args)) |
3541 { | |
3542 Elemcount len = EMACS_INT_MAX; | |
3543 Lisp_Object sequence = args[1]; | |
3544 struct gcpro gcpro1; | |
3545 int i; | |
3546 | |
3547 for (i = 1; i < nargs; ++i) | |
3548 { | |
3549 CHECK_SEQUENCE (args[i]); | |
3550 len = min (len, XINT (Flength (args[i]))); | |
3551 } | |
3552 | |
3553 /* We need to GCPRO sequence, because mapcarX will modify the | |
3554 elements of the args array handed to it, and this may involve | |
3555 elements of sequence getting garbage collected. */ | |
3556 GCPRO1 (sequence); | |
3557 mapcarX (len, NULL, Qnil, args[0], nargs - 1, args + 1); | |
3558 RETURN_UNGCPRO (sequence); | |
3559 } | |
3560 | |
3561 DEFUN ("map", Fmap, 3, MANY, 0, /* | |
3562 Map FUNCTION across one or more sequences, returning a sequence. | |
3563 | |
3564 TYPE is the sequence type to return, FUNCTION is the function, SEQUENCE is | |
3565 the first argument sequence, SEQUENCES are the other argument sequences. | |
3566 | |
3567 FUNCTION will be called with (1+ (length SEQUENCES)) arguments, and must be | |
3568 capable of accepting this number of arguments. | |
3569 | |
3570 Certain TYPEs are recognised internally by `map', but others are not, and | |
3571 `coerce' may throw an error on an attempt to convert to a TYPE it does not | |
3572 understand. A null TYPE means do not accumulate any values. | |
3573 | |
3574 arguments: (TYPE FUNCTION SEQUENCE &rest SEQUENCES) | |
3575 */ | |
3576 (int nargs, Lisp_Object *args)) | |
3577 { | |
3578 Lisp_Object type = args[0]; | |
3579 Lisp_Object function = args[1]; | |
3580 Lisp_Object result = Qnil; | |
3581 Lisp_Object *args0 = NULL; | |
3582 Elemcount len = EMACS_INT_MAX; | |
3583 int i; | |
3584 struct gcpro gcpro1; | |
3585 | |
3586 for (i = 2; i < nargs; ++i) | |
3587 { | |
3588 CHECK_SEQUENCE (args[i]); | |
3589 len = min (len, XINT (Flength (args[i]))); | |
3590 } | |
3591 | |
3592 if (!NILP (type)) | |
3593 { | |
3594 args0 = alloca_array (Lisp_Object, len); | |
3595 } | |
3596 | |
3597 mapcarX (len, args0, Qnil, function, nargs - 2, args + 2); | |
3598 | |
3599 if (EQ (type, Qnil)) | |
3600 { | |
3601 return result; | |
3602 } | |
3603 | |
3604 if (EQ (type, Qvector) || EQ (type, Qarray)) | |
3605 { | |
3606 result = Fvector (len, args0); | |
3607 } | |
3608 else if (EQ (type, Qstring)) | |
3609 { | |
3610 result = Fstring (len, args0); | |
3611 } | |
3612 else if (EQ (type, Qlist)) | |
3613 { | |
3614 result = Flist (len, args0); | |
3615 } | |
3616 else if (EQ (type, Qbit_vector)) | |
3617 { | |
3618 result = Fbit_vector (len, args0); | |
3619 } | |
3620 else | |
3621 { | |
3622 result = Flist (len, args0); | |
3623 GCPRO1 (result); | |
3624 result = call2 (Qcoerce, result, type); | |
3625 UNGCPRO; | |
3626 } | |
3627 | |
3628 return result; | |
3629 } | |
3630 | |
3631 DEFUN ("map-into", Fmap_into, 2, MANY, 0, /* | |
3632 Modify RESULT-SEQUENCE using the return values of FUNCTION on SEQUENCES. | |
3633 | |
3634 RESULT-SEQUENCE and SEQUENCES can be lists or arrays. | |
3635 | |
3636 FUNCTION must accept at least as many arguments as there are SEQUENCES | |
3637 \(possibly zero). If RESULT-SEQUENCE and the elements of SEQUENCES are not | |
3638 the same length, stop when the shortest is exhausted; any elements of | |
3639 RESULT-SEQUENCE beyond that are unmodified. | |
3640 | |
3641 Return RESULT-SEQUENCE. | |
3642 | |
3643 arguments: (RESULT-SEQUENCE FUNCTION &rest SEQUENCES) | |
3644 */ | |
3645 (int nargs, Lisp_Object *args)) | |
3646 { | |
3647 Elemcount len = EMACS_INT_MAX; | |
3648 Lisp_Object result_sequence = args[0]; | |
3649 Lisp_Object function = args[1]; | |
3650 int i; | |
3651 | |
3652 args[0] = function; | |
3653 args[1] = result_sequence; | |
3654 | |
3655 for (i = 1; i < nargs; ++i) | |
3656 { | |
3657 CHECK_SEQUENCE (args[i]); | |
3658 len = min (len, XINT (Flength (args[i]))); | |
3659 } | |
3660 | |
3661 mapcarX (len, NULL, result_sequence, function, nargs - 2, args + 2); | |
3662 | |
3663 return result_sequence; | |
3664 } | |
3665 | |
3666 /* Call FUNCTION with NLISTS arguments repeatedly, each Nth argument | |
3667 corresponding to the result of calling (nthcdr ITERATION-COUNT LISTS[N]), | |
3668 until that #'nthcdr expression gives nil for some element of LISTS. | |
3669 | |
3670 If MAPLP is zero, return LISTS[0]. Otherwise, return a list of the return | |
3671 values from FUNCTION; if NCONCP is non-zero, nconc them together. | |
3672 | |
3673 In contrast to mapcarX, we don't require our callers to check LISTS for | |
3674 well-formedness, we signal wrong-type-argument if it's not a list, or | |
3675 circular-list if it's circular. */ | |
3676 | |
3677 static Lisp_Object | |
3678 maplist (Lisp_Object function, int nlists, Lisp_Object *lists, int maplp, | |
3679 int nconcp) | |
3680 { | |
3681 Lisp_Object result = maplp ? lists[0] : Fcons (Qnil, Qnil), funcalled; | |
3682 Lisp_Object nconcing[2], accum = result, *args; | |
3683 struct gcpro gcpro1, gcpro2, gcpro3; | |
3684 int i, j, continuing = (nlists > 0), called_count = 0; | |
3685 | |
3686 args = alloca_array (Lisp_Object, nlists + 1); | |
3687 args[0] = function; | |
3688 for (i = 1; i <= nlists; ++i) | |
3689 { | |
3690 args[i] = Qnil; | |
3691 } | |
3692 | |
3693 if (nconcp) | |
3694 { | |
3695 nconcing[0] = result; | |
3696 nconcing[1] = Qnil; | |
3697 GCPRO3 (args[0], nconcing[0], result); | |
3698 gcpro1.nvars = 1; | |
3699 gcpro2.nvars = 2; | |
3700 } | |
3701 else | |
3702 { | |
3703 GCPRO2 (args[0], result); | |
3704 gcpro1.nvars = 1; | |
3705 } | |
3706 | |
3707 while (continuing) | |
3708 { | |
3709 for (j = 0; j < nlists; ++j) | |
3710 { | |
3711 if (CONSP (lists[j])) | |
3712 { | |
3713 args[j + 1] = lists[j]; | |
3714 lists[j] = XCDR (lists[j]); | |
3715 } | |
3716 else if (NILP (lists[j])) | |
3717 { | |
3718 continuing = 0; | |
3719 break; | |
3720 } | |
3721 else | |
3722 { | |
3723 dead_wrong_type_argument (Qlistp, lists[j]); | |
3724 } | |
3725 } | |
3726 if (!continuing) break; | |
3727 funcalled = Ffuncall (nlists + 1, args); | |
3728 if (!maplp) | |
3729 { | |
3730 if (nconcp) | |
3731 { | |
3732 /* This order of calls means we check that each list is | |
3733 well-formed once and once only. The last result does | |
3734 not have to be a list. */ | |
3735 nconcing[1] = funcalled; | |
3736 nconcing[0] = bytecode_nconc2 (nconcing); | |
3737 } | |
3738 else | |
3739 { | |
3740 /* Add to the end, avoiding the need to call nreverse | |
3741 once we're done: */ | |
3742 XSETCDR (accum, Fcons (funcalled, Qnil)); | |
3743 accum = XCDR (accum); | |
3744 } | |
3745 } | |
3746 | |
3747 if (++called_count % CIRCULAR_LIST_SUSPICION_LENGTH) continue; | |
3748 | |
3749 for (j = 0; j < nlists; ++j) | |
3750 { | |
3751 EXTERNAL_LIST_LOOP_1 (lists[j]) | |
3752 { | |
3753 /* Just check the lists aren't circular, using the | |
3754 EXTERNAL_LIST_LOOP_1 macro. */ | |
3755 } | |
3756 } | |
3757 } | |
3758 | |
3759 if (!maplp) | |
3760 { | |
3761 result = XCDR (result); | |
3762 } | |
3763 | |
3764 RETURN_UNGCPRO (result); | |
3765 } | |
3766 | |
3767 DEFUN ("maplist", Fmaplist, 2, MANY, 0, /* | |
3768 Call FUNCTION on each sublist of LIST and LISTS. | |
3769 Like `mapcar', except applies to lists and their cdr's rather than to | |
3770 the elements themselves." | |
3771 | |
3772 arguments: (FUNCTION LIST &rest LISTS) | |
3773 */ | |
3774 (int nargs, Lisp_Object *args)) | |
3775 { | |
3776 return maplist (args[0], nargs - 1, args + 1, 0, 0); | |
3777 } | |
3778 | |
3779 DEFUN ("mapl", Fmapl, 2, MANY, 0, /* | |
3780 Like `maplist', but do not accumulate values returned by the function. | |
3781 | |
3782 arguments: (FUNCTION LIST &rest LISTS) | |
3783 */ | |
3784 (int nargs, Lisp_Object *args)) | |
3785 { | |
3786 return maplist (args[0], nargs - 1, args + 1, 1, 0); | |
3787 } | |
3788 | |
3789 DEFUN ("mapcon", Fmapcon, 2, MANY, 0, /* | |
3790 Like `maplist', but chains together the values returned by FUNCTION. | |
3791 | |
3792 FUNCTION must return a list (unless it happens to be the last | |
3793 iteration); the results will be concatenated together using `nconc'. | |
3794 | |
3795 arguments: (FUNCTION LIST &rest LISTS) | |
3796 */ | |
3797 (int nargs, Lisp_Object *args)) | |
3798 { | |
3799 return maplist (args[0], nargs - 1, args + 1, 0, 1); | |
3800 } | |
3355 | 3801 |
3356 /* Extra random functions */ | 3802 /* Extra random functions */ |
3357 | 3803 |
3358 DEFUN ("replace-list", Freplace_list, 2, 2, 0, /* | 3804 DEFUN ("replace-list", Freplace_list, 2, 2, 0, /* |
3359 Destructively replace the list OLD with NEW. | 3805 Destructively replace the list OLD with NEW. |
3393 old = Qnil; | 3839 old = Qnil; |
3394 | 3840 |
3395 return old; | 3841 return old; |
3396 } | 3842 } |
3397 | 3843 |
3844 | |
3398 Lisp_Object | 3845 Lisp_Object |
3399 add_suffix_to_symbol (Lisp_Object symbol, const Ascbyte *ascii_string) | 3846 add_suffix_to_symbol (Lisp_Object symbol, const Ascbyte *ascii_string) |
3400 { | 3847 { |
3401 return Fintern (concat2 (Fsymbol_name (symbol), | 3848 return Fintern (concat2 (Fsymbol_name (symbol), |
3402 build_string (ascii_string)), | 3849 build_string (ascii_string)), |
4031 { | 4478 { |
4032 INIT_LRECORD_IMPLEMENTATION (bit_vector); | 4479 INIT_LRECORD_IMPLEMENTATION (bit_vector); |
4033 | 4480 |
4034 DEFSYMBOL (Qstring_lessp); | 4481 DEFSYMBOL (Qstring_lessp); |
4035 DEFSYMBOL (Qidentity); | 4482 DEFSYMBOL (Qidentity); |
4483 DEFSYMBOL (Qvector); | |
4484 DEFSYMBOL (Qarray); | |
4485 DEFSYMBOL (Qstring); | |
4486 DEFSYMBOL (Qlist); | |
4487 DEFSYMBOL (Qbit_vector); | |
4488 | |
4036 DEFSYMBOL (Qyes_or_no_p); | 4489 DEFSYMBOL (Qyes_or_no_p); |
4037 | 4490 |
4038 DEFERROR_STANDARD (Qbase64_conversion_error, Qconversion_error); | 4491 DEFERROR_STANDARD (Qbase64_conversion_error, Qconversion_error); |
4039 | 4492 |
4040 DEFSUBR (Fidentity); | 4493 DEFSUBR (Fidentity); |
4107 DEFSUBR (Fobject_plist); | 4560 DEFSUBR (Fobject_plist); |
4108 DEFSUBR (Fequal); | 4561 DEFSUBR (Fequal); |
4109 DEFSUBR (Fold_equal); | 4562 DEFSUBR (Fold_equal); |
4110 DEFSUBR (Ffillarray); | 4563 DEFSUBR (Ffillarray); |
4111 DEFSUBR (Fnconc); | 4564 DEFSUBR (Fnconc); |
4112 DEFSUBR (Fmapcar); | 4565 DEFSUBR (FmapcarX); |
4113 DEFSUBR (Fmapvector); | 4566 DEFSUBR (Fmapvector); |
4114 DEFSUBR (Fmapc_internal); | 4567 DEFSUBR (Fmapcan); |
4568 DEFSUBR (Fmapc); | |
4115 DEFSUBR (Fmapconcat); | 4569 DEFSUBR (Fmapconcat); |
4570 DEFSUBR (Fmap); | |
4571 DEFSUBR (Fmap_into); | |
4572 Ffset (intern ("mapc-internal"), Fsymbol_function (intern ("mapc"))); | |
4573 Ffset (intern ("mapcar"), Fsymbol_function (intern ("mapcar*"))); | |
4574 DEFSUBR (Fmaplist); | |
4575 DEFSUBR (Fmapl); | |
4576 DEFSUBR (Fmapcon); | |
4577 | |
4116 DEFSUBR (Freplace_list); | 4578 DEFSUBR (Freplace_list); |
4117 DEFSUBR (Fload_average); | 4579 DEFSUBR (Fload_average); |
4118 DEFSUBR (Ffeaturep); | 4580 DEFSUBR (Ffeaturep); |
4119 DEFSUBR (Frequire); | 4581 DEFSUBR (Frequire); |
4120 DEFSUBR (Fprovide); | 4582 DEFSUBR (Fprovide); |