diff options
-rwxr-xr-x | src/bootstrap/main.c | 171 |
1 files changed, 169 insertions, 2 deletions
diff --git a/src/bootstrap/main.c b/src/bootstrap/main.c index a8e39f5..3c5663a 100755 --- a/src/bootstrap/main.c +++ b/src/bootstrap/main.c | |||
@@ -211,6 +211,7 @@ typedef enum ObjectType { | |||
211 | OBJ_TYPE_SYMBOL, | 211 | OBJ_TYPE_SYMBOL, |
212 | OBJ_TYPE_STRING, | 212 | OBJ_TYPE_STRING, |
213 | OBJ_TYPE_PAIR, | 213 | OBJ_TYPE_PAIR, |
214 | OBJ_TYPE_PROCEDURE, | ||
214 | } ObjectType; | 215 | } ObjectType; |
215 | 216 | ||
216 | typedef struct Object { | 217 | typedef struct Object { |
@@ -239,6 +240,9 @@ typedef struct Object { | |||
239 | char *symbol; | 240 | char *symbol; |
240 | size_t symbol_n; | 241 | size_t symbol_n; |
241 | }; | 242 | }; |
243 | |||
244 | // OBJ_TYPE_PROCEDURE | ||
245 | struct Object *(*proc)(struct Object *args); | ||
242 | }; | 246 | }; |
243 | } Object; | 247 | } Object; |
244 | 248 | ||
@@ -248,6 +252,19 @@ typedef struct Object { | |||
248 | 252 | ||
249 | Object *empty_list; | 253 | Object *empty_list; |
250 | 254 | ||
255 | // | ||
256 | // Environment. | ||
257 | // | ||
258 | |||
259 | typedef struct EnvSymbol { | ||
260 | Object *symbol; | ||
261 | Object *value; | ||
262 | } EnvSymbol; | ||
263 | |||
264 | #define ENV_SIZE 256 | ||
265 | static EnvSymbol environment[ENV_SIZE]; | ||
266 | static size_t env_n = 0; | ||
267 | |||
251 | Object * | 268 | Object * |
252 | make_fixnum(ssize_t num) { | 269 | make_fixnum(ssize_t num) { |
253 | Object *obj = malloc(sizeof(Object)); | 270 | Object *obj = malloc(sizeof(Object)); |
@@ -325,7 +342,7 @@ bool | |||
325 | token_is_fixnum(StringView token) { | 342 | token_is_fixnum(StringView token) { |
326 | for (size_t i = 0; i < token.n; i++) { | 343 | for (size_t i = 0; i < token.n; i++) { |
327 | char c = token.start[i]; | 344 | char c = token.start[i]; |
328 | if (i == 0 && c == '-') { | 345 | if (i == 0 && c == '-' && token.n > 1) { |
329 | continue; | 346 | continue; |
330 | } | 347 | } |
331 | if (!isdigit(c)) { | 348 | if (!isdigit(c)) { |
@@ -473,10 +490,160 @@ display(Object *root) { | |||
473 | 490 | ||
474 | #define REPL_PROMPT "bdl> " | 491 | #define REPL_PROMPT "bdl> " |
475 | 492 | ||
493 | Object * eval(Object *root); | ||
494 | |||
495 | Object * | ||
496 | proc_add(Object *args) { | ||
497 | ssize_t tot = 0; | ||
498 | while (args->type == OBJ_TYPE_PAIR) { | ||
499 | Object *car = eval(args->car); | ||
500 | if (car->type != OBJ_TYPE_FIXNUM) { | ||
501 | fprintf(stderr, "addition not supported for type %d\n", car->type); | ||
502 | return NULL; | ||
503 | } | ||
504 | tot += car->fixnum; | ||
505 | args = args->cdr; | ||
506 | } | ||
507 | return make_fixnum(tot); | ||
508 | } | ||
509 | |||
510 | Object * | ||
511 | proc_sub(Object *args) { | ||
512 | if (args->type != OBJ_TYPE_PAIR) { | ||
513 | fprintf(stderr, "substraction not supported for type %d\n", args->type); | ||
514 | return NULL; | ||
515 | } | ||
516 | |||
517 | // Extract first parameter. | ||
518 | Object *car = eval(args->car); | ||
519 | args = args->cdr; | ||
520 | ssize_t tot = car->fixnum; | ||
521 | |||
522 | while (args->type == OBJ_TYPE_PAIR) { | ||
523 | Object *car = eval(args->car); | ||
524 | if (car->type != OBJ_TYPE_FIXNUM) { | ||
525 | fprintf(stderr, "substraction not supported for type %d\n", car->type); | ||
526 | return NULL; | ||
527 | } | ||
528 | tot -= car->fixnum; | ||
529 | args = args->cdr; | ||
530 | } | ||
531 | return make_fixnum(tot); | ||
532 | } | ||
533 | |||
534 | Object * | ||
535 | proc_mul(Object *args) { | ||
536 | ssize_t tot = 1; | ||
537 | while (args->type == OBJ_TYPE_PAIR) { | ||
538 | Object *car = eval(args->car); | ||
539 | if (car->type != OBJ_TYPE_FIXNUM) { | ||
540 | fprintf(stderr, "multiply not supported for type %d\n", car->type); | ||
541 | return NULL; | ||
542 | } | ||
543 | tot *= car->fixnum; | ||
544 | args = args->cdr; | ||
545 | } | ||
546 | return make_fixnum(tot); | ||
547 | } | ||
548 | |||
549 | Object * | ||
550 | proc_div(Object *args) { | ||
551 | if (args->type != OBJ_TYPE_PAIR) { | ||
552 | fprintf(stderr, "substraction not supported for type %d\n", args->type); | ||
553 | return NULL; | ||
554 | } | ||
555 | |||
556 | // Extract first parameter. | ||
557 | Object *car = eval(args->car); | ||
558 | args = args->cdr; | ||
559 | ssize_t tot = car->fixnum; | ||
560 | |||
561 | while (args->type == OBJ_TYPE_PAIR) { | ||
562 | Object *car = eval(args->car); | ||
563 | if (car->type != OBJ_TYPE_FIXNUM) { | ||
564 | fprintf(stderr, "div not supported for type %d\n", car->type); | ||
565 | return NULL; | ||
566 | } | ||
567 | tot /= car->fixnum; | ||
568 | args = args->cdr; | ||
569 | } | ||
570 | return make_fixnum(tot); | ||
571 | } | ||
572 | |||
573 | bool | ||
574 | symbol_eq(Object *a, Object *b) { | ||
575 | if (a->type != b->type || a->type != OBJ_TYPE_SYMBOL || a->symbol_n != b->symbol_n) { | ||
576 | return false; | ||
577 | } | ||
578 | for (size_t i = 0; i < a->symbol_n; i++) { | ||
579 | if (a->symbol[i] != b->symbol[i]) { | ||
580 | return false; | ||
581 | } | ||
582 | } | ||
583 | return true; | ||
584 | } | ||
585 | |||
586 | Object * | ||
587 | find_environment_symbol(Object *symbol) { | ||
588 | for (size_t i = 0; i < env_n; i++) { | ||
589 | if (symbol_eq(environment[i].symbol, symbol)) { | ||
590 | return environment[i].value; | ||
591 | } | ||
592 | } | ||
593 | return NULL; | ||
594 | } | ||
595 | |||
476 | void | 596 | void |
477 | init(void) { | 597 | init(void) { |
598 | // Clear env. | ||
599 | for (size_t i = 0; i < ENV_SIZE; i++) { | ||
600 | environment[i] = (EnvSymbol){0}; | ||
601 | } | ||
602 | |||
478 | // Initialize singletons. | 603 | // Initialize singletons. |
479 | empty_list = make_empty_list(); | 604 | empty_list = make_empty_list(); |
605 | |||
606 | // Add primitive functions. | ||
607 | environment[env_n++] = (EnvSymbol){make_symbol("+", 1), make_procedure(proc_add)}; | ||
608 | environment[env_n++] = (EnvSymbol){make_symbol("-", 1), make_procedure(proc_sub)}; | ||
609 | environment[env_n++] = (EnvSymbol){make_symbol("*", 1), make_procedure(proc_mul)}; | ||
610 | environment[env_n++] = (EnvSymbol){make_symbol("/", 1), make_procedure(proc_div)}; | ||
611 | } | ||
612 | |||
613 | Object * | ||
614 | eval(Object *root) { | ||
615 | if (root == NULL) { | ||
616 | return NULL; | ||
617 | } | ||
618 | |||
619 | switch (root->type) { | ||
620 | case OBJ_TYPE_FIXNUM: | ||
621 | case OBJ_TYPE_BOOL: | ||
622 | case OBJ_TYPE_NIL: | ||
623 | case OBJ_TYPE_STRING: | ||
624 | case OBJ_TYPE_SYMBOL: { | ||
625 | return root; | ||
626 | } break; | ||
627 | case OBJ_TYPE_PAIR: { | ||
628 | if (root->car->type == OBJ_TYPE_SYMBOL) { | ||
629 | Object *value = find_environment_symbol(root->car); | ||
630 | if (value == NULL) { | ||
631 | printf("error: symbol not found: `"); | ||
632 | display(root->car); | ||
633 | printf("`\n"); | ||
634 | return NULL; | ||
635 | } | ||
636 | if (value->type == OBJ_TYPE_PROCEDURE) { | ||
637 | return value->proc(root->cdr); | ||
638 | } | ||
639 | } | ||
640 | } break; | ||
641 | default: { | ||
642 | printf("TYPE NOT IMPLEMENTED FOR EVAL.\n"); | ||
643 | } break; | ||
644 | } | ||
645 | |||
646 | return NULL; | ||
480 | } | 647 | } |
481 | 648 | ||
482 | int | 649 | int |
@@ -489,7 +656,7 @@ main(void) { | |||
489 | Tokens tokens = tokenize(line); | 656 | Tokens tokens = tokenize(line); |
490 | Object *ast = build_ast(&tokens); | 657 | Object *ast = build_ast(&tokens); |
491 | if (ast) { | 658 | if (ast) { |
492 | display(ast); | 659 | display(eval(ast)); |
493 | printf("\n"); | 660 | printf("\n"); |
494 | } | 661 | } |
495 | } | 662 | } |