diff options
-rw-r--r-- | examples/variables.bdl | 80 | ||||
-rw-r--r-- | src/bootstrap/environment.c | 8 | ||||
-rwxr-xr-x | src/bootstrap/main.c | 1 | ||||
-rw-r--r-- | src/bootstrap/objects.c | 4 | ||||
-rw-r--r-- | src/bootstrap/primitives.c | 43 | ||||
-rw-r--r-- | tests/variables_expected.txt | 34 |
6 files changed, 104 insertions, 66 deletions
diff --git a/examples/variables.bdl b/examples/variables.bdl index 2e2543a..7b343d1 100644 --- a/examples/variables.bdl +++ b/examples/variables.bdl | |||
@@ -2,64 +2,55 @@ | |||
2 | ;; Variable declarations and updates | 2 | ;; Variable declarations and updates |
3 | ;; | 3 | ;; |
4 | 4 | ||
5 | (supress-errors true) | 5 | (print "(def a 20)") (def a 20) (newline) |
6 | (print "(error? (def a 1)) -> ") (error? (def a 1)) | 6 | (print "((lambda (a b) (+ 10 a b)) 1 2) -> ") ((lambda (a b) (+ 10 a b)) 1 2) |
7 | (print "a -> ") a | 7 | (print "((lambda (a b) (+ 10 a b)) a 3) -> ") ((lambda (a b) (+ 10 a b)) a 3) |
8 | (print "(error? (def a 300)) -> ") (error? (def a 300)) | 8 | (print "(def myfun (lambda (a b) (+ a b))) (myfun 6 9) -> ") (def myfun (lambda (a b) (+ a b))) (myfun 6 9) |
9 | (print "a -> ") a | 9 | (print "(fun myfun (a b) (+ a b)) (myfun 6 9) -> ") (fun myfun (a b) (+ a b)) (myfun 6 9) |
10 | (print "(error? (def a \"strings\")) -> ") (error? (def a "strings")) | 10 | (print "(+ 1 (myfun 10 (myfun a a)) 30) -> ") (+ 1 (myfun 10 (myfun a a)) 30) |
11 | (print "a -> ") a | 11 | (print "(myfun 10 (myfun 5 0)) -> ") (myfun 10 (myfun 5 0)) |
12 | (print "(error? (def a 1)) -> ") (error? (def a '(quoted symbols 123 or "strings"))) | ||
13 | (print "a -> ") a | ||
14 | (print "(error? (set! a 42)) -> ") (error? (set! a 42)) | ||
15 | (print "a -> ") a | ||
16 | (print "(error? (set! b 99)) -> ") (error? (set! b 99)) | ||
17 | (lambda (a b) (+ 10 a b)) | ||
18 | |||
19 | (def a 20) | ||
20 | ((lambda (a b) (+ 10 a b)) 1 2) | ||
21 | ((lambda (a b) (+ 10 a b)) a 3) | ||
22 | (def myfun (lambda (a b) (+ a b))) | ||
23 | (myfun 6 9) | ||
24 | (+ 1 (myfun 10 (myfun a a)) 30) | ||
25 | (myfun 10 (myfun 5 0)) | ||
26 | 12 | ||
27 | ;; Closures. | 13 | ;; Closures. |
28 | (def make-counter (lambda () | 14 | (print "(fun make-counter () (def value 0) (def counter (lambda () (set! value (+ value 1)) value)) counter)") |
15 | (newline) | ||
16 | (fun make-counter () | ||
29 | (def value 0) | 17 | (def value 0) |
30 | (def counter (lambda () | 18 | (def counter (lambda () |
31 | (set! value (+ value 1)) | 19 | (set! value (+ value 1)) |
32 | value)) | 20 | value)) |
33 | counter)) | 21 | counter) |
34 | 22 | ||
35 | (def counter-a (make-counter)) | 23 | (print "(def counter-a (make-counter))") (def counter-a (make-counter)) (newline) |
36 | (def counter-b (make-counter)) | 24 | (print "(def counter-b (make-counter))") (def counter-b (make-counter)) (newline) |
37 | (counter-a) | 25 | (print "(counter-a) -> ") (counter-a) |
38 | (counter-a) | 26 | (print "(counter-b) -> ") (counter-b) |
39 | (counter-b) | 27 | (print "(counter-a) -> ") (counter-a) |
40 | (counter-b) | 28 | (print "(counter-a) -> ") (counter-a) |
41 | (counter-b) | 29 | (print "(counter-a) -> ") (counter-a) |
42 | (counter-b) | 30 | (print "(counter-b) -> ") (counter-b) |
43 | (counter-a) | 31 | (print "(counter-b) -> ") (counter-b) |
32 | (print "(counter-b) -> ") (counter-b) | ||
44 | 33 | ||
45 | ;; Fibonacci. | 34 | ;; Fibonacci. |
46 | (def fib (lambda (n) | 35 | (print "(fun fib (n) (if (<= n 2) 1 (+ (fib (- n 1)) (fib (- n 2)))))") (newline) |
47 | (if (<= n 2) | 36 | (fun fib (n) |
48 | 1 | 37 | (if (<= n 2) |
49 | (+ (fib (- n 1)) (fib (- n 2)))))) | 38 | 1 |
50 | (fib 15) | 39 | (+ (fib (- n 1)) (fib (- n 2))))) |
40 | |||
41 | (print "(fib 15) -> ")(fib 15) | ||
51 | 42 | ||
52 | ;; Lambda capture. | 43 | ;; Lambda capture. |
53 | (def a 20) | 44 | (print "(fun b () (display a) (print \" --- \") (def a 42) (display a) (newline))") (newline) |
54 | (def b (lambda () | 45 | (fun b () |
55 | (display a) | 46 | (display a) |
56 | (newline) | 47 | (print " --- ") |
57 | (def a 42) | 48 | (def a 42) |
58 | (display a) | 49 | (display a) |
59 | (newline))) | 50 | (newline)) |
60 | 51 | ||
61 | (b) | 52 | (print "(b) -> ") (b) |
62 | (b) | 53 | (print "(b) -> ") (b) |
63 | 54 | ||
64 | 55 | ||
65 | ;; Infinite loop. (For teseting purposes) | 56 | ;; Infinite loop. (For teseting purposes) |
@@ -68,5 +59,4 @@ | |||
68 | ; (if (<= n 2) | 59 | ; (if (<= n 2) |
69 | ; 'ok | 60 | ; 'ok |
70 | ; (test (+ n 1))))) | 61 | ; (test (+ n 1))))) |
71 | |||
72 | ; (test 3) | 62 | ; (test 3) |
diff --git a/src/bootstrap/environment.c b/src/bootstrap/environment.c index e111753..78f31fb 100644 --- a/src/bootstrap/environment.c +++ b/src/bootstrap/environment.c | |||
@@ -106,15 +106,15 @@ env_extend(Environment *parent, Environment *extra) { | |||
106 | for (size_t i = 0; i < extra->size; i++) { | 106 | for (size_t i = 0; i < extra->size; i++) { |
107 | EnvEntry entry = extra->buf[i]; | 107 | EnvEntry entry = extra->buf[i]; |
108 | Environment *tmp = env; | 108 | Environment *tmp = env; |
109 | ssize_t idx = -1; | 109 | bool found = false; |
110 | while (tmp != NULL) { | 110 | while (tmp != NULL) { |
111 | idx = env_index_current(tmp, entry.symbol); | 111 | if (env_index_current(tmp, entry.symbol) != -1) { |
112 | if (idx != -1) { | 112 | found = true; |
113 | break; | 113 | break; |
114 | } | 114 | } |
115 | tmp = tmp->parent; | 115 | tmp = tmp->parent; |
116 | } | 116 | } |
117 | if (idx == -1) { | 117 | if (!found) { |
118 | env_add_symbol(env, obj_duplicate(entry.symbol), obj_duplicate(entry.value)); | 118 | env_add_symbol(env, obj_duplicate(entry.symbol), obj_duplicate(entry.value)); |
119 | } | 119 | } |
120 | } | 120 | } |
diff --git a/src/bootstrap/main.c b/src/bootstrap/main.c index 7591834..5191fd0 100755 --- a/src/bootstrap/main.c +++ b/src/bootstrap/main.c | |||
@@ -76,6 +76,7 @@ init(void) { | |||
76 | MAKE_ENV_PROC(global_env, "def", proc_define); | 76 | MAKE_ENV_PROC(global_env, "def", proc_define); |
77 | MAKE_ENV_PROC(global_env, "set!", proc_set); | 77 | MAKE_ENV_PROC(global_env, "set!", proc_set); |
78 | MAKE_ENV_PROC(global_env, "lambda", proc_lambda); | 78 | MAKE_ENV_PROC(global_env, "lambda", proc_lambda); |
79 | MAKE_ENV_PROC(global_env, "fun", proc_fun); | ||
79 | 80 | ||
80 | // Runtime procedures. | 81 | // Runtime procedures. |
81 | MAKE_ENV_PROC(global_env, "supress-errors", proc_supress_errors); | 82 | MAKE_ENV_PROC(global_env, "supress-errors", proc_supress_errors); |
diff --git a/src/bootstrap/objects.c b/src/bootstrap/objects.c index b3aa3de..b03a616 100644 --- a/src/bootstrap/objects.c +++ b/src/bootstrap/objects.c | |||
@@ -41,7 +41,7 @@ typedef struct Object { | |||
41 | 41 | ||
42 | // OBJ_TYPE_LAMBDA | 42 | // OBJ_TYPE_LAMBDA |
43 | struct { | 43 | struct { |
44 | struct Object *args; | 44 | struct Object *params; |
45 | struct Object *body; | 45 | struct Object *body; |
46 | struct Environment *env; | 46 | struct Environment *env; |
47 | }; | 47 | }; |
@@ -186,7 +186,7 @@ free_objects(Object *root) { | |||
186 | free(root); | 186 | free(root); |
187 | } break; | 187 | } break; |
188 | case OBJ_TYPE_LAMBDA: { | 188 | case OBJ_TYPE_LAMBDA: { |
189 | free_objects(root->args); | 189 | free_objects(root->params); |
190 | free_objects(root->body); | 190 | free_objects(root->body); |
191 | // TODO: free_env(root->env); | 191 | // TODO: free_env(root->env); |
192 | free(root); | 192 | free(root); |
diff --git a/src/bootstrap/primitives.c b/src/bootstrap/primitives.c index 4ef56d5..4c3e4c6 100644 --- a/src/bootstrap/primitives.c +++ b/src/bootstrap/primitives.c | |||
@@ -54,7 +54,7 @@ eval_lambda: | |||
54 | if (lambda->type == OBJ_TYPE_LAMBDA) { | 54 | if (lambda->type == OBJ_TYPE_LAMBDA) { |
55 | Object *fun = lambda; | 55 | Object *fun = lambda; |
56 | Object *args = root->cdr; | 56 | Object *args = root->cdr; |
57 | Object *params = fun->args; | 57 | Object *params = fun->params; |
58 | env = env_extend(fun->env, env); | 58 | env = env_extend(fun->env, env); |
59 | while (params != obj_nil) { | 59 | while (params != obj_nil) { |
60 | if (args == obj_nil) { | 60 | if (args == obj_nil) { |
@@ -742,8 +742,8 @@ proc_lambda(Environment *env, Object *obj) { | |||
742 | }); | 742 | }); |
743 | return obj_err; | 743 | return obj_err; |
744 | } | 744 | } |
745 | Object *args = obj->car; | 745 | Object *params = obj->car; |
746 | if (args != obj_nil && args->type != OBJ_TYPE_PAIR) { | 746 | if (params != obj_nil && params->type != OBJ_TYPE_PAIR) { |
747 | error_push((Error){ | 747 | error_push((Error){ |
748 | .type = ERR_TYPE_RUNTIME, | 748 | .type = ERR_TYPE_RUNTIME, |
749 | .value = ERR_WRONG_ARG_TYPE, | 749 | .value = ERR_WRONG_ARG_TYPE, |
@@ -752,12 +752,47 @@ proc_lambda(Environment *env, Object *obj) { | |||
752 | } | 752 | } |
753 | Object *body = obj->cdr; | 753 | Object *body = obj->cdr; |
754 | Object *fun = alloc_object(OBJ_TYPE_LAMBDA); | 754 | Object *fun = alloc_object(OBJ_TYPE_LAMBDA); |
755 | fun->args = obj_duplicate(args); | 755 | fun->params = obj_duplicate(params); |
756 | fun->body = obj_duplicate(body); | 756 | fun->body = obj_duplicate(body); |
757 | fun->env = env; | 757 | fun->env = env; |
758 | return fun; | 758 | return fun; |
759 | } | 759 | } |
760 | 760 | ||
761 | Object * | ||
762 | proc_fun(Environment *env, Object *obj) { | ||
763 | if (obj == obj_nil || obj->cdr == obj_nil || obj->cdr->cdr == obj_nil) { | ||
764 | error_push((Error){ | ||
765 | .type = ERR_TYPE_RUNTIME, | ||
766 | .value = ERR_NOT_ENOUGH_ARGS, | ||
767 | }); | ||
768 | return obj_err; | ||
769 | } | ||
770 | |||
771 | Object *name = obj->car; | ||
772 | if (name->type != OBJ_TYPE_SYMBOL) { | ||
773 | error_push((Error){ | ||
774 | .type = ERR_TYPE_RUNTIME, | ||
775 | .value = ERR_WRONG_ARG_TYPE, | ||
776 | }); | ||
777 | return obj_err; | ||
778 | } | ||
779 | |||
780 | Object *params = obj->cdr->car; | ||
781 | if (params != obj_nil && params->type != OBJ_TYPE_PAIR) { | ||
782 | error_push((Error){ | ||
783 | .type = ERR_TYPE_RUNTIME, | ||
784 | .value = ERR_WRONG_ARG_TYPE, | ||
785 | }); | ||
786 | return obj_err; | ||
787 | } | ||
788 | Object *body = obj->cdr->cdr; | ||
789 | Object *fun = alloc_object(OBJ_TYPE_LAMBDA); | ||
790 | fun->params = obj_duplicate(params); | ||
791 | fun->body = obj_duplicate(body); | ||
792 | fun->env = env; | ||
793 | env_add_or_update_current(env, name, fun); | ||
794 | return obj_nil; | ||
795 | } | ||
761 | 796 | ||
762 | // | 797 | // |
763 | // Evaluation. | 798 | // Evaluation. |
diff --git a/tests/variables_expected.txt b/tests/variables_expected.txt index 2e6e2be..02a5f7a 100644 --- a/tests/variables_expected.txt +++ b/tests/variables_expected.txt | |||
@@ -1,11 +1,23 @@ | |||
1 | (error? (def a 1)) -> false | 1 | (def a 20) |
2 | a -> 1 | 2 | ((lambda (a b) (+ 10 a b)) 1 2) -> 13 |
3 | (error? (def a 300)) -> false | 3 | ((lambda (a b) (+ 10 a b)) a 3) -> 33 |
4 | a -> 300 | 4 | (def myfun (lambda (a b) (+ a b))) (myfun 6 9) -> 15 |
5 | (error? (def a "strings")) -> false | 5 | (fun myfun (a b) (+ a b)) (myfun 6 9) -> 15 |
6 | a -> "strings" | 6 | (+ 1 (myfun 10 (myfun a a)) 30) -> 81 |
7 | (error? (def a 1)) -> false | 7 | (myfun 10 (myfun 5 0)) -> 15 |
8 | a -> (:quoted :symbols 123 :or "strings") | 8 | (fun make-counter () (def value 0) (def counter (lambda () (set! value (+ value 1)) value)) counter) |
9 | (error? (set! a 42)) -> false | 9 | (def counter-a (make-counter)) |
10 | a -> 42 | 10 | (def counter-b (make-counter)) |
11 | (error? (set! b 99)) -> true | 11 | (counter-a) -> 1 |
12 | (counter-b) -> 1 | ||
13 | (counter-a) -> 2 | ||
14 | (counter-a) -> 3 | ||
15 | (counter-a) -> 4 | ||
16 | (counter-b) -> 2 | ||
17 | (counter-b) -> 3 | ||
18 | (counter-b) -> 4 | ||
19 | (fun fib (n) (if (<= n 2) 1 (+ (fib (- n 1)) (fib (- n 2))))) | ||
20 | (fib 15) -> 610 | ||
21 | (fun b () (display a) (print " --- ") (def a 42) (display a) (newline)) | ||
22 | (b) -> 20 --- 42 | ||
23 | (b) -> 20 --- 42 | ||