Mercurial > hg > xemacs-beta
comparison src/fns.c @ 5300:9f738305f80f
Accept sequences generally, not just lists, #'reverse, #'nreverse.
src/ChangeLog addition:
2010-11-06 Aidan Kehoe <kehoea@parhasard.net>
* bytecode.c (bytecode_nreverse): Call Fnreverse() if SEQUENCE is
not a cons in this function.
(Fnreverse, Freverse):
Accept sequences, not just lists, in these functions.
man/ChangeLog addition:
2010-11-06 Aidan Kehoe <kehoea@parhasard.net>
* lispref/lists.texi (Rearrangement, Building Lists):
Document that #'nreverse and #'reverse now accept sequences, not
just lists, in this file.
tests/ChangeLog addition:
2010-11-06 Aidan Kehoe <kehoea@parhasard.net>
* automated/lisp-tests.el (list-nreverse):
Check that #'reverse and #'nreverse handle non-list sequences
properly.
author | Aidan Kehoe <kehoea@parhasard.net> |
---|---|
date | Sat, 06 Nov 2010 21:18:52 +0000 |
parents | 28651c24b3f8 |
children | 6468cf6f0b9d 46491edfd94a |
comparison
equal
deleted
inserted
replaced
5299:28651c24b3f8 | 5300:9f738305f80f |
---|---|
2090 EQ_WITH_EBOLA_NOTICE (value, XCDR (elt)))); | 2090 EQ_WITH_EBOLA_NOTICE (value, XCDR (elt)))); |
2091 return alist; | 2091 return alist; |
2092 } | 2092 } |
2093 | 2093 |
2094 DEFUN ("nreverse", Fnreverse, 1, 1, 0, /* | 2094 DEFUN ("nreverse", Fnreverse, 1, 1, 0, /* |
2095 Reverse LIST by destructively modifying cdr pointers. | 2095 Reverse SEQUENCE, destructively. |
2096 Return the beginning of the reversed list. | 2096 |
2097 Also see: `reverse'. | 2097 Return the beginning of the reversed sequence, which will be a distinct Lisp |
2098 */ | 2098 object if SEQUENCE is a list with length greater than one. See also |
2099 (list)) | 2099 `reverse', the non-destructive version of this function. |
2100 { | 2100 */ |
2101 struct gcpro gcpro1, gcpro2; | 2101 (sequence)) |
2102 Lisp_Object prev = Qnil; | 2102 { |
2103 Lisp_Object tail = list; | 2103 CHECK_SEQUENCE (sequence); |
2104 | 2104 |
2105 /* We gcpro our args; see `nconc' */ | 2105 if (CONSP (sequence)) |
2106 GCPRO2 (prev, tail); | 2106 { |
2107 while (!NILP (tail)) | 2107 struct gcpro gcpro1, gcpro2; |
2108 { | 2108 Lisp_Object prev = Qnil; |
2109 REGISTER Lisp_Object next; | 2109 Lisp_Object tail = sequence; |
2110 CONCHECK_CONS (tail); | 2110 |
2111 next = XCDR (tail); | 2111 /* We gcpro our args; see `nconc' */ |
2112 XCDR (tail) = prev; | 2112 GCPRO2 (prev, tail); |
2113 prev = tail; | 2113 while (!NILP (tail)) |
2114 tail = next; | 2114 { |
2115 } | 2115 REGISTER Lisp_Object next; |
2116 UNGCPRO; | 2116 CONCHECK_CONS (tail); |
2117 return prev; | 2117 next = XCDR (tail); |
2118 XCDR (tail) = prev; | |
2119 prev = tail; | |
2120 tail = next; | |
2121 } | |
2122 UNGCPRO; | |
2123 return prev; | |
2124 } | |
2125 else if (VECTORP (sequence)) | |
2126 { | |
2127 Elemcount length = XVECTOR_LENGTH (sequence), ii = length; | |
2128 Elemcount half = length / 2; | |
2129 Lisp_Object swap = Qnil; | |
2130 | |
2131 while (ii > half) | |
2132 { | |
2133 swap = XVECTOR_DATA (sequence) [length - ii]; | |
2134 XVECTOR_DATA (sequence) [length - ii] | |
2135 = XVECTOR_DATA (sequence) [ii - 1]; | |
2136 XVECTOR_DATA (sequence) [ii - 1] = swap; | |
2137 --ii; | |
2138 } | |
2139 } | |
2140 else if (STRINGP (sequence)) | |
2141 { | |
2142 Elemcount length = XSTRING_LENGTH (sequence); | |
2143 Ibyte *staging = alloca_ibytes (length), *staging_end = staging + length; | |
2144 Ibyte *cursor = XSTRING_DATA (sequence), *endp = cursor + length; | |
2145 | |
2146 while (cursor < endp) | |
2147 { | |
2148 staging_end -= itext_ichar_len (cursor); | |
2149 itext_copy_ichar (cursor, staging_end); | |
2150 INC_IBYTEPTR (cursor); | |
2151 } | |
2152 | |
2153 assert (staging == staging_end); | |
2154 | |
2155 memcpy (XSTRING_DATA (sequence), staging, length); | |
2156 init_string_ascii_begin (sequence); | |
2157 bump_string_modiff (sequence); | |
2158 sledgehammer_check_ascii_begin (sequence); | |
2159 } | |
2160 else if (BIT_VECTORP (sequence)) | |
2161 { | |
2162 Lisp_Bit_Vector *bv = XBIT_VECTOR (sequence); | |
2163 Elemcount length = bit_vector_length (bv), ii = length; | |
2164 Elemcount half = length / 2; | |
2165 int swap = 0; | |
2166 | |
2167 while (ii > half) | |
2168 { | |
2169 swap = bit_vector_bit (bv, length - ii); | |
2170 set_bit_vector_bit (bv, length - ii, bit_vector_bit (bv, ii - 1)); | |
2171 set_bit_vector_bit (bv, ii - 1, swap); | |
2172 --ii; | |
2173 } | |
2174 } | |
2175 else | |
2176 { | |
2177 assert (NILP (sequence)); | |
2178 } | |
2179 | |
2180 return sequence; | |
2118 } | 2181 } |
2119 | 2182 |
2120 DEFUN ("reverse", Freverse, 1, 1, 0, /* | 2183 DEFUN ("reverse", Freverse, 1, 1, 0, /* |
2121 Reverse LIST, copying. Return the beginning of the reversed list. | 2184 Reverse SEQUENCE, copying. Return the reversed sequence. |
2122 See also the function `nreverse', which is used more often. | 2185 See also the function `nreverse', which is used more often. |
2123 */ | 2186 */ |
2124 (list)) | 2187 (sequence)) |
2125 { | 2188 { |
2126 Lisp_Object reversed_list = Qnil; | 2189 Lisp_Object result = Qnil; |
2127 EXTERNAL_LIST_LOOP_2 (elt, list) | 2190 |
2128 { | 2191 CHECK_SEQUENCE (sequence); |
2129 reversed_list = Fcons (elt, reversed_list); | 2192 |
2130 } | 2193 if (CONSP (sequence)) |
2131 return reversed_list; | 2194 { |
2195 EXTERNAL_LIST_LOOP_2 (elt, sequence) | |
2196 { | |
2197 result = Fcons (elt, result); | |
2198 } | |
2199 } | |
2200 else if (VECTORP (sequence)) | |
2201 { | |
2202 Elemcount length = XVECTOR_LENGTH (sequence), ii = length; | |
2203 Lisp_Object *staging = alloca_array (Lisp_Object, length); | |
2204 | |
2205 while (ii > 0) | |
2206 { | |
2207 staging[length - ii] = XVECTOR_DATA (sequence) [ii - 1]; | |
2208 --ii; | |
2209 } | |
2210 | |
2211 result = Fvector (length, staging); | |
2212 } | |
2213 else if (STRINGP (sequence)) | |
2214 { | |
2215 Elemcount length = XSTRING_LENGTH (sequence); | |
2216 Ibyte *staging = alloca_ibytes (length), *staging_end = staging + length; | |
2217 Ibyte *cursor = XSTRING_DATA (sequence), *endp = cursor + length; | |
2218 | |
2219 while (cursor < endp) | |
2220 { | |
2221 staging_end -= itext_ichar_len (cursor); | |
2222 itext_copy_ichar (cursor, staging_end); | |
2223 INC_IBYTEPTR (cursor); | |
2224 } | |
2225 | |
2226 assert (staging == staging_end); | |
2227 | |
2228 result = make_string (staging, length); | |
2229 } | |
2230 else if (BIT_VECTORP (sequence)) | |
2231 { | |
2232 Lisp_Bit_Vector *bv = XBIT_VECTOR (sequence), *res; | |
2233 Elemcount length = bit_vector_length (bv), ii = length; | |
2234 | |
2235 result = make_bit_vector (length, Qzero); | |
2236 res = XBIT_VECTOR (result); | |
2237 | |
2238 while (ii > 0) | |
2239 { | |
2240 set_bit_vector_bit (res, length - ii, bit_vector_bit (bv, ii - 1)); | |
2241 --ii; | |
2242 } | |
2243 } | |
2244 else | |
2245 { | |
2246 assert (NILP (sequence)); | |
2247 } | |
2248 | |
2249 return result; | |
2132 } | 2250 } |
2133 | 2251 |
2134 static Lisp_Object | 2252 static Lisp_Object |
2135 c_merge_predicate_key (Lisp_Object obj1, Lisp_Object obj2, | 2253 c_merge_predicate_key (Lisp_Object obj1, Lisp_Object obj2, |
2136 Lisp_Object pred, Lisp_Object key_func) | 2254 Lisp_Object pred, Lisp_Object key_func) |