diff options
-rw-r--r-- | src/bootstrap/environment.c | 13 | ||||
-rwxr-xr-x | src/bootstrap/main.c | 2 | ||||
-rw-r--r-- | src/bootstrap/primitives.c | 68 |
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 | ||
63 | void | 63 | ssize_t |
64 | env_update_symbol(Environment *env, Object *symbol, Object *value) { | 64 | env_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 | ||
77 | void | 79 | void |
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 | |||
642 | Object * | ||
643 | proc_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 | |||
684 | Object * | ||
685 | proc_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). | ||