]> git.lizzy.rs Git - nothing.git/blob - src/script/expr.c
(#288) split create_atom
[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     switch (expr.type) {
80     case EXPR_ATOM:
81         print_atom_as_sexpr(expr.atom);
82         break;
83
84     case EXPR_CONS:
85         print_cons_as_sexpr(expr.cons);
86         break;
87     }
88 }
89
90 void destroy_expr(struct Expr expr)
91 {
92     switch (expr.type) {
93     case EXPR_ATOM:
94         destroy_atom(expr.atom);
95         break;
96
97     case EXPR_CONS:
98         destroy_cons(expr.cons);
99         break;
100     }
101 }
102
103 struct Cons *create_cons(struct Expr car, struct Expr cdr)
104 {
105     struct Cons *cons = malloc(sizeof(struct Cons));
106     if (cons == NULL) {
107         return NULL;
108     }
109
110     cons->car = car;
111     cons->cdr = cdr;
112
113     return cons;
114 }
115
116 void destroy_cons(struct Cons *cons)
117 {
118     destroy_expr(cons->car);
119     destroy_expr(cons->cdr);
120     free(cons);
121 }
122
123 struct Atom *create_number_atom(float num)
124 {
125     struct Atom *atom = malloc(sizeof(struct Atom));
126     if (atom == NULL) {
127         return NULL;
128     }
129     atom->type = ATOM_NUMBER;
130     atom->num = num;
131     return atom;
132 }
133
134 struct Atom *create_string_atom(const char *str, const char *str_end)
135 {
136     struct Atom *atom = malloc(sizeof(struct Atom));
137     if (atom == NULL) {
138         return NULL;
139     }
140     atom->type = ATOM_STRING;
141     atom->str = string_duplicate(str, str_end);
142     if (atom->str == NULL) {
143         free(atom);
144         return NULL;
145     }
146
147     return atom;
148 }
149
150 struct Atom *create_symbol_atom(const char *sym, const char *sym_end)
151 {
152     struct Atom *atom = malloc(sizeof(struct Atom));
153     if (atom == NULL) {
154         return NULL;
155     }
156     atom->type = ATOM_SYMBOL;
157     atom->sym = string_duplicate(sym, sym_end);
158     if (atom->sym == NULL) {
159         free(atom);
160         return NULL;
161     }
162
163     return atom;
164 }
165
166 void destroy_atom(struct Atom *atom)
167 {
168     switch (atom->type) {
169     case ATOM_SYMBOL:
170     case ATOM_STRING: {
171         free(atom->str);
172     } break;
173
174     case ATOM_NUMBER: {
175         /* Nothing */
176     } break;
177     }
178
179     free(atom);
180 }