1 #include "system/stacktrace.h"
8 #include "ebisp/expr.h"
12 struct Expr atom_as_expr(struct Atom *atom)
22 struct Expr cons_as_expr(struct Cons *cons)
32 struct Expr void_expr(void)
41 void print_atom_as_sexpr(FILE *stream, struct Atom *atom)
47 fprintf(stream, "%s", atom->sym);
51 fprintf(stream, "%ld", atom->num);
55 fprintf(stream, "\"%s\"", atom->str);
59 /* TODO(#649): Print LAMBDAs with arglists (and maybe bodies) in print_atom_as_sexpr and atom_as_sexpr */
60 fprintf(stream, "<lambda>");
64 fprintf(stream, "<native>");
69 void print_cons_as_sexpr(FILE *stream, struct Cons *head)
73 struct Cons *cons = head;
76 print_expr_as_sexpr(stream, cons->car);
78 while (cons->cdr.type == EXPR_CONS) {
79 cons = cons->cdr.cons;
81 print_expr_as_sexpr(stream, cons->car);
84 if (cons->cdr.atom->type != ATOM_SYMBOL ||
85 strcmp("nil", cons->cdr.atom->sym) != 0) {
86 fprintf(stream, " . ");
87 print_expr_as_sexpr(stream, cons->cdr);
93 void print_expr_as_sexpr(FILE *stream, struct Expr expr)
97 print_atom_as_sexpr(stream, expr.atom);
101 print_cons_as_sexpr(stream, expr.cons);
109 void destroy_expr(struct Expr expr)
113 destroy_atom(expr.atom);
117 destroy_cons(expr.cons);
125 struct Cons *create_cons(Gc *gc, struct Expr car, struct Expr cdr)
127 struct Cons *cons = malloc(sizeof(struct Cons));
135 if (gc_add_expr(gc, cons_as_expr(cons)) < 0) {
143 void destroy_cons(struct Cons *cons)
148 struct Atom *create_number_atom(Gc *gc, long int num)
150 struct Atom *atom = malloc(sizeof(struct Atom));
154 atom->type = ATOM_NUMBER;
157 if (gc_add_expr(gc, atom_as_expr(atom)) < 0) {
165 struct Atom *create_string_atom(Gc *gc, const char *str, const char *str_end)
167 struct Atom *atom = malloc(sizeof(struct Atom));
173 atom->type = ATOM_STRING;
174 atom->str = string_duplicate(str, str_end);
176 if (atom->str == NULL) {
180 if (gc_add_expr(gc, atom_as_expr(atom)) < 0) {
188 if (atom->str != NULL) {
197 struct Atom *create_symbol_atom(Gc *gc, const char *sym, const char *sym_end)
199 struct Atom *atom = malloc(sizeof(struct Atom));
205 atom->type = ATOM_SYMBOL;
206 atom->sym = string_duplicate(sym, sym_end);
208 if (atom->sym == NULL) {
212 if (gc_add_expr(gc, atom_as_expr(atom)) < 0) {
220 if (atom->sym != NULL) {
229 struct Atom *create_lambda_atom(Gc *gc, struct Expr args_list, struct Expr body, struct Expr environ)
231 struct Atom *atom = malloc(sizeof(struct Atom));
237 atom->type = ATOM_LAMBDA;
238 atom->lambda.args_list = args_list;
239 atom->lambda.body = body;
240 atom->lambda.environ = environ;
242 if (gc_add_expr(gc, atom_as_expr(atom)) < 0) {
256 struct Atom *create_native_atom(Gc *gc, NativeFunction fun, void *param)
258 struct Atom *atom = malloc(sizeof(struct Atom));
264 atom->type = ATOM_NATIVE;
265 atom->native.fun = fun;
266 atom->native.param = param;
268 if (gc_add_expr(gc, atom_as_expr(atom)) < 0) {
282 void destroy_atom(struct Atom *atom)
284 switch (atom->type) {
300 static int atom_as_sexpr(struct Atom *atom, char *output, size_t n)
303 trace_assert(output);
305 switch (atom->type) {
307 return snprintf(output, n, "%s", atom->sym);
310 return snprintf(output, n, "%ld", atom->num);
313 return snprintf(output, n, "\"%s\"", atom->str);
316 return snprintf(output, n, "<lambda>");
319 return snprintf(output, n, "<native>");
325 static int cons_as_sexpr(struct Cons *head, char *output, size_t n)
328 trace_assert(output);
330 /* TODO(#378): cons_as_sexpr does not handle encoding errors of snprintf */
332 struct Cons *cons = head;
336 int c = snprintf(output, n, "(");
341 c += expr_as_sexpr(cons->car, output + c, (size_t) (m - c));
346 while (cons->cdr.type == EXPR_CONS) {
347 cons = cons->cdr.cons;
349 c += snprintf(output + c, (size_t) (m - c), " ");
354 c += expr_as_sexpr(cons->car, output + c, (size_t) (m - c));
360 if (cons->cdr.atom->type != ATOM_SYMBOL ||
361 strcmp("nil", cons->cdr.atom->sym) != 0) {
363 c += snprintf(output + c, (size_t) (m - c), " . ");
368 c += expr_as_sexpr(cons->cdr, output + c, (size_t) (m - c));
374 c += snprintf(output + c, (size_t) (m - c), ")");
382 int expr_as_sexpr(struct Expr expr, char *output, size_t n)
386 return atom_as_sexpr(expr.atom, output, n);
389 return cons_as_sexpr(expr.cons, output, n);
398 const char *expr_type_as_string(enum ExprType expr_type)
401 case EXPR_ATOM: return "EXPR_ATOM";
402 case EXPR_CONS: return "EXPR_CONS";
403 case EXPR_VOID: return "EXPR_VOID";
409 const char *atom_type_as_string(enum AtomType atom_type)
412 case ATOM_SYMBOL: return "ATOM_SYMBOL";
413 case ATOM_NUMBER: return "ATOM_NUMBER";
414 case ATOM_STRING: return "ATOM_STRING";
415 case ATOM_LAMBDA: return "ATOM_LAMBDA";
416 case ATOM_NATIVE: return "ATOM_NATIVE";