]> git.lizzy.rs Git - nothing.git/blobdiff - src/script/expr.c
(#395) Make region print eval errors on stdout
[nothing.git] / src / script / expr.c
index b97351ccf55496d32b9e773030aa98e374ffc504..bf25ba17f8d2cb5340f655f51cc9d714154cb0f9 100644 (file)
@@ -38,62 +38,62 @@ struct Expr void_expr(void)
     return expr;
 }
 
-void print_atom_as_sexpr(struct Atom *atom)
+void print_atom_as_sexpr(FILE *stream, struct Atom *atom)
 {
     assert(atom);
 
     switch (atom->type) {
     case ATOM_SYMBOL:
-        printf("%s", atom->sym);
+        fprintf(stream, "%s", atom->sym);
         break;
 
     case ATOM_NUMBER:
-        printf("%ld", atom->num);
+        fprintf(stream, "%ld", atom->num);
         break;
 
     case ATOM_STRING:
-        printf("\"%s\"", atom->str);
+        fprintf(stream, "\"%s\"", atom->str);
         break;
 
     case ATOM_NATIVE:
-        printf("<native>");
+        fprintf(stream, "<native>");
         break;
     }
 }
 
-void print_cons_as_sexpr(struct Cons *head)
+void print_cons_as_sexpr(FILE *stream, struct Cons *head)
 {
     assert(head);
 
     struct Cons *cons = head;
 
-    printf("(");
-    print_expr_as_sexpr(cons->car);
+    fprintf(stream, "(");
+    print_expr_as_sexpr(stream, cons->car);
 
     while (cons->cdr.type == EXPR_CONS) {
         cons = cons->cdr.cons;
-        printf(" ");
-        print_expr_as_sexpr(cons->car);
+        fprintf(stream, " ");
+        print_expr_as_sexpr(stream, cons->car);
     }
 
     if (cons->cdr.atom->type != ATOM_SYMBOL ||
         strcmp("nil", cons->cdr.atom->sym) != 0) {
-        printf(" . ");
-        print_expr_as_sexpr(cons->cdr);
+        fprintf(stream, " . ");
+        print_expr_as_sexpr(stream, cons->cdr);
     }
 
-    printf(")");
+    fprintf(stream, ")");
 }
 
-void print_expr_as_sexpr(struct Expr expr)
+void print_expr_as_sexpr(FILE *stream, struct Expr expr)
 {
     switch (expr.type) {
     case EXPR_ATOM:
-        print_atom_as_sexpr(expr.atom);
+        print_atom_as_sexpr(stream, expr.atom);
         break;
 
     case EXPR_CONS:
-        print_cons_as_sexpr(expr.cons);
+        print_cons_as_sexpr(stream, expr.cons);
         break;
 
     case EXPR_VOID:
@@ -286,15 +286,17 @@ static int atom_as_sexpr(struct Atom *atom, char *output, size_t n)
     return 0;
 }
 
-static int cons_as_sexpr(struct Cons *cons, char *output, size_t n)
+static int cons_as_sexpr(struct Cons *head, char *output, size_t n)
 {
-    assert(cons);
+    assert(head);
     assert(output);
 
     /* TODO(#378): cons_as_sexpr does not handle encoding errors of snprintf */
-    /* TODO(#379): cons_as_sexpr does not support lists */
+
+    struct Cons *cons = head;
 
     int m = (int) n;
+
     int c = snprintf(output, n, "(");
     if (m - c <= c) {
         return c;
@@ -305,14 +307,32 @@ static int cons_as_sexpr(struct Cons *cons, char *output, size_t n)
         return c;
     }
 
-    c += snprintf(output + c, (size_t) (m - c), " . ");
-    if (m - c <= 0) {
-        return c;
+    while (cons->cdr.type == EXPR_CONS) {
+        cons = cons->cdr.cons;
+
+        c += snprintf(output + c, (size_t) (m - c), " ");
+        if (m - c <= 0) {
+            return c;
+        }
+
+        c += expr_as_sexpr(cons->car, output + c, (size_t) (m - c));
+        if (m - c <= 0) {
+            return c;
+        }
     }
 
-    c += expr_as_sexpr(cons->cdr, output + c, (size_t) (m - c));
-    if (m - c <= 0) {
-        return c;
+    if (cons->cdr.atom->type != ATOM_SYMBOL ||
+        strcmp("nil", cons->cdr.atom->sym) != 0) {
+
+        c += snprintf(output + c, (size_t) (m - c), " . ");
+        if (m - c <= 0) {
+            return c;
+        }
+
+        c += expr_as_sexpr(cons->cdr, output + c, (size_t) (m - c));
+        if (m - c <= 0) {
+            return c;
+        }
     }
 
     c += snprintf(output + c, (size_t) (m - c), ")");