aboutsummaryrefslogtreecommitdiffstats
path: root/src/bootstrap
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-10-14 17:05:37 +0200
committerBad Diode <bd@badd10de.dev>2021-10-14 17:05:37 +0200
commit530ed15ec941194e661010498cf30b7842710939 (patch)
treeccd1d771350453b59049e06ac224728f321f2b15 /src/bootstrap
parentab23395b1fc88bbc63bef88de3477cc316857ace (diff)
downloadbdl-530ed15ec941194e661010498cf30b7842710939.tar.gz
bdl-530ed15ec941194e661010498cf30b7842710939.zip
Fix lambda and closures
Diffstat (limited to 'src/bootstrap')
-rw-r--r--src/bootstrap/environment.c52
-rw-r--r--src/bootstrap/primitives.c55
2 files changed, 75 insertions, 32 deletions
diff --git a/src/bootstrap/environment.c b/src/bootstrap/environment.c
index 99dd7fd..e111753 100644
--- a/src/bootstrap/environment.c
+++ b/src/bootstrap/environment.c
@@ -60,8 +60,27 @@ env_lookup(Environment *env, Object *symbol) {
60 return obj_err; 60 return obj_err;
61} 61}
62 62
63Object *
64env_update(Environment *env, Object *symbol, Object *value) {
65 while (env != NULL) {
66 for (size_t i = 0; i < env->size; i++) {
67 EnvEntry entry = env->buf[i];
68 if (obj_eq(symbol, entry.symbol)) {
69 env->buf[i].value = obj_duplicate(value);
70 return obj_nil;
71 }
72 }
73 env = env->parent;
74 }
75 error_push((Error){
76 .type = ERR_TYPE_RUNTIME,
77 .value = ERR_SYMBOL_NOT_FOUND,
78 });
79 return obj_err;
80}
81
63ssize_t 82ssize_t
64env_symbol_index_in_current_env(Environment *env, Object *symbol) { 83env_index_current(Environment *env, Object *symbol) {
65 for (size_t i = 0; i < env->size; i++) { 84 for (size_t i = 0; i < env->size; i++) {
66 EnvEntry entry = env->buf[i]; 85 EnvEntry entry = env->buf[i];
67 if (obj_eq(symbol, entry.symbol)) { 86 if (obj_eq(symbol, entry.symbol)) {
@@ -70,3 +89,34 @@ env_symbol_index_in_current_env(Environment *env, Object *symbol) {
70 } 89 }
71 return -1; 90 return -1;
72} 91}
92
93void
94env_add_or_update_current(Environment *env, Object *symbol, Object *value) {
95 ssize_t index = env_index_current(env, symbol);
96 if (index == -1) {
97 env_add_symbol(env, obj_duplicate(symbol), obj_duplicate(value));
98 } else {
99 env->buf[index].value = obj_duplicate(value);
100 }
101}
102
103Environment *
104env_extend(Environment *parent, Environment *extra) {
105 Environment *env = env_create(parent);
106 for (size_t i = 0; i < extra->size; i++) {
107 EnvEntry entry = extra->buf[i];
108 Environment *tmp = env;
109 ssize_t idx = -1;
110 while (tmp != NULL) {
111 idx = env_index_current(tmp, entry.symbol);
112 if (idx != -1) {
113 break;
114 }
115 tmp = tmp->parent;
116 }
117 if (idx == -1) {
118 env_add_symbol(env, obj_duplicate(entry.symbol), obj_duplicate(entry.value));
119 }
120 }
121 return env;
122}
diff --git a/src/bootstrap/primitives.c b/src/bootstrap/primitives.c
index 461799e..4ef56d5 100644
--- a/src/bootstrap/primitives.c
+++ b/src/bootstrap/primitives.c
@@ -1,6 +1,7 @@
1#define DEBUG_OBJ(MSG,OBJ) printf((MSG)); display(OBJ); printf("\n");
2
1Object * 3Object *
2eval(Environment* env, Object *root) { 4eval(Environment* env, Object *root) {
3tailcall:
4 switch (root->type) { 5 switch (root->type) {
5 case OBJ_TYPE_ERR: 6 case OBJ_TYPE_ERR:
6 case OBJ_TYPE_PROCEDURE: 7 case OBJ_TYPE_PROCEDURE:
@@ -35,17 +36,26 @@ tailcall:
35 if (val->type == OBJ_TYPE_PROCEDURE) { 36 if (val->type == OBJ_TYPE_PROCEDURE) {
36 return val->proc(env, root->cdr); 37 return val->proc(env, root->cdr);
37 } 38 }
39 if (val->type == OBJ_TYPE_LAMBDA) {
40 goto eval_lambda;
41 }
38 error_push((Error){ 42 error_push((Error){
39 .type = ERR_TYPE_RUNTIME, 43 .type = ERR_TYPE_RUNTIME,
40 .value = ERR_OBJ_NOT_CALLABLE, 44 .value = ERR_OBJ_NOT_CALLABLE,
41 }); 45 });
42 return obj_err; 46 return obj_err;
43 } 47 }
44 Object* lambda = eval(env, root->car); 48 Object* lambda;
49eval_lambda:
50 lambda = eval(env, root->car);
51 if (lambda == obj_err) {
52 return obj_err;
53 }
45 if (lambda->type == OBJ_TYPE_LAMBDA) { 54 if (lambda->type == OBJ_TYPE_LAMBDA) {
46 Object *fun = lambda; 55 Object *fun = lambda;
47 Object *args = root->cdr; 56 Object *args = root->cdr;
48 Object *params = fun->args; 57 Object *params = fun->args;
58 env = env_extend(fun->env, env);
49 while (params != obj_nil) { 59 while (params != obj_nil) {
50 if (args == obj_nil) { 60 if (args == obj_nil) {
51 error_push((Error){ 61 error_push((Error){
@@ -66,12 +76,7 @@ tailcall:
66 }); 76 });
67 return obj_err; 77 return obj_err;
68 } 78 }
69 ssize_t index = env_symbol_index_in_current_env(fun->env, symbol); 79 env_add_or_update_current(env, symbol, value);
70 if (index == -1) {
71 env_add_symbol(fun->env, obj_duplicate(symbol), obj_duplicate(value));
72 } else {
73 fun->env->buf[index].value = obj_duplicate(value);
74 }
75 args = args->cdr; 80 args = args->cdr;
76 params = params->cdr; 81 params = params->cdr;
77 } 82 }
@@ -82,10 +87,14 @@ tailcall:
82 }); 87 });
83 return obj_err; 88 return obj_err;
84 } 89 }
85
86 env = fun->env;
87 root = fun->body; 90 root = fun->body;
88 goto tailcall; 91 while (root->cdr != obj_nil) {
92 if (eval(env, root->car) == obj_err) {
93 return obj_err;
94 };
95 root = root->cdr;
96 }
97 return eval(env, root->car);
89 } 98 }
90 } break; 99 } break;
91 } 100 }
@@ -693,13 +702,7 @@ proc_define(Environment *env, Object *obj) {
693 return obj_err; 702 return obj_err;
694 } 703 }
695 704
696 // Make a copy of the symbol and to make them permanent in the environment. 705 env_add_or_update_current(env, symbol, value);
697 ssize_t index = env_symbol_index_in_current_env(env, symbol);
698 if (index == -1) {
699 env_add_symbol(env, obj_duplicate(symbol), obj_duplicate(value));
700 } else {
701 env->buf[index].value = obj_duplicate(value);
702 }
703 return obj_nil; 706 return obj_nil;
704} 707}
705 708
@@ -727,17 +730,7 @@ proc_set(Environment *env, Object *obj) {
727 return obj_err; 730 return obj_err;
728 } 731 }
729 732
730 ssize_t index = env_symbol_index_in_current_env(env, symbol); 733 return env_update(env, symbol, value);
731 if (index == -1) {
732 error_push((Error){
733 .type = ERR_TYPE_RUNTIME,
734 .value = ERR_SYMBOL_NOT_FOUND,
735 });
736 return obj_err;
737 }
738
739 env->buf[index].value = obj_duplicate(value);
740 return obj_nil;
741} 734}
742 735
743Object * 736Object *
@@ -757,11 +750,11 @@ proc_lambda(Environment *env, Object *obj) {
757 }); 750 });
758 return obj_err; 751 return obj_err;
759 } 752 }
760 Object *body = obj->cdr->car; 753 Object *body = obj->cdr;
761 Object *fun = alloc_object(OBJ_TYPE_LAMBDA); 754 Object *fun = alloc_object(OBJ_TYPE_LAMBDA);
762 fun->args = obj_duplicate(args); 755 fun->args = obj_duplicate(args);
763 fun->body = obj_duplicate(body); 756 fun->body = obj_duplicate(body);
764 fun->env = env_create(env); 757 fun->env = env;
765 return fun; 758 return fun;
766} 759}
767 760