1
/*===========================================================================
3
* About : R5SR pairs and lists
5
* Copyright (C) 2005-2006 Kazuki Ohta <mover AT hct.zaq.ne.jp>
9
* Redistribution and use in source and binary forms, with or without
10
* modification, are permitted provided that the following conditions
13
* 1. Redistributions of source code must retain the above copyright
14
* notice, this list of conditions and the following disclaimer.
15
* 2. Redistributions in binary form must reproduce the above copyright
16
* notice, this list of conditions and the following disclaimer in the
17
* documentation and/or other materials provided with the distribution.
18
* 3. Neither the name of authors nor the names of its contributors
19
* may be used to endorse or promote products derived from this software
20
* without specific prior written permission.
22
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
23
* IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
24
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
26
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
29
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
===========================================================================*/
37
/*=======================================
39
=======================================*/
41
/*=======================================
43
=======================================*/
44
#include "sigscheme.h"
45
#include "sigschemeinternal.h"
47
/*=======================================
48
File Local Struct Declarations
49
=======================================*/
51
/*=======================================
52
File Local Macro Declarations
53
=======================================*/
55
/*=======================================
57
=======================================*/
59
/*=======================================
60
File Local Function Declarations
61
=======================================*/
62
static ScmObj list_tail(ScmObj lst, scm_int_t k);
64
/*=======================================
65
Function Implementations
66
=======================================*/
67
/*===========================================================================
68
R5RS : 6.3 Other data types : 6.3.2 Pairs and lists
69
===========================================================================*/
73
DECLARE_FUNCTION("car", procedure_fixed_1);
74
#if SCM_COMPAT_SIOD_BUGS
87
DECLARE_FUNCTION("cdr", procedure_fixed_1);
88
#if SCM_COMPAT_SIOD_BUGS
99
scm_p_pairp(ScmObj obj)
101
DECLARE_FUNCTION("pair?", procedure_fixed_1);
103
return MAKE_BOOL(CONSP(obj));
107
scm_p_cons(ScmObj car, ScmObj cdr)
109
DECLARE_FUNCTION("cons", procedure_fixed_2);
111
return CONS(car, cdr);
115
scm_p_set_card(ScmObj pair, ScmObj car)
117
DECLARE_FUNCTION("set-car!", procedure_fixed_2);
120
ENSURE_MUTABLE_CONS(pair);
132
scm_p_set_cdrd(ScmObj pair, ScmObj cdr)
134
DECLARE_FUNCTION("set-cdr!", procedure_fixed_2);
137
ENSURE_MUTABLE_CONS(pair);
149
scm_p_caar(ScmObj lst)
151
DECLARE_FUNCTION("caar", procedure_fixed_1);
153
return scm_p_car( scm_p_car(lst) );
157
scm_p_cadr(ScmObj lst)
159
DECLARE_FUNCTION("cadr", procedure_fixed_1);
161
return scm_p_car( scm_p_cdr(lst) );
165
scm_p_cdar(ScmObj lst)
167
DECLARE_FUNCTION("cdar", procedure_fixed_1);
169
return scm_p_cdr( scm_p_car(lst) );
173
scm_p_cddr(ScmObj lst)
175
DECLARE_FUNCTION("cddr", procedure_fixed_1);
177
return scm_p_cdr( scm_p_cdr(lst) );
181
scm_p_caddr(ScmObj lst)
183
DECLARE_FUNCTION("caddr", procedure_fixed_1);
185
return scm_p_car( scm_p_cdr( scm_p_cdr(lst) ));
189
scm_p_cdddr(ScmObj lst)
191
DECLARE_FUNCTION("cdddr", procedure_fixed_1);
193
return scm_p_cdr( scm_p_cdr( scm_p_cdr(lst) ));
197
scm_p_list(ScmObj args)
199
DECLARE_FUNCTION("list", procedure_variadic_0);
205
scm_p_nullp(ScmObj obj)
207
DECLARE_FUNCTION("null?", procedure_fixed_1);
209
return MAKE_BOOL(NULLP(obj));
213
scm_p_listp(ScmObj obj)
215
DECLARE_FUNCTION("list?", procedure_fixed_1);
223
return MAKE_BOOL(PROPER_LISTP(obj));
226
#define TERMINATOR_LEN 1
228
/* scm_length() for non-circular list */
230
scm_finite_length(ScmObj lst)
234
for (len = 0; CONSP(lst); lst = CDR(lst))
240
return SCM_LISTLEN_ENCODE_DOTTED(len + TERMINATOR_LEN);
246
* This function is ported from Gauche, by Shiro Kawai(shiro@acm.org)
248
/* FIXME: Insert its copyright and license into this file properly */
252
* 2006-01-05 YamaKen Return dot list length and circular indication.
255
/* Returns -1 as one length improper list for non-list obj. */
257
scm_length(ScmObj lst)
260
scm_int_t proper_len;
262
for (proper_len = 0, slow = lst;;) {
263
if (NULLP(lst)) break;
265
return SCM_LISTLEN_ENCODE_DOTTED(proper_len + TERMINATOR_LEN);
266
if (proper_len != 0 && lst == slow)
267
return SCM_LISTLEN_ENCODE_CIRCULAR(proper_len);
271
if (NULLP(lst)) break;
273
return SCM_LISTLEN_ENCODE_DOTTED(proper_len + TERMINATOR_LEN);
275
return SCM_LISTLEN_ENCODE_CIRCULAR(proper_len);
285
#undef TERMINATOR_LEN
288
scm_p_length(ScmObj obj)
291
DECLARE_FUNCTION("length", procedure_fixed_1);
293
len = scm_length(obj);
294
if (!SCM_LISTLEN_PROPERP(len))
295
ERR_OBJ("proper list required but got", obj);
297
return MAKE_INT(len);
301
scm_p_append(ScmObj args)
304
ScmObj lst, elm, ret;
305
DECLARE_FUNCTION("append", procedure_variadic_0);
311
SCM_QUEUE_POINT_TO(q, ret);
312
/* duplicate and merge all but the last argument */
313
FOR_EACH_BUTLAST (lst, args) {
315
SCM_QUEUE_ADD(q, elm);
316
ENSURE_PROPER_LIST_TERMINATION(lst, args);
318
/* append the last argument */
319
SCM_QUEUE_SLOPPY_APPEND(q, lst);
325
scm_p_reverse(ScmObj lst)
328
DECLARE_FUNCTION("reverse", procedure_fixed_1);
332
ret = CONS(elm, ret);
338
list_tail(ScmObj lst, scm_int_t k)
350
scm_p_list_tail(ScmObj lst, ScmObj k)
353
DECLARE_FUNCTION("list-tail", procedure_fixed_2);
357
ret = list_tail(lst, SCM_INT_VALUE(k));
359
ERR_OBJ("out of range or invalid list", LIST_2(lst, k));
365
scm_p_list_ref(ScmObj lst, ScmObj k)
368
DECLARE_FUNCTION("list-ref", procedure_fixed_2);
372
tail = list_tail(lst, SCM_INT_VALUE(k));
373
if (!VALIDP(tail) || NULLP(tail))
374
ERR_OBJ("out of range or invalid list", LIST_2(lst, k));
379
#define MEMBER_BODY(obj, lst, cmp) \
381
for (; CONSP(lst); lst = CDR(lst)) \
382
if (cmp(obj, CAR(lst))) \
384
CHECK_PROPER_LIST_TERMINATION(lst, lst); \
386
} while (/* CONSTCOND */ 0)
389
scm_p_memq(ScmObj obj, ScmObj lst)
391
DECLARE_FUNCTION("memq", procedure_fixed_2);
393
MEMBER_BODY(obj, lst, EQ);
397
scm_p_memv(ScmObj obj, ScmObj lst)
399
DECLARE_FUNCTION("memv", procedure_fixed_2);
401
#if (SCM_HAS_IMMEDIATE_NUMBER_ONLY && SCM_HAS_IMMEDIATE_CHAR_ONLY)
402
MEMBER_BODY(obj, lst, EQ);
404
MEMBER_BODY(obj, lst, EQVP);
409
scm_p_member(ScmObj obj, ScmObj lst)
411
DECLARE_FUNCTION("member", procedure_fixed_2);
413
MEMBER_BODY(obj, lst, EQUALP);
418
#define ASSOC_BODY(obj, alist, cmp) \
422
FOR_EACH (pair, alist) { \
428
CHECK_PROPER_LIST_TERMINATION(alist, alist); \
430
} while (/* CONSTCOND */ 0)
433
scm_p_assq(ScmObj obj, ScmObj alist)
435
DECLARE_FUNCTION("assq", procedure_fixed_2);
437
ASSOC_BODY(obj, alist, EQ);
441
scm_p_assv(ScmObj obj, ScmObj alist)
443
DECLARE_FUNCTION("assv", procedure_fixed_2);
445
#if (SCM_HAS_IMMEDIATE_NUMBER_ONLY && SCM_HAS_IMMEDIATE_CHAR_ONLY)
446
ASSOC_BODY(obj, alist, EQ);
448
ASSOC_BODY(obj, alist, EQVP);
453
scm_p_assoc(ScmObj obj, ScmObj alist)
455
DECLARE_FUNCTION("assoc", procedure_fixed_2);
457
ASSOC_BODY(obj, alist, EQUALP);