1
/*===========================================================================
2
* FileName : procedure.c
3
* About : Miscellaneous R5RS procedures
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
=======================================*/
58
/* canonical internal encoding for identifiers */
59
ScmCharCodec *scm_identifier_codec;
61
/*=======================================
62
File Local Function Declarations
63
=======================================*/
64
static ScmObj map_single_arg(ScmObj proc, ScmObj args);
65
static ScmObj map_multiple_args(ScmObj proc, ScmObj args);
67
/*=======================================
68
Function Implementations
69
=======================================*/
70
/*===========================================================================
71
R5RS : 6.1 Equivalence predicates
72
===========================================================================*/
74
scm_p_eqp(ScmObj obj1, ScmObj obj2)
76
DECLARE_FUNCTION("eq?", procedure_fixed_2);
78
return MAKE_BOOL(EQ(obj1, obj2));
82
scm_p_eqvp(ScmObj obj1, ScmObj obj2)
84
#if (!(SCM_HAS_IMMEDIATE_NUMBER_ONLY && SCM_HAS_IMMEDIATE_CHAR_ONLY))
87
DECLARE_FUNCTION("eqv?", procedure_fixed_2);
92
#if (!(SCM_HAS_IMMEDIATE_NUMBER_ONLY && SCM_HAS_IMMEDIATE_CHAR_ONLY))
93
type = SCM_TYPE(obj1);
96
if (type != SCM_TYPE(obj2))
101
#if !SCM_HAS_IMMEDIATE_INT_ONLY
103
return MAKE_BOOL(SCM_INT_VALUE(obj1) == SCM_INT_VALUE(obj2));
106
#if !SCM_HAS_IMMEDIATE_CHAR_ONLY
108
return MAKE_BOOL(SCM_CHAR_VALUE(obj1) == SCM_CHAR_VALUE(obj2));
114
#endif /* (!(SCM_HAS_IMMEDIATE_NUMBER_ONLY && SCM_HAS_IMMEDIATE_CHAR_ONLY)) */
120
scm_p_equalp(ScmObj obj1, ScmObj obj2)
122
enum ScmObjType type;
123
ScmObj elm1, elm2, *v1, *v2;
125
DECLARE_FUNCTION("equal?", procedure_fixed_2);
130
type = SCM_TYPE(obj1);
133
if (type != SCM_TYPE(obj2))
138
#if !SCM_HAS_IMMEDIATE_INT_ONLY
140
return MAKE_BOOL(SCM_INT_VALUE(obj1) == SCM_INT_VALUE(obj2));
143
#if !SCM_HAS_IMMEDIATE_CHAR_ONLY
145
return MAKE_BOOL(SCM_CHAR_VALUE(obj1) == SCM_CHAR_VALUE(obj2));
149
return MAKE_BOOL(STRING_EQUALP(obj1, obj2));
152
for (; CONSP(obj1) && CONSP(obj2); obj1 = CDR(obj1), obj2 = CDR(obj2))
157
&& (SCM_TYPE(elm1) != SCM_TYPE(elm2)
158
|| !EQUALP(elm1, elm2)))
161
/* compare last cdr */
162
return (EQ(obj1, obj2)) ? SCM_TRUE : scm_p_equalp(obj1, obj2);
165
len = SCM_VECTOR_LEN(obj1);
166
if (len != SCM_VECTOR_LEN(obj2))
169
v1 = SCM_VECTOR_VEC(obj1);
170
v2 = SCM_VECTOR_VEC(obj2);
171
for (i = 0; i < len; i++) {
175
&& (SCM_TYPE(elm1) != SCM_TYPE(elm2)
176
|| !EQUALP(elm1, elm2)))
181
#if SCM_USE_SSCM_EXTENSIONS
183
return MAKE_BOOL(SCM_C_POINTER_VALUE(obj1)
184
== SCM_C_POINTER_VALUE(obj2));
186
case ScmCFuncPointer:
187
return MAKE_BOOL(SCM_C_FUNCPOINTER_VALUE(obj1)
188
== SCM_C_FUNCPOINTER_VALUE(obj2));
198
/*===================================
199
R5RS : 6.3 Other data types
200
===================================*/
201
/*===========================================================================
202
R5RS : 6.3 Other data types : 6.3.1 Booleans
203
===========================================================================*/
205
scm_p_not(ScmObj obj)
207
DECLARE_FUNCTION("not", procedure_fixed_1);
209
return MAKE_BOOL(FALSEP(obj));
213
scm_p_booleanp(ScmObj obj)
215
DECLARE_FUNCTION("boolean?", procedure_fixed_1);
217
return MAKE_BOOL(EQ(obj, SCM_FALSE) || EQ(obj, SCM_TRUE));
220
/*===========================================================================
221
R5RS : 6.3 Other data types : 6.3.3 Symbols
222
===========================================================================*/
224
scm_p_symbolp(ScmObj obj)
226
DECLARE_FUNCTION("symbol?", procedure_fixed_1);
228
return MAKE_BOOL(SYMBOLP(obj));
232
scm_p_symbol2string(ScmObj sym)
234
DECLARE_FUNCTION("symbol->string", procedure_fixed_1);
238
return CONST_STRING(SCM_SYMBOL_NAME(sym));
242
scm_p_string2symbol(ScmObj str)
244
DECLARE_FUNCTION("string->symbol", procedure_fixed_1);
248
return scm_intern(SCM_STRING_STR(str));
251
/*=======================================
252
R5RS : 6.4 Control Features
253
=======================================*/
255
scm_p_procedurep(ScmObj obj)
257
DECLARE_FUNCTION("procedure?", procedure_fixed_1);
259
return MAKE_BOOL(PROCEDUREP(obj));
263
scm_p_map(ScmObj proc, ScmObj args)
265
DECLARE_FUNCTION("map", procedure_variadic_1);
268
ERR("wrong number of arguments");
270
/* fast path for single arg case */
271
if (NULLP(CDR(args)))
272
return map_single_arg(proc, CAR(args));
274
/* multiple args case */
275
return map_multiple_args(proc, args);
279
map_single_arg(ScmObj proc, ScmObj lst)
283
DECLARE_INTERNAL_FUNCTION("map");
286
SCM_QUEUE_POINT_TO(q, ret);
287
FOR_EACH (elm, lst) {
288
elm = scm_call(proc, LIST_1(elm));
289
SCM_QUEUE_ADD(q, elm);
296
map_multiple_args(ScmObj proc, ScmObj args)
299
ScmObj ret, elm, map_args, rest_args, arg;
300
DECLARE_INTERNAL_FUNCTION("map");
303
SCM_QUEUE_POINT_TO(retq, ret);
307
SCM_QUEUE_POINT_TO(argq, map_args);
308
for (rest_args = args; CONSP(rest_args); rest_args = CDR(rest_args)) {
309
arg = CAR(rest_args);
311
SCM_QUEUE_ADD(argq, CAR(arg));
315
ERR_OBJ("invalid argument", arg);
316
/* pop destructively */
317
SET_CAR(rest_args, CDR(arg));
320
elm = scm_call(proc, map_args);
321
SCM_QUEUE_ADD(retq, elm);
326
scm_p_for_each(ScmObj proc, ScmObj args)
328
DECLARE_FUNCTION("for-each", procedure_variadic_1);
330
scm_p_map(proc, args);
336
scm_p_force(ScmObj closure)
338
DECLARE_FUNCTION("force", procedure_fixed_1);
340
ENSURE_CLOSURE(closure);
342
return scm_call(closure, SCM_NULL);
346
scm_p_call_with_current_continuation(ScmObj proc, ScmEvalState *eval_state)
348
DECLARE_FUNCTION("call-with-current-continuation",
349
procedure_fixed_tailrec_1);
351
ENSURE_PROCEDURE(proc);
353
return scm_call_with_current_continuation(proc, eval_state);
357
scm_p_values(ScmObj args)
359
DECLARE_FUNCTION("values", procedure_variadic_0);
361
/* Values with one arg must return something that fits an ordinary
366
/* Otherwise, we'll return the values in a packet. */
367
return SCM_MAKE_VALUEPACKET(args);
371
scm_p_call_with_values(ScmObj producer, ScmObj consumer,
372
ScmEvalState *eval_state)
375
DECLARE_FUNCTION("call-with-values", procedure_fixed_tailrec_2);
377
ENSURE_PROCEDURE(producer);
378
ENSURE_PROCEDURE(consumer);
380
vals = scm_call(producer, SCM_NULL);
382
if (!VALUEPACKETP(vals)) {
383
/* got back a single value */
387
vals = SCM_VALUEPACKET_VALUES(vals);
390
return scm_tailcall(consumer, vals, eval_state);
394
scm_p_dynamic_wind(ScmObj before, ScmObj thunk, ScmObj after)
396
DECLARE_FUNCTION("dynamic-wind", procedure_fixed_3);
398
ENSURE_PROCEDURE(before);
399
ENSURE_PROCEDURE(thunk);
400
ENSURE_PROCEDURE(after);
402
return scm_dynamic_wind(before, thunk, after);