aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-10-16 21:56:00 +0200
committerBad Diode <bd@badd10de.dev>2021-10-16 21:56:00 +0200
commit54060b06acd084f75bfda00517479902a5652391 (patch)
tree1dae8d79b8ea7627dcd3647b8bc4035a19f0260d
parentbb58afb57221eb0316d6ee14e19c5f4c4a822ba1 (diff)
downloadbdl-54060b06acd084f75bfda00517479902a5652391.tar.gz
bdl-54060b06acd084f75bfda00517479902a5652391.zip
Add explicit TCO for lambda and if procedure
-rw-r--r--src/bootstrap/gc.c4
-rw-r--r--src/bootstrap/primitives.c53
2 files changed, 45 insertions, 12 deletions
diff --git a/src/bootstrap/gc.c b/src/bootstrap/gc.c
index 6e15c63..b63ee2b 100644
--- a/src/bootstrap/gc.c
+++ b/src/bootstrap/gc.c
@@ -35,7 +35,7 @@ alloc_env(void) {
35 if (gc.envs.size < gc.envs.cap) { 35 if (gc.envs.size < gc.envs.cap) {
36 return &gc.envs.buf[gc.envs.size++]; 36 return &gc.envs.buf[gc.envs.size++];
37 } 37 }
38 printf("error: not enough room for more environments\n"); 38 fprintf(stderr, "error: not enough room for more environments\n");
39 return NULL; 39 return NULL;
40} 40}
41 41
@@ -188,7 +188,7 @@ alloc_object(ObjectType type) {
188 if (gc.available_slots == 0) { 188 if (gc.available_slots == 0) {
189 mark_and_sweep(); 189 mark_and_sweep();
190 if (gc.available_slots == 0) { 190 if (gc.available_slots == 0) {
191 printf("NOT MORE MEMORY AVAILABLE WHERE IS YOUR GOD NOW MWAHAHA\n"); 191 fprintf(stderr, "NOT MORE MEMORY AVAILABLE WHERE IS YOUR GOD NOW MWAHAHA\n");
192 dump_gc(); 192 dump_gc();
193 exit(EXIT_FAILURE); 193 exit(EXIT_FAILURE);
194 // TODO: grow heap tables. 194 // TODO: grow heap tables.
diff --git a/src/bootstrap/primitives.c b/src/bootstrap/primitives.c
index abb87e7..a814e40 100644
--- a/src/bootstrap/primitives.c
+++ b/src/bootstrap/primitives.c
@@ -1,7 +1,12 @@
1#define DEBUG_OBJ(MSG,OBJ) printf((MSG)); display(OBJ); printf("\n"); 1#define DEBUG_OBJ(MSG,OBJ) printf((MSG)); display(OBJ); printf("\n");
2 2
3Object * proc_if(Environment *env, Object *obj);
4
3Object * 5Object *
4eval(Environment* env, Object *root) { 6eval(Environment *env, Object *root) {
7 Object* lambda;
8 bool recursion_active = false;
9eval_start:
5 switch (root->type) { 10 switch (root->type) {
6 case OBJ_TYPE_ERR: 11 case OBJ_TYPE_ERR:
7 case OBJ_TYPE_PROCEDURE: 12 case OBJ_TYPE_PROCEDURE:
@@ -34,9 +39,35 @@ eval(Environment* env, Object *root) {
34 return obj_err; 39 return obj_err;
35 } 40 }
36 if (val->type == OBJ_TYPE_PROCEDURE) { 41 if (val->type == OBJ_TYPE_PROCEDURE) {
42 // TODO: This is very messy, needs refactoring.
43 if (val->proc == proc_if) {
44 Object *obj = root->cdr;
45 if (obj == obj_nil || obj->cdr == obj_nil) {
46 error_push((Error){
47 .type = ERR_TYPE_RUNTIME,
48 .value = ERR_NOT_ENOUGH_ARGS,
49 });
50 return obj_err;
51 }
52 Object *car = obj->car;
53 Object *cdr = obj->cdr;
54 Object *condition = eval(env, car);
55 if (condition == obj_err) {
56 return obj_err;
57 }
58 if (condition == obj_true) {
59 root = cdr->car;
60 } else if (cdr->cdr != obj_nil) {
61 root = cdr->cdr->car;
62 } else {
63 return obj_nil;
64 }
65 goto eval_start;
66 }
37 return val->proc(env, root->cdr); 67 return val->proc(env, root->cdr);
38 } 68 }
39 if (val->type == OBJ_TYPE_LAMBDA) { 69 if (val->type == OBJ_TYPE_LAMBDA) {
70 lambda = val;
40 goto eval_lambda; 71 goto eval_lambda;
41 } 72 }
42 error_push((Error){ 73 error_push((Error){
@@ -45,17 +76,19 @@ eval(Environment* env, Object *root) {
45 }); 76 });
46 return obj_err; 77 return obj_err;
47 } 78 }
48 Object* lambda;
49eval_lambda:
50 lambda = eval(env, root->car); 79 lambda = eval(env, root->car);
51 if (lambda == obj_err) { 80 if (lambda == obj_err) {
52 return obj_err; 81 return obj_err;
53 } 82 }
54 if (lambda->type == OBJ_TYPE_LAMBDA) { 83 if (lambda->type == OBJ_TYPE_LAMBDA) {
55 Object *fun = lambda; 84 Object *args;
56 Object *args = root->cdr; 85eval_lambda:
57 Object *params = fun->params; 86 args = root->cdr;
58 env = env_extend(fun->env, env); 87 Object *params = lambda->params;
88 if (!recursion_active) {
89 env = env_extend(lambda->env, env);
90 recursion_active = true;
91 }
59 while (params != obj_nil) { 92 while (params != obj_nil) {
60 if (args == obj_nil) { 93 if (args == obj_nil) {
61 error_push((Error){ 94 error_push((Error){
@@ -87,15 +120,15 @@ eval_lambda:
87 }); 120 });
88 return obj_err; 121 return obj_err;
89 } 122 }
90 root = fun->body; 123 root = lambda->body;
91 while (root->cdr != obj_nil) { 124 while (root->cdr != obj_nil) {
92 if (eval(env, root->car) == obj_err) { 125 if (eval(env, root->car) == obj_err) {
93 return obj_err; 126 return obj_err;
94 }; 127 };
95 root = root->cdr; 128 root = root->cdr;
96 } 129 }
97 root = eval(env, root->car); 130 root = root->car;
98 return root; 131 goto eval_start;
99 } 132 }
100 } break; 133 } break;
101 } 134 }