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)