aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-10-14 18:06:54 +0200
committerBad Diode <bd@badd10de.dev>2021-10-14 18:06:54 +0200
commit14814ecbf53760654aab34e0613abf347a54113f (patch)
tree19decb356b5a4041ca1c953bdfa34b3f3a6636f1
parent530ed15ec941194e661010498cf30b7842710939 (diff)
downloadbdl-0.5.tar.gz
bdl-0.5.zip
Add fun sugar for function variable declarationv0.5
-rw-r--r--examples/variables.bdl80
-rw-r--r--src/bootstrap/environment.c8
-rwxr-xr-xsrc/bootstrap/main.c1
-rw-r--r--src/bootstrap/objects.c4
-rw-r--r--src/bootstrap/primitives.c43
-rw-r--r--tests/variables_expected.txt34
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
761Object *
762proc_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)
2a -> 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
4a -> 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
6a -> "strings" 6(+ 1 (myfun 10 (myfun a a)) 30) -> 81
7(error? (def a 1)) -> false 7(myfun 10 (myfun 5 0)) -> 15
8a -> (: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))
10a -> 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