1 /*===========================================================================
2  *  Filename : syntax.c
3  *  About    : R5RS syntaxes
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 #include <config.h>
39 
40 #include "sigscheme.h"
41 #include "sigschemeinternal.h"
42 
43 /*=======================================
44   File Local Macro Definitions
45 =======================================*/
46 #define ERRMSG_CLAUSE_REQUIRED     "at least 1 clause required"
47 #define ERRMSG_EXPRESSION_REQUIRED "at least 1 expression required"
48 #define ERRMSG_INVALID_BINDINGS    "invalid bindings form"
49 #define ERRMSG_INVALID_BINDING     "invalid binding form"
50 #define ERRMSG_SYNTAX_AS_VALUE     "syntactic keyword is passed as value"
51 #define ERRMSG_DUPLICATE_VARNAME   "duplicate variable name"
52 #define ERRMSG_BAD_DEFINE_FORM     "bad definition form"
53 
54 #if SCM_USE_INTERNAL_DEFINITIONS
55 #define ERRMSG_BAD_DEFINE_PLACEMENT "definitions are valid only at toplevel" \
56                                     " or beginning of a binding construct"
57 #else
58 #define ERRMSG_BAD_DEFINE_PLACEMENT "internal definitions feature is disabled"
59 #endif
60 
61 /* FIXME: temporary hack */
62 #if SCM_STRICT_TOPLEVEL_DEFINITIONS
63 #define FORBID_TOPLEVEL_DEFINITIONS(env)                                     \
64     (EQ((env), SCM_INTERACTION_ENV) ? SCM_INTERACTION_ENV_INDEFINABLE : (env))
65 #else
66 #define FORBID_TOPLEVEL_DEFINITIONS(env) (env)
67 #endif
68 
69 #if SCM_USE_HYGIENIC_MACRO
70 #define CHECK_VALID_BINDEE(permitted_type, bindee)                           \
71     do {                                                                     \
72         if (permitted_type == ScmFirstClassObj)                              \
73             CHECK_VALID_EVALED_VALUE(bindee);                                \
74         else if (permitted_type == ScmMacro)                                 \
75             SCM_ASSERT(HMACROP(bindee));                                     \
76         else                                                                 \
77             SCM_NOTREACHED;                                                  \
78     } while (/* CONSTCOND */ 0)
79 #else
80 #define CHECK_VALID_BINDEE(permitted_type, bindee)                           \
81     do {                                                                     \
82         if (permitted_type == ScmFirstClassObj)                              \
83             CHECK_VALID_EVALED_VALUE(bindee);                                \
84         else                                                                 \
85             SCM_NOTREACHED;                                                  \
86     } while (/* CONSTCOND */ 0)
87 #endif
88 
89 /*=======================================
90   File Local Type Definitions
91 =======================================*/
92 
93 /*=======================================
94   Variable Definitions
95 =======================================*/
96 #include "functable-r5rs-syntax.c"
97 
98 SCM_DEFINE_EXPORTED_VARS(syntax);
99 
100 SCM_GLOBAL_VARS_BEGIN(static_syntax);
101 #define static
102 static ScmObj l_sym_else, l_sym_yields, l_sym_define;
103 #if SCM_USE_INTERNAL_DEFINITIONS
104 static ScmObj l_sym_begin, l_syn_lambda;
105 #endif /* SCM_USE_INTERNAL_DEFINITIONS */
106 #undef static
107 SCM_GLOBAL_VARS_END(static_syntax);
108 #define l_sym_else   SCM_GLOBAL_VAR(static_syntax, l_sym_else)
109 #define l_sym_yields SCM_GLOBAL_VAR(static_syntax, l_sym_yields)
110 #define l_sym_define SCM_GLOBAL_VAR(static_syntax, l_sym_define)
111 #define l_sym_begin  SCM_GLOBAL_VAR(static_syntax, l_sym_begin)
112 #define l_syn_lambda SCM_GLOBAL_VAR(static_syntax, l_syn_lambda)
113 SCM_DEFINE_STATIC_VARS(static_syntax);
114 
115 /*=======================================
116   File Local Function Declarations
117 =======================================*/
118 #if SCM_USE_INTERNAL_DEFINITIONS
119 static ScmObj filter_definitions(ScmObj body, ScmObj *formals, ScmObj *actuals,
120                                  ScmQueue *def_expq);
121 #endif
122 
123 /*=======================================
124   Function Definitions
125 =======================================*/
126 SCM_EXPORT void
scm_init_syntax(void)127 scm_init_syntax(void)
128 {
129     SCM_GLOBAL_VARS_INIT(syntax);
130     SCM_GLOBAL_VARS_INIT(static_syntax);
131 
132     scm_register_funcs(scm_functable_r5rs_syntax);
133 
134     scm_sym_quote            = scm_intern("quote");
135     scm_sym_quasiquote       = scm_intern("quasiquote");
136     scm_sym_unquote          = scm_intern("unquote");
137     scm_sym_unquote_splicing = scm_intern("unquote-splicing");
138     scm_sym_ellipsis         = scm_intern("...");
139 
140     l_sym_else   = scm_intern("else");
141     l_sym_yields = scm_intern("=>");
142     l_sym_define = scm_intern("define");
143 #if SCM_USE_INTERNAL_DEFINITIONS
144     l_sym_begin  = scm_intern("begin");
145     scm_gc_protect_with_init(&l_syn_lambda,
146                              scm_symbol_value(scm_intern("lambda"),
147                                               SCM_INTERACTION_ENV));
148 #endif
149 }
150 
151 /*=======================================
152   R5RS : 4.1 Primitive expression types
153 =======================================*/
154 /*===========================================================================
155   R5RS : 4.1 Primitive expression types : 4.1.2 Literal expressions
156 ===========================================================================*/
157 SCM_EXPORT ScmObj
scm_s_quote(ScmObj datum,ScmObj env)158 scm_s_quote(ScmObj datum, ScmObj env)
159 {
160     DECLARE_FUNCTION("quote", syntax_fixed_1);
161 
162 #if SCM_USE_HYGIENIC_MACRO
163     /* Passing objects that contain a circular list to SCM_UNWRAP_SYNTAX()
164      * causes infinite loop. For instance, (error circular-list) raises it via
165      * the error object which contains the circular list.
166      *   -- YamaKen 2006-10-02 */
167     if (ERROBJP(datum))
168         return datum;
169 #endif
170 
171     return SCM_UNWRAP_SYNTAX(datum);
172 }
173 
174 /*===========================================================================
175   R5RS : 4.1 Primitive expression types : 4.1.4 Procedures
176 ===========================================================================*/
177 SCM_EXPORT ScmObj
scm_s_lambda(ScmObj formals,ScmObj body,ScmObj env)178 scm_s_lambda(ScmObj formals, ScmObj body, ScmObj env)
179 {
180     DECLARE_FUNCTION("lambda", syntax_variadic_1);
181 
182 #if SCM_STRICT_ARGCHECK
183     if (SCM_LISTLEN_ERRORP(scm_validate_formals(formals)))
184         ERR_OBJ("bad formals", formals);
185 
186     /* Keeping variable name unique is user's responsibility. R5RS: "It is an
187      * error for a <variable> to appear more than once in <formals>.". */
188 #else
189     /* Crashless no-validation:
190      * Regard any non-list object as symbol. Since the lookup operation search
191      * for a variable by EQ, this is safe although loosely allows
192      * R5RS-incompatible code. */
193 #endif
194 
195     /* Internal definitions-only body such as ((define foo bar)) is
196      * invalid. But since checking it here is inefficient, it is deferred to
197      * scm_s_body() on being called. */
198     if (!CONSP(body))
199         ERR_OBJ(ERRMSG_EXPRESSION_REQUIRED, body);
200 
201     return MAKE_CLOSURE(CONS(formals, body), env);
202 }
203 
204 /*===========================================================================
205   R5RS : 4.1 Primitive expression types : 4.1.5 Conditionals
206 ===========================================================================*/
207 SCM_EXPORT ScmObj
scm_s_if(ScmObj test,ScmObj conseq,ScmObj rest,ScmEvalState * eval_state)208 scm_s_if(ScmObj test, ScmObj conseq, ScmObj rest, ScmEvalState *eval_state)
209 {
210     ScmObj env, alt;
211     DECLARE_FUNCTION("if", syntax_variadic_tailrec_2);
212 
213     env = eval_state->env;
214 
215     /*=======================================================================
216       (if <test> <consequent>)
217       (if <test> <consequent> <alternate>)
218     =======================================================================*/
219 
220     test = EVAL(test, env);
221     CHECK_VALID_EVALED_VALUE(test);
222     if (TRUEP(test)) {
223 #if SCM_STRICT_ARGCHECK
224         SAFE_POP(rest);
225         ASSERT_NO_MORE_ARG(rest);
226 #endif
227         return conseq;
228     } else {
229 #if SCM_COMPAT_SIOD_BUGS
230         alt = (CONSP(rest)) ? CAR(rest) : SCM_FALSE;
231 #else
232         alt = (CONSP(rest)) ? CAR(rest) : SCM_UNDEF;
233 #endif
234 #if SCM_STRICT_ARGCHECK
235         SAFE_POP(rest);
236         ASSERT_NO_MORE_ARG(rest);
237 #endif
238         return alt;
239     }
240 }
241 
242 /*===========================================================================
243   R5RS : 4.1 Primitive expression types : 4.1.6 Assignments
244 ===========================================================================*/
245 SCM_EXPORT ScmObj
scm_s_setx(ScmObj sym,ScmObj exp,ScmObj env)246 scm_s_setx(ScmObj sym, ScmObj exp, ScmObj env)
247 {
248     ScmObj evaled;
249     ScmRef locally_bound;
250     DECLARE_FUNCTION("set!", syntax_fixed_2);
251 
252     ENSURE_SYMBOL(sym);
253 
254     evaled = EVAL(exp, env);
255     CHECK_VALID_EVALED_VALUE(evaled);
256     locally_bound = scm_lookup_environment(sym, env);
257     if (locally_bound != SCM_INVALID_REF) {
258         SET(locally_bound, evaled);
259     } else {
260         if (!SCM_SYMBOL_BOUNDP(sym))
261             ERR_OBJ("unbound variable", sym);
262 
263         SCM_SYMBOL_SET_VCELL(sym, evaled);
264     }
265 
266 #if SCM_STRICT_R5RS
267     return SCM_UNDEF;
268 #else
269     return evaled;
270 #endif
271 }
272 
273 
274 /*=======================================
275   R5RS : 4.2 Derived expression types
276 =======================================*/
277 /*===========================================================================
278   R5RS : 4.2 Derived expression types : 4.2.1 Conditionals
279 ===========================================================================*/
280 /* body of 'cond' and 'guard' of SRFI-34 */
281 SCM_EXPORT ScmObj
scm_s_cond_internal(ScmObj clauses,ScmEvalState * eval_state)282 scm_s_cond_internal(ScmObj clauses, ScmEvalState *eval_state)
283 {
284     ScmObj env, clause, test, exps, proc;
285     DECLARE_INTERNAL_FUNCTION("cond" /* , syntax_variadic_tailrec_0 */);
286 
287     env = eval_state->env;
288 #if SCM_STRICT_TOPLEVEL_DEFINITIONS
289     eval_state->nest = SCM_NEST_COMMAND;
290 #endif
291 
292     /*
293      * (cond <cond clause>+)
294      * (cond <cond clause>* (else <sequence>))
295      *
296      * <cond clause> --> (<test> <sequence>)
297      *       | (<test>)
298      *       | (<test> => <recipient>)
299      * <recipient> --> <expression>
300      * <test> --> <expression>
301      * <sequence> --> <command>* <expression>
302      * <command> --> <expression>
303      */
304 
305     if (NO_MORE_ARG(clauses))
306         ERR(ERRMSG_CLAUSE_REQUIRED);
307 
308     /* looping in each clause */
309     FOR_EACH (clause, clauses) {
310         if (!CONSP(clause))
311             ERR_OBJ("bad clause", clause);
312 
313         test = CAR(clause);
314         exps = CDR(clause);
315 
316 #if 0
317         test = SCM_UNWRAP_SYNTAX(test);  /* FIXME: needed? */
318 #endif
319         if (EQ(test, l_sym_else)) {
320             ASSERT_NO_MORE_ARG(clauses);
321             return scm_s_begin(exps, eval_state);
322         }
323 
324         test = EVAL(test, env);
325         CHECK_VALID_EVALED_VALUE(test);
326         if (TRUEP(test)) {
327             /*
328              * if the selected <clause> contains only the <test> and no
329              * <expression>s, then the value of the <test> is returned as the
330              * result.
331              */
332             if (NULLP(exps)) {
333                 eval_state->ret_type = SCM_VALTYPE_AS_IS;
334                 return test;
335             }
336 
337             /*
338              * If the selected <clause> uses the => alternate form, then the
339              * <expression> is evaluated. Its value must be a procedure that
340              * accepts one argument; this procedure is then called on the value
341              * of the <test> and the value returned by this procedure is
342              * returned by the cond expression.
343              */
344             if (EQ(l_sym_yields, CAR(exps)) && LIST_2_P(exps)) {
345                 proc = EVAL(CADR(exps), env);
346                 if (!PROCEDUREP(proc))
347                     ERR_OBJ("exp after => must be a procedure but got", proc);
348 
349                 /*
350                  * R5RS: 3.5 Proper tail recursion
351                  *
352                  * If a `cond' expression is in a tail context, and has a
353                  * clause of the form `(<expression1> => <expression2>)' then
354                  * the (implied) call to the procedure that results from the
355                  * evaluation of <expression2> is in a tail
356                  * context. <expression2> itself is not in a tail context.
357                  */
358                 return LIST_2(proc, LIST_2(SYM_QUOTE, test));
359             }
360 
361             return scm_s_begin(exps, eval_state);
362         }
363     }
364     ASSERT_NO_MORE_ARG(clauses);
365 
366     /*
367      * To distinguish unmatched status from SCM_UNDEF from a clause, pure
368      * internal value SCM_INVALID is returned. Don't pass it to Scheme world.
369      */
370     eval_state->ret_type = SCM_VALTYPE_AS_IS;
371     return SCM_INVALID;
372 }
373 
374 SCM_EXPORT ScmObj
scm_s_cond(ScmObj clauses,ScmEvalState * eval_state)375 scm_s_cond(ScmObj clauses, ScmEvalState *eval_state)
376 {
377     ScmObj ret;
378     DECLARE_FUNCTION("cond", syntax_variadic_tailrec_0);
379 
380     ret = scm_s_cond_internal(clauses, eval_state);
381     return (VALIDP(ret)) ? ret : SCM_UNDEF;
382 }
383 
384 SCM_EXPORT ScmObj
scm_s_case(ScmObj key,ScmObj clauses,ScmEvalState * eval_state)385 scm_s_case(ScmObj key, ScmObj clauses, ScmEvalState *eval_state)
386 {
387     ScmObj clause, test, exps;
388     DECLARE_FUNCTION("case", syntax_variadic_tailrec_1);
389 
390     /*
391      * (case <expression>
392      *   <case clause>+)
393      *
394      * (case <expression>
395      *   <case clause>*
396      *   (else <sequence>))
397      *
398      * <case clause> --> ((<datum>*) <sequence>)
399      * <sequence> --> <command>* <expression>
400      * <command> --> <expression>
401      * <Datum> is what the read procedure (see section 6.6.2 Input)
402      * successfully parses.
403      */
404 
405     if (NO_MORE_ARG(clauses))
406         ERR(ERRMSG_CLAUSE_REQUIRED);
407 
408     key = EVAL(key, eval_state->env);
409     CHECK_VALID_EVALED_VALUE(key);
410 
411     FOR_EACH (clause, clauses) {
412         if (!CONSP(clause))
413             ERR_OBJ("bad clause", clause);
414 
415         test = CAR(clause);
416         exps = CDR(clause);
417 
418         test = SCM_UNWRAP_SYNTAX(test);
419         if (EQ(test, l_sym_else))
420             ASSERT_NO_MORE_ARG(clauses);
421         else
422             test = scm_p_memv(key, test);
423 
424         if (TRUEP(test)) {
425 #if SCM_STRICT_TOPLEVEL_DEFINITIONS
426             eval_state->nest = SCM_NEST_COMMAND;
427 #endif
428             return scm_s_begin(exps, eval_state);
429         }
430     }
431     ASSERT_NO_MORE_ARG(clauses);
432 
433     return SCM_UNDEF;
434 }
435 
436 SCM_EXPORT ScmObj
scm_s_and(ScmObj args,ScmEvalState * eval_state)437 scm_s_and(ScmObj args, ScmEvalState *eval_state)
438 {
439     ScmObj expr, val, env;
440     DECLARE_FUNCTION("and", syntax_variadic_tailrec_0);
441 
442     if (NO_MORE_ARG(args)) {
443         eval_state->ret_type = SCM_VALTYPE_AS_IS;
444         return SCM_TRUE;
445     }
446     env = FORBID_TOPLEVEL_DEFINITIONS(eval_state->env);
447 
448     FOR_EACH_BUTLAST (expr, args) {
449         val = EVAL(expr, env);
450         CHECK_VALID_EVALED_VALUE(val);
451         if (FALSEP(val)) {
452             ASSERT_PROPER_ARG_LIST(args);
453             eval_state->ret_type = SCM_VALTYPE_AS_IS;
454             return SCM_FALSE;
455         }
456     }
457     ASSERT_NO_MORE_ARG(args);
458 
459     return expr;
460 }
461 
462 SCM_EXPORT ScmObj
scm_s_or(ScmObj args,ScmEvalState * eval_state)463 scm_s_or(ScmObj args, ScmEvalState *eval_state)
464 {
465     ScmObj expr, val, env;
466     DECLARE_FUNCTION("or", syntax_variadic_tailrec_0);
467 
468     if (NO_MORE_ARG(args)) {
469         eval_state->ret_type = SCM_VALTYPE_AS_IS;
470         return SCM_FALSE;
471     }
472     env = FORBID_TOPLEVEL_DEFINITIONS(eval_state->env);
473 
474     FOR_EACH_BUTLAST (expr, args) {
475         val = EVAL(expr, env);
476         CHECK_VALID_EVALED_VALUE(val);
477         if (TRUEP(val)) {
478             ASSERT_PROPER_ARG_LIST(args);
479             eval_state->ret_type = SCM_VALTYPE_AS_IS;
480             return val;
481         }
482     }
483     ASSERT_NO_MORE_ARG(args);
484 
485     return expr;
486 }
487 
488 /*===========================================================================
489   R5RS : 4.2 Derived expression types : 4.2.2 Binding constructs
490 ===========================================================================*/
491 SCM_EXPORT ScmObj
scm_s_let(ScmObj bindings,ScmObj body,ScmEvalState * eval_state)492 scm_s_let(ScmObj bindings, ScmObj body, ScmEvalState *eval_state)
493 {
494     DECLARE_FUNCTION("let", syntax_variadic_tailrec_1);
495 
496     return scm_s_let_internal(ScmFirstClassObj, bindings, body, eval_state);
497 }
498 
499 SCM_EXPORT ScmObj
scm_s_let_internal(enum ScmObjType permitted,ScmObj bindings,ScmObj body,ScmEvalState * eval_state)500 scm_s_let_internal(enum ScmObjType permitted, ScmObj bindings, ScmObj body,
501                    ScmEvalState *eval_state)
502 {
503     ScmObj env, named_let_sym, proc, binding;
504     ScmObj formals, var, actuals, val, exp;
505     ScmQueue varq, valq;
506     DECLARE_INTERNAL_FUNCTION("let" /* , syntax_variadic_tailrec_1 */);
507 
508     env = eval_state->env;
509     named_let_sym = SCM_FALSE;
510 
511     /*=======================================================================
512       normal let:
513 
514         (let (<binding spec>*) <body>)
515 
516       named let:
517 
518         (let <variable> (<binding spec>*) <body>)
519 
520       <binding spec> --> (<variable> <expression>)
521       <body> --> <definition>* <sequence>
522       <definition> --> (define <variable> <expression>)
523             | (define (<variable> <def formals>) <body>)
524             | (begin <definition>*)
525       <sequence> --> <command>* <expression>
526       <command> --> <expression>
527     =======================================================================*/
528 
529     /* named let */
530     if (IDENTIFIERP(bindings)) {
531         named_let_sym = bindings;
532 
533         if (!CONSP(body))
534             ERR("invalid named let form");
535         bindings = POP(body);
536     }
537 
538     formals = actuals = SCM_NULL;
539     SCM_QUEUE_POINT_TO(varq, formals);
540     SCM_QUEUE_POINT_TO(valq, actuals);
541     FOR_EACH (binding, bindings) {
542 #if SCM_COMPAT_SIOD_BUGS
543         /* temporary solution. the inefficiency is not a problem */
544         if (LIST_1_P(binding))
545             binding = LIST_2(CAR(binding), SCM_FALSE);
546 #endif
547 
548         if (!LIST_2_P(binding) || !IDENTIFIERP(var = CAR(binding)))
549             ERR_OBJ(ERRMSG_INVALID_BINDING, binding);
550 #if SCM_STRICT_ARGCHECK
551         /* Optional check. Keeping variable name unique is user's
552          * responsibility. R5RS: "It is an error for a <variable> to appear
553          * more than once in the list of variables being bound." */
554         if (TRUEP(scm_p_memq(var, formals)))
555             ERR_OBJ(ERRMSG_DUPLICATE_VARNAME, var);
556 #endif
557         exp = CADR(binding);
558         val = EVAL(exp, env);
559         CHECK_VALID_BINDEE(permitted, val);
560 
561         SCM_QUEUE_ADD(varq, var);
562         SCM_QUEUE_ADD(valq, val);
563     }
564     if (!NULLP(bindings))
565         ERR_OBJ(ERRMSG_INVALID_BINDINGS, bindings);
566 
567     env = scm_extend_environment(formals, actuals, env);
568 
569     /* named let */
570     if (IDENTIFIERP(named_let_sym)) {
571         proc = MAKE_CLOSURE(CONS(formals, body), env);
572         env = scm_add_environment(named_let_sym, proc, env);
573         SCM_CLOSURE_SET_ENV(proc, env);
574     }
575 
576     eval_state->env = env;
577     return scm_s_body(body, eval_state);
578 }
579 
580 SCM_EXPORT ScmObj
scm_s_letstar(ScmObj bindings,ScmObj body,ScmEvalState * eval_state)581 scm_s_letstar(ScmObj bindings, ScmObj body, ScmEvalState *eval_state)
582 {
583     ScmObj env, var, val, exp, binding;
584     DECLARE_FUNCTION("let*", syntax_variadic_tailrec_1);
585 
586     env = eval_state->env;
587 
588     /*=======================================================================
589       (let* (<binding spec>*) <body>)
590 
591       <binding spec> --> (<variable> <expression>)
592       <body> --> <definition>* <sequence>
593       <definition> --> (define <variable> <expression>)
594             | (define (<variable> <def formals>) <body>)
595             | (begin <definition>*)
596       <sequence> --> <command>* <expression>
597       <command> --> <expression>
598     =======================================================================*/
599 
600     FOR_EACH (binding, bindings) {
601 #if SCM_COMPAT_SIOD_BUGS
602         /* temporary solution. the inefficiency is not a problem */
603         if (LIST_1_P(binding))
604             binding = LIST_2(CAR(binding), SCM_FALSE);
605 #endif
606 
607         if (!LIST_2_P(binding) || !IDENTIFIERP(var = CAR(binding)))
608             ERR_OBJ(ERRMSG_INVALID_BINDING, binding);
609 
610         exp = CADR(binding);
611         val = EVAL(exp, env);
612         CHECK_VALID_EVALED_VALUE(val);
613 
614         /* extend env for each variable */
615         env = scm_extend_environment(LIST_1(var), LIST_1(val), env);
616     }
617     if (!NULLP(bindings))
618         ERR_OBJ(ERRMSG_INVALID_BINDINGS, bindings);
619 
620     eval_state->env = env;
621     return scm_s_body(body, eval_state);
622 }
623 
624 SCM_EXPORT ScmObj
scm_s_letrec(ScmObj bindings,ScmObj body,ScmEvalState * eval_state)625 scm_s_letrec(ScmObj bindings, ScmObj body, ScmEvalState *eval_state)
626 {
627     DECLARE_FUNCTION("letrec", syntax_variadic_tailrec_1);
628 
629     return scm_s_letrec_internal(ScmFirstClassObj, bindings, body, eval_state);
630 }
631 
632 SCM_EXPORT ScmObj
scm_s_letrec_internal(enum ScmObjType permitted,ScmObj bindings,ScmObj body,ScmEvalState * eval_state)633 scm_s_letrec_internal(enum ScmObjType permitted, ScmObj bindings, ScmObj body,
634                       ScmEvalState *eval_state)
635 {
636     ScmObj binding, formals, actuals, var, val, exp, env;
637     DECLARE_INTERNAL_FUNCTION("letrec" /* , syntax_variadic_tailrec_1 */);
638 
639     /*=======================================================================
640       (letrec (<binding spec>*) <body>)
641 
642       <binding spec> --> (<variable> <expression>)
643       <body> --> <definition>* <sequence>
644       <definition> --> (define <variable> <expression>)
645             | (define (<variable> <def formals>) <body>)
646             | (begin <definition>*)
647       <sequence> --> <command>* <expression>
648       <command> --> <expression>
649     =======================================================================*/
650 
651     /* extend env by placeholder frame for subsequent lambda evaluations */
652     env = scm_extend_environment(SCM_NULL, SCM_NULL, eval_state->env);
653 
654     formals = actuals = SCM_NULL;
655     FOR_EACH (binding, bindings) {
656         if (!LIST_2_P(binding) || !IDENTIFIERP(var = CAR(binding)))
657             ERR_OBJ(ERRMSG_INVALID_BINDING, binding);
658 #if SCM_STRICT_ARGCHECK
659         /* Optional check. Keeping variable name unique is user's
660          * responsibility. R5RS: "It is an error for a <variable> to appear
661          * more than once in the list of variables being bound." */
662         if (TRUEP(scm_p_memq(var, formals)))
663             ERR_OBJ(ERRMSG_DUPLICATE_VARNAME, var);
664 #endif
665         exp = CADR(binding);
666         val = EVAL(exp, env);
667         CHECK_VALID_BINDEE(permitted, val);
668 
669         /* construct formals and actuals list: any <init> must not refer a
670          * <variable> at this time */
671         formals = CONS(var, formals);
672         actuals = CONS(val, actuals);
673     }
674     if (!NULLP(bindings))
675         ERR_OBJ(ERRMSG_INVALID_BINDINGS, bindings);
676 
677     /* fill the placeholder frame */
678     eval_state->env = scm_replace_environment(formals, actuals, env);
679 
680     return scm_s_body(body, eval_state);
681 }
682 
683 /*
684  * Valid placement for definitions
685  *
686  * Definitions on SigScheme is strictly conformed to the three rule specified
687  * in R5RS (see below), when SCM_USE_INTERNAL_DEFINITIONS is enabled. All
688  * conditions that are not specified by the rules cause syntax error.
689  *
690  * 5.2 Definitions
691  *
692  * Definitions are valid in some, but not all, contexts where expressions are
693  * allowed. They are valid only at the top level of a <program> and at the
694  * beginning of a <body>.
695  *
696  * 5.2.2 Internal definitions
697  *
698  * Definitions may occur at the beginning of a <body> (that is, the body of a
699  * lambda, let, let*, letrec, let-syntax, or letrec-syntax expression or that
700  * of a definition of an appropriate form).
701  *
702  * Wherever an internal definition may occur (begin <definition1> ...) is
703  * equivalent to the sequence of definitions that form the body of the begin.
704  *
705  * 7.1.6 Programs and definitions
706  *
707  * <definition> --> (define <variable> <expression>)
708  *       | (define (<variable> <def formals>) <body>)
709  *       | (begin <definition>*)
710  */
711 
712 #if SCM_USE_INTERNAL_DEFINITIONS
713 static ScmObj
filter_definitions(ScmObj body,ScmObj * formals,ScmObj * actuals,ScmQueue * def_expq)714 filter_definitions(ScmObj body, ScmObj *formals, ScmObj *actuals,
715                    ScmQueue *def_expq)
716 {
717     ScmObj exp, var, sym, begin_rest, lambda_formals, lambda_body;
718     DECLARE_INTERNAL_FUNCTION("(body)");
719 
720     for (; CONSP(body); POP(body)) {
721         exp = CAR(body);
722         if (!CONSP(exp))
723             break;
724         sym = POP(exp);
725         if (EQ(sym, l_sym_begin)) {
726             begin_rest = filter_definitions(exp, formals, actuals, def_expq);
727             if (!NULLP(begin_rest)) {
728                 /* no definitions found */
729                 if (begin_rest == exp)
730                     return body;
731 
732                 ERR_OBJ("definitions and expressions intermixed", CAR(body));
733             }
734             /* '(begin)' is a valid R5RS definition form */
735         } else if (EQ(sym, l_sym_define)) {
736             var = MUST_POP_ARG(exp);
737             if (IDENTIFIERP(var)) {
738                 /* (define <variable> <expression>) */
739                 if (!LIST_1_P(exp))
740                     ERR_OBJ(ERRMSG_BAD_DEFINE_FORM, CAR(body));
741                 exp = CAR(exp);
742             } else if (CONSP(var)) {
743                 /* (define (<variable> . <formals>) <body>) */
744                 sym            = CAR(var);
745                 lambda_formals = CDR(var);
746                 lambda_body    = exp;
747 
748                 ENSURE_SYMBOL(sym);
749                 var = sym;
750                 exp = CONS(l_syn_lambda, CONS(lambda_formals, lambda_body));
751             } else {
752                 ERR_OBJ(ERRMSG_BAD_DEFINE_FORM, CAR(body));
753             }
754             *formals = CONS(var, *formals);
755             *actuals = CONS(SCM_UNBOUND, *actuals);
756             SCM_QUEUE_ADD(*def_expq, exp);
757         } else {
758             break;
759         }
760     }
761 
762     return body;
763 }
764 
765 /* <body> part of let, let*, letrec and lambda. This function performs strict
766  * form validation for internal definitions as specified in R5RS ("5.2.2
767  * Internal definitions" and "7.1.6 Programs and definitions"). */
768 /* TODO: Introduce compilation phase and reorganize into compile-time syntax
769  * transformer */
770 SCM_EXPORT ScmObj
scm_s_body(ScmObj body,ScmEvalState * eval_state)771 scm_s_body(ScmObj body, ScmEvalState *eval_state)
772 {
773     ScmQueue def_expq;
774     ScmObj env, formals, actuals, def_exps, exp, val;
775     DECLARE_INTERNAL_FUNCTION("(body)" /* , syntax_variadic_tailrec_0 */);
776 
777     if (CONSP(body)) {
778         /* collect internal definitions */
779         def_exps = formals = actuals = SCM_NULL;
780         SCM_QUEUE_POINT_TO(def_expq, def_exps);
781         body = filter_definitions(body, &formals, &actuals, &def_expq);
782 
783         if (!NULLP(def_exps)) {
784             /* extend env with the unbound variables */
785             env = scm_extend_environment(formals, actuals, eval_state->env);
786 
787             /* eval the definitions and fill the variables with the results as
788              * if letrec */
789             actuals = SCM_NULL;
790             FOR_EACH (exp, def_exps) {
791                 val = EVAL(exp, env);
792                 CHECK_VALID_EVALED_VALUE(val);
793                 actuals = CONS(val, actuals);
794             }
795             eval_state->env = scm_update_environment(actuals, env);
796         }
797     }
798     /* eval rest of the body */
799     return scm_s_begin(body, eval_state);
800 }
801 #endif /* SCM_USE_INTERNAL_DEFINITIONS */
802 
803 /*===========================================================================
804   R5RS : 4.2 Derived expression types : 4.2.3 Sequencing
805 ===========================================================================*/
806 SCM_EXPORT ScmObj
scm_s_begin(ScmObj args,ScmEvalState * eval_state)807 scm_s_begin(ScmObj args, ScmEvalState *eval_state)
808 {
809     ScmObj expr, env;
810     DECLARE_FUNCTION("begin", syntax_variadic_tailrec_0);
811 
812     if (SCM_DEFINABLE_TOPLEVELP(eval_state)) {
813         if (!CONSP(args)) {
814             /* '(begin)' */
815             ASSERT_NO_MORE_ARG(args);
816             eval_state->ret_type = SCM_VALTYPE_AS_IS;
817             return SCM_UNDEF;
818         }
819         env = eval_state->env;
820 #if SCM_STRICT_TOPLEVEL_DEFINITIONS
821         eval_state->nest = SCM_NEST_RETTYPE_BEGIN;
822 #endif
823     } else {
824         if (!CONSP(args))
825             ERR(ERRMSG_EXPRESSION_REQUIRED);
826         env = FORBID_TOPLEVEL_DEFINITIONS(eval_state->env);
827     }
828 
829     FOR_EACH_BUTLAST (expr, args) {
830         expr = EVAL(expr, env);
831         CHECK_VALID_EVALED_VALUE(expr);
832     }
833     ASSERT_NO_MORE_ARG(args);
834 
835     return expr;
836 }
837 
838 /*===========================================================================
839   R5RS : 4.2 Derived expression types : 4.2.4 Iteration
840 ===========================================================================*/
841 SCM_EXPORT ScmObj
scm_s_do(ScmObj bindings,ScmObj test_exps,ScmObj commands,ScmEvalState * eval_state)842 scm_s_do(ScmObj bindings, ScmObj test_exps, ScmObj commands,
843          ScmEvalState *eval_state)
844 {
845     ScmQueue stepq;
846     ScmObj env, orig_env, rest, rest_commands, val, termp;
847     ScmObj formals, actuals, steps;
848     ScmObj binding, var, init, step;
849     ScmObj test, exps, command;
850     DECLARE_FUNCTION("do", syntax_variadic_tailrec_2);
851 
852     orig_env = eval_state->env;
853 
854     /*
855      * (do ((<variable1> <init1> <step1>)
856      *      (<variable2> <init2> <step2>)
857      *      ...)
858      *     (<test> <expression> ...)
859      *   <command> ...)
860      */
861 
862     /* extract bindings ((<variable> <init> <step>) ...) */
863     env = FORBID_TOPLEVEL_DEFINITIONS(orig_env);
864     formals = actuals = steps = SCM_NULL;
865     SCM_QUEUE_POINT_TO(stepq, steps);
866     rest = bindings;
867     FOR_EACH (binding, rest) {
868         if (!CONSP(binding))
869             goto err;
870         var  = POP(binding);
871         ENSURE_SYMBOL(var);
872 #if SCM_STRICT_ARGCHECK
873         /* Optional check. Keeping variable name unique is user's
874          * responsibility. R5RS: "It is an error for a <variable> to appear
875          * more than once in the list of `do' variables.". */
876         if (TRUEP(scm_p_memq(var, formals)))
877             ERR_OBJ(ERRMSG_DUPLICATE_VARNAME, var);
878 #endif
879 
880         if (!CONSP(binding))
881             goto err;
882         init = POP(binding);
883 
884         step = (CONSP(binding)) ? POP(binding) : var;
885         if (!NULLP(binding))
886             goto err;
887 
888         init = EVAL(init, env);
889         CHECK_VALID_EVALED_VALUE(init);
890         formals = CONS(var, formals);
891         actuals = CONS(init, actuals);
892         SCM_QUEUE_ADD(stepq, step);
893     }
894     if (!NULLP(rest))
895         goto err;
896 
897     /* (<test> <expression> ...) */
898     if (!CONSP(test_exps))
899         ERR_OBJ("invalid test form", test_exps);
900     test = CAR(test_exps);
901     exps = CDR(test_exps);
902 
903     /* iteration phase */
904     rest_commands = commands;
905     /* extend env by <init>s */
906     env = scm_extend_environment(formals, actuals, orig_env);
907     while (termp = EVAL(test, env), FALSEP(termp)) {
908         rest_commands = commands;
909         FOR_EACH (command, rest_commands)
910             EVAL(command, env);
911         ASSERT_NO_MORE_ARG(rest_commands);
912 
913         /* Update variables by <step>s: <step>s evaluation must be isolated
914          * from the env for the next iteration. */
915         actuals = SCM_NULL;
916         rest = steps;
917         FOR_EACH (step, rest) {
918             val = EVAL(step, env);
919             CHECK_VALID_EVALED_VALUE(val);
920             actuals = CONS(val, actuals);
921         }
922         /* the envs for each iteration must be isolated and not be
923          * overwritten */
924         env = scm_extend_environment(formals, actuals, orig_env);
925     }
926 #if SCM_STRICT_ARGCHECK
927     /* no iteration occurred */
928     if (rest_commands == commands)
929         ENSURE_PROPER_ARG_LIST(commands);
930 #endif
931 
932     /* R5RS: If no <expression>s are present, then the value of the `do'
933      * expression is unspecified. */
934     eval_state->env = env;
935     if (NULLP(exps)) {
936         eval_state->ret_type = SCM_VALTYPE_AS_IS;
937         return SCM_UNDEF;
938     } else {
939 #if SCM_STRICT_TOPLEVEL_DEFINITIONS
940         eval_state->nest = SCM_NEST_COMMAND;
941 #endif
942         return scm_s_begin(exps, eval_state);
943     }
944 
945  err:
946     ERR_OBJ(ERRMSG_INVALID_BINDINGS, bindings);
947     /* NOTREACHED */
948     return SCM_FALSE;
949 }
950 
951 /*=======================================
952   R5RS : 5.2 Definitions
953 =======================================*/
954 SCM_EXPORT void
scm_s_define_internal(enum ScmObjType permitted,ScmObj var,ScmObj exp,ScmObj env)955 scm_s_define_internal(enum ScmObjType permitted,
956                       ScmObj var, ScmObj exp, ScmObj env)
957 {
958     ScmObj val;
959     DECLARE_INTERNAL_FUNCTION("define");
960 
961 #if SCM_USE_HYGIENIC_MACRO
962     SCM_ASSERT(SYMBOLP(var) || SYMBOLP(SCM_FARSYMBOL_SYM(var)));
963 #else
964     SCM_ASSERT(SYMBOLP(var));
965 #endif
966     var = SCM_UNWRAP_KEYWORD(var);
967     val = EVAL(exp, env);
968     CHECK_VALID_BINDEE(permitted, val);
969 
970     SCM_SYMBOL_SET_VCELL(var, val);
971 }
972 
973 /* To test ScmNestState, scm_s_define() needs eval_state although this is not a
974  * tail-recursive syntax */
975 SCM_EXPORT ScmObj
scm_s_define(ScmObj var,ScmObj rest,ScmEvalState * eval_state)976 scm_s_define(ScmObj var, ScmObj rest, ScmEvalState *eval_state)
977 {
978     ScmObj procname, body, formals, proc, env;
979     DECLARE_FUNCTION("define", syntax_variadic_tailrec_1);
980 
981     /* internal definitions are handled as a virtual letrec in
982      * scm_s_body() */
983     if (!SCM_DEFINABLE_TOPLEVELP(eval_state)) {
984 #if SCM_STRICT_TOPLEVEL_DEFINITIONS
985         if (scm_toplevel_environmentp(eval_state->env))
986             ERR_OBJ("toplevel definition is not allowed here", var);
987         else
988 #endif
989             ERR_OBJ(ERRMSG_BAD_DEFINE_PLACEMENT, var);
990     }
991     env = eval_state->env;
992 
993     /*=======================================================================
994       (define <variable> <expression>)
995     =======================================================================*/
996     if (IDENTIFIERP(var)) {
997         if (!LIST_1_P(rest))
998             goto err;
999 
1000         scm_s_define_internal(ScmFirstClassObj, var, CAR(rest), env);
1001     }
1002 
1003     /*=======================================================================
1004       (define (<variable> . <formals>) <body>)
1005 
1006       => (define <variable>
1007              (lambda <formals> <body>))
1008     =======================================================================*/
1009     else if (CONSP(var)) {
1010         procname = CAR(var);
1011         formals  = CDR(var);
1012         body     = rest;
1013 
1014         ENSURE_SYMBOL(procname);
1015         proc = scm_s_lambda(formals, body, env);
1016         scm_s_define_internal(ScmFirstClassObj, procname, proc, env);
1017     } else {
1018         goto err;
1019     }
1020 
1021     eval_state->ret_type = SCM_VALTYPE_AS_IS;
1022 #if SCM_STRICT_R5RS
1023     return SCM_UNDEF;
1024 #else
1025     return var;
1026 #endif
1027 
1028  err:
1029     ERR_OBJ(ERRMSG_BAD_DEFINE_FORM,
1030             CONS(l_sym_define, CONS(var, rest)));
1031     /* NOTREACHED */
1032     return SCM_FALSE;
1033 }
1034