Add first lisp bits
[fw/altos] / src / lisp / ao_lisp_atom.c
1 /*
2  * Copyright © 2016 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; version 2 of the License.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
16  */
17
18 #include "ao_lisp.h"
19
20 static int name_size(char *name)
21 {
22         return sizeof(struct ao_lisp_atom) + strlen(name) + 1;
23 }
24
25 static int atom_size(void *addr)
26 {
27         struct ao_lisp_atom     *atom = addr;
28         if (!atom)
29                 return 0;
30         return name_size(atom->name);
31 }
32
33 static void atom_mark(void *addr)
34 {
35         struct ao_lisp_atom     *atom = addr;
36
37         if (atom->next == AO_LISP_ATOM_CONST)
38                 return;
39
40         for (;;) {
41                 ao_lisp_poly_mark(atom->val);
42                 atom = atom->next;
43                 if (!atom)
44                         break;
45                 if (ao_lisp_mark_memory(atom, atom_size(atom)))
46                         break;
47         }
48 }
49
50 static void atom_move(void *addr)
51 {
52         struct ao_lisp_atom     *atom = addr;
53
54         if (atom->next == AO_LISP_ATOM_CONST)
55                 return;
56
57         for (;;) {
58                 struct ao_lisp_atom     *next;
59
60                 atom->val = ao_lisp_poly_move(atom->val);
61                 next = ao_lisp_move_memory(atom->next, atom_size(atom->next));
62                 if (!next)
63                         break;
64                 atom->next = next;
65                 atom = next;
66         }
67 }
68
69 const struct ao_lisp_mem_type ao_lisp_atom_type = {
70         .mark = atom_mark,
71         .size = atom_size,
72         .move = atom_move,
73 };
74
75 struct ao_lisp_atom     *atoms;
76
77 struct ao_lisp_atom *
78 ao_lisp_atom_intern(char *name)
79 {
80         struct ao_lisp_atom     *atom;
81         int                     b;
82
83         for (atom = atoms; atom; atom = atom->next) {
84                 if (!strcmp(atom->name, name))
85                         return atom;
86         }
87         for (b = 0; ao_lisp_builtins[b]; b++)
88                 if (!strcmp(ao_lisp_builtins[b]->name, name))
89                         return (struct ao_lisp_atom *) ao_lisp_builtins[b];
90         if (!atoms)
91                 ao_lisp_root_add(&ao_lisp_atom_type, (void **) &atoms);
92         atom = ao_lisp_alloc(name_size(name));
93         if (atom) {
94                 atom->type = AO_LISP_ATOM;
95                 atom->next = atoms;
96                 atoms = atom;
97                 strcpy(atom->name, name);
98                 atom->val = AO_LISP_NIL;
99         }
100         return atom;
101 }
102
103 void
104 ao_lisp_atom_print(struct ao_lisp_atom *a)
105 {
106         fputs(a->name, stdout);
107 }