1
/*===========================================================================
2
* FileName : operations-srfi1.c
3
* About : srfi1 procedures
5
* Copyright (C) 2005 by Kazuki Ohta (mover@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 IS''
23
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
26
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
28
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33
===========================================================================*/
35
/*=======================================
37
=======================================*/
39
/*=======================================
41
=======================================*/
43
/*=======================================
44
File Local Struct Declarations
45
=======================================*/
47
/*=======================================
48
File Local Macro Declarations
49
=======================================*/
51
/*=======================================
53
=======================================*/
55
/*=======================================
56
File Local Function Declarations
57
=======================================*/
58
static ScmObj compare_list(ScmObj eqproc, ScmObj lst1, ScmObj lst2);
60
/*=======================================
61
Function Implementations
62
=======================================*/
63
void SigScm_Initialize_SRFI1(void)
65
/*=======================================================================
67
=======================================================================*/
68
Scm_RegisterProcedureFixed1("list-copy" , ScmOp_SRFI1_list_copy);
69
Scm_RegisterProcedureFixed2("xcons" , ScmOp_SRFI1_xcons);
70
Scm_RegisterProcedureVariadic0("circular-list" , ScmOp_SRFI1_circular_list);
71
Scm_RegisterProcedureVariadic1("iota" , ScmOp_SRFI1_iota);
72
Scm_RegisterProcedureVariadic0("cons*" , ScmOp_SRFI1_cons_star);
73
Scm_RegisterProcedureVariadic1("make-list" , ScmOp_SRFI1_make_list);
74
Scm_RegisterProcedureVariadic1("list-tabulate" , ScmOp_SRFI1_list_tabulate);
75
Scm_RegisterProcedureFixed1("proper-list?" , ScmOp_SRFI1_proper_listp);
76
Scm_RegisterProcedureFixed1("circular-list?" , ScmOp_SRFI1_circular_listp);
77
Scm_RegisterProcedureFixed1("dotted-list?" , ScmOp_SRFI1_dotted_listp);
78
Scm_RegisterProcedureFixed1("not-pair?" , ScmOp_SRFI1_not_pairp);
79
Scm_RegisterProcedureFixed1("null-list?" , ScmOp_SRFI1_null_listp);
80
Scm_RegisterProcedureVariadic1("list=" , ScmOp_SRFI1_listequal);
81
Scm_RegisterProcedureFixed1("first" , ScmOp_SRFI1_first);
82
Scm_RegisterProcedureFixed1("second" , ScmOp_SRFI1_second);
83
Scm_RegisterProcedureFixed1("third" , ScmOp_SRFI1_third);
84
Scm_RegisterProcedureFixed1("fourth" , ScmOp_SRFI1_fourth);
85
Scm_RegisterProcedureFixed1("fifth" , ScmOp_SRFI1_fifth);
86
Scm_RegisterProcedureFixed1("sixth" , ScmOp_SRFI1_sixth);
87
Scm_RegisterProcedureFixed1("seventh" , ScmOp_SRFI1_seventh);
88
Scm_RegisterProcedureFixed1("eighth" , ScmOp_SRFI1_eighth);
89
Scm_RegisterProcedureFixed1("ninth" , ScmOp_SRFI1_ninth);
90
Scm_RegisterProcedureFixed1("tenth" , ScmOp_SRFI1_tenth);
91
Scm_RegisterProcedureFixed2("take" , ScmOp_SRFI1_take);
92
Scm_RegisterProcedureFixed2("drop" , ScmOp_SRFI1_drop);
93
Scm_RegisterProcedureFixed2("take-right" , ScmOp_SRFI1_take_right);
94
Scm_RegisterProcedureFixed2("drop-right" , ScmOp_SRFI1_drop_right);
95
Scm_RegisterProcedureFixed2("take!" , ScmOp_SRFI1_take_d);
96
Scm_RegisterProcedureFixed2("drop-right!" , ScmOp_SRFI1_drop_right_d);
97
Scm_RegisterProcedureFixed2("split-at" , ScmOp_SRFI1_split_at);
98
Scm_RegisterProcedureFixed2("split-at!" , ScmOp_SRFI1_split_at_d);
99
Scm_RegisterProcedureFixed1("last" , ScmOp_SRFI1_last);
100
Scm_RegisterProcedureFixed1("last-pair" , ScmOp_SRFI1_last_pair);
101
Scm_RegisterProcedureFixed1("length+" , ScmOp_SRFI1_lengthplus);
102
Scm_RegisterProcedureVariadic0("concatenate" , ScmOp_SRFI1_concatenate);
105
/*==============================================================================
106
SRFI1 : The procedures : Constructors
107
==============================================================================*/
108
ScmObj ScmOp_SRFI1_xcons(ScmObj a, ScmObj b)
110
DECLARE_FUNCTION("xcons", ProcedureFixed2);
114
ScmObj ScmOp_SRFI1_cons_star(ScmObj args)
116
ScmObj tail_cons = SCM_FALSE;
117
ScmObj prev_last = args;
118
DECLARE_FUNCTION("cons*", ProcedureVariadic0);
120
if (NULLP(CDR(args)))
123
for (tail_cons = CDR(args); !NULLP(tail_cons); tail_cons = CDR(tail_cons)) {
124
/* check tail cons cell */
125
if (NULLP(CDR(tail_cons))) {
126
SET_CDR(prev_last, CAR(tail_cons));
129
prev_last = tail_cons;
135
ScmObj ScmOp_SRFI1_make_list(ScmObj length, ScmObj args)
137
ScmObj filler = SCM_FALSE;
138
ScmObj head = SCM_FALSE;
141
DECLARE_FUNCTION("make-list", ProcedureVariadic1);
145
len = SCM_INT_VALUE(length);
147
/* get filler if available */
153
/* then create list */
154
for (i = len; 0 < i; i--) {
155
head = CONS(filler, head);
161
ScmObj ScmOp_SRFI1_list_tabulate(ScmObj scm_n, ScmObj args)
163
ScmObj proc = SCM_FALSE;
164
ScmObj head = SCM_NULL;
165
ScmObj num = SCM_FALSE;
168
DECLARE_FUNCTION("list-tabulate", ProcedureVariadic1);
173
n = SCM_INT_VALUE(scm_n);
175
/* get init_proc if available */
179
/* then create list */
180
for (i = n; 0 < i; i--) {
181
num = Scm_NewInt(i - 1);
184
num = Scm_call(proc, LIST_1(num));
186
head = CONS(num, head);
192
ScmObj ScmOp_SRFI1_list_copy(ScmObj lst)
194
ScmObj head = SCM_FALSE;
195
ScmObj tail = SCM_FALSE;
196
ScmObj obj = SCM_FALSE;
197
DECLARE_FUNCTION("list-copy", ProcedureFixed1);
199
if (FALSEP(ScmOp_listp(lst)))
200
ERR_OBJ("list required but got ", lst);
202
for (; !NULLP(lst); lst = CDR(lst)) {
207
obj = ScmOp_SRFI1_list_copy(obj);
209
/* then create new cons */
210
obj = CONS(obj, SCM_NULL);
223
ScmObj ScmOp_SRFI1_circular_list(ScmObj args)
225
DECLARE_FUNCTION("circular-list", ProcedureVariadic0);
227
if (FALSEP(ScmOp_listp(args)))
228
ERR_OBJ("list required but got ", args);
230
SET_CDR(ScmOp_SRFI1_last_pair(args), args);
234
ScmObj ScmOp_SRFI1_iota(ScmObj scm_count, ScmObj args)
236
ScmObj scm_start = SCM_FALSE;
237
ScmObj scm_step = SCM_FALSE;
238
ScmObj head = SCM_NULL;
243
DECLARE_FUNCTION("iota", ProcedureVariadic1);
247
scm_start = CAR(args);
249
if (!NULLP(scm_start) && !NULLP(CDR(args)))
250
scm_step = CAR(CDR(args));
252
/* param type check */
253
ASSERT_INTP(scm_count);
254
if (!NULLP(scm_start))
255
ASSERT_INTP(scm_start);
256
if (!NULLP(scm_step))
257
ASSERT_INTP(scm_step);
259
/* now create list */
260
count = SCM_INT_VALUE(scm_count);
261
start = NULLP(scm_start) ? 0 : SCM_INT_VALUE(scm_start);
262
step = NULLP(scm_step) ? 1 : SCM_INT_VALUE(scm_step);
263
for (i = count - 1; 0 <= i; i--) {
264
head = CONS(Scm_NewInt(start + i*step), head);
270
/*==============================================================================
271
SRFI1 : The procedures : Predicates
272
==============================================================================*/
273
ScmObj ScmOp_SRFI1_proper_listp(ScmObj lst)
275
DECLARE_FUNCTION("proper-list?", ProcedureFixed1);
276
return ScmOp_listp(lst);
279
ScmObj ScmOp_SRFI1_circular_listp(ScmObj obj)
283
DECLARE_FUNCTION("circular-list?", ProcedureFixed1);
286
if (NULLP(obj)) break;
287
if (!CONSP(obj)) return SCM_FALSE;
288
if (len != 0 && obj == slow) return SCM_TRUE; /* circular */
292
if (NULLP(obj)) break;
293
if (!CONSP(obj)) return SCM_FALSE;
294
if (obj == slow) return SCM_TRUE; /* circular */
304
ScmObj ScmOp_SRFI1_dotted_listp(ScmObj obj)
308
DECLARE_FUNCTION("dotted-list?", ProcedureFixed1);
311
if (NULLP(obj)) break;
312
if (!CONSP(obj)) return SCM_TRUE;
313
if (len != 0 && obj == slow) return SCM_FALSE; /* circular */
317
if (NULLP(obj)) break;
318
if (!CONSP(obj)) return SCM_TRUE;
319
if (obj == slow) return SCM_FALSE; /* circular */
329
ScmObj ScmOp_SRFI1_not_pairp(ScmObj pair)
331
DECLARE_FUNCTION("not-pari?", ProcedureFixed1);
332
return CONSP(pair) ? SCM_FALSE : SCM_TRUE;
335
ScmObj ScmOp_SRFI1_null_listp(ScmObj lst)
337
DECLARE_FUNCTION("null-list?", ProcedureFixed1);
338
/* TODO : check circular list */
339
return NULLP(lst) ? SCM_TRUE : SCM_FALSE;
342
ScmObj ScmOp_SRFI1_listequal(ScmObj eqproc, ScmObj args)
344
ScmObj first_lst = SCM_FALSE;
345
DECLARE_FUNCTION("list=", ProcedureVariadic1);
350
first_lst = CAR(args);
356
for (; !NULLP(args); args = CDR(args)) {
357
if (FALSEP(compare_list(eqproc, first_lst, CAR(args))))
364
static ScmObj compare_list(ScmObj eqproc, ScmObj lst1, ScmObj lst2)
366
#define CHECK_LIST_EQUALITY_WITH_EQPROC(eqproc, obj1, obj2) \
370
ScmObj ret_cmp = SCM_FALSE;
372
for (; !NULLP(lst1); lst1 = CDR(lst1), lst2 = CDR(lst2)) {
374
ret_cmp = CHECK_LIST_EQUALITY_WITH_EQPROC(eqproc, CAR(lst1), CAR(lst2));
378
/* check next cdr's type */
379
if (SCM_TYPE(CDR(lst1)) != SCM_TYPE(CDR(lst2)))
383
if (!CONSP(CDR(lst1))) {
384
return CHECK_LIST_EQUALITY_WITH_EQPROC(eqproc, CDR(lst1), CDR(lst2));
390
ScmObj ScmOp_SRFI1_first(ScmObj lst)
392
DECLARE_FUNCTION("first", ProcedureFixed1);
393
return ScmOp_car(lst);
396
ScmObj ScmOp_SRFI1_second(ScmObj lst)
398
DECLARE_FUNCTION("second", ProcedureFixed1);
399
return ScmOp_cadr(lst);
402
ScmObj ScmOp_SRFI1_third(ScmObj lst)
404
DECLARE_FUNCTION("third", ProcedureFixed1);
405
return ScmOp_caddr(lst);
408
ScmObj ScmOp_SRFI1_fourth(ScmObj lst)
410
DECLARE_FUNCTION("fourth", ProcedureFixed1);
411
return ScmOp_cadddr(lst);
414
ScmObj ScmOp_SRFI1_fifth(ScmObj lst)
416
DECLARE_FUNCTION("fifth", ProcedureFixed1);
417
return ScmOp_car(ScmOp_cddddr(lst));
420
ScmObj ScmOp_SRFI1_sixth(ScmObj lst)
422
DECLARE_FUNCTION("sixth", ProcedureFixed1);
423
return ScmOp_cadr(ScmOp_cddddr(lst));
426
ScmObj ScmOp_SRFI1_seventh(ScmObj lst)
428
DECLARE_FUNCTION("seventh", ProcedureFixed1);
429
return ScmOp_caddr(ScmOp_cddddr(lst));
432
ScmObj ScmOp_SRFI1_eighth(ScmObj lst)
434
DECLARE_FUNCTION("eighth", ProcedureFixed1);
435
return ScmOp_cadddr(ScmOp_cddddr(lst));
438
ScmObj ScmOp_SRFI1_ninth(ScmObj lst)
440
DECLARE_FUNCTION("ninth", ProcedureFixed1);
441
return ScmOp_car(ScmOp_cddddr(ScmOp_cddddr(lst)));
444
ScmObj ScmOp_SRFI1_tenth(ScmObj lst)
446
DECLARE_FUNCTION("tenth", ProcedureFixed1);
447
return ScmOp_cadr(ScmOp_cddddr(ScmOp_cddddr(lst)));
450
ScmObj ScmOp_SRFI1_carpluscdr(ScmObj lst)
452
DECLARE_FUNCTION("car+cdr", ProcedureFixed1);
453
return ScmOp_values(LIST_2(CAR(lst), CDR(lst)));
456
ScmObj ScmOp_SRFI1_take(ScmObj lst, ScmObj scm_idx)
459
ScmObj ret = SCM_FALSE;
460
ScmObj ret_tail = SCM_FALSE;
463
DECLARE_FUNCTION("take", ProcedureFixed2);
465
ASSERT_INTP(scm_idx);
467
idx = SCM_INT_VALUE(scm_idx);
468
for (i = 0; i < idx; i++) {
470
ERR_OBJ("illegal index is specified for ", lst);
473
SET_CDR(ret_tail, CONS(CAR(tmp), SCM_NULL));
474
ret_tail = CDR(ret_tail);
476
ret = CONS(CAR(tmp), SCM_NULL);
486
ScmObj ScmOp_SRFI1_drop(ScmObj lst, ScmObj scm_idx)
491
DECLARE_FUNCTION("drop", ProcedureFixed2);
493
ASSERT_INTP(scm_idx);
495
idx = SCM_INT_VALUE(scm_idx);
496
for (i = 0; i < idx; i++) {
498
ERR_OBJ("illegal index is specified for ", lst);
506
ScmObj ScmOp_SRFI1_take_right(ScmObj lst, ScmObj scm_elem)
510
DECLARE_FUNCTION("take-right", ProcedureFixed2);
512
ASSERT_INTP(scm_elem);
514
for (; CONSP(tmp); tmp = CDR(tmp))
517
len -= SCM_INT_VALUE(scm_elem);
519
return ScmOp_SRFI1_drop(lst, Scm_NewInt(len));
522
ScmObj ScmOp_SRFI1_drop_right(ScmObj lst, ScmObj scm_elem)
526
DECLARE_FUNCTION("drop-right", ProcedureFixed2);
528
ASSERT_INTP(scm_elem);
530
for (; CONSP(tmp); tmp = CDR(tmp))
533
len -= SCM_INT_VALUE(scm_elem);
535
return ScmOp_SRFI1_take(lst, Scm_NewInt(len));
538
ScmObj ScmOp_SRFI1_take_d(ScmObj lst, ScmObj scm_idx)
543
DECLARE_FUNCTION("take!", ProcedureFixed2);
545
ASSERT_INTP(scm_idx);
547
idx = SCM_INT_VALUE(scm_idx);
549
for (i = 0; i < idx - 1; i++) {
553
SET_CDR(tmp, SCM_NULL);
558
ScmObj ScmOp_SRFI1_drop_right_d(ScmObj lst, ScmObj scm_idx)
563
DECLARE_FUNCTION("drop-right!", ProcedureFixed2);
565
ASSERT_INTP(scm_idx);
567
for (; CONSP(tmp); tmp = CDR(tmp))
570
len -= SCM_INT_VALUE(scm_idx);
573
for (i = 0; i < len - 1; i++) {
577
SET_CDR(tmp, SCM_NULL);
582
ScmObj ScmOp_SRFI1_split_at(ScmObj lst, ScmObj idx)
584
DECLARE_FUNCTION("split-at", ProcedureFixed2);
586
return ScmOp_values(LIST_2(ScmOp_SRFI1_take(lst, idx),
587
ScmOp_SRFI1_drop(lst, idx)));
590
ScmObj ScmOp_SRFI1_split_at_d(ScmObj lst, ScmObj idx)
592
ScmObj drop = ScmOp_SRFI1_drop(lst, idx);
593
DECLARE_FUNCTION("split-at!", ProcedureFixed2);
595
return ScmOp_values(LIST_2(ScmOp_SRFI1_take_d(lst, idx),
599
ScmObj ScmOp_SRFI1_last(ScmObj lst)
601
DECLARE_FUNCTION("last", ProcedureFixed1);
605
ERR_OBJ("non-empty, proper list is required but got ", lst);
607
return CAR(ScmOp_SRFI1_last_pair(lst));
610
ScmObj ScmOp_SRFI1_last_pair(ScmObj lst)
612
DECLARE_FUNCTION("last-pair", ProcedureFixed1);
616
ERR_OBJ("non-empty, proper list is required but got ", lst);
618
for (; CONSP(CDR(lst)); lst = CDR(lst))
624
/*==============================================================================
625
SRFI1 : The procedures : Miscellaneous
626
==============================================================================*/
627
ScmObj ScmOp_SRFI1_lengthplus(ScmObj lst)
629
DECLARE_FUNCTION("length+", ProcedureFixed0);
631
/* FIXME!: remove expensive circular_listp */
632
if (NFALSEP(ScmOp_SRFI1_circular_listp(lst)))
635
return ScmOp_length(lst);
638
ScmObj ScmOp_SRFI1_concatenate(ScmObj args)
640
ScmObj lsts_of_lst = CAR(args);
641
DECLARE_FUNCTION("concatenate", ProcedureFixed0);
643
#if SCM_STRICT_ARGCHECK
644
if (!NULLP(CDR(args)))
645
ERR_OBJ("superfluous arguments: ", args);
648
return ScmOp_append(lsts_of_lst);