diff options
Diffstat (limited to 'src/bootstrap/primitives.c')
-rw-r--r-- | src/bootstrap/primitives.c | 53 |
1 files changed, 43 insertions, 10 deletions
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 | ||
3 | Object * proc_if(Environment *env, Object *obj); | ||
4 | |||
3 | Object * | 5 | Object * |
4 | eval(Environment* env, Object *root) { | 6 | eval(Environment *env, Object *root) { |
7 | Object* lambda; | ||
8 | bool recursion_active = false; | ||
9 | eval_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; | ||
49 | eval_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; | 85 | eval_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 | } |