]> git.lizzy.rs Git - nothing.git/blob - src/script/expr.c
(#284) Implement print_expr_as_sexpr
[nothing.git] / src / script / expr.c
1 #include <assert.h>
2 #include <stdarg.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6
7 #include "script/expr.h"
8
9 struct Expr atom_as_expr(struct Atom *atom)
10 {
11     struct Expr expr = {
12         .type = EXPR_ATOM,
13         .atom = atom
14     };
15
16     return expr;
17 }
18
19 struct Expr cons_as_expr(struct Cons *cons)
20 {
21     struct Expr expr = {
22         .type = EXPR_CONS,
23         .cons = cons
24     };
25
26     return expr;
27 }
28
29 void print_atom_as_sexpr(struct Atom *atom)
30 {
31     assert(atom);
32
33     switch (atom->type) {
34     case ATOM_SYMBOL:
35         printf("%s", atom->sym);
36         break;
37
38     case ATOM_NUMBER:
39         printf("%f", atom->num);
40         break;
41
42     case ATOM_STRING:
43         printf("\"%s\"", atom->str);
44         break;
45     }
46 }
47
48 void print_cons_as_sexpr(struct Cons *cons)
49 {
50     assert(cons);
51
52     printf("(");
53     print_expr_as_sexpr(cons->car);
54     printf(" . ");
55     print_expr_as_sexpr(cons->cdr);
56     printf(")");
57 }
58
59 void print_expr_as_sexpr(struct Expr expr)
60 {
61     switch (expr.type) {
62     case EXPR_ATOM:
63         print_atom_as_sexpr(expr.atom);
64         break;
65
66     case EXPR_CONS:
67         print_cons_as_sexpr(expr.cons);
68         break;
69     }
70 }
71
72 struct Expr create_expr_from_str(const char *str)
73 {
74     /* TODO(#283): create_expr_from_str is not implemented */
75     assert(str);
76     return atom_as_expr(0);
77 }
78
79 void destroy_expr(struct Expr expr)
80 {
81     switch (expr.type) {
82     case EXPR_ATOM:
83         destroy_atom(expr.atom);
84         break;
85
86     case EXPR_CONS:
87         destroy_cons(expr.cons);
88         break;
89     }
90 }
91
92 struct Cons *create_cons(struct Expr car, struct Expr cdr)
93 {
94     struct Cons *cons = malloc(sizeof(struct Cons));
95     if (cons == NULL) {
96         return NULL;
97     }
98
99     cons->car = car;
100     cons->cdr = cdr;
101
102     return cons;
103 }
104
105 void destroy_cons(struct Cons *cons)
106 {
107     destroy_expr(cons->car);
108     destroy_expr(cons->cdr);
109     free(cons);
110 }
111
112 struct Atom *create_atom(enum AtomType type, ...)
113 {
114     struct Atom *atom = malloc(sizeof(struct Atom));
115     if (atom == NULL) {
116         return NULL;
117     }
118
119     va_list args;
120     va_start(args, type);
121
122     atom->type = type;
123
124     switch (type) {
125     case ATOM_SYMBOL:
126     case ATOM_STRING: {
127         const char *arg_str = va_arg(args, const char *);
128         const size_t n = strlen(arg_str);
129         char *str = malloc(sizeof(char) * (n + 1));
130
131         if (str == NULL) {
132             free(atom);
133             return NULL;
134         }
135
136         memcpy(str, arg_str, n + 1);
137         atom->str = str;
138     } break;
139
140     case ATOM_NUMBER: {
141         atom->num = (float) va_arg(args, double);
142     } break;
143     }
144
145     va_end(args);
146
147     return atom;
148 }
149
150 void destroy_atom(struct Atom *atom)
151 {
152     switch (atom->type) {
153     case ATOM_SYMBOL:
154     case ATOM_STRING: {
155         free(atom->str);
156     } break;
157
158     case ATOM_NUMBER: {
159         /* Nothing */
160     } break;
161     }
162
163     free(atom);
164 }