1 /*
2 * macro.c - macro implementation
3 *
4 * Copyright (c) 2000-2020 Shiro Kawai <shiro@acm.org>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the authors nor the names of its contributors
18 * may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
27 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #define LIBGAUCHE_BODY
35 #include "gauche.h"
36 #include "gauche/code.h"
37 #include "gauche/vminsn.h"
38 #include "gauche/priv/macroP.h"
39 #include "gauche/priv/identifierP.h"
40 #include "gauche/priv/builtin-syms.h"
41
42 /* avoid C++ reserved name conflict.
43 (I hate languages that take away names from programmers!) */
44 #define template templat
45
46 /* define if you want to debug syntax-rule expander */
47 /*#define DEBUG_SYNRULE*/
48
49 /*===================================================================
50 * Syntax object
51 */
52
syntax_print(ScmObj obj,ScmPort * port,ScmWriteContext * mode SCM_UNUSED)53 static void syntax_print(ScmObj obj, ScmPort *port,
54 ScmWriteContext *mode SCM_UNUSED)
55 {
56 ScmSymbol *name = SCM_SYNTAX(obj)->name;
57 ScmModule *mod = SCM_SYNTAX(obj)->mod;
58 if (mod == NULL) {
59 Scm_Printf(port, "#<syntax %A>", (name ? SCM_OBJ(name) : SCM_FALSE));
60 } else {
61 Scm_Printf(port, "#<syntax %A#%A>",
62 mod->name,
63 (name ? SCM_OBJ(name) : SCM_FALSE));
64 }
65 }
66
67 SCM_DEFINE_BUILTIN_CLASS_SIMPLE(Scm_SyntaxClass, syntax_print);
68
Scm_MakeSyntax(ScmSymbol * name,ScmModule * mod,ScmObj handler)69 ScmObj Scm_MakeSyntax(ScmSymbol *name, ScmModule *mod, ScmObj handler)
70 {
71 ScmSyntax *s = SCM_NEW(ScmSyntax);
72 SCM_SET_CLASS(s, SCM_CLASS_SYNTAX);
73 s->name = name;
74 s->mod = mod;
75 s->handler = handler;
76 return SCM_OBJ(s);
77 }
78
79 /*===================================================================
80 * Macro object
81 */
82
Scm_MakeMacro(ScmObj name,ScmObj transformer,ScmObj src,ScmObj describer)83 ScmObj Scm_MakeMacro(ScmObj name, ScmObj transformer,
84 ScmObj src, ScmObj describer)
85 {
86 ScmMacro *s = SCM_NEW(ScmMacro);
87 SCM_SET_CLASS(s, SCM_CLASS_MACRO);
88 s->name = name;
89 s->transformer = transformer;
90 s->src = src;
91 s->describer = describer;
92 return SCM_OBJ(s);
93 }
94
Scm_MacroTransformer(ScmMacro * mac)95 ScmObj Scm_MacroTransformer(ScmMacro *mac)
96 {
97 return mac->transformer;
98 }
99
Scm_MacroName(ScmMacro * mac)100 ScmObj Scm_MacroName(ScmMacro *mac)
101 {
102 return (mac->name? SCM_OBJ(mac->name) : SCM_FALSE);
103 }
104
105 /*===================================================================
106 * SyntaxPattern object
107 * Repesents a repeatable subpattern
108 * (e.g. x ...), as well as the placeholder of the repeated match
109 * in a template.
110 */
111
112 typedef struct ScmSyntaxPatternRec {
113 SCM_HEADER;
114 ScmObj pattern; /* subpattern */
115 ScmObj vars; /* pattern variables in this subpattern */
116 short level; /* level of this subpattern */
117 short numFollowingItems; /* only used in pattern (not template).
118 this specifies the # of items that follows
119 the repetition, excluding the last CDR.
120
121 E.g. From (x ... y z), `x ...' part becomes
122 SyntaxPattern with numFollowingItems=2.
123 From (x ... . y), `x ...' part becomes
124 SyntaxPattern with numFollowingItems=0. */
125 } ScmSyntaxPattern;
126
127 SCM_CLASS_DECL(Scm_SyntaxPatternClass);
128 #define SCM_CLASS_SYNTAX_PATTERN (&Scm_SyntaxPatternClass)
129
130 #define SCM_SYNTAX_PATTERN(obj) ((ScmSyntaxPattern*)(obj))
131 #define SCM_SYNTAX_PATTERN_P(obj) SCM_XTYPEP(obj, SCM_CLASS_SYNTAX_PATTERN)
132
pattern_print(ScmObj obj,ScmPort * port,ScmWriteContext * ctx SCM_UNUSED)133 static void pattern_print(ScmObj obj, ScmPort *port,
134 ScmWriteContext *ctx SCM_UNUSED)
135 {
136 Scm_Printf(port, "#<pattern:%d%S %S%s>",
137 SCM_SYNTAX_PATTERN(obj)->level,
138 SCM_SYNTAX_PATTERN(obj)->vars,
139 SCM_SYNTAX_PATTERN(obj)->pattern,
140 SCM_SYNTAX_PATTERN(obj)->numFollowingItems? " ..." : "");
141 }
142
143 SCM_DEFINE_BUILTIN_CLASS_SIMPLE(Scm_SyntaxPatternClass, pattern_print);
144
make_syntax_pattern(int level,int numFollowing)145 ScmSyntaxPattern *make_syntax_pattern(int level, int numFollowing)
146 {
147 ScmSyntaxPattern *p = SCM_NEW(ScmSyntaxPattern);
148 SCM_SET_CLASS(p, SCM_CLASS_SYNTAX_PATTERN);
149 p->pattern = SCM_NIL;
150 p->vars = SCM_NIL;
151 p->level = level;
152 p->numFollowingItems = numFollowing;
153 return p;
154 }
155
156 /*===================================================================
157 * SyntaxRules object
158 * Internal object to construct pattern matcher
159 */
160
synrule_print(ScmObj obj,ScmPort * port,ScmWriteContext * mode SCM_UNUSED)161 static void synrule_print(ScmObj obj, ScmPort *port,
162 ScmWriteContext *mode SCM_UNUSED)
163 {
164 ScmSyntaxRules *r = SCM_SYNTAX_RULES(obj);
165
166 Scm_Printf(port, "#<syntax-rules(%d)\n", r->numRules);
167 for (int i = 0; i < r->numRules; i++) {
168 Scm_Printf(port, "%2d: (numPvars=%d, maxLevel=%d)\n",
169 i, r->rules[i].numPvars, r->rules[i].maxLevel);
170 Scm_Printf(port, " pattern = %S\n", r->rules[i].pattern);
171 Scm_Printf(port, " template = %S\n", r->rules[i].template);
172 }
173 Scm_Printf(port, ">");
174 }
175
176 SCM_DEFINE_BUILTIN_CLASS_SIMPLE(Scm_SyntaxRulesClass, synrule_print);
177
make_syntax_rules(int nr)178 ScmSyntaxRules *make_syntax_rules(int nr)
179 {
180 ScmSyntaxRules *r = SCM_NEW2(ScmSyntaxRules *,
181 sizeof(ScmSyntaxRules)+(nr-1)*sizeof(ScmSyntaxRuleBranch));
182 SCM_SET_CLASS(r, SCM_CLASS_SYNTAX_RULES);
183 r->numRules = nr;
184 return r;
185 }
186
187 /*===================================================================
188 * Traditional Macro
189 */
190
191 /* TRANSIENT
192 This used to be called via make-macro-transformer, but no longer.
193 We leave stub here for ABI compatibility. */
194 #if GAUCHE_API_VERSION < 1000
Scm_MakeMacroTransformerOld(ScmSymbol * name SCM_UNUSED,ScmProcedure * proc SCM_UNUSED)195 ScmObj Scm_MakeMacroTransformerOld(ScmSymbol *name SCM_UNUSED,
196 ScmProcedure *proc SCM_UNUSED)
197 {
198 Scm_Panic("Obsoleted Scm_MakeMacroTransformerOld called! Something is wrong!");
199 }
200 #endif /*GAUCHE_API_VERSION < 1000*/
201
resolve_macro_autoload(ScmAutoload * adata)202 static ScmMacro *resolve_macro_autoload(ScmAutoload *adata)
203 {
204 ScmObj mac = Scm_ResolveAutoload(adata, 0);
205 if (SCM_UNBOUNDP(mac)) {
206 Scm_Error("tried to autoload macro %S, but it caused circular autoload.", adata->name);
207 }
208 if (!SCM_MACROP(mac)) {
209 Scm_Error("tried to autoload macro %S, but it yields non-macro object: %S", adata->name, mac);
210 }
211 return SCM_MACRO(mac);
212 }
213
macro_autoload(ScmObj * argv,int argc,void * data)214 static ScmObj macro_autoload(ScmObj *argv, int argc, void *data)
215 {
216 SCM_ASSERT(argc == 2);
217 ScmObj form = argv[0];
218 ScmObj env = argv[1];
219 /* Important to save form and env before calling resolve_macro_autoload,
220 for it may overwrite stack region pointed by argv. */
221 SCM_ASSERT(SCM_AUTOLOADP(data));
222 ScmMacro *mac = resolve_macro_autoload(SCM_AUTOLOAD(data));
223 return Scm_CallMacroExpander(mac, form, env);
224 }
225
226 #define AUTOLOAD_MACRO_SUFFIX " (autoload)"
227
Scm_MakeMacroAutoload(ScmSymbol * name,ScmAutoload * adata)228 ScmObj Scm_MakeMacroAutoload(ScmSymbol *name, ScmAutoload *adata)
229 {
230 ScmObj transformer = Scm_MakeSubr(macro_autoload, adata,
231 2, 0, SCM_FALSE);
232 ScmObj name1 = Scm_StringAppendC(SCM_SYMBOL_NAME(name),
233 AUTOLOAD_MACRO_SUFFIX,
234 sizeof(AUTOLOAD_MACRO_SUFFIX)-1,
235 sizeof(AUTOLOAD_MACRO_SUFFIX)-1);
236 return Scm_MakeMacro(Scm_MakeSymbol(SCM_STRING(name1), FALSE),
237 transformer, SCM_FALSE, SCM_FALSE);
238 }
239
240 /*===================================================================
241 * R5RS Macro
242 */
243
244 /* Keeping hygienic reference
245 *
246 * - symbols which a template inserts into the expanded form are
247 * converted to identifiers at the macro definition time, encapsulating
248 * the defining environment of the macro. So it doesn't interfere
249 * with the macro call environment.
250 *
251 * - literal symbols provided to the syntax-rules are also converted
252 * to identifiers encapsulating the defining environment, and the
253 * environment information is used when comparing with the symbols
254 * in the macro call.
255 *
256 * - symbols in the macro call is treated as they are. Since the result
257 * of macro expansion is immediately compiled in the macro call
258 * environment, those symbols can refer proper bindings.
259 */
260
261 /*-------------------------------------------------------------------
262 * pattern language compiler
263 * - recognize repeatable subpatterns and replace it to SyntaxPattern node.
264 * - convert free symbols in the template into identifiers
265 * - convert pattern variables into LREF object.
266 */
267 /* TODO: avoid unnecessary consing as much as possible */
268
269 /* context of pattern traversal */
270 typedef struct {
271 ScmObj name; /* name of this macro (for error msg)*/
272 ScmObj form; /* form being compiled (for error msg) */
273 ScmObj literals; /* list of literals */
274 ScmObj pvars; /* list of (pvar . pvref) */
275 ScmObj renames; /* list of (var . identifier) Keep mapping
276 of input symbol/identifier to fresh
277 identifier */
278 ScmObj ellipsis; /* symbol/identifier/keyword for ellipsis
279 SCM_TRUE means default (...)
280 SCM_FALSE means disabled */
281 int pvcnt; /* counter of pattern variables */
282 int maxlev; /* maximum level */
283 ScmModule *mod; /* module where this macro is defined */
284 ScmObj env; /* compiler env of this macro definition */
285 } PatternContext;
286
287 #define PVREF_P(pvref) SCM_PVREF_P(pvref)
288 #define PVREF_LEVEL(pvref) (int)SCM_PVREF_LEVEL(pvref)
289 #define PVREF_COUNT(pvref) (int)SCM_PVREF_COUNT(pvref)
290
291 #define PVREF_LEVEL_MAX 0xff
292 #define PVREF_COUNT_MAX 0xff
293
294 /* add pattern variable pvar. called when compiling a pattern */
add_pvar(PatternContext * ctx,ScmSyntaxPattern * pat,ScmObj pvar)295 static inline ScmObj add_pvar(PatternContext *ctx,
296 ScmSyntaxPattern *pat,
297 ScmObj pvar)
298 {
299 if (pat->level > PVREF_LEVEL_MAX) {
300 Scm_Error("Pattern levels too deeply nested in the macro definition of %S", ctx->name);
301 }
302 if (ctx->pvcnt > PVREF_COUNT_MAX) {
303 Scm_Error("Too many pattern variables in the macro definition of %S", ctx->name);
304 }
305 ScmObj pvref = SCM_MAKE_PVREF(pat->level, ctx->pvcnt);
306 if (!SCM_FALSEP(Scm_Assq(pvar, ctx->pvars))) {
307 Scm_Error("Pattern variable %S appears more than once in the macro definition of %S: %S",
308 pvar, ctx->name, ctx->form);
309 }
310 ctx->pvcnt++;
311 ctx->pvars = Scm_Acons(pvar, pvref, ctx->pvars);
312 pat->vars = Scm_Cons(pvref, pat->vars);
313 return pvref;
314 }
315
316 /* returns pvref corresponds to the given pvar in template compilation.
317 if pvar is not a valid pvar, returns pvar itself. */
pvar_to_pvref(PatternContext * ctx,ScmSyntaxPattern * pat,ScmObj pvar)318 static inline ScmObj pvar_to_pvref(PatternContext *ctx,
319 ScmSyntaxPattern *pat,
320 ScmObj pvar)
321 {
322 ScmObj q = Scm_Assq(pvar, ctx->pvars);
323 if (!SCM_PAIRP(q)) return pvar;
324 ScmObj pvref = SCM_CDR(q);
325 if (PVREF_LEVEL(pvref) > pat->level) {
326 Scm_Error("%S: Pattern variable %S is used in wrong level: %S",
327 ctx->name, pvar, ctx->form);
328 }
329 return pvref;
330 }
331
isEllipsis(PatternContext * ctx,ScmObj obj)332 static int isEllipsis(PatternContext *ctx, ScmObj obj)
333 {
334 if (SCM_FALSEP(ctx->ellipsis)) return FALSE; /* inside (... TEMPLATE) */
335 if (SCM_TRUEP(ctx->ellipsis)) {
336 /* default ellipsis (...) */
337 return Scm__ERCompare(SCM_SYM_ELLIPSIS, obj, ctx->mod, ctx->env);
338 } else {
339 /* specified ellipsis */
340 return SCM_EQ(ctx->ellipsis, obj);
341 }
342 }
343
344 #define ELLIPSIS_FOLLOWING(Pat, Ctx) \
345 (SCM_PAIRP(SCM_CDR(Pat)) && isEllipsis(Ctx, SCM_CADR(Pat)))
346
347 #define BAD_ELLIPSIS(Ctx) \
348 Scm_Error("Bad ellipsis usage in macro definition of %S: %S", \
349 Ctx->name, Ctx->form)
350
check_literals(ScmObj literals)351 static ScmObj check_literals(ScmObj literals)
352 {
353 ScmObj lp, h = SCM_NIL, t = SCM_NIL;
354 SCM_FOR_EACH(lp, literals) {
355 ScmObj lit = SCM_CAR(lp);
356 if (SCM_SYMBOLP(lit) || SCM_IDENTIFIERP(lit))
357 SCM_APPEND1(h, t, lit);
358 else if (SCM_KEYWORDP(lit))
359 /* This branch is to allow r7rs-compliant code to go through
360 with legacy mode. If keyword-symbol integration is turned on,
361 we never reach here. */;
362 else Scm_Error("literal list contains non-symbol: %S", literals);
363 }
364 if (!SCM_NULLP(lp))
365 Scm_Error("bad literal list in syntax-rules: %S", literals);
366 return h;
367 }
368
369 /* Renaming: Map input variable (symbol or identifier) to fresh identifier.
370 The same (eq?) variable must map to the same identifier. */
rename_variable(ScmObj var,ScmObj * id_alist,ScmModule * mod,ScmObj env)371 static ScmObj rename_variable(ScmObj var,
372 ScmObj *id_alist, /* ((var . id) ...) */
373 ScmModule *mod,
374 ScmObj env)
375 {
376 ScmObj id, p = Scm_Assq(var, *id_alist);
377 if (SCM_PAIRP(p)) return SCM_CDR(p);
378 if (SCM_SYMBOLP(var)) {
379 id = Scm_MakeIdentifier(var, mod, env);
380 } else {
381 SCM_ASSERT(SCM_IDENTIFIERP(var));
382 id = Scm_WrapIdentifier(SCM_IDENTIFIER(var));
383 }
384 *id_alist = Scm_Acons(var, id, *id_alist);
385 return id;
386 }
387
388
389 /* Compile a pattern or a template.
390 In the pattern, we replace variables to identifiers.
391 We also recognize pattern variables, and replace them for PVARs in
392 the pattern, and for PVREFs in the template.
393 When encounters a repeatable subpattern, replace it with
394 SyntaxPattern node.
395 */
compile_rule1(ScmObj form,ScmSyntaxPattern * spat,PatternContext * ctx,int patternp)396 static ScmObj compile_rule1(ScmObj form,
397 ScmSyntaxPattern *spat,
398 PatternContext *ctx,
399 int patternp)
400 {
401 if (SCM_PAIRP(form)) {
402 ScmObj h = SCM_NIL, t = SCM_NIL;
403 int ellipsis_seen = FALSE;
404
405 if (SCM_PAIRP(SCM_CDR(form)) && isEllipsis(ctx, SCM_CAR(form))) {
406 /* (... <template>) */
407 if (patternp) {
408 Scm_Error("in definition of macro %S: "
409 "<ellipsis> can't appear at the beginning of "
410 "list/vector: %S", ctx->name, form);
411 }
412 ScmObj save_elli = ctx->ellipsis, r;
413 ctx->ellipsis = SCM_FALSE;
414 r = compile_rule1(SCM_CADR(form), spat, ctx, FALSE);
415 ctx->ellipsis = save_elli;
416 return r;
417 }
418
419 ScmObj pp;
420 SCM_FOR_EACH(pp, form) {
421 if (ELLIPSIS_FOLLOWING(pp, ctx)) {
422 if (patternp && ellipsis_seen) {
423 Scm_Error("in definition of macro %S: "
424 "Ellipses are not allowed to appear "
425 "within the same list/vector more than once "
426 "in a pattern: %S", ctx->name, form);
427 }
428 ellipsis_seen = TRUE;
429
430 ScmObj base = SCM_CAR(pp);
431 pp = SCM_CDR(pp);
432
433 int num_trailing = 0;
434 int ellipsis_nesting = 1;
435 if (patternp) {
436 /* Count trailing items to set ScmSyntaxPattern->repeat. */
437 ScmObj trailing = SCM_CDR(pp);
438 while (SCM_PAIRP(trailing)) {
439 num_trailing++;
440 trailing = SCM_CDR(trailing);
441 }
442 } else {
443 /* srfi-149 allows more than one ellipsis to follow a
444 template. */
445 while (ELLIPSIS_FOLLOWING(pp, ctx)) {
446 ellipsis_nesting++;
447 if (!SCM_PAIRP(SCM_CDR(pp))) break;
448 pp = SCM_CDR(pp);
449 }
450 }
451 /* at this point, pp points the last ellipsis */
452
453 if (ctx->maxlev < spat->level + ellipsis_nesting)
454 ctx->maxlev = spat->level + ellipsis_nesting + 1;
455
456 ScmSyntaxPattern *outermost =
457 make_syntax_pattern(spat->level+1, num_trailing);
458 ScmSyntaxPattern *outer = outermost;
459 for (int i=1; i<ellipsis_nesting; i++) {
460 ScmSyntaxPattern *inner =
461 make_syntax_pattern(spat->level+i+1, 0);
462 outer->pattern = SCM_OBJ(inner);
463 outer = inner;
464 }
465 outer->pattern = compile_rule1(base, outer, ctx, patternp);
466 outermost->vars = outer->vars;
467 SCM_APPEND1(h, t, SCM_OBJ(outermost));
468 if (!patternp) {
469 ScmObj vp;
470 if (SCM_NULLP(outermost->vars)) {
471 Scm_Error("in definition of macro %S: "
472 "a template contains repetition "
473 "of constant form: %S",
474 ctx->name, form);
475 }
476 SCM_FOR_EACH(vp, outermost->vars) {
477 if (PVREF_LEVEL(SCM_CAR(vp)) >= outermost->level) break;
478 }
479 if (SCM_NULLP(vp)) {
480 Scm_Error("in definition of macro %S: "
481 "template's ellipsis nesting"
482 " is deeper than pattern's: %S",
483 ctx->name, form);
484 }
485 }
486 spat->vars = Scm_Append2(spat->vars, outermost->vars);
487 } else {
488 SCM_APPEND1(h, t,
489 compile_rule1(SCM_CAR(pp), spat, ctx, patternp));
490 }
491 }
492 if (!SCM_NULLP(pp))
493 SCM_APPEND(h, t, compile_rule1(pp, spat, ctx, patternp));
494 return h;
495 }
496 else if (SCM_VECTORP(form)) {
497 /* TODO: this is a sloppy implementation.
498 Eliminate intermediate list structure! */
499 ScmObj l = Scm_VectorToList(SCM_VECTOR(form), 0, -1);
500 return Scm_ListToVector(compile_rule1(l, spat, ctx, patternp), 0, -1);
501 }
502 if (SCM_SYMBOLP(form)||SCM_IDENTIFIERP(form)) {
503 if (isEllipsis(ctx, form)) BAD_ELLIPSIS(ctx);
504 if (!SCM_FALSEP(Scm_Memq(form, ctx->literals))) {
505 if (patternp)
506 return rename_variable(form, &ctx->renames, ctx->mod, ctx->env);
507 else
508 return form; /* template renaming is done in expansion time */
509 }
510 if (patternp && Scm__ERCompare(form, SCM_SYM_UNDERBAR,
511 ctx->mod, ctx->env)) {
512 return SCM_SYM_UNDERBAR;
513 }
514 if (patternp) {
515 return add_pvar(ctx, spat, form);
516 } else {
517 ScmObj pvref = pvar_to_pvref(ctx, spat, form);
518 if (pvref == form) {
519 return form;
520 } else {
521 spat->vars = Scm_Cons(pvref, spat->vars);
522 return pvref;
523 }
524 }
525 }
526 return form;
527 }
528
529 /* compile rules into ScmSyntaxRules structure
530 NB: We use ScmSyntaxPattern for the toplevel node of pattern and template;
531 they are just a placeholders and they don't represent repetition. */
compile_rules(ScmObj name,ScmObj ellipsis,ScmObj literals,ScmObj rules,ScmModule * mod,ScmObj env)532 static ScmSyntaxRules *compile_rules(ScmObj name,
533 ScmObj ellipsis,
534 ScmObj literals,
535 ScmObj rules,
536 ScmModule *mod,
537 ScmObj env) /* compiler env */
538 {
539 PatternContext ctx;
540 int numRules = Scm_Length(rules);
541
542 if (numRules < 0) goto badform;
543 if (Scm_Length(literals) < 0) goto badform;
544
545 ctx.name = name;
546 ctx.ellipsis = ellipsis;
547 ctx.literals = check_literals(literals);
548 ctx.mod = mod;
549 ctx.env = env;
550 ctx.renames = SCM_NIL;
551
552 /* Corner case when literal contains the same (free-identifer=?) symbol
553 as ellipsis. R7RS specifies the literal has precedence.
554 https://srfi-email.schemers.org/srfi-148/msg/6115633 */
555 if (!SCM_FALSEP(ellipsis)) {
556 ScmObj cp;
557 SCM_FOR_EACH(cp, ctx.literals) {
558 if (isEllipsis(&ctx, SCM_CAR(cp))) {
559 ctx.ellipsis = SCM_FALSE;
560 break;
561 }
562 }
563 }
564
565 ScmSyntaxRules *sr = make_syntax_rules(numRules);
566 sr->name = name;
567 sr->numRules = numRules;
568 sr->maxNumPvars = 0;
569 sr->mod = mod;
570 sr->env = env;
571 ScmObj rp = rules;
572 for (int i=0; i < numRules; i++, rp = SCM_CDR(rp)) {
573 ScmObj rule = SCM_CAR(rp);
574 if (Scm_Length(rule) != 2) goto badform;
575
576 ScmSyntaxPattern *pat = make_syntax_pattern(0, 0);
577 ScmSyntaxPattern *tmpl = make_syntax_pattern(0, 0);
578 ctx.pvars = SCM_NIL;
579 ctx.pvcnt = 0;
580 ctx.maxlev = 0;
581
582 ctx.form = SCM_CAR(rule);
583 if (!SCM_PAIRP(ctx.form)) goto badform;
584 pat->pattern = compile_rule1(SCM_CDR(ctx.form), pat, &ctx, TRUE);
585
586 ctx.form = SCM_CADR(rule);
587 tmpl->pattern = compile_rule1(ctx.form, tmpl, &ctx, FALSE);
588
589 sr->rules[i].pattern = SCM_OBJ(pat->pattern);
590 sr->rules[i].template = SCM_OBJ(tmpl->pattern);
591 sr->rules[i].numPvars = ctx.pvcnt;
592 sr->rules[i].maxLevel = ctx.maxlev;
593 if (ctx.pvcnt > sr->maxNumPvars) sr->maxNumPvars = ctx.pvcnt;
594 }
595 return sr;
596
597 badform:
598 Scm_Error("malformed macro %S: %S", name,
599 Scm_Cons(SCM_SYM_SYNTAX_RULES, Scm_Cons(literals, rules)));
600 return NULL; /* dummy */
601 }
602
603 /*-------------------------------------------------------------------
604 * pattern language matcher
605 */
606
607 /* Matchvec
608 * A sort of shallow binding technique is used to bind pattern
609 * variables with matched patterns.
610 *
611 * Matchlist itself is an assoc list whose key is a pattern variable.
612 * It's value is a tree of the same depth of the pattern variable.
613 *
614 * Suppose you have a pattern
615 * (?a (?b (?c ?d ...) ...) ...)
616 * In it, pattern variable ?a is level 0, ?b is 1, ?c is 2 and ?d is 3.
617 * When the pattern matches the following form:
618 * (1 (2 (3 4 5) (6)) (7 (8 9) (10 11 12)))
619 * trees bound to each pattern variables are like this:
620 *
621 * ?a => 1
622 * ?b => (2 7)
623 * ?c => ((3 6) (8 10))
624 * ?d => (((4 5) ()) ((9) (11 12)))
625 */
626
627 typedef struct {
628 ScmObj branch; /* current level match */
629 ScmObj sprout; /* current sprout */
630 ScmObj root; /* root of the tree */
631 } MatchVar;
632
alloc_matchvec(int numPvars)633 static MatchVar *alloc_matchvec(int numPvars)
634 {
635 return SCM_NEW_ARRAY(MatchVar, numPvars);
636 }
637
init_matchvec(MatchVar * mvec,int numPvars)638 static void init_matchvec(MatchVar *mvec, int numPvars)
639 {
640 int i;
641 for (i=0; i<numPvars; i++) {
642 mvec[i].branch = mvec[i].sprout = mvec[i].root = SCM_NIL;
643 }
644 }
645
646 /* get value associated to the pvref. if exhausted, return SCM_UNBOUND
647 and set exhaust level in *exlev. */
get_pvref_value(ScmObj pvref,MatchVar * mvec,int * indices,int * exlev)648 static ScmObj get_pvref_value(ScmObj pvref, MatchVar *mvec,
649 int *indices, int *exlev)
650 {
651 int level = PVREF_LEVEL(pvref), count = PVREF_COUNT(pvref);
652 ScmObj tree = mvec[count].root;
653 for (int i=1; i<=level; i++) {
654 for (int j=0; j<indices[i]; j++) {
655 if (!SCM_PAIRP(tree)) {
656 *exlev = i;
657 return SCM_UNBOUND;
658 }
659 tree = SCM_CDR(tree);
660 }
661 if (!SCM_PAIRP(tree)) {
662 *exlev = i;
663 return SCM_UNBOUND;
664 }
665 tree = SCM_CAR(tree);
666 }
667 return tree;
668 }
669
670 /* for debug */
671 #ifdef DEBUG_SYNRULE
print_matchvec(MatchVar * mvec,int numPvars,ScmPort * port)672 static void print_matchvec(MatchVar *mvec, int numPvars, ScmPort *port)
673 {
674 for (int i=0; i<numPvars; i++) {
675 Scm_Printf(port, "[%S %S %S]\n",
676 mvec[i].branch, mvec[i].sprout, mvec[i].root);
677 }
678 }
679 #endif
680
681 static int match_synrule(ScmObj form, ScmObj pattern, ScmObj mod, ScmObj env,
682 MatchVar *mvec);
683
684 #define SPROUT Scm_Cons(SCM_NIL, SCM_NIL)
685
686 /* add a new "sprout" to the given tree at the given level. */
grow_branch(MatchVar * rec,int level)687 static void grow_branch(MatchVar *rec, int level)
688 {
689 if (level <= 1) return;
690 if (rec->root == SCM_NIL) {
691 rec->sprout = rec->root = SPROUT;
692 if (level == 2) return;
693 }
694
695 ScmObj trunc = rec->root;
696 for (int i=1; i<level-1; i++, trunc = SCM_CAR(trunc)) {
697 SCM_FOR_EACH(trunc, trunc) {
698 if (SCM_NULLP(SCM_CDR(trunc))) break;
699 }
700 if (SCM_NULLP(SCM_CAR(trunc))) {
701 for (i++; i<level-1; i++, trunc = SCM_CAR(trunc)) {
702 SCM_SET_CAR_UNCHECKED(trunc, SPROUT);
703 }
704 rec->sprout = SPROUT;
705 SCM_SET_CAR_UNCHECKED(trunc, rec->sprout);
706 return;
707 }
708 }
709 SCM_FOR_EACH(trunc, trunc) {
710 if (SCM_NULLP(SCM_CDR(trunc))) {
711 rec->sprout = SPROUT;
712 SCM_SET_CDR_UNCHECKED(trunc, rec->sprout);
713 break;
714 }
715 }
716 }
717
enter_subpattern(ScmSyntaxPattern * subpat,MatchVar * mvec)718 static void enter_subpattern(ScmSyntaxPattern *subpat, MatchVar *mvec)
719 {
720 ScmObj pp;
721 SCM_FOR_EACH(pp, subpat->vars) {
722 ScmObj pvref = SCM_CAR(pp);
723 int count = PVREF_COUNT(pvref);
724 grow_branch(mvec+count, subpat->level);
725 }
726 }
727
exit_subpattern(ScmSyntaxPattern * subpat,MatchVar * mvec)728 static void exit_subpattern(ScmSyntaxPattern *subpat, MatchVar *mvec)
729 {
730 ScmObj pp;
731 SCM_FOR_EACH(pp, subpat->vars) {
732 ScmObj pvref = SCM_CAR(pp);
733 int count = PVREF_COUNT(pvref);
734 if (PVREF_LEVEL(pvref) == subpat->level) {
735 if (subpat->level == 1) {
736 mvec[count].root = Scm_ReverseX(mvec[count].branch);
737 } else {
738 SCM_SET_CAR_UNCHECKED(mvec[count].sprout,
739 Scm_ReverseX(mvec[count].branch));
740 mvec[count].branch = SCM_NIL;
741 }
742 }
743 }
744 }
745
746 /* add pattern variable PVREF and its matched object MATCHED into MVEC */
match_insert(ScmObj pvref,ScmObj matched,MatchVar * mvec)747 static inline void match_insert(ScmObj pvref, ScmObj matched, MatchVar *mvec)
748 {
749 int count = PVREF_COUNT(pvref);
750 if (PVREF_LEVEL(pvref) == 0) {
751 mvec[count].root = matched;
752 } else {
753 mvec[count].branch = Scm_Cons(matched, mvec[count].branch);
754 }
755 }
756
match_subpattern(ScmObj form,ScmSyntaxPattern * pat,ScmObj rest,ScmObj mod,ScmObj env,MatchVar * mvec)757 static inline int match_subpattern(ScmObj form, ScmSyntaxPattern *pat,
758 ScmObj rest, ScmObj mod, ScmObj env,
759 MatchVar *mvec)
760 {
761 /* TODO: If pat->numFollowingItems == 0, we don't need to calculate
762 length beforehand. Some optimization opportunity. */
763 int limit = 0;
764 for (ScmObj p = form; SCM_PAIRP(p); p = SCM_CDR(p)) {
765 limit++;
766 }
767 limit -= pat->numFollowingItems;
768
769 enter_subpattern(pat, mvec);
770 while (limit > 0) {
771 if (!match_synrule(SCM_CAR(form), pat->pattern, mod, env, mvec))
772 return FALSE;
773 form = SCM_CDR(form);
774 limit--;
775 }
776 exit_subpattern(pat, mvec);
777 return match_synrule(form, rest, mod, env, mvec);
778 }
779
780 /* See if form matches pattern. If match, add matched syntax variable
781 bindings to match vector and return TRUE; otherwise, return FALSE
782 */
match_synrule(ScmObj form,ScmObj pattern,ScmObj mod,ScmObj env,MatchVar * mvec)783 static int match_synrule(ScmObj form, ScmObj pattern, ScmObj mod, ScmObj env,
784 MatchVar *mvec)
785 {
786 if (PVREF_P(pattern)) {
787 match_insert(pattern, form, mvec);
788 return TRUE;
789 }
790 if (SCM_EQ(pattern, SCM_SYM_UNDERBAR)) {
791 return TRUE; /* unconditional match */
792 }
793 if (SCM_IDENTIFIERP(pattern)) {
794 return Scm__ERCompare(pattern, form, SCM_MODULE(mod), env);
795 }
796 if (SCM_SYNTAX_PATTERN_P(pattern)) {
797 return match_subpattern(form, SCM_SYNTAX_PATTERN(pattern),
798 SCM_NIL, mod, env, mvec);
799 }
800 if (SCM_PAIRP(pattern)) {
801 while (SCM_PAIRP(pattern)) {
802 ScmObj elt = SCM_CAR(pattern);
803 if (SCM_SYNTAX_PATTERN_P(elt)) {
804 return match_subpattern(form, SCM_SYNTAX_PATTERN(elt),
805 SCM_CDR(pattern),
806 mod, env, mvec);
807 } else if (!SCM_PAIRP(form)) {
808 return FALSE;
809 } else {
810 if (!match_synrule(SCM_CAR(form), elt, mod, env, mvec))
811 return FALSE;
812 pattern = SCM_CDR(pattern);
813 form = SCM_CDR(form);
814 }
815 }
816 if (!SCM_NULLP(pattern))
817 return match_synrule(form, pattern, mod, env, mvec);
818 else
819 return SCM_NULLP(form);
820 }
821 if (SCM_VECTORP(pattern)) {
822 if (!SCM_VECTORP(form)) return FALSE;
823 int plen = SCM_VECTOR_SIZE(pattern);
824 int elli = SCM_VECTOR_SIZE(form);
825 int flen = elli;
826 int has_elli = FALSE;
827 if (plen == 0) return (flen == 0);
828 for (int i=0; i < plen; i++) {
829 if (SCM_SYNTAX_PATTERN_P(SCM_VECTOR_ELEMENT(pattern, i))) {
830 has_elli = TRUE;
831 elli = i;
832 break;
833 }
834 }
835 if ((!has_elli && plen!=flen) || (has_elli && plen-1>flen)) return FALSE;
836
837 for (int i=0; i < elli; i++) {
838 if (!match_synrule(SCM_VECTOR_ELEMENT(form, i),
839 SCM_VECTOR_ELEMENT(pattern, i),
840 mod, env, mvec))
841 return FALSE;
842 }
843 if (elli < flen) {
844 ScmObj pat = SCM_VECTOR_ELEMENT(pattern, elli);
845 ScmObj prest = Scm_VectorToList(SCM_VECTOR(pattern), elli+1, plen);
846 ScmObj frest = Scm_VectorToList(SCM_VECTOR(form), elli, flen);
847 return match_subpattern(frest, SCM_SYNTAX_PATTERN(pat),
848 prest, mod, env, mvec);
849 } else {
850 return TRUE;
851 }
852 }
853
854 /* literal */
855 return Scm_EqualP(pattern, form);
856 }
857
858 /*-------------------------------------------------------------------
859 * pattern language transformer
860 */
861
862 /* If a pattern variable is exhausted, SCM_UNDEFINED is returned. */
realize_template_rec(ScmSyntaxRules * sr,ScmObj template,MatchVar * mvec,int level,int * indices,ScmObj * idlist,int * exlev)863 static ScmObj realize_template_rec(ScmSyntaxRules *sr,
864 ScmObj template,
865 MatchVar *mvec,
866 int level,
867 int *indices,
868 ScmObj *idlist,
869 int *exlev)
870 {
871 if (SCM_PAIRP(template)) {
872 ScmObj h = SCM_NIL, t = SCM_NIL;
873 while (SCM_PAIRP(template)) {
874 ScmObj e = SCM_CAR(template);
875 if (SCM_SYNTAX_PATTERN_P(e)) {
876 ScmObj r = realize_template_rec(sr, e, mvec, level, indices, idlist, exlev);
877 if (SCM_UNBOUNDP(r)) return r;
878 SCM_APPEND(h, t, r);
879 } else {
880 ScmObj r = realize_template_rec(sr, e, mvec, level, indices, idlist, exlev);
881 if (SCM_UNBOUNDP(r)) return r;
882 SCM_APPEND1(h, t, r);
883 }
884 template = SCM_CDR(template);
885 }
886 if (!SCM_NULLP(template)) {
887 ScmObj r = realize_template_rec(sr, template, mvec, level, indices, idlist, exlev);
888 if (SCM_UNBOUNDP(r)) return r;
889 if (SCM_NULLP(h)) return r; /* (a ... . b) and a ... is empty */
890 SCM_APPEND(h, t, r);
891 }
892 return h;
893 }
894 if (PVREF_P(template)) {
895 return get_pvref_value(template, mvec, indices, exlev);
896 }
897 if (SCM_SYNTAX_PATTERN_P(template)) {
898 ScmSyntaxPattern *pat = SCM_SYNTAX_PATTERN(template);
899 ScmObj h = SCM_NIL, t = SCM_NIL;
900 indices[level+1] = 0;
901 for (;;) {
902 ScmObj r = realize_template_rec(sr, pat->pattern, mvec, level+1, indices, idlist, exlev);
903 if (SCM_UNBOUNDP(r)) return (*exlev < pat->level)? r : h;
904 if (SCM_SYNTAX_PATTERN_P(pat->pattern)) {
905 SCM_APPEND(h, t, r);
906 } else {
907 SCM_APPEND1(h, t, r);
908 }
909 indices[level+1]++;
910 }
911 }
912 if (SCM_VECTORP(template)) {
913 ScmObj h = SCM_NIL, t = SCM_NIL;
914 int len = SCM_VECTOR_SIZE(template);
915 ScmObj *pe = SCM_VECTOR_ELEMENTS(template);
916
917 for (int i=0; i<len; i++, pe++) {
918 if (SCM_SYNTAX_PATTERN_P(*pe)) {
919 ScmObj r = realize_template_rec(sr, *pe, mvec, level, indices, idlist, exlev);
920 if (SCM_UNBOUNDP(r)) return r;
921 SCM_APPEND(h, t, r);
922 } else {
923 ScmObj r = realize_template_rec(sr, *pe, mvec, level, indices, idlist, exlev);
924 if (SCM_UNBOUNDP(r)) return r;
925 SCM_APPEND1(h, t, r);
926 }
927 }
928 return Scm_ListToVector(h, 0, -1);
929 }
930 if (SCM_SYMBOLP(template) || SCM_IDENTIFIERP(template)) {
931 return rename_variable(template, idlist, sr->mod, sr->env);
932 }
933 return template;
934 }
935
936 #define DEFAULT_MAX_LEVEL 10
937
realize_template(ScmSyntaxRules * sr,ScmSyntaxRuleBranch * branch,MatchVar * mvec)938 static ScmObj realize_template(ScmSyntaxRules *sr,
939 ScmSyntaxRuleBranch *branch,
940 MatchVar *mvec)
941 {
942 int index[DEFAULT_MAX_LEVEL], *indices = index;
943 int exlev = 0;
944 ScmObj idlist = SCM_NIL;
945
946 if (branch->maxLevel > DEFAULT_MAX_LEVEL)
947 indices = SCM_NEW_ATOMIC2(int*, (branch->maxLevel+1) * sizeof(int));
948 for (int i=0; i<=branch->maxLevel; i++) indices[i] = 0;
949 return realize_template_rec(sr, branch->template, mvec, 0,
950 indices, &idlist, &exlev);
951 }
952
synrule_expand(ScmObj form,ScmObj mod,ScmObj env,ScmSyntaxRules * sr)953 static ScmObj synrule_expand(ScmObj form, ScmObj mod, ScmObj env, ScmSyntaxRules *sr)
954 {
955 MatchVar *mvec = alloc_matchvec(sr->maxNumPvars);
956
957 #ifdef DEBUG_SYNRULE
958 Scm_Printf(SCM_CUROUT, "**** synrule_transform: %S\n", form);
959 #endif
960 for (int i=0; i<sr->numRules; i++) {
961 #ifdef DEBUG_SYNRULE
962 Scm_Printf(SCM_CUROUT, "pattern #%d: %S\n", i, sr->rules[i].pattern);
963 #endif
964 init_matchvec(mvec, sr->rules[i].numPvars);
965 if (match_synrule(SCM_CDR(form), sr->rules[i].pattern, mod, env, mvec)) {
966 #ifdef DEBUG_SYNRULE
967 Scm_Printf(SCM_CUROUT, "success #%d:\n", i);
968 print_matchvec(mvec, sr->rules[i].numPvars, SCM_CUROUT);
969 #endif
970 ScmObj expanded = realize_template(sr, &sr->rules[i], mvec);
971 #ifdef DEBUG_SYNRULE
972 Scm_Printf(SCM_CUROUT, "result: %S\n", expanded);
973 #endif
974 return expanded;
975 }
976 }
977 Scm_Error("malformed %S: %S", SCM_CAR(form), form);
978 return SCM_NIL;
979 }
980
synrule_transform(ScmObj * argv,int argc,void * data)981 static ScmObj synrule_transform(ScmObj *argv, int argc, void *data)
982 {
983 SCM_ASSERT(argc == 2);
984 ScmObj form = argv[0];
985 ScmObj cenv = argv[1];
986 SCM_ASSERT(SCM_VECTORP(cenv));
987 ScmObj module = SCM_VECTOR_ELEMENT(cenv, 0); /* macro use env */
988 ScmObj frames = SCM_VECTOR_ELEMENT(cenv, 1); /* macro use env */
989 ScmSyntaxRules *sr = (ScmSyntaxRules *)data;
990 return synrule_expand(form, module, frames, sr);
991 }
992
993 /* NB: a stub for the new compiler (TEMPORARY) */
Scm_CompileSyntaxRules(ScmObj name,ScmObj src,ScmObj ellipsis,ScmObj literals,ScmObj rules,ScmObj mod,ScmObj env)994 ScmObj Scm_CompileSyntaxRules(ScmObj name, ScmObj src, ScmObj ellipsis,
995 ScmObj literals, ScmObj rules,
996 ScmObj mod, ScmObj env)
997 {
998 if (SCM_IDENTIFIERP(name)) name = SCM_OBJ(SCM_IDENTIFIER(name)->name);
999 if (!SCM_MODULEP(mod)) Scm_Error("module required, but got %S", mod);
1000 ScmSyntaxRules *sr = compile_rules(name, ellipsis, literals, rules,
1001 SCM_MODULE(mod), env);
1002 ScmObj sr_xform = Scm_MakeSubr(synrule_transform, sr,
1003 2, 0, SCM_FALSE);
1004 return Scm_MakeMacro(name, sr_xform, src, SCM_FALSE);
1005 }
1006
1007 /*===================================================================
1008 * macro-expand
1009 */
1010
1011 /* TRANSIENT
1012 Now it's in compile.scm (%internal-macro-expand). This is kept
1013 for ABI compatibility, but nobody is supposed to call this.
1014 */
1015 #if GAUCHE_API_VERSION < 1000
Scm_VMMacroExpand(ScmObj expr SCM_UNUSED,ScmObj env SCM_UNUSED,int oncep SCM_UNUSED)1016 ScmObj Scm_VMMacroExpand(ScmObj expr SCM_UNUSED,
1017 ScmObj env SCM_UNUSED,
1018 int oncep SCM_UNUSED)
1019 {
1020 Scm_Error("Scm_VMMacroExpand is obsoleted.");
1021 return SCM_UNDEFINED;
1022 }
1023 #endif /*GAUCHE_API_VERSION < 1000*/
1024
Scm_CallMacroExpander(ScmMacro * mac,ScmObj expr,ScmObj cenv)1025 ScmObj Scm_CallMacroExpander(ScmMacro *mac, ScmObj expr, ScmObj cenv)
1026 {
1027 SCM_ASSERT(SCM_VECTORP(cenv));
1028 return Scm_ApplyRec2(mac->transformer, expr, cenv);
1029 }
1030
1031 /*===================================================================
1032 * Initializer
1033 */
1034
Scm__InitMacro(void)1035 void Scm__InitMacro(void)
1036 {
1037 Scm_InitStaticClass(&Scm_SyntaxPatternClass, "<syntax-pattern>",
1038 Scm_GaucheInternalModule(), NULL, 0);
1039 }
1040