]> git.lizzy.rs Git - nothing.git/blob - src/script/expr.c
7773bf163c847717c39acad6455eaadb68735eed
[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 destroy_expr(struct Expr expr)
30 {
31     switch (expr.type) {
32     case EXPR_ATOM:
33         destroy_atom(expr.atom);
34         break;
35
36     case EXPR_CONS:
37         destroy_cons(expr.cons);
38         break;
39     }
40 }
41
42 struct Cons *create_cons(struct Expr car, struct Expr cdr)
43 {
44     struct Cons *cons = malloc(sizeof(struct Cons));
45     if (cons == NULL) {
46         return NULL;
47     }
48
49     cons->car = car;
50     cons->cdr = cdr;
51
52     return cons;
53 }
54
55 void destroy_cons(struct Cons *cons)
56 {
57     destroy_expr(cons->car);
58     destroy_expr(cons->cdr);
59     free(cons);
60 }
61
62 struct Atom *create_atom(enum AtomType type, ...)
63 {
64     struct Atom *atom = malloc(sizeof(struct Atom));
65     if (atom == NULL) {
66         return NULL;
67     }
68
69     va_list args;
70     va_start(args, type);
71
72     switch (type) {
73     case ATOM_SYMBOL:
74     case ATOM_STRING: {
75         const char *arg_str = va_arg(args, const char *);
76         const size_t n = strlen(arg_str);
77         char *str = malloc(sizeof(char) * (n + 1));
78
79         if (str == NULL) {
80             free(atom);
81             return NULL;
82         }
83
84         strncpy(str, arg_str, n);
85         atom->text = str;
86     } break;
87
88     case ATOM_NUMBER: {
89         atom->number = va_arg(args, int);
90     } break;
91     }
92
93     va_end(args);
94
95     return atom;
96 }
97
98 void destroy_atom(struct Atom *atom)
99 {
100     switch (atom->type) {
101     case ATOM_SYMBOL:
102     case ATOM_STRING: {
103         free(atom->text);
104     } break;
105
106     case ATOM_NUMBER: {
107         /* Nothing */
108     } break;
109     }
110
111     free(atom);
112 }