6
* expression library C program generator
9
#define _EX_CC_PRIVATE_ \
10
char* id; /* prefix + _ */ \
11
int lastop; /* last op */ \
12
int tmp; /* temp var index */ \
13
Exccdisc_t* ccdisc; /* excc() discipline */
18
#define EX_CC_DUMP 0x8000
20
static const char quote[] = "\"";
22
static void gen(Excc_t*, Exnode_t*);
25
* return C name for op
86
sfsprintf(buf, sizeof(buf) - 1, "(OP=%03o)", op);
95
print(Excc_t* cc, Exnode_t* expr)
100
if (x = expr->data.print.args)
102
sfprintf(cc->ccdisc->text, "sfprintf(%s, \"%s", expr->data.print.descriptor->op == CONSTANT && expr->data.print.descriptor->data.constant.value.integer == 2 ? "sfstderr" : "sfstdout", fmtesq(x->format, quote));
104
sfprintf(cc->ccdisc->text, "%s", fmtesq(x->format, quote));
105
sfprintf(cc->ccdisc->text, "\"");
106
for (x = expr->data.print.args; x; x = x->next)
110
for (i = 0; i < elementsof(x->param) && x->param[i]; i++)
112
sfprintf(cc->ccdisc->text, ", (");
113
gen(cc, x->param[i]);
114
sfprintf(cc->ccdisc->text, ")");
116
sfprintf(cc->ccdisc->text, ", (");
118
sfprintf(cc->ccdisc->text, ")");
121
sfprintf(cc->ccdisc->text, ");\n");
130
gen(Excc_t* cc, register Exnode_t* expr)
132
register Exnode_t* x;
133
register Exnode_t* y;
143
if (expr->op == CALL) {
144
sfprintf(cc->ccdisc->text, "%s(", expr->data.call.procedure->name);
145
if (expr->data.call.args) gen (cc, expr->data.call.args);
146
sfprintf(cc->ccdisc->text, ")");
149
x = expr->data.operand.left;
153
sfprintf(cc->ccdisc->text, "break;\n");
156
sfprintf(cc->ccdisc->text, "continue;\n");
162
sfprintf(cc->ccdisc->text, "%g", expr->data.constant.value.floating);
165
sfprintf(cc->ccdisc->text, "\"%s\"", fmtesq(expr->data.constant.value.string, quote));
168
sfprintf(cc->ccdisc->text, "%I*u", sizeof(expr->data.constant.value.integer), expr->data.constant.value.integer);
171
sfprintf(cc->ccdisc->text, "%I*d", sizeof(expr->data.constant.value.integer), expr->data.constant.value.integer);
176
sfprintf(cc->ccdisc->text, "%s--", x->data.variable.symbol->name);
179
sfprintf(cc->ccdisc->text, "%s", expr->data.variable.symbol->name);
182
sfprintf(cc->ccdisc->text, "exit(");
184
sfprintf(cc->ccdisc->text, ");\n");
187
sfprintf(cc->ccdisc->text, "if (");
189
sfprintf(cc->ccdisc->text, ") {\n");
190
gen(cc, expr->data.operand.right->data.operand.left);
191
if (expr->data.operand.right->data.operand.right)
193
sfprintf(cc->ccdisc->text, "} else {\n");
194
gen(cc, expr->data.operand.right->data.operand.right);
196
sfprintf(cc->ccdisc->text, "}\n");
199
sfprintf(cc->ccdisc->text, "for (;");
201
sfprintf(cc->ccdisc->text, ");");
202
if (expr->data.operand.left)
204
sfprintf(cc->ccdisc->text, "(");
205
gen(cc, expr->data.operand.left);
206
sfprintf(cc->ccdisc->text, ")");
208
sfprintf(cc->ccdisc->text, ") {");
209
if (expr->data.operand.right)
210
gen(cc, expr->data.operand.right);
211
sfprintf(cc->ccdisc->text, "}");
215
(*cc->ccdisc->ccf)(cc, expr, expr->data.variable.symbol, expr->data.variable.reference, expr->data.variable.index, cc->ccdisc);
217
sfprintf(cc->ccdisc->text, "%s", expr->data.variable.symbol->name);
220
sfprintf(cc->ccdisc->text, "%s++", x->data.variable.symbol->name);
223
if (expr->op == DYNAMIC)
225
sfprintf(cc->ccdisc->text, "{ Exassoc_t* %stmp_%d;", cc->id, ++cc->tmp);
226
sfprintf(cc->ccdisc->text, "for (%stmp_%d = (Exassoc_t*)dtfirst(%s); %stmp_%d && (%s = %stmp_%d->name); %stmp_%d = (Exassoc_t*)dtnext(%s, %stmp_%d)) {", cc->id, cc->tmp, expr->data.generate.array->data.variable.symbol->name, cc->id, cc->tmp, expr->data.generate.index->name, cc->id, cc->tmp, cc->id, cc->tmp, expr->data.generate.array->data.variable.symbol->name, cc->id, cc->tmp);
227
gen(cc, expr->data.generate.statement);
228
sfprintf(cc->ccdisc->text, "} }");
235
sfprintf(cc->ccdisc->text, "return(");
237
sfprintf(cc->ccdisc->text, ");\n");
241
sfprintf(cc->ccdisc->text, "{ %s %stmp_%d = ", extype(t), cc->id, ++cc->tmp);
243
sfprintf(cc->ccdisc->text, ";");
244
x = expr->data.operand.right;
245
y = x->data.select.statement;
247
while (x = x->data.select.next)
250
sfprintf(cc->ccdisc->text, "else ");
251
if (!(p = x->data.select.constant))
252
y = x->data.select.statement;
259
sfprintf(cc->ccdisc->text, "||");
263
sfprintf(cc->ccdisc->text, "if (");
266
sfprintf(cc->ccdisc->text, "strmatch(%stmp_%d, \"%s\")", cc->id, cc->tmp, fmtesq(v->string, quote));
269
sfprintf(cc->ccdisc->text, "%stmp_%d == ", cc->id, cc->tmp);
274
sfprintf(cc->ccdisc->text, "%I*u", sizeof(v->integer), v->integer);
277
sfprintf(cc->ccdisc->text, "%g", v->floating);
282
sfprintf(cc->ccdisc->text, ") {");
283
gen(cc, x->data.select.statement);
284
sfprintf(cc->ccdisc->text, "}");
290
sfprintf(cc->ccdisc->text, "else ");
291
sfprintf(cc->ccdisc->text, "{");
293
sfprintf(cc->ccdisc->text, "}");
295
sfprintf(cc->ccdisc->text, "}");
298
sfprintf(cc->ccdisc->text, "while (");
300
sfprintf(cc->ccdisc->text, ") {");
301
if (expr->data.operand.right)
302
gen(cc, expr->data.operand.right);
303
sfprintf(cc->ccdisc->text, "}");
306
sfprintf(cc->ccdisc->text, "(%s%s=", x->data.variable.symbol->name, expr->subop == '=' ? "" : opname(expr->subop));
307
gen(cc, expr->data.operand.right);
308
sfprintf(cc->ccdisc->text, ")");
313
if (!(x = expr->data.operand.right))
314
switch (cc->lastop = expr->data.operand.left->op)
323
sfprintf(cc->ccdisc->text, "_%svalue=", cc->id);
326
gen(cc, expr->data.operand.left);
327
sfprintf(cc->ccdisc->text, ";\n");
330
switch (cc->lastop = expr->op)
341
sfprintf(cc->ccdisc->text, "_%svalue=", cc->id);
345
sfprintf(cc->ccdisc->text, ";\n");
350
sfprintf(cc->ccdisc->text, "(");
352
while ((expr = expr->data.operand.right) && expr->op == ',')
354
sfprintf(cc->ccdisc->text, "), (");
355
gen(cc, expr->data.operand.left);
359
sfprintf(cc->ccdisc->text, "), (");
362
sfprintf(cc->ccdisc->text, ")");
365
sfprintf(cc->ccdisc->text, "(");
367
sfprintf(cc->ccdisc->text, ") ? (");
368
gen(cc, expr->data.operand.right->data.operand.left);
369
sfprintf(cc->ccdisc->text, ") : (");
370
gen(cc, expr->data.operand.right->data.operand.right);
371
sfprintf(cc->ccdisc->text, ")");
374
sfprintf(cc->ccdisc->text, "(");
376
sfprintf(cc->ccdisc->text, ") && (");
377
gen(cc, expr->data.operand.right);
378
sfprintf(cc->ccdisc->text, ")");
381
sfprintf(cc->ccdisc->text, "(");
383
sfprintf(cc->ccdisc->text, ") || (");
384
gen(cc, expr->data.operand.right);
385
sfprintf(cc->ccdisc->text, ")");
388
sfprintf(cc->ccdisc->text, "(%s)(", extype(INTEGER));
390
sfprintf(cc->ccdisc->text, ")");
393
sfprintf(cc->ccdisc->text, "(%s)(", extype(FLOATING));
395
sfprintf(cc->ccdisc->text, ")");
398
sfprintf(cc->ccdisc->text, "strto%s(", sizeof(_ast_intmax_t) > sizeof(long) ? "ll" : "l");
400
sfprintf(cc->ccdisc->text, ",(char**)0,0)");
403
y = expr->data.operand.right;
404
if (x->type == STRING)
409
sfprintf(cc->ccdisc->text, "*(");
411
sfprintf(cc->ccdisc->text, ")!=0");
414
sfprintf(cc->ccdisc->text, "strtod(");
416
sfprintf(cc->ccdisc->text, ",0)");
419
sfprintf(cc->ccdisc->text, "strtol(");
421
sfprintf(cc->ccdisc->text, ",0,0)");
424
sfprintf(cc->ccdisc->text, "** cannot convert string value to external **");
427
sfprintf(cc->ccdisc->text, "!");
430
sfprintf(cc->ccdisc->text, "strmatch(");
432
sfprintf(cc->ccdisc->text, ",");
434
sfprintf(cc->ccdisc->text, ")");
442
sfprintf(cc->ccdisc->text, "** string bits not supported **");
460
s = "** unknown string op **";
463
sfprintf(cc->ccdisc->text, "strcoll(");
465
sfprintf(cc->ccdisc->text, ",");
467
sfprintf(cc->ccdisc->text, ")%s", s);
473
sfprintf(cc->ccdisc->text, "%s", opname(expr->op));
474
sfprintf(cc->ccdisc->text, "(");
478
sfprintf(cc->ccdisc->text, ")%s(", opname(expr->op));
481
sfprintf(cc->ccdisc->text, ")");
487
* generate global declarations
491
global(Dt_t* table, void* object, void* handle)
493
register Excc_t* cc = (Excc_t*)handle;
494
register Exid_t* sym = (Exid_t*)object;
496
if (sym->lex == DYNAMIC)
497
sfprintf(cc->ccdisc->text, "static %s %s;\n", extype(sym->type), sym->name);
502
* open C program generator context
506
exccopen(Expr_t* expr, Exccdisc_t* disc)
511
if (!(id = disc->id))
513
if (!(cc = newof(0, Excc_t, 1, strlen(id) + 2)))
516
cc->disc = expr->disc;
517
cc->id = (char*)(cc + 1);
519
if (!(disc->flags & EX_CC_DUMP))
521
sfprintf(disc->text, "/* : : generated by %s : : */\n", exversion);
522
sfprintf(disc->text, "\n#include <ast.h>\n");
524
sfsprintf(cc->id, strlen(id) + 2, "%s_", id);
525
sfprintf(disc->text, "\n");
526
dtwalk(expr->symbols, global, cc);
532
* close C program generator context
536
exccclose(Excc_t* cc)
544
if (!(cc->ccdisc->flags & EX_CC_DUMP))
546
if (cc->ccdisc->text)
547
sfclose(cc->ccdisc->text);
557
* generate the program for name or sym coerced to type
561
excc(Excc_t* cc, const char* name, Exid_t* sym, int type)
568
sym = name ? (Exid_t*)dtmatch(cc->expr->symbols, name) : &cc->expr->main;
569
if (sym && sym->lex == PROCEDURE && sym->value)
572
sfprintf(cc->ccdisc->text, "\n%s %s%s(data) char** data; {\n%s _%svalue = 0;\n", t, cc->id, sym->name, t, cc->id);
573
gen(cc, sym->value->data.procedure.body);
574
sfprintf(cc->ccdisc->text, ";\n");
575
if (cc->lastop != RETURN)
576
sfprintf(cc->ccdisc->text, "return _%svalue;\n", cc->id);
577
sfprintf(cc->ccdisc->text, "}\n");
584
* dump an expression tree on sp
588
exdump(Expr_t* expr, Exnode_t* node, Sfio_t* sp)
594
memset(&ccdisc, 0, sizeof(ccdisc));
595
ccdisc.flags = EX_CC_DUMP;
597
if (!(cc = exccopen(expr, &ccdisc)))
602
for (sym = (Exid_t*)dtfirst(expr->symbols); sym; sym = (Exid_t*)dtnext(expr->symbols, sym))
603
if (sym->lex == PROCEDURE && sym->value)
605
sfprintf(sp, "\n%s:\n", sym->name);
606
gen(cc, sym->value->data.procedure.body);
609
return exccclose(cc);