~ubuntu-branches/ubuntu/maverick/uim/maverick

« back to all changes in this revision

Viewing changes to sigscheme/src/env.c

  • Committer: Bazaar Package Importer
  • Author(s): Masahito Omote
  • Date: 2008-06-25 19:56:33 UTC
  • mfrom: (3.1.18 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080625195633-8jljph4rfq00l8o7
Tags: 1:1.5.1-2
* uim-tcode: provide tutcode-custom.scm, tutcode-bushudic.scm
  and tutcode-rule.scm (Closes: #482659)
* Fix FTBFS: segv during compile (Closes: #483078).
  I personally think this bug is not specific for uim but is a optimization
  problem on gcc-4.3.1. (https://bugs.freedesktop.org/show_bug.cgi?id=16477)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*===========================================================================
 
2
 *  Filename : env.c
 
3
 *  About    : A Scheme environemnt implementation
 
4
 *
 
5
 *  Copyright (C) 2005      Kazuki Ohta <mover AT hct.zaq.ne.jp>
 
6
 *  Copyright (C) 2005-2006 Jun Inoue <jun.lambda AT gmail.com>
 
7
 *  Copyright (C) 2005-2006 YAMAMOTO Kengo <yamaken AT bp.iij4u.or.jp>
 
8
 *  Copyright (c) 2007-2008 SigScheme Project <uim-en AT googlegroups.com>
 
9
 *
 
10
 *  All rights reserved.
 
11
 *
 
12
 *  Redistribution and use in source and binary forms, with or without
 
13
 *  modification, are permitted provided that the following conditions
 
14
 *  are met:
 
15
 *
 
16
 *  1. Redistributions of source code must retain the above copyright
 
17
 *     notice, this list of conditions and the following disclaimer.
 
18
 *  2. Redistributions in binary form must reproduce the above copyright
 
19
 *     notice, this list of conditions and the following disclaimer in the
 
20
 *     documentation and/or other materials provided with the distribution.
 
21
 *  3. Neither the name of authors nor the names of its contributors
 
22
 *     may be used to endorse or promote products derived from this software
 
23
 *     without specific prior written permission.
 
24
 *
 
25
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
 
26
 *  IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 
27
 *  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 
28
 *  PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
 
29
 *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 
30
 *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 
31
 *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 
32
 *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 
33
 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 
34
 *  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 
35
 *  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
36
===========================================================================*/
 
37
 
 
38
/*
 
39
 *   SigScheme's environment object is a list formed as below.
 
40
 *
 
41
 *     frame = (cons (var1 var2 var3 ...)
 
42
 *                   (val1 val2 val3 ...))
 
43
 *     env   = (frame1 frame2 frame3 ...)
 
44
 *
 
45
 *   Other 2 forms are also used to handle dotted args.
 
46
 *
 
47
 *     frame = (cons (var1 var2 var3 . rest1)
 
48
 *                   (val1 val2 val3 var4 var5 ...))
 
49
 *
 
50
 *     frame = (cons rest2
 
51
 *                   (val1 val2 val3 var4 var5 ...))
 
52
 *
 
53
 *   In this case, rest1 is bound to (var4 var5 ...) and rest2 is bound to
 
54
 *   (val1 val2 val3 var4 var5 ...).
 
55
 *
 
56
 *   The environment object should not be manipulated manually, to allow
 
57
 *   replacing with another implementation. Use the function interfaces.
 
58
 *
 
59
 *   To ensure valid use of the environment objects is environment
 
60
 *   constructor's responsibility. i.e. Any lookup operations assume that the
 
61
 *   environment object is valid. To keep the assumption true, any environemnt
 
62
 *   object modification and injection from user code must be
 
63
 *   validated. Although the validation for the injection may cost high,
 
64
 *   ordinary code only use (interaction-environment) and other R5RS
 
65
 *   environment specifiers. Since these 'trusted' specifiers can cheaply be
 
66
 *   identified, the validation cost is also. The validation can reject any
 
67
 *   handmade invalid environment objects.
 
68
 */
 
69
 
 
70
#include <config.h>
 
71
 
 
72
#include "sigscheme.h"
 
73
#include "sigschemeinternal.h"
 
74
 
 
75
/*=======================================
 
76
  File Local Macro Definitions
 
77
=======================================*/
 
78
#define TRUSTED_ENVP(env) (EQ(env, SCM_INTERACTION_ENV)                      \
 
79
                           || EQ(env, SCM_R5RS_ENV)                          \
 
80
                           || EQ(env, SCM_NULL_ENV))
 
81
 
 
82
/*=======================================
 
83
  File Local Type Definitions
 
84
=======================================*/
 
85
 
 
86
/*=======================================
 
87
  Variable Definitions
 
88
=======================================*/
 
89
 
 
90
/*=======================================
 
91
  File Local Function Declarations
 
92
=======================================*/
 
93
static scm_bool valid_framep(ScmObj frame);
 
94
 
 
95
/*=======================================
 
96
  Function Definitions
 
97
=======================================*/
 
98
SCM_EXPORT scm_bool
 
99
scm_toplevel_environmentp(ScmObj env)
 
100
{
 
101
    return NULLP(env);
 
102
}
 
103
 
 
104
#if SCM_USE_HYGIENIC_MACRO
 
105
 
 
106
/* ScmPackedEnv is scm_int_t. */
 
107
 
 
108
SCM_EXPORT ScmPackedEnv
 
109
scm_pack_env(ScmObj env)
 
110
{
 
111
    scm_int_t depth;
 
112
    DECLARE_INTERNAL_FUNCTION("scm_env_depth");
 
113
 
 
114
    depth = scm_length(env);
 
115
    SCM_ASSERT(SCM_LISTLEN_PROPERP(depth));
 
116
    return depth;
 
117
}
 
118
 
 
119
/* Not used. */
 
120
SCM_EXPORT ScmObj
 
121
scm_unpack_env(ScmPackedEnv packed, ScmObj context)
 
122
{
 
123
    scm_int_t depth;
 
124
 
 
125
    depth = scm_length(context);
 
126
    while (depth-- > packed)
 
127
        context = CDR(context);
 
128
    return context;
 
129
}
 
130
 
 
131
 
 
132
static ScmRef
 
133
lookup_n_frames(ScmObj id, scm_int_t n, ScmObj env)
 
134
{
 
135
    ScmRef ref;
 
136
 
 
137
    while (n--) {
 
138
        SCM_ASSERT(ENVP(env));
 
139
        ref = scm_lookup_frame(id, CAR(env));
 
140
        if (ref != SCM_INVALID_REF)
 
141
            return ref;
 
142
        env = CDR(env);
 
143
    }
 
144
    return SCM_INVALID_REF;
 
145
}
 
146
 
 
147
 
 
148
/**
 
149
 * Resolves X in scm_unpack_env(XPENV, ENV), Y in ENV and tests
 
150
 * whether they are bound to the same location.  The parameters x and
 
151
 * y are thus UNINTERCHANGEABLE.
 
152
 *
 
153
 * The pattern matcher must compare scm_wrap_identifier(x, xpenv) with
 
154
 * y, but for performance we'd like to do that without actually
 
155
 * allocating the wrapper.  In the absence of syntax-case or
 
156
 * comparable mechanisms allowing for unhygienic transforms, the
 
157
 * binding frame of X and Y are always both contained in ENV, so we
 
158
 * might as well require that ENV be the environment in which one of
 
159
 * the operands (namely, Y) is to be looked up.
 
160
 *
 
161
 * But this is definitely an ugly interface, and also inconvenient
 
162
 * because the function needs a different signature when unhygienic
 
163
 * transforms are enabled.  So, FIXME: is there a better way?
 
164
 *
 
165
 * Moving this to macro.c can be an option, but keep in mind some
 
166
 * aspects are inherently tightly coupled with the lookup functions.
 
167
 */
 
168
SCM_EXPORT scm_bool
 
169
scm_identifierequalp(ScmObj x, ScmPackedEnv xpenv,
 
170
                     ScmObj y, ScmPackedEnv penv, ScmObj env)
 
171
{
 
172
    ScmRef yloc;
 
173
 
 
174
    SCM_ASSERT(xpenv <= penv);
 
175
    SCM_ASSERT(SCM_PENV_EQ(scm_pack_env(env), penv));
 
176
 
 
177
    while (penv-- > xpenv) {
 
178
        if (scm_lookup_frame(y, CAR(env)) != SCM_INVALID_REF)
 
179
            return scm_false;
 
180
        env = CDR(env);
 
181
    }
 
182
    if (EQ(x, y))
 
183
        return scm_true;
 
184
    yloc = scm_lookup_environment(y, env);
 
185
    if (yloc != SCM_INVALID_REF)
 
186
        return (scm_lookup_environment(x, env) == yloc);
 
187
    if (scm_lookup_environment(x, env) != SCM_INVALID_REF)
 
188
        return scm_false;
 
189
    return EQ(SCM_UNWRAP_KEYWORD(x), SCM_UNWRAP_KEYWORD(y));
 
190
}
 
191
 
 
192
/**
 
193
 * Returns an identifier that is bound to the same location as ID
 
194
 * within ENV (whose packed representation is DEPTH), but is not eq?
 
195
 * with ID.
 
196
 */
 
197
SCM_EXPORT ScmObj
 
198
scm_wrap_identifier(ScmObj id, ScmPackedEnv depth, ScmObj env)
 
199
{
 
200
    scm_int_t id_depth;
 
201
 
 
202
    SCM_ASSERT(IDENTIFIERP(id));
 
203
    SCM_ASSERT(depth == scm_pack_env(env));
 
204
 
 
205
    if (FARSYMBOLP(id)) {
 
206
        /* Try to reduce lookup overhead. */
 
207
        id_depth = SCM_FARSYMBOL_ENV(id);
 
208
        SCM_ASSERT(id_depth <= depth);
 
209
        if (lookup_n_frames(id, depth - id_depth, env) == SCM_INVALID_REF) {
 
210
            /* ID hasn't been bound since it was captured. */
 
211
            return MAKE_FARSYMBOL(SCM_FARSYMBOL_SYM(id), id_depth);
 
212
        }
 
213
    }
 
214
    return MAKE_FARSYMBOL(id, depth);
 
215
}
 
216
#endif /* SCM_USE_HYGIENIC_MACRO */
 
217
 
 
218
/**
 
219
 * Construct a new frame on an env
 
220
 *
 
221
 * @a formals and @a actuals must be valid.
 
222
 *
 
223
 * @param formals Symbol list as variable names of new frame. It accepts dotted
 
224
 *                list to handle function arguments directly.
 
225
 * @param actuals Arbitrary Scheme object list as values of new frame.
 
226
 *
 
227
 * @see scm_eval()
 
228
 */
 
229
SCM_EXPORT ScmObj
 
230
scm_extend_environment(ScmObj formals, ScmObj actuals, ScmObj env)
 
231
{
 
232
    ScmObj frame;
 
233
    DECLARE_INTERNAL_FUNCTION("scm_extend_environment");
 
234
 
 
235
    SCM_ASSERT(scm_valid_environment_extensionp(formals, actuals));
 
236
    SCM_ASSERT(VALID_ENVP(env));
 
237
 
 
238
    frame = CONS(formals, actuals);
 
239
    return CONS(frame, env);
 
240
}
 
241
 
 
242
/**
 
243
 * Replace entire content of recentmost frame of an env
 
244
 *
 
245
 * The environment must be replaced with returned one in caller side even if
 
246
 * this implementation returns identical to the one passed. This rule is
 
247
 * required to be compatible with future alternative implementations.
 
248
 */
 
249
SCM_EXPORT ScmObj
 
250
scm_replace_environment(ScmObj formals, ScmObj actuals, ScmObj env)
 
251
{
 
252
    ScmObj frame;
 
253
    DECLARE_INTERNAL_FUNCTION("scm_replace_environment");
 
254
 
 
255
    SCM_ASSERT(scm_valid_environment_extensionp(formals, actuals));
 
256
    SCM_ASSERT(VALID_ENVP(env));
 
257
    SCM_ASSERT(CONSP(env));
 
258
 
 
259
    frame = CAR(env);
 
260
    SET_CAR(frame, formals);
 
261
    SET_CDR(frame, actuals);
 
262
 
 
263
    return env;
 
264
}
 
265
 
 
266
/**
 
267
 * Replace all actuals of recentmost frame of an env
 
268
 *
 
269
 * The environment must be replaced with returned one in caller side even if
 
270
 * this implementation returns identical to the one passed. This rule is
 
271
 * required to be compatible with future alternative implementations.
 
272
 */
 
273
SCM_EXPORT ScmObj
 
274
scm_update_environment(ScmObj actuals, ScmObj env)
 
275
{
 
276
    ScmObj frame;
 
277
    DECLARE_INTERNAL_FUNCTION("scm_update_environment");
 
278
 
 
279
    SCM_ASSERT(VALID_ENVP(env));
 
280
    SCM_ASSERT(CONSP(env));
 
281
 
 
282
    frame = CAR(env);
 
283
    SCM_ASSERT(scm_valid_environment_extensionp(CAR(frame), actuals));
 
284
    SET_CDR(frame, actuals);
 
285
 
 
286
    return env;
 
287
}
 
288
 
 
289
/** Add a binding to recentmost frame of an env */
 
290
SCM_EXPORT ScmObj
 
291
scm_add_environment(ScmObj var, ScmObj val, ScmObj env)
 
292
{
 
293
    ScmObj frame, formals, actuals;
 
294
    DECLARE_INTERNAL_FUNCTION("scm_add_environment");
 
295
 
 
296
    SCM_ASSERT(IDENTIFIERP(var));
 
297
    SCM_ASSERT(VALID_ENVP(env));
 
298
 
 
299
    /* add (var, val) pair to recentmost frame of the env */
 
300
    if (NULLP(env)) {
 
301
        frame = CONS(LIST_1(var), LIST_1(val));
 
302
        env = LIST_1(frame);
 
303
    } else if (CONSP(env)) {
 
304
        frame = CAR(env);
 
305
        formals = CONS(var, CAR(frame));
 
306
        actuals = CONS(val, CDR(frame));
 
307
        SET_CAR(frame, formals);
 
308
        SET_CDR(frame, actuals);
 
309
    } else {
 
310
        SCM_NOTREACHED;
 
311
    }
 
312
    return env;
 
313
}
 
314
 
 
315
/**
 
316
 * Lookup a variable of an env
 
317
 *
 
318
 * @return Reference to the variable. SCM_INVALID_REF if not found.
 
319
 */
 
320
SCM_EXPORT ScmRef
 
321
scm_lookup_environment(ScmObj var, ScmObj env)
 
322
{
 
323
    ScmObj frame;
 
324
    ScmRef ref;
 
325
#if SCM_USE_HYGIENIC_MACRO
 
326
    scm_int_t depth, id_depth;
 
327
    ScmObj env_save;
 
328
#endif /* SCM_USE_HYGIENIC_MACRO */
 
329
    DECLARE_INTERNAL_FUNCTION("scm_lookup_environment");
 
330
 
 
331
    SCM_ASSERT(IDENTIFIERP(var));
 
332
    SCM_ASSERT(VALID_ENVP(env));
 
333
 
 
334
    /* lookup in frames */
 
335
#if SCM_USE_HYGIENIC_MACRO
 
336
    env_save = env;
 
337
    depth = 0;
 
338
#endif
 
339
    for (; !NULLP(env); env = CDR(env)) {
 
340
        frame = CAR(env);
 
341
        ref = scm_lookup_frame(var, frame);
 
342
        if (ref != SCM_INVALID_REF)
 
343
            return ref;
 
344
#if SCM_USE_HYGIENIC_MACRO
 
345
        ++depth;
 
346
#endif
 
347
    }
 
348
    SCM_ASSERT(NULLP(env));
 
349
 
 
350
#if SCM_USE_HYGIENIC_MACRO
 
351
    if (FARSYMBOLP(var)) {
 
352
        scm_int_t i;
 
353
        id_depth = SCM_FARSYMBOL_ENV(var);
 
354
        if (id_depth > depth)
 
355
            scm_macro_bad_scope(var);
 
356
        for (i = depth - id_depth; i--; )
 
357
            env_save = CDR(env_save);
 
358
        ref = lookup_n_frames(SCM_FARSYMBOL_SYM(var),
 
359
                              id_depth, env_save);
 
360
        SCM_ASSERT(ref != SCM_INVALID_REF || SYMBOLP(SCM_FARSYMBOL_SYM(var)));
 
361
        return ref;
 
362
    }
 
363
#endif
 
364
 
 
365
    return SCM_INVALID_REF;
 
366
}
 
367
 
 
368
/** Lookup a variable in a frame */
 
369
SCM_EXPORT ScmRef
 
370
scm_lookup_frame(ScmObj var, ScmObj frame)
 
371
{
 
372
    ScmObj formals;
 
373
    ScmRef actuals;
 
374
    DECLARE_INTERNAL_FUNCTION("scm_lookup_frame");
 
375
 
 
376
    SCM_ASSERT(IDENTIFIERP(var));
 
377
    SCM_ASSERT(valid_framep(frame));
 
378
 
 
379
    for (formals = CAR(frame), actuals = REF_CDR(frame);
 
380
         CONSP(formals);
 
381
         formals = CDR(formals), actuals = REF_CDR(DEREF(actuals)))
 
382
    {
 
383
        if (EQ(var, CAR(formals)))
 
384
            return REF_CAR(DEREF(actuals));
 
385
    }
 
386
    /* dotted list */
 
387
    if (EQ(var, formals))
 
388
        return actuals;
 
389
 
 
390
    return SCM_INVALID_REF;
 
391
}
 
392
 
 
393
ScmObj
 
394
scm_symbol_value(ScmObj var, ScmObj env)
 
395
{
 
396
    ScmRef ref;
 
397
    ScmObj val;
 
398
    DECLARE_INTERNAL_FUNCTION("scm_symbol_value");
 
399
 
 
400
    SCM_ASSERT(IDENTIFIERP(var));
 
401
 
 
402
    ref = scm_lookup_environment(var, env);
 
403
    if (ref != SCM_INVALID_REF) {
 
404
        /* Found in the environment. Since scm_s_body() may produce unbound
 
405
         * variables as internal definitions, subsequent error check is
 
406
         * required. */
 
407
        val = DEREF(ref);
 
408
    } else {
 
409
        /* Fallback to top-level binding. */
 
410
#if SCM_USE_HYGIENIC_MACRO
 
411
        if (FARSYMBOLP(var))
 
412
            var = SCM_FARSYMBOL_SYM(var);
 
413
        SCM_ASSERT(SYMBOLP(var));
 
414
#endif
 
415
        val = SCM_SYMBOL_VCELL(var);
 
416
    }
 
417
 
 
418
    if (EQ(val, SCM_UNBOUND))
 
419
        ERR_OBJ("unbound variable", var);
 
420
 
 
421
    return val;
 
422
}
 
423
 
 
424
/*
 
425
 * Validators
 
426
 */
 
427
SCM_EXPORT scm_bool
 
428
scm_valid_environmentp(ScmObj env)
 
429
{
 
430
    ScmObj frame, rest;
 
431
    DECLARE_INTERNAL_FUNCTION("scm_valid_environmentp");
 
432
 
 
433
    if (TRUSTED_ENVP(env))
 
434
        return scm_true;
 
435
 
 
436
    /*
 
437
     * The env is extended and untrusted. Since this case rarely occurs in
 
438
     * ordinary codes, the expensive validation cost is acceptable.
 
439
     */
 
440
 
 
441
    if (!PROPER_LISTP(env))
 
442
        return scm_false;
 
443
    for (rest = env; !NULLP(rest); rest = CDR(rest)) {
 
444
        frame = CAR(rest);
 
445
        if (!valid_framep(frame))
 
446
            return scm_false;
 
447
    }
 
448
 
 
449
    return scm_true;
 
450
}
 
451
 
 
452
static scm_bool
 
453
valid_framep(ScmObj frame)
 
454
{
 
455
    ScmObj formals, actuals;
 
456
    DECLARE_INTERNAL_FUNCTION("valid_framep");
 
457
 
 
458
    if (CONSP(frame)) {
 
459
        formals = CAR(frame);
 
460
        actuals = CDR(frame);
 
461
        if (scm_valid_environment_extensionp(formals, actuals))
 
462
            return scm_true;
 
463
    }
 
464
    return scm_false;
 
465
}
 
466
 
 
467
SCM_EXPORT scm_bool
 
468
scm_valid_environment_extensionp(ScmObj formals, ScmObj actuals)
 
469
{
 
470
    scm_int_t formals_len, actuals_len;
 
471
 
 
472
    formals_len = scm_validate_formals(formals);
 
473
    actuals_len = scm_validate_actuals(actuals);
 
474
    return scm_valid_environment_extension_lengthp(formals_len, actuals_len);
 
475
}
 
476
 
 
477
/* formals_len must be validated by scm_validate_formals() prior to here */
 
478
SCM_EXPORT scm_bool
 
479
scm_valid_environment_extension_lengthp(scm_int_t formals_len,
 
480
                                        scm_int_t actuals_len)
 
481
{
 
482
    if (SCM_LISTLEN_ERRORP(formals_len))
 
483
        return scm_false;
 
484
    if (SCM_LISTLEN_DOTTEDP(formals_len)) {
 
485
        formals_len = SCM_LISTLEN_DOTTED(formals_len);
 
486
        if (SCM_LISTLEN_PROPERP(actuals_len))
 
487
            return (formals_len <= actuals_len);
 
488
 
 
489
        /* (lambda args (set-cdr! args #t) args) */
 
490
        if (SCM_LISTLEN_DOTTEDP(actuals_len))
 
491
            return (formals_len <= SCM_LISTLEN_DOTTED(actuals_len));
 
492
 
 
493
        /* (lambda args (set-cdr! args args) args) */
 
494
        if (SCM_LISTLEN_CIRCULARP(actuals_len))  /* always true */
 
495
            return scm_true;
 
496
    }
 
497
    return (formals_len == actuals_len);
 
498
}
 
499
 
 
500
SCM_EXPORT scm_int_t
 
501
scm_validate_formals(ScmObj formals)
 
502
{
 
503
#if SCM_STRICT_ARGCHECK
 
504
    scm_int_t len;
 
505
    DECLARE_INTERNAL_FUNCTION("scm_validate_formals");
 
506
 
 
507
    /*
 
508
     * SigScheme does not perform the check for duplicate variable name in
 
509
     * formals. It is an user's responsibility.
 
510
     *
 
511
     * R5RS: 4.1.4 Procedures
 
512
     * It is an error for a <variable> to appear more than once in <formals>.
 
513
     */
 
514
 
 
515
    /* This loop goes infinite if the formals is circular. SigSchme expects
 
516
     * that user codes are sane here. */
 
517
    for (len = 0; CONSP(formals); formals = CDR(formals), len++) {
 
518
        if (!IDENTIFIERP(CAR(formals)))
 
519
            return SCM_LISTLEN_ENCODE_ERROR(len);
 
520
    }
 
521
    if (NULLP(formals))
 
522
        return len;
 
523
    /* dotted list allowed */
 
524
    if (IDENTIFIERP(formals))
 
525
        return SCM_LISTLEN_ENCODE_DOTTED(len);
 
526
    return SCM_LISTLEN_ENCODE_ERROR(len);
 
527
#else
 
528
    /* Crashless loose validation:
 
529
     * Regard any non-list object as symbol. Since the lookup operation search
 
530
     * for a variable by EQ, this is safe although loosely allows
 
531
     * R5RS-incompatible code. */
 
532
    return scm_finite_length(formals);
 
533
#endif
 
534
}
 
535
 
 
536
SCM_EXPORT scm_int_t
 
537
scm_validate_actuals(ScmObj actuals)
 
538
{
 
539
    scm_int_t len;
 
540
 
 
541
#if SCM_STRICT_ARGCHECK
 
542
    len = scm_length(actuals);
 
543
#else
 
544
    /* Crashless loose validation:
 
545
     * This loop goes infinite if the formals is circular. SigSchme expects
 
546
     * that user codes are sane here. */
 
547
    len = scm_finite_length(actuals);
 
548
#endif
 
549
    if (SCM_LISTLEN_DOTTEDP(len))
 
550
        return SCM_LISTLEN_ENCODE_ERROR(len);
 
551
    return len;
 
552
}