1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36: #define LIBGAUCHE_BODY
37: #include "gauche.h"
38: #include "gauche/macro.h"
39: #include "gauche/code.h"
40: #include "gauche/vminsn.h"
41: #include "gauche/builtin-syms.h"
42:
43:
44:
45: #define template templat
46:
47:
48:
49:
50:
51:
52:
53:
54: static void syntax_print(ScmObj obj, ScmPort *port, ScmWriteContext *mode)
55: {
56: Scm_Printf(port, "#<syntax %A>", SCM_SYNTAX(obj)->name);
57: }
58:
59: SCM_DEFINE_BUILTIN_CLASS_SIMPLE(Scm_SyntaxClass, syntax_print);
60:
61: ScmObj Scm_MakeSyntax(ScmSymbol *name, ScmObj handler)
62: {
63: ScmSyntax *s = SCM_NEW(ScmSyntax);
64: SCM_SET_CLASS(s, SCM_CLASS_SYNTAX);
65: s->name = name;
66: s->handler = handler;
67: return SCM_OBJ(s);
68: }
69:
70:
71:
72:
73:
74: static void macro_print(ScmObj obj, ScmPort *port, ScmWriteContext *mode)
75: {
76: Scm_Printf(port, "#<macro %A>", SCM_MACRO(obj)->name);
77: }
78:
79: SCM_DEFINE_BUILTIN_CLASS_SIMPLE(Scm_MacroClass, macro_print);
80:
81: ScmObj Scm_MakeMacro(ScmSymbol *name, ScmTransformerProc transformer,
82: void *data)
83: {
84: ScmMacro *s = SCM_NEW(ScmMacro);
85: SCM_SET_CLASS(s, SCM_CLASS_MACRO);
86: s->name = name;
87: s->transformer = transformer;
88: s->data = data;
89: return SCM_OBJ(s);
90: }
91:
92:
93:
94:
95:
96:
97: static void pattern_print(ScmObj obj, ScmPort *port, ScmWriteContext *ctx)
98: {
99: Scm_Printf(port, "#<pattern:%d%S %S%s>",
100: SCM_SYNTAX_PATTERN(obj)->level,
101: SCM_SYNTAX_PATTERN(obj)->vars,
102: SCM_SYNTAX_PATTERN(obj)->pattern,
103: SCM_SYNTAX_PATTERN(obj)->repeat? " ..." : "");
104: }
105:
106: SCM_DEFINE_BUILTIN_CLASS_SIMPLE(Scm_SyntaxPatternClass, pattern_print);
107:
108: ScmSyntaxPattern *make_syntax_pattern(int level, int repeat)
109: {
110: ScmSyntaxPattern *p = SCM_NEW(ScmSyntaxPattern);
111: SCM_SET_CLASS(p, SCM_CLASS_SYNTAX_PATTERN);
112: p->pattern = SCM_NIL;
113: p->vars = SCM_NIL;
114: p->level = level;
115: p->repeat = repeat;
116: return p;
117: }
118:
119:
120:
121:
122:
123:
124: static void synrule_print(ScmObj obj, ScmPort *port, ScmWriteContext *mode)
125: {
126: int i;
127: ScmSyntaxRules *r = SCM_SYNTAX_RULES(obj);
128:
129: Scm_Printf(port, "#<syntax-rules(%d)\n", r->numRules);
130: for (i = 0; i < r->numRules; i++) {
131: Scm_Printf(port, "%2d: (numPvars=%d, maxLevel=%d)\n",
132: i, r->rules[i].numPvars, r->rules[i].maxLevel);
133: Scm_Printf(port, " pattern = %S\n", r->rules[i].pattern);
134: Scm_Printf(port, " template = %S\n", r->rules[i].template);
135: }
136: Scm_Printf(port, ">");
137: }
138:
139: SCM_DEFINE_BUILTIN_CLASS_SIMPLE(Scm_SyntaxRulesClass, synrule_print);
140:
141: ScmSyntaxRules *make_syntax_rules(int nr)
142: {
143: ScmSyntaxRules *r = SCM_NEW2(ScmSyntaxRules *,
144: sizeof(ScmSyntaxRules)+(nr-1)*sizeof(ScmSyntaxRuleBranch));
145: SCM_SET_CLASS(r, SCM_CLASS_SYNTAX_RULES);
146: r->numRules = nr;
147: return r;
148: }
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186: static ScmObj macro_transform(ScmObj self, ScmObj form, ScmObj env,
187: void *data)
188: {
189: ScmObj proc = SCM_OBJ(data);
190: SCM_ASSERT(SCM_SYNTACTIC_CLOSURE_P(form));
191: return Scm_ApplyRec(proc, SCM_LIST1(form));
192: }
193:
194: ScmObj Scm_MakeMacroTransformer(ScmSymbol *name, ScmObj proc)
195: {
196: return Scm_MakeMacro(name, macro_transform, (void*)proc);
197: }
198:
199:
200:
201:
202:
203:
204:
205:
206:
207: static ScmObj macro_transform_old(ScmObj self, ScmObj form,
208: ScmObj env, void *data)
209: {
210: ScmObj proc = SCM_OBJ(data);
211: SCM_ASSERT(SCM_PAIRP(form));
212: return Scm_VMApply(proc, SCM_CDR(form));
213: }
214:
215: ScmObj Scm_MakeMacroTransformerOld(ScmSymbol *name, ScmProcedure *proc)
216: {
217: return Scm_MakeMacro(name, macro_transform_old, (void*)proc);
218: }
219:
220: static ScmMacro *resolve_macro_autoload(ScmAutoload *adata)
221: {
222: ScmObj mac = Scm_ResolveAutoload(adata, 0);
223: if (SCM_UNBOUNDP(mac)) {
224: Scm_Error("tried to autoload macro %S, but it caused circular autoload.", adata->name);
225: }
226: if (!SCM_MACROP(mac)) {
227: Scm_Error("tried to autoload macro %S, but it yields non-macro object: %S", adata->name, mac);
228: }
229: return SCM_MACRO(mac);
230: }
231:
232: static ScmObj macro_autoload(ScmObj self, ScmObj form, ScmObj env, void *data)
233: {
234: ScmMacro *mac = resolve_macro_autoload(SCM_AUTOLOAD(data));
235: return mac->transformer(SCM_OBJ(mac), form, env, mac->data);
236: }
237:
238: ScmObj Scm_MakeMacroAutoload(ScmSymbol *name, ScmAutoload *adata)
239: {
240: return Scm_MakeMacro(name, macro_autoload, (void*)adata);
241: }
242:
243:
244:
245:
246:
247:
248:
249:
250:
251:
252:
253:
254:
255:
256:
257:
258:
259:
260:
261:
262:
263:
264:
265:
266:
267:
268:
269:
270:
271:
272:
273:
274: typedef struct {
275: ScmObj name;
276: ScmObj form;
277: ScmObj literals;
278: ScmObj pvars;
279: int pvcnt;
280: int maxlev;
281: ScmObj tvars;
282: ScmModule *mod;
283: ScmObj env;
284: } PatternContext;
285:
286: #define PVREF_P(pvref) SCM_PVREF_P(pvref)
287: #define PVREF_LEVEL(pvref) (int)SCM_PVREF_LEVEL(pvref)
288: #define PVREF_COUNT(pvref) (int)SCM_PVREF_COUNT(pvref)
289:
290:
291: static inline ScmObj add_pvar(PatternContext *ctx,
292: ScmSyntaxPattern *pat,
293: ScmObj pvar)
294: {
295: ScmObj pvref = SCM_MAKE_PVREF(pat->level, ctx->pvcnt);
296: if (!SCM_FALSEP(Scm_Assq(pvar, ctx->pvars))) {
297: Scm_Error("pattern variable %S appears more than once in the macro definition of %S: %S",
298: pvar, ctx->name, ctx->form);
299: }
300: ctx->pvcnt++;
301: ctx->pvars = Scm_Acons(pvar, pvref, ctx->pvars);
302: pat->vars = Scm_Cons(pvref, pat->vars);
303: return pvref;
304: }
305:
306:
307:
308: static inline ScmObj pvar_to_pvref(PatternContext *ctx,
309: ScmSyntaxPattern *pat,
310: ScmObj pvar)
311: {
312: ScmObj q = Scm_Assq(pvar, ctx->pvars), pvref;
313: if (!SCM_PAIRP(q)) return pvar;
314: pvref = SCM_CDR(q);
315: if (PVREF_LEVEL(pvref) > pat->level) {
316: Scm_Error("%S: Pattern variable %S is used in wrong level: %S",
317: ctx->name, pvar, ctx->form);
318: }
319: return pvref;
320: }
321:
322: static inline ScmObj pvref_to_pvar(PatternContext *ctx, ScmObj pvref)
323: {
324: int count = PVREF_COUNT(pvref);
325: ScmObj q = Scm_ListRef(ctx->pvars, count, SCM_UNBOUND);
326: SCM_ASSERT(SCM_PAIRP(q));
327: return SCM_CAR(q);
328: }
329:
330:
331: static ScmObj id_memq(ScmObj name, ScmObj list)
332: {
333: ScmObj lp;
334: ScmObj n;
335: if (SCM_IDENTIFIERP(name)) {
336: n = SCM_OBJ(SCM_IDENTIFIER(name)->name);
337: } else {
338: n = name;
339: }
340: SCM_FOR_EACH(lp, list) {
341: if (SCM_OBJ(SCM_IDENTIFIER(SCM_CAR(lp))->name) == name)
342: return SCM_CAR(lp);
343: }
344: return SCM_FALSE;
345: }
346:
347: #define ELLIPSIS_FOLLOWING(Pat) \
348: (SCM_PAIRP(SCM_CDR(Pat)) && SCM_CADR(Pat)==SCM_SYM_ELLIPSIS)
349:
350: #define BAD_ELLIPSIS(Ctx) \
351: Scm_Error("Bad ellipsis usage in macro definition of %S: %S", \
352: Ctx->name, Ctx->form)
353:
354:
355: static ScmObj preprocess_literals(ScmObj literals, ScmModule *mod, ScmObj env)
356: {
357: ScmObj lp, h = SCM_NIL, t = SCM_NIL;
358: SCM_FOR_EACH(lp, literals) {
359: ScmObj lit = SCM_CAR(lp);
360: if (SCM_IDENTIFIERP(lit))
361: SCM_APPEND1(h, t, lit);
362: else if (SCM_SYMBOLP(lit))
363: SCM_APPEND1(h, t, Scm_MakeIdentifier(SCM_SYMBOL(lit), mod, env));
364: else
365: Scm_Error("literal list contains non-symbol: %S", literals);
366: }
367: if (!SCM_NULLP(lp))
368: Scm_Error("bad literal list in syntax-rules: %S", literals);
369: return h;
370: }
371:
372:
373:
374:
375:
376:
377:
378:
379:
380: static ScmObj compile_rule1(ScmObj form,
381: ScmSyntaxPattern *spat,
382: PatternContext *ctx,
383: int patternp)
384: {
385: if (SCM_PAIRP(form)) {
386: ScmObj pp, h = SCM_NIL, t = SCM_NIL;
387: SCM_FOR_EACH(pp, form) {
388: if (ELLIPSIS_FOLLOWING(pp)) {
389: ScmSyntaxPattern *nspat;
390: if (patternp && !SCM_NULLP(SCM_CDDR(pp))) BAD_ELLIPSIS(ctx);
391: nspat = make_syntax_pattern(spat->level+1, TRUE);
392: if (ctx->maxlev <= spat->level) ctx->maxlev++;
393: nspat->pattern = compile_rule1(SCM_CAR(pp), nspat, ctx,
394: patternp);
395: SCM_APPEND1(h, t, SCM_OBJ(nspat));
396: if (!patternp) {
397: ScmObj vp;
398: if (SCM_NULLP(nspat->vars)) {
399: Scm_Error("in definition of macro %S: "
400: "a template contains repetition "
401: "of constant form: %S",
402: ctx->name, form);
403: }
404: SCM_FOR_EACH(vp, nspat->vars) {
405: if (PVREF_LEVEL(SCM_CAR(vp)) >= nspat->level) break;
406: }
407: if (SCM_NULLP(vp)) {
408: Scm_Error("in definition of macro %S: "
409: "template's ellipsis nesting"
410: " is deeper than pattern's: %S",
411: ctx->name, form);
412: }
413: }
414: spat->vars = Scm_Append2(spat->vars, nspat->vars);
415: pp = SCM_CDR(pp);
416: } else {
417: SCM_APPEND1(h, t,
418: compile_rule1(SCM_CAR(pp), spat, ctx, patternp));
419: }
420: }
421: if (!SCM_NULLP(pp))
422: SCM_APPEND(h, t, compile_rule1(pp, spat, ctx, patternp));
423: return h;
424: }
425: else if (SCM_VECTORP(form)) {
426:
427:
428: ScmObj l = Scm_VectorToList(SCM_VECTOR(form), 0, -1);
429: return Scm_ListToVector(compile_rule1(l, spat, ctx, patternp), 0, -1);
430: }
431: #if 0
432: else if (patternp && SCM_IDENTIFIERP(form)) {
433:
434: form = SCM_OBJ(SCM_IDENTIFIER(form)->name);
435: }
436: #endif
437: if (SCM_SYMBOLP(form)||SCM_IDENTIFIERP(form)) {
438: ScmObj q;
439: if (form == SCM_SYM_ELLIPSIS) BAD_ELLIPSIS(ctx);
440: if (!SCM_FALSEP(q = id_memq(form, ctx->literals))) return q;
441:
442: if (patternp) {
443: return add_pvar(ctx, spat, form);
444: } else {
445: ScmObj id, pvref = pvar_to_pvref(ctx, spat, form);
446: if (pvref == form) {
447:
448: if (!SCM_FALSEP(q = id_memq(form, ctx->tvars))) return q;
449: if (SCM_IDENTIFIERP(form)) {
450: id = form;
451: } else {
452: id = Scm_MakeIdentifier(SCM_SYMBOL(form),
453: ctx->mod, ctx->env);
454: }
455: ctx->tvars = Scm_Cons(id, ctx->tvars);
456: return id;
457: } else {
458: spat->vars = Scm_Cons(pvref, spat->vars);
459: }
460: return pvref;
461: }
462: }
463: return form;
464: }
465:
466:
467: static ScmSyntaxRules *compile_rules(ScmObj name,
468: ScmObj literals,
469: ScmObj rules,
470: ScmModule *mod,
471: ScmObj env)
472: {
473: PatternContext ctx;
474: ScmSyntaxPattern *pat, *tmpl;
475: ScmSyntaxRules *sr;
476: ScmObj rp;
477: int numRules = Scm_Length(rules), i;
478:
479: if (numRules < 1) goto badform;
480: if (Scm_Length(literals) < 0) goto badform;
481:
482: ctx.name = name;
483: ctx.literals = preprocess_literals(literals, mod, env);
484: ctx.mod = mod;
485: ctx.env = env;
486:
487: sr = make_syntax_rules(numRules);
488: sr->name = name;
489: sr->numRules = numRules;
490: sr->maxNumPvars = 0;
491: for (i=0, rp = rules; i < numRules; i++, rp = SCM_CDR(rp)) {
492: ScmObj rule = SCM_CAR(rp);
493: if (Scm_Length(rule) != 2) goto badform;
494:
495: pat = make_syntax_pattern(0, FALSE);
496: tmpl = make_syntax_pattern(0, FALSE);
497: ctx.pvars = SCM_NIL;
498: ctx.tvars = SCM_NIL;
499: ctx.pvcnt = 0;
500: ctx.maxlev = 0;
501:
502: ctx.form = SCM_CAR(rule);
503: if (!SCM_PAIRP(ctx.form)) goto badform;
504: pat->pattern = compile_rule1(SCM_CDR(ctx.form), pat, &ctx, TRUE);
505:
506: ctx.form = SCM_CADR(rule);
507: tmpl->pattern = compile_rule1(ctx.form, tmpl, &ctx, FALSE);
508:
509: sr->rules[i].pattern = SCM_OBJ(pat->pattern);
510: sr->rules[i].template = SCM_OBJ(tmpl->pattern);
511: sr->rules[i].numPvars = ctx.pvcnt;
512: sr->rules[i].maxLevel = ctx.maxlev;
513: if (ctx.pvcnt > sr->maxNumPvars) sr->maxNumPvars = ctx.pvcnt;
514: }
515: return sr;
516:
517: badform:
518: Scm_Error("malformed macro %S: %S", name,
519: Scm_Cons(SCM_SYM_SYNTAX_RULES, Scm_Cons(literals, rules)));
520: return NULL;
521: }
522:
523:
524:
525:
526:
527:
528:
529:
530:
531:
532:
533:
534:
535:
536:
537:
538:
539:
540:
541:
542:
543:
544:
545:
546:
547: typedef struct {
548: ScmObj branch;
549: ScmObj sprout;
550: ScmObj root;
551: } MatchVar;
552:
553: static MatchVar *alloc_matchvec(int numPvars)
554: {
555: return SCM_NEW_ARRAY(MatchVar, numPvars);
556: }
557:
558: static void init_matchvec(MatchVar *mvec, int numPvars)
559: {
560: int i;
561: for (i=0; i<numPvars; i++) {
562: mvec[i].branch =