+#include <stdlib.h>
+#include <stdio.h>
+
+#include "ast.h"
+
+struct ast *ast_alloc()
+{
+ struct ast *res = malloc(sizeof(struct ast));
+ if (res == NULL) {
+ perror("malloc");
+ exit(1);
+ }
+ return res;
+}
+
+struct ast *ast_cons(struct ast *el, struct ast *tail)
+{
+ struct ast *res = ast_alloc();
+ res->type = an_cons;
+ res->data.an_cons.el = el;
+ res->data.an_cons.tail = tail;
+ return res;
+}
+
+struct ast *ast_binop(struct ast *l, enum binop op, struct ast *r)
+{
+ struct ast *res = ast_alloc();
+ res->type = an_binop;
+ res->data.an_binop.l = l;
+ res->data.an_binop.op = op;
+ res->data.an_binop.r = r;
+ return res;
+}
+
+struct ast *ast_int(int integer)
+{
+ struct ast *res = ast_alloc();
+ res->type = an_int;
+ res->data.an_int = integer;
+ return res;
+}
+
+static const char *binop_str[] = {
+ [plus] = "+",
+ [minus] = "+",
+ [times] = "+",
+ [divide] = "+",
+};
+
+void ast_print(struct ast * ast, FILE *out)
+{
+ if (ast == NULL)
+ return;
+ switch(ast->type) {
+ case an_binop:
+ fprintf(out, "(");
+ ast_print(ast->data.an_binop.l, out);
+ fprintf(out, "%s", binop_str[ast->data.an_binop.op]);
+ ast_print(ast->data.an_binop.r, out);
+ fprintf(out, ")");
+ break;
+ case an_cons:
+ ast_print(ast->data.an_cons.el, out);
+ fprintf(out, ";\n");
+ ast_print(ast->data.an_cons.tail, out);
+ break;
+ case an_int:
+ fprintf(out, "%d", ast->data.an_int);
+ break;
+ default:
+ fprintf(stderr, "Unsupported AST node\n");
+ exit(1);
+ }
+}
+
+void ast_free(struct ast *ast)
+{
+ if (ast == NULL)
+ return;
+ switch(ast->type) {
+ case an_binop:
+ ast_free(ast->data.an_binop.l);
+ ast_free(ast->data.an_binop.r);
+ break;
+ case an_cons:
+ ast_free(ast->data.an_cons.el);
+ ast_free(ast->data.an_cons.tail);
+ break;
+ case an_int:
+ break;
+ default:
+ fprintf(stderr, "Unsupported AST node\n");
+ exit(1);
+ }
+ free(ast);
+}