@@ -75,6 +75,38 @@ static StObject syntax_let1(StObject module, StObject expr)
75
75
return St_SyntaxExpand (module , ret );
76
76
}
77
77
78
+ static StObject syntax_letrec (StObject module , StObject expr )
79
+ {
80
+ // (letrec <bindings> <body>)
81
+ // <bindings> ::= ((sym <expr>)*)
82
+ // =>
83
+ // ((lambda () (define s1 e1) (define e2 s2) ... body))
84
+
85
+ if (St_Length (expr ) < 2 )
86
+ {
87
+ St_Error ("letrec: malformed letrec" );
88
+ }
89
+
90
+ StObject bindings = ST_CADR (expr );
91
+ StObject body = ST_CDDR (expr );
92
+
93
+ validate_bindings (bindings );
94
+
95
+ StObject ds = Nil , t = Nil ;
96
+
97
+ ST_FOREACH (p , bindings ) {
98
+ StObject s = ST_CAAR (p );
99
+ StObject e = ST_CAR (ST_CDAR (p ));
100
+
101
+ ST_APPEND1 (ds , t , ST_LIST3 (I ("define" ), s , St_SyntaxExpand (module , e )));
102
+ }
103
+
104
+ return ST_LIST1 (St_Cons (I ("lambda" ),
105
+ St_Cons (Nil ,
106
+ St_Cons (St_Cons (I ("begin" ), ds ),
107
+ St_SyntaxExpand (module , body )))));
108
+ }
109
+
78
110
static StObject syntax_define (StObject module , StObject expr )
79
111
{
80
112
if (St_Length (expr ) < 2 )
@@ -180,6 +212,8 @@ void St_InitSyntax(void)
180
212
St_AddSyntax (m , "let" , syntax_let );
181
213
St_AddSyntax (m , "let*" , syntax_let );
182
214
St_AddSyntax (m , "let1" , syntax_let1 );
215
+ St_AddSyntax (m , "letrec" , syntax_letrec );
216
+ St_AddSyntax (m , "letrec*" , syntax_letrec );
183
217
St_AddSyntax (m , "define" , syntax_define );
184
218
St_AddSyntax (m , "cond" , syntax_cond );
185
219
St_AddSyntax (m , "case" , syntax_case );
0 commit comments