diff options
author | Bad Diode <bd@badd10de.dev> | 2021-10-08 13:20:00 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2021-10-08 13:20:00 +0200 |
commit | aa699fc05d0945528c9ccf2b9b3d7e53e425d186 (patch) | |
tree | 521cd4c2f421c67497bcaeb193ed1a0e039dbfd7 /src/bootstrap/main.c | |
parent | baaef414186e60dbb127662d5f4ffab10ebf225e (diff) | |
download | bdl-aa699fc05d0945528c9ccf2b9b3d7e53e425d186.tar.gz bdl-aa699fc05d0945528c9ccf2b9b3d7e53e425d186.zip |
Add initial ast construction for fixnum/bool
Diffstat (limited to 'src/bootstrap/main.c')
-rwxr-xr-x | src/bootstrap/main.c | 198 |
1 files changed, 184 insertions, 14 deletions
diff --git a/src/bootstrap/main.c b/src/bootstrap/main.c index 98f313b..b346cca 100755 --- a/src/bootstrap/main.c +++ b/src/bootstrap/main.c | |||
@@ -1,5 +1,7 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <ctype.h> | 1 | #include <ctype.h> |
2 | #include <stdio.h> | ||
3 | #include <stdlib.h> | ||
4 | #include <string.h> | ||
3 | 5 | ||
4 | #include "shorthand.h" | 6 | #include "shorthand.h" |
5 | 7 | ||
@@ -15,6 +17,19 @@ sv_write(StringView sv) { | |||
15 | } | 17 | } |
16 | } | 18 | } |
17 | 19 | ||
20 | bool | ||
21 | sv_equal(StringView a, StringView b) { | ||
22 | if (a.n == b.n) { | ||
23 | for (size_t i = 0; i < a.n; i++) { | ||
24 | if (a.start[i] != b.start[i]) { | ||
25 | return false; | ||
26 | } | ||
27 | } | ||
28 | return true; | ||
29 | } | ||
30 | return false; | ||
31 | } | ||
32 | |||
18 | StringView | 33 | StringView |
19 | read_line(void) { | 34 | read_line(void) { |
20 | #define RL_BUF_SIZE 1024 | 35 | #define RL_BUF_SIZE 1024 |
@@ -121,6 +136,7 @@ tokenize(StringView sv) { | |||
121 | .n = 1, | 136 | .n = 1, |
122 | }; | 137 | }; |
123 | } break; | 138 | } break; |
139 | // TODO: Handle double quotes and escaped quotes. | ||
124 | default: { | 140 | default: { |
125 | token_n++; | 141 | token_n++; |
126 | } break; | 142 | } break; |
@@ -134,23 +150,174 @@ tokenize(StringView sv) { | |||
134 | }; | 150 | }; |
135 | } | 151 | } |
136 | 152 | ||
153 | return (Tokens){.start = (StringView *)&tokens_buf, .n = n}; | ||
154 | } | ||
155 | |||
156 | typedef enum ObjectType { | ||
157 | OBJ_TYPE_FIXNUM, | ||
158 | OBJ_TYPE_BOOL, | ||
159 | OBJ_TYPE_NIL, | ||
160 | OBJ_TYPE_SYMBOL, | ||
161 | OBJ_TYPE_STRING, | ||
162 | OBJ_TYPE_PAIR, | ||
163 | OBJ_TYPE_LIST, | ||
164 | } ObjectType; | ||
165 | |||
166 | typedef struct Object { | ||
167 | ObjectType type; | ||
168 | union { | ||
169 | // OBJ_TYPE_FIXNUM | ||
170 | ssize_t fixnum; | ||
171 | |||
172 | // OBJ_TYPE_BOOL | ||
173 | bool boolean; | ||
174 | |||
175 | // OBJ_TYPE_STRING | ||
176 | struct { | ||
177 | char *string; | ||
178 | size_t string_n; | ||
179 | }; | ||
180 | |||
181 | // OBJ_TYPE_PAIR | ||
182 | struct { | ||
183 | struct Object *car; | ||
184 | struct Object *cdr; | ||
185 | }; | ||
186 | |||
187 | // OBJ_TYPE_LIST | ||
188 | struct { | ||
189 | struct Object **list_elems; | ||
190 | size_t list_n; | ||
191 | }; | ||
192 | }; | ||
193 | } Object; | ||
194 | |||
195 | Object * | ||
196 | make_fixnum(ssize_t num) { | ||
197 | Object *obj = malloc(sizeof(Object)); | ||
198 | obj->type = OBJ_TYPE_FIXNUM; | ||
199 | obj->fixnum = num; | ||
200 | return obj; | ||
201 | } | ||
202 | |||
203 | Object * | ||
204 | make_boolean(bool b) { | ||
205 | Object *obj = malloc(sizeof(Object)); | ||
206 | obj->type = OBJ_TYPE_BOOL; | ||
207 | obj->boolean = b; | ||
208 | return obj; | ||
209 | } | ||
210 | |||
211 | Object * | ||
212 | make_string(const char *str, size_t n) { | ||
213 | Object *obj = malloc(sizeof(Object)); | ||
214 | obj->type = OBJ_TYPE_STRING; | ||
215 | obj->string = malloc(sizeof(char) * n); | ||
216 | memcpy(obj->string, str, n); | ||
217 | obj->string_n = n; | ||
218 | return obj; | ||
219 | } | ||
220 | |||
221 | Object * | ||
222 | make_empty_list(void) { | ||
223 | Object *obj = malloc(sizeof(Object)); | ||
224 | obj->type = OBJ_TYPE_LIST; | ||
225 | obj->list_elems = NULL; | ||
226 | obj->list_n = 0; | ||
227 | return obj; | ||
228 | } | ||
229 | |||
230 | void | ||
231 | push_obj_to_list(Object *list, Object obj) { | ||
232 | assert(false && "todo: Not implemented"); | ||
233 | } | ||
234 | |||
235 | bool | ||
236 | token_is_fixnum(StringView token) { | ||
237 | for (size_t i = 0; i < token.n; i++) { | ||
238 | char c = token.start[i]; | ||
239 | if (i == 0 && c == '-') { | ||
240 | continue; | ||
241 | } | ||
242 | if (!isdigit(c)) { | ||
243 | return false; | ||
244 | } | ||
245 | } | ||
246 | return true; | ||
247 | } | ||
248 | |||
249 | #define TRUE_TOKEN (StringView){"true", 4} | ||
250 | #define FALSE_TOKEN (StringView){"false", 5} | ||
251 | |||
252 | Object * | ||
253 | build_ast(Tokens tokens) { | ||
137 | // DEBUG: Printing tokens. | 254 | // DEBUG: Printing tokens. |
138 | printf("N_TOKENS: %ld\n", n); | 255 | // printf("N_TOKENS: %ld\n", tokens.n); |
139 | for (size_t i = 0; i < n; i++) { | 256 | // for (size_t i = 0; i < tokens.n; i++) { |
140 | printf("TOKEN: "); | 257 | // printf("TOKEN: "); |
141 | sv_write(tokens_buf[i]); | 258 | // sv_write(tokens.start[i]); |
142 | printf("\tN: %ld", tokens_buf[i].n); | 259 | // printf("\tN: %ld", tokens.start[i].n); |
143 | printf("\n"); | 260 | // printf("\n"); |
261 | // } | ||
262 | |||
263 | // TODO: Report error if we haven't consumed all the tokens? | ||
264 | for (size_t i = 0; i < tokens.n; i++) { | ||
265 | StringView token = tokens.start[i]; | ||
266 | |||
267 | // OBJ_TYPE_FIXNUM | ||
268 | if (token_is_fixnum(token)) { | ||
269 | // Convert token to fixnum. | ||
270 | ssize_t num = 0; | ||
271 | int sign = 1; | ||
272 | for (size_t i = 0; i < token.n; i++) { | ||
273 | char c = token.start[i]; | ||
274 | if (c == '-') { | ||
275 | sign = -1; | ||
276 | continue; | ||
277 | } | ||
278 | num = num * 10 + (c - '0'); | ||
279 | } | ||
280 | return make_fixnum(num * sign); | ||
281 | } | ||
282 | |||
283 | // OBJ_TYPE_BOOL | ||
284 | if (sv_equal(token, TRUE_TOKEN)) { | ||
285 | return make_boolean(true); | ||
286 | } | ||
287 | if (sv_equal(token, FALSE_TOKEN)) { | ||
288 | return make_boolean(false); | ||
289 | } | ||
144 | } | 290 | } |
145 | 291 | ||
146 | return (Tokens){.start = (StringView *)&tokens_buf, .n = n}; | 292 | return NULL; |
147 | } | 293 | } |
148 | 294 | ||
149 | void | 295 | void |
150 | display(StringView sv) { | 296 | display(Object *root) { |
151 | if (sv.n != 0) { | 297 | if (root == NULL) { |
152 | sv_write(sv); | 298 | return; |
153 | printf("\n"); | 299 | } |
300 | |||
301 | switch (root->type) { | ||
302 | case OBJ_TYPE_FIXNUM: { | ||
303 | printf("%zd", root->fixnum); | ||
304 | } break; | ||
305 | case OBJ_TYPE_BOOL: { | ||
306 | if (root->boolean) { | ||
307 | printf("true"); | ||
308 | } else { | ||
309 | printf("false"); | ||
310 | } | ||
311 | } break; | ||
312 | case OBJ_TYPE_NIL: { | ||
313 | printf("()"); | ||
314 | } break; | ||
315 | case OBJ_TYPE_STRING: { | ||
316 | printf("\"%.*s\"", (int)root->string_n, root->string); | ||
317 | } break; | ||
318 | default: { | ||
319 | printf("TYPE NOT IMPLEMENTED FOR DISPLAY\n"); | ||
320 | } break; | ||
154 | } | 321 | } |
155 | } | 322 | } |
156 | 323 | ||
@@ -162,8 +329,11 @@ main(void) { | |||
162 | while (true) { | 329 | while (true) { |
163 | printf(REPL_PROMPT); | 330 | printf(REPL_PROMPT); |
164 | StringView line = read_line(); | 331 | StringView line = read_line(); |
165 | tokenize(line); | 332 | Object *ast = build_ast(tokenize(line)); |
166 | display(line); | 333 | if (ast) { |
334 | display(ast); | ||
335 | printf("\n"); | ||
336 | } | ||
167 | } | 337 | } |
168 | return 0; | 338 | return 0; |
169 | } | 339 | } |