]> git.lizzy.rs Git - nothing.git/blobdiff - src/script/expr.c
TODO(#296)
[nothing.git] / src / script / expr.c
index 51c809efe5cde4b416522564e9fdf3a071af452c..39fd84cc7f8081a295b87b5a58bd2e4406a5e328 100644 (file)
@@ -1,4 +1,5 @@
 #include <assert.h>
+#include <ctype.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -6,6 +7,23 @@
 
 #include "script/expr.h"
 
+static char *string_duplicate(const char *str,
+                              const char *str_end)
+{
+    if (str_end != NULL && str > str_end) {
+        return NULL;
+    }
+
+    const size_t n = str_end == NULL ? strlen(str) : (size_t) (str_end - str);
+    char *dup_str = malloc(sizeof(char) * (n + 1));
+    if (dup_str == NULL) {
+        return NULL;
+    }
+
+    memcpy(dup_str, str, n);
+    return dup_str;
+}
+
 struct Expr atom_as_expr(struct Atom *atom)
 {
     struct Expr expr = {
@@ -26,11 +44,48 @@ struct Expr cons_as_expr(struct Cons *cons)
     return expr;
 }
 
-struct Expr create_expr_from_str(const char *str)
+void print_atom_as_sexpr(struct Atom *atom)
 {
-    /* TODO(#283): create_expr_from_str is not implemented */
-    assert(str);
-    return atom_as_expr(0);
+    assert(atom);
+
+    switch (atom->type) {
+    case ATOM_SYMBOL:
+        printf("%s", atom->sym);
+        break;
+
+    case ATOM_NUMBER:
+        printf("%f", atom->num);
+        break;
+
+    case ATOM_STRING:
+        printf("\"%s\"", atom->str);
+        break;
+    }
+}
+
+void print_cons_as_sexpr(struct Cons *cons)
+{
+    assert(cons);
+
+    printf("(");
+    print_expr_as_sexpr(cons->car);
+    printf(" . ");
+    print_expr_as_sexpr(cons->cdr);
+    printf(")");
+}
+
+void print_expr_as_sexpr(struct Expr expr)
+{
+    /* TODO(#296): print_expr_as_sexpr doesn't support lists */
+    switch (expr.type) {
+    case EXPR_ATOM:
+        print_atom_as_sexpr(expr.atom);
+        break;
+
+    case EXPR_CONS:
+        print_cons_as_sexpr(expr.cons);
+        break;
+    }
 }
 
 void destroy_expr(struct Expr expr)
@@ -66,38 +121,45 @@ void destroy_cons(struct Cons *cons)
     free(cons);
 }
 
-struct Atom *create_atom(enum AtomType type, ...)
+struct Atom *create_number_atom(float num)
 {
     struct Atom *atom = malloc(sizeof(struct Atom));
     if (atom == NULL) {
         return NULL;
     }
+    atom->type = ATOM_NUMBER;
+    atom->num = num;
+    return atom;
+}
 
-    va_list args;
-    va_start(args, type);
-
-    switch (type) {
-    case ATOM_SYMBOL:
-    case ATOM_STRING: {
-        const char *arg_str = va_arg(args, const char *);
-        const size_t n = strlen(arg_str);
-        char *str = malloc(sizeof(char) * (n + 1));
-
-        if (str == NULL) {
-            free(atom);
-            return NULL;
-        }
+struct Atom *create_string_atom(const char *str, const char *str_end)
+{
+    struct Atom *atom = malloc(sizeof(struct Atom));
+    if (atom == NULL) {
+        return NULL;
+    }
+    atom->type = ATOM_STRING;
+    atom->str = string_duplicate(str, str_end);
+    if (atom->str == NULL) {
+        free(atom);
+        return NULL;
+    }
 
-        strncpy(str, arg_str, n);
-        atom->text = str;
-    } break;
+    return atom;
+}
 
-    case ATOM_NUMBER: {
-        atom->number = va_arg(args, int);
-    } break;
+struct Atom *create_symbol_atom(const char *sym, const char *sym_end)
+{
+    struct Atom *atom = malloc(sizeof(struct Atom));
+    if (atom == NULL) {
+        return NULL;
+    }
+    atom->type = ATOM_SYMBOL;
+    atom->sym = string_duplicate(sym, sym_end);
+    if (atom->sym == NULL) {
+        free(atom);
+        return NULL;
     }
-
-    va_end(args);
 
     return atom;
 }
@@ -107,7 +169,7 @@ void destroy_atom(struct Atom *atom)
     switch (atom->type) {
     case ATOM_SYMBOL:
     case ATOM_STRING: {
-        free(atom->text);
+        free(atom->str);
     } break;
 
     case ATOM_NUMBER: {
@@ -117,9 +179,3 @@ void destroy_atom(struct Atom *atom)
 
     free(atom);
 }
-
-void print_expr_as_sexpr(struct Expr expr)
-{
-    (void) expr;
-    /* TODO: print_expr_as_sexpr is not implemented */
-}