aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-10-08 19:14:36 +0200
committerBad Diode <bd@badd10de.dev>2021-10-08 19:14:36 +0200
commit33c9c0cd69f6a3f5954222704755771f03c2ea04 (patch)
tree30f20d26662b32ee177c61c7ae9f1af5f383389a
parent92a1c58179183493647959838c8ad13975ece47c (diff)
downloadbdl-33c9c0cd69f6a3f5954222704755771f03c2ea04.tar.gz
bdl-33c9c0cd69f6a3f5954222704755771f03c2ea04.zip
Add support for arithmetic procedures
-rwxr-xr-xsrc/bootstrap/main.c171
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
216typedef struct Object { 217typedef 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
249Object *empty_list; 253Object *empty_list;
250 254
255//
256// Environment.
257//
258
259typedef struct EnvSymbol {
260 Object *symbol;
261 Object *value;
262} EnvSymbol;
263
264#define ENV_SIZE 256
265static EnvSymbol environment[ENV_SIZE];
266static size_t env_n = 0;
267
251Object * 268Object *
252make_fixnum(ssize_t num) { 269make_fixnum(ssize_t num) {
253 Object *obj = malloc(sizeof(Object)); 270 Object *obj = malloc(sizeof(Object));
@@ -325,7 +342,7 @@ bool
325token_is_fixnum(StringView token) { 342token_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
493Object * eval(Object *root);
494
495Object *
496proc_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
510Object *
511proc_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
534Object *
535proc_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
549Object *
550proc_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
573bool
574symbol_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
586Object *
587find_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
476void 596void
477init(void) { 597init(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
613Object *
614eval(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
482int 649int
@@ -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 }