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