aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-10-13 20:46:26 +0200
committerBad Diode <bd@badd10de.dev>2021-10-13 20:46:26 +0200
commitd38ae947933fe26773a810d91fba3b23766d4d92 (patch)
tree036d3b100c19210d5e742c7a3334ca83833e209a
parent3ed2c60da6ef2e18d7e273cf39056833c5b41c13 (diff)
downloadbdl-d38ae947933fe26773a810d91fba3b23766d4d92.tar.gz
bdl-d38ae947933fe26773a810d91fba3b23766d4d92.zip
Add set! and eval procedures
-rw-r--r--src/bootstrap/environment.c13
-rwxr-xr-xsrc/bootstrap/main.c2
-rw-r--r--src/bootstrap/primitives.c68
3 files changed, 70 insertions, 13 deletions
diff --git a/src/bootstrap/environment.c b/src/bootstrap/environment.c
index d4e9f86..99dd7fd 100644
--- a/src/bootstrap/environment.c
+++ b/src/bootstrap/environment.c
@@ -60,18 +60,13 @@ env_lookup(Environment *env, Object *symbol) {
60 return obj_err; 60 return obj_err;
61} 61}
62 62
63void 63ssize_t
64env_update_symbol(Environment *env, Object *symbol, Object *value) { 64env_symbol_index_in_current_env(Environment *env, Object *symbol) {
65 // Try to find an existing symbol in the current environment.
66 for (size_t i = 0; i < env->size; i++) { 65 for (size_t i = 0; i < env->size; i++) {
67 EnvEntry entry = env->buf[i]; 66 EnvEntry entry = env->buf[i];
68 if (obj_eq(symbol, entry.symbol)) { 67 if (obj_eq(symbol, entry.symbol)) {
69 env->buf[i].value = value; 68 return i;
70 return;
71 } 69 }
72 } 70 }
73 // If we don't find the symbol, add a new entry. 71 return -1;
74 env_add_symbol(env, symbol, value);
75} 72}
76
77// TODO: Free env function.
diff --git a/src/bootstrap/main.c b/src/bootstrap/main.c
index e8e530d..052f1c0 100755
--- a/src/bootstrap/main.c
+++ b/src/bootstrap/main.c
@@ -40,6 +40,7 @@ init(void) {
40 MAKE_ENV_VAR(global_env, "nil", obj_nil); 40 MAKE_ENV_VAR(global_env, "nil", obj_nil);
41 41
42 // Primitive procedures. 42 // Primitive procedures.
43 MAKE_ENV_PROC(global_env, "eval", proc_eval);
43 MAKE_ENV_PROC(global_env, "quote", proc_quote); 44 MAKE_ENV_PROC(global_env, "quote", proc_quote);
44 MAKE_ENV_PROC(global_env, "car", proc_car); 45 MAKE_ENV_PROC(global_env, "car", proc_car);
45 MAKE_ENV_PROC(global_env, "cdr", proc_cdr); 46 MAKE_ENV_PROC(global_env, "cdr", proc_cdr);
@@ -72,6 +73,7 @@ init(void) {
72 MAKE_ENV_PROC(global_env, "=", proc_num_equal); 73 MAKE_ENV_PROC(global_env, "=", proc_num_equal);
73 MAKE_ENV_PROC(global_env, "eq?", proc_equal); 74 MAKE_ENV_PROC(global_env, "eq?", proc_equal);
74 MAKE_ENV_PROC(global_env, "def", proc_define); 75 MAKE_ENV_PROC(global_env, "def", proc_define);
76 MAKE_ENV_PROC(global_env, "set!", proc_set);
75} 77}
76 78
77void 79void
diff --git a/src/bootstrap/primitives.c b/src/bootstrap/primitives.c
index af8e9da..a3b69f6 100644
--- a/src/bootstrap/primitives.c
+++ b/src/bootstrap/primitives.c
@@ -630,15 +630,75 @@ proc_define(Environment *env, Object *obj) {
630 } 630 }
631 631
632 // Make a copy of the symbol and to make them permanent in the environment. 632 // Make a copy of the symbol and to make them permanent in the environment.
633 env_update_symbol(env, obj_duplicate(symbol), obj_duplicate(value)); 633 ssize_t index = env_symbol_index_in_current_env(env, symbol);
634 if (index == -1) {
635 env_add_symbol(env, obj_duplicate(symbol), obj_duplicate(value));
636 } else {
637 env->buf[index].value = obj_duplicate(value);
638 }
639 return obj_nil;
640}
641
642Object *
643proc_set(Environment *env, Object *obj) {
644 if (obj == obj_nil || obj->cdr == obj_nil) {
645 error_push((Error){
646 .type = ERR_TYPE_RUNTIME,
647 .value = ERR_NOT_ENOUGH_ARGS,
648 });
649 return obj_err;
650 }
651
652 Object *symbol = obj->car;
653 if (symbol->type != OBJ_TYPE_SYMBOL) {
654 error_push((Error){
655 .type = ERR_TYPE_RUNTIME,
656 .value = ERR_WRONG_ARG_TYPE,
657 });
658 return obj_err;
659 }
660
661 Object *value = eval(env, obj->cdr->car);
662 if (value == obj_err) {
663 return obj_err;
664 }
665
666 ssize_t index = env_symbol_index_in_current_env(env, symbol);
667 if (index == -1) {
668 error_push((Error){
669 .type = ERR_TYPE_RUNTIME,
670 .value = ERR_SYMBOL_NOT_FOUND,
671 });
672 return obj_err;
673 }
674
675 env->buf[index].value = obj_duplicate(value);
634 return obj_nil; 676 return obj_nil;
635} 677}
636 678
679
680//
681// Evaluation.
682//
683
684Object *
685proc_eval(Environment *env, Object *obj) {
686 if (obj == obj_nil) {
687 error_push((Error){
688 .type = ERR_TYPE_RUNTIME,
689 .value = ERR_NOT_ENOUGH_ARGS,
690 });
691 return obj_err;
692 }
693 return eval(env, eval(env, obj->car));
694}
695
696// TODO: map
697// TODO: apply
698// TODO: filter
699
637// TODO: fixnum left/right shift, mask, invert 700// TODO: fixnum left/right shift, mask, invert
638// TODO: add primitives for type transforms: string->symbol, symbol->string, etc 701// TODO: add primitives for type transforms: string->symbol, symbol->string, etc
639// TODO: implement support for semi-quotes 702// TODO: implement support for semi-quotes
640// TODO: LAMBDA 703// TODO: LAMBDA
641// TODO: let 704// TODO: let
642// TODO: Revise all instances where we are returning an object, since currently
643// we may be returning a pointer to an object instead of a new one. Check also
644// on eval function and everytime we do make_xxx(obj).