[an_assign] = "assign", [an_bool] = "bool", [an_binop] = "binop",
[an_char] = "char", [an_cons] = "cons", [an_funcall] = "funcall",
[an_fundecl] = "fundecl", [an_ident] = "ident", [an_if] = "if",
- [an_int] = "int", [an_list] = "list", [an_return] = "return",
- [an_stmt_expr] = "stmt_expr", [an_unop] = "unop",
- [an_vardecl] = "vardecl", [an_while] = "while",
+ [an_int] = "int", [an_nil] = "nil", [an_list] = "list",
+ [an_return] = "return", [an_stmt_expr] = "stmt_expr",
+ [an_unop] = "unop", [an_vardecl] = "vardecl", [an_while] = "while",
};
#endif
static const char *binop_str[] = {
[plus] = "+", [minus] = "-", [times] = "*", [divide] = "/",
[modulo] = "%", [power] = "^",
};
+static const char *fieldspec_str[] = {
+ [fst] = "fst", [snd] = "snd", [hd] = "hd", [tl] = "tl"};
static const char *unop_str[] = { [inverse] = "!", [negate] = "-", };
#ifdef DEBUG
{
struct ast *res = ast_alloc();
res->type = an_assign;
-
- must_be(ident, an_ident, "ident of an assign");
- res->data.an_assign.ident = ident->data.an_ident;
- free(ident);
-
+ res->data.an_assign.ident = ident;
res->data.an_assign.expr = expr;
return res;
}
//ident
must_be(ident, an_ident, "ident of a funcall");
- res->data.an_funcall.ident = ident->data.an_ident;
+ res->data.an_funcall.ident = ident->data.an_ident.ident;
+ free(ident->data.an_ident.fields);
free(ident);
//args
//ident
must_be(ident, an_ident, "ident of a fundecl");
- res->data.an_fundecl.ident = ident->data.an_ident;
+ res->data.an_fundecl.ident = ident->data.an_ident.ident;
+ free(ident->data.an_ident.fields);
free(ident);
//args
must_be(args, an_list, "args of a fundecl");
res->data.an_fundecl.nargs = args->data.an_list.n;
- res->data.an_fundecl.args = (char **)safe_malloc(
- args->data.an_list.n*sizeof(char *));
+ res->data.an_fundecl.args = (char **)args->data.an_list.ptr;
for (int i = 0; i<args->data.an_list.n; i++) {
struct ast *e = args->data.an_list.ptr[i];
must_be(e, an_ident, "arg of a fundecl")
- res->data.an_fundecl.args[i] = e->data.an_ident;
+ res->data.an_fundecl.args[i] = e->data.an_ident.ident;
+ free(e->data.an_ident.fields);
free(e);
}
free(args);
res->type = an_if;
res->data.an_if.pred = pred;
- must_be(body, an_list, "body of a then");
+ must_be(then, an_list, "body of a then");
res->data.an_if.nthen = then->data.an_list.n;
res->data.an_if.then = then->data.an_list.ptr;
free(then);
- must_be(body, an_list, "body of a els");
+ must_be(els, an_list, "body of a els");
res->data.an_if.nels = els->data.an_list.n;
res->data.an_if.els = els->data.an_list.ptr;
free(els);
return res;
}
-struct ast *ast_ident(char *ident)
+struct ast *ast_identc(char *ident)
+{
+ struct ast *res = ast_alloc();
+ res->type = an_ident;
+ res->data.an_ident.ident = safe_strdup(ident);
+ res->data.an_ident.nfields = 0;
+ res->data.an_ident.fields = NULL;
+ return res;
+}
+
+struct ast *ast_ident(struct ast *ident, struct ast *fields)
{
struct ast *res = ast_alloc();
res->type = an_ident;
- res->data.an_ident = safe_strdup(ident);
+ must_be(fields, an_ident, "ident of an ident");
+ res->data.an_ident.ident = ident->data.an_ident.ident;
+ free(ident);
+
+ must_be(fields, an_list, "fields of an ident");
+ res->data.an_ident.nfields = fields->data.an_list.n;
+ res->data.an_ident.fields = (enum fieldspec *)safe_malloc(
+ fields->data.an_list.n*sizeof(enum fieldspec));
+ for (int i = 0; i<fields->data.an_list.n; i++) {
+ struct ast *t = fields->data.an_list.ptr[i];
+ must_be(t, an_ident, "field of an ident");
+ if (strcmp(t->data.an_ident.ident, "fst") == 0)
+ res->data.an_ident.fields[i] = fst;
+ else if (strcmp(t->data.an_ident.ident, "snd") == 0)
+ res->data.an_ident.fields[i] = snd;
+ else if (strcmp(t->data.an_ident.ident, "hd") == 0)
+ res->data.an_ident.fields[i] = hd;
+ else if (strcmp(t->data.an_ident.ident, "tl") == 0)
+ res->data.an_ident.fields[i] = tl;
+ free(t->data.an_ident.ident);
+ free(t);
+ }
+ free(fields->data.an_list.ptr);
+ free(fields);
return res;
}
res->type = an_vardecl;
must_be(ident, an_ident, "ident of a vardecl");
- res->data.an_vardecl.ident = ident->data.an_ident;
+ res->data.an_vardecl.ident = ident->data.an_ident.ident;
+ free(ident->data.an_ident.fields);
free(ident);
res->data.an_vardecl.l = l;
return res;
switch(ast->type) {
case an_assign:
pindent(indent, out);
- safe_fprintf(out, "%s = ", ast->data.an_assign.ident);
+ ast_print(ast->data.an_assign.ident, indent, out);
+ safe_fprintf(out, " = ");
ast_print(ast->data.an_assign.expr, indent, out);
safe_fprintf(out, ";\n");
break;
safe_fprintf(out, "%d", ast->data.an_int);
break;
case an_ident:
- safe_fprintf(out, "%s", ast->data.an_ident);
+ fprintf(out, "%s", ast->data.an_ident.ident);
+ for (int i = 0; i<ast->data.an_ident.nfields; i++)
+ fprintf(out, ".%s",
+ fieldspec_str[ast->data.an_ident.fields[i]]);
break;
case an_cons:
ast_print(ast->data.an_cons.el, indent, out);
#endif
switch(ast->type) {
case an_assign:
- free(ast->data.an_assign.ident);
+ ast_free(ast->data.an_assign.ident);
ast_free(ast->data.an_assign.expr);
break;
case an_binop:
case an_funcall:
free(ast->data.an_funcall.ident);
for (int i = 0; i<ast->data.an_fundecl.nargs; i++)
- free(ast->data.an_fundecl.args[i]);
+ ast_free(ast->data.an_funcall.args[i]);
free(ast->data.an_funcall.args);
break;
case an_fundecl:
case an_int:
break;
case an_ident:
- free(ast->data.an_ident);
+ free(ast->data.an_ident.ident);
+ free(ast->data.an_ident.fields);
break;
case an_list:
for (int i = 0; i<ast->data.an_list.n; i++)