diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | examples/arithmetic.bdl | 60 | ||||
-rw-r--r-- | examples/booleans.bdl | 82 | ||||
-rw-r--r-- | examples/lists.bdl | 24 | ||||
-rw-r--r-- | examples/rule110.bdl | 47 | ||||
-rw-r--r-- | examples/types.bdl | 72 | ||||
-rw-r--r-- | examples/variables.bdl | 84 | ||||
-rw-r--r-- | src/main.c | 336 | ||||
-rw-r--r-- | tests/arithmetic_expected.txt | 13 | ||||
-rw-r--r-- | tests/booleans_expected.txt | 53 | ||||
-rw-r--r-- | tests/constants/numbers.bdl | 41 | ||||
-rw-r--r-- | tests/constants/strings.bdl | 5 | ||||
-rw-r--r-- | tests/lists_expected.txt | 15 | ||||
-rw-r--r-- | tests/types_expected.txt | 55 | ||||
-rw-r--r-- | tests/variables.bad | 57 | ||||
-rw-r--r-- | tests/variables_expected.txt | 23 |
16 files changed, 346 insertions, 623 deletions
@@ -5,7 +5,7 @@ | |||
5 | SRC_DIR := src | 5 | SRC_DIR := src |
6 | BUILD_DIR := build | 6 | BUILD_DIR := build |
7 | SRC_MAIN := $(SRC_DIR)/main.c | 7 | SRC_MAIN := $(SRC_DIR)/main.c |
8 | SRC_BAD := tests/literals.bad | 8 | SRC_BAD := tests/variables.bad |
9 | WATCH_SRC := $(shell find $(SRC_DIR) -name "*.c" -or -name "*.s" -or -name "*.h") | 9 | WATCH_SRC := $(shell find $(SRC_DIR) -name "*.c" -or -name "*.s" -or -name "*.h") |
10 | INC_DIRS := $(shell find $(SRC_DIR) -type d) | 10 | INC_DIRS := $(shell find $(SRC_DIR) -type d) |
11 | INC_FLAGS := $(addprefix -I,$(INC_DIRS)) | 11 | INC_FLAGS := $(addprefix -I,$(INC_DIRS)) |
diff --git a/examples/arithmetic.bdl b/examples/arithmetic.bdl deleted file mode 100644 index c313dbb..0000000 --- a/examples/arithmetic.bdl +++ /dev/null | |||
@@ -1,60 +0,0 @@ | |||
1 | ;; | ||
2 | ;; Basic arithmetic operations. | ||
3 | ;; | ||
4 | |||
5 | ;; Addition. | ||
6 | (print "(+ 10 100) -> ") | ||
7 | (display (+ 10 100)) | ||
8 | (newline) | ||
9 | |||
10 | (print "(+ 1 -2 3 4) -> ") | ||
11 | (display (+ 1 -2 3 4)) | ||
12 | (newline) | ||
13 | |||
14 | ;; Substraction. | ||
15 | (print "(- 100 75) -> ") | ||
16 | (display (- 100 75)) | ||
17 | (newline) | ||
18 | |||
19 | (print "(- 10 20 30) -> ") | ||
20 | (display (- 10 20 30)) | ||
21 | (newline) | ||
22 | |||
23 | ;; Multiplication. | ||
24 | (print "(* 10 7) -> ") | ||
25 | (display (* 10 7)) | ||
26 | (newline) | ||
27 | |||
28 | (print "(* -1 66) -> ") | ||
29 | (display (* -1 66)) | ||
30 | (newline) | ||
31 | |||
32 | ;; Division. | ||
33 | (print "(/ 45 5) -> ") | ||
34 | (display (/ 45 5)) | ||
35 | (newline) | ||
36 | |||
37 | (print "(/ 10 5 2) -> ") | ||
38 | (display (/ 10 5 2)) | ||
39 | (newline) | ||
40 | |||
41 | ;; Remainder/modulo. | ||
42 | (print "(% 45 5) -> ") | ||
43 | (display (% 45 5)) | ||
44 | (newline) | ||
45 | |||
46 | (print "(% 45 7) -> ") | ||
47 | (display (% 45 7)) | ||
48 | (newline) | ||
49 | |||
50 | (print "(% 120 45) -> ") | ||
51 | (display (% 120 45)) | ||
52 | (newline) | ||
53 | |||
54 | (print "(% 120 45 8) -> ") | ||
55 | (display (% 120 45 8)) | ||
56 | (newline) | ||
57 | |||
58 | ;; Nesting operations. | ||
59 | (print "(* 20 (+ 100 (- 50 30) (/ 300 3)) 10) -> ") | ||
60 | (display (* 20 (+ 100 (- 50 30) (/ 300 3)) 10)) | ||
diff --git a/examples/booleans.bdl b/examples/booleans.bdl deleted file mode 100644 index 3d647a6..0000000 --- a/examples/booleans.bdl +++ /dev/null | |||
@@ -1,82 +0,0 @@ | |||
1 | ;; | ||
2 | ;; Boolean primitives. | ||
3 | ;; | ||
4 | |||
5 | ;; Not. | ||
6 | (print "(not true) -> ") (display (not true))(newline) | ||
7 | (print "(not false) -> ") (display (not false))(newline) | ||
8 | (print "(not (not true)) -> ") (display (not (not true)))(newline) | ||
9 | (print "(not (not false)) -> ") (display (not (not false)))(newline) | ||
10 | (print "(not 1) -> ") (display (not 1))(newline) | ||
11 | (print "(not (not 1)) -> ") (display (not (not 1)))(newline) | ||
12 | (print "(not \"string\") -> ") (display (not "string"))(newline) | ||
13 | (print "(not (not \"string\")) -> ") (display (not (not "string")))(newline) | ||
14 | |||
15 | ;; And. | ||
16 | (print "(and 1 \"string\" 4 true) -> ") (display (and 1 "string" 4 true))(newline) | ||
17 | (print "(and true true true) -> ") (display (and true true true))(newline) | ||
18 | ; (print "(and (+ 1 2 3)) -> ") (display (and (+ 1 2 3)))(newline) | ||
19 | (print "(and false false false) -> ") (display (and false false false))(newline) | ||
20 | (print "(and true false false) -> ") (display (and true false false))(newline) | ||
21 | (print "(and false true false) -> ") (display (and false true false))(newline) | ||
22 | (print "(and false true true) -> ") (display (and false true true))(newline) | ||
23 | (print "(and (not false) true true) -> ") (display (and (not false) true true))(newline) | ||
24 | |||
25 | ;; Or. | ||
26 | (print "(or 1 \"string\" 4 true) -> ") (display (or 1 "string" 4 true))(newline) | ||
27 | (print "(or false 1) -> ") (display (or false 1))(newline) | ||
28 | (print "(or false \"string\") -> ") (display (or false "string"))(newline) | ||
29 | ; (print "(or false) -> ") (display (or false))(newline) | ||
30 | (print "(or true true true) -> ") (display (or true true true))(newline) | ||
31 | (print "(or false false false) -> ") (display (or false false false))(newline) | ||
32 | (print "(or true false false) -> ") (display (or true false false))(newline) | ||
33 | (print "(or false true false) -> ") (display (or false true false))(newline) | ||
34 | (print "(or false true true) -> ") (display (or false true true))(newline) | ||
35 | (print "(or (not false) true true) -> ") (display (or (not false) true true))(newline) | ||
36 | (print "(or (not true) false) -> ") (display (or (not true) false))(newline) | ||
37 | |||
38 | ;; If. | ||
39 | (print "(if true true false) -> ") (display (if true true false))(newline) | ||
40 | (print "(if false true false) -> ") (display (if false true false))(newline) | ||
41 | (print "(if true (+ 1 2 3) 0) -> ") (display (if true (+ 1 2 3) 0))(newline) | ||
42 | (print "(if false (+ 1 2 3) 0) -> ") (display (if false (+ 1 2 3) 0))(newline) | ||
43 | (print "(if (or true false) (+ 1 2 3) (+ 7 8 9)) -> ") (display (if (or true false) (+ 1 2 3) (+ 7 8 9)))(newline) | ||
44 | (print "(if (or false false) (+ 1 2 3) (+ 7 8 9)) -> ") (display (if (or false false) (+ 1 2 3) (+ 7 8 9)))(newline) | ||
45 | (print "(if (or (+ 1 2 3) false) (+ 1 2 3) (+ 7 8 9)) -> ") (display (if (or (+ 1 2 3) false) (+ 1 2 3) (+ 7 8 9)))(newline) | ||
46 | (print "(if true 7) -> ") (display (if true 7))(newline) | ||
47 | (print "(if false 7) -> ") (display (if false 7))(newline) | ||
48 | |||
49 | ; ; ;; Cond. | ||
50 | ; ; (print "(cond ((and true true true) 1) ((or true true false) 2) (else 3)) -> ") | ||
51 | ; ; (cond ((and true true true) 1) | ||
52 | ; ; ((or true true false) 2) | ||
53 | ; ; (else 3)) | ||
54 | ; ; (print "(cond ((and true true false) 1) ((or true true false) 2) (else 3)) -> ") | ||
55 | ; ; (cond ((and true true false) 1) | ||
56 | ; ; ((or true true false) 2) | ||
57 | ; ; (else 3)) | ||
58 | ; ; (print "(cond ((and true true false) 1) ((or false false false) 2) (else 3)) -> ") | ||
59 | ; ; (cond ((and true true false) 1) | ||
60 | ; ; ((or false false false) 2) | ||
61 | ; ; (else 3)) | ||
62 | ; ; (print "(cond ((and true true true) 1) ((or true true false) 2)) -> ") | ||
63 | ; ; (cond ((and true true false) 1) | ||
64 | ; ; ((or false false false) 2)) (newline) | ||
65 | ; ; (print "(cond ((and true true true) (+ 1 2 3)) ((or true true false) 2) (else 3)) -> ") | ||
66 | ; ; (cond ((and true true true) (+ 1 2 3)) | ||
67 | ; ; ((or true true false) 2) | ||
68 | ; ; (else 3)) | ||
69 | |||
70 | ;; Numeric comparisons. | ||
71 | (print "(< 1 2 3) -> ") (display (< 1 2 3))(newline) | ||
72 | (print "(< 3 2 1) -> ") (display (< 3 2 1))(newline) | ||
73 | (print "(> 1 2 3) -> ") (display (> 1 2 3))(newline) | ||
74 | (print "(> 3 2 1) -> ") (display (> 3 2 1))(newline) | ||
75 | (print "(= 1 2 3) -> ") (display (= 1 2 3))(newline) | ||
76 | (print "(= 3 2 1) -> ") (display (= 3 2 1))(newline) | ||
77 | (print "(= 3 3 3) -> ") (display (= 3 3 3))(newline) | ||
78 | (print "(= (+ 1 2) 3 (- 6 3)) -> ") (display (= (+ 1 2) 3 (- 6 3)))(newline) | ||
79 | (print "(< 1 1 3) -> ") (display (< 1 1 3))(newline) | ||
80 | (print "(<= 1 1 3) -> ") (display (<= 1 1 3))(newline) | ||
81 | (print "(> 3 3 1) -> ") (display (> 3 3 1))(newline) | ||
82 | (print "(>= 3 3 1) -> ") (display (>= 3 3 1))(newline) | ||
diff --git a/examples/lists.bdl b/examples/lists.bdl deleted file mode 100644 index 36063d6..0000000 --- a/examples/lists.bdl +++ /dev/null | |||
@@ -1,24 +0,0 @@ | |||
1 | ;; | ||
2 | ;; List operations. | ||
3 | ;; | ||
4 | |||
5 | ;; List function. | ||
6 | (print "(list) -> ") (list) (newline) | ||
7 | (print "(list 1) -> ") (list 1) | ||
8 | (print "(list 1 2) -> ") (list 1 2) | ||
9 | (print "(list 1 2 3) -> ") (list 1 2 3) | ||
10 | (print "(list 4 5 (+ 1 2 3)) -> ") (list 4 5 (+ 1 2 3)) | ||
11 | |||
12 | ;; Car/cdr. | ||
13 | (print "(car (list 1 2 3)) -> ") (car (list 1 2 3)) | ||
14 | (print "(cdr (list 1 2 3)) -> ") (cdr (list 1 2 3)) | ||
15 | (print "(car (list (* 10 20) (+ 1 2 3) 50 60)) -> ") (car (list (* 10 20) (+ 1 2 3) 50 60)) | ||
16 | (print "(cdr (list (* 10 20) (+ 1 2 3) 50 60)) -> ") (cdr (list (* 10 20) (+ 1 2 3) 50 60)) | ||
17 | (print "(car (cdr (list (* 10 20) (+ 1 2 3) 50 60))) -> ") (car (cdr (list (* 10 20) (+ 1 2 3) 50 60))) | ||
18 | |||
19 | ;; Pairs construction. | ||
20 | (print "(cons 1 2) -> ") (cons 1 2) | ||
21 | (print "(cons \"a\" \"b\") -> ") (cons "a" "b") | ||
22 | (print "(cons \"a\" (cons \"c\" ())) -> ") (cons "a" (cons "c" ())) | ||
23 | (print "(cons 1 (cons 2 (cons (+ 1 2) ()))) -> ") (cons 1 (cons 2 (cons (+ 1 2) ()))) | ||
24 | (print "(cons 1 (cons 2 (cons (+ 1 2) 4))) -> ") (cons 1 (cons 2 (cons (+ 1 2) 4))) | ||
diff --git a/examples/rule110.bdl b/examples/rule110.bdl deleted file mode 100644 index abc89a9..0000000 --- a/examples/rule110.bdl +++ /dev/null | |||
@@ -1,47 +0,0 @@ | |||
1 | (def sequence (list 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1)) | ||
2 | |||
3 | (fun reverse (ls) | ||
4 | (fun rev-acc (ls acc) | ||
5 | (if (nil? ls) | ||
6 | acc | ||
7 | (rev-acc (cdr ls) (cons (car ls) acc)))) | ||
8 | (rev-acc ls '())) | ||
9 | |||
10 | (fun print-line (seq) | ||
11 | (if (or (nil? seq) (= 0 (car seq))) | ||
12 | (print " ") | ||
13 | (print "🖤")) | ||
14 | (if (not (nil? seq)) (print-line (cdr seq)))) | ||
15 | |||
16 | (fun rule-110 (seq n) | ||
17 | (print-line seq) | ||
18 | (newline) | ||
19 | (fun new-generation (lst seq) | ||
20 | (def a (if (nil? seq) 0 (car seq))) | ||
21 | (def b (if (or (nil? seq) | ||
22 | (nil? (cdr seq))) | ||
23 | 0 | ||
24 | (car (cdr seq)))) | ||
25 | (def c (if (or (nil? seq) | ||
26 | (nil? (cdr seq)) | ||
27 | (nil? (cdr (cdr seq)))) | ||
28 | 0 | ||
29 | (car (cdr (cdr seq))))) | ||
30 | (def number (+ (* a 2 2) (* b 2) c)) | ||
31 | (def cell (cond ((= number 0) 0) | ||
32 | ((= number 1) 1) | ||
33 | ((= number 2) 1) | ||
34 | ((= number 3) 1) | ||
35 | ((= number 4) 0) | ||
36 | ((= number 5) 1) | ||
37 | ((= number 6) 1) | ||
38 | ((= number 7) 0))) | ||
39 | (if (nil? (cdr seq)) | ||
40 | lst | ||
41 | (new-generation (cons cell lst) (cdr seq)))) | ||
42 | (def seq (cons 0 (reverse (new-generation '() seq)))) | ||
43 | (if (= n 0) | ||
44 | () | ||
45 | (rule-110 seq (- n 1)))) | ||
46 | |||
47 | (rule-110 sequence 25) | ||
diff --git a/examples/types.bdl b/examples/types.bdl deleted file mode 100644 index 22ffdce..0000000 --- a/examples/types.bdl +++ /dev/null | |||
@@ -1,72 +0,0 @@ | |||
1 | ;; | ||
2 | ;; Type testing. | ||
3 | ;; | ||
4 | |||
5 | ;; Boolean. | ||
6 | (print "(boolean? true) -> ") (boolean? true) | ||
7 | (print "(boolean? false) -> ") (boolean? false) | ||
8 | (print "(boolean? 1) -> ") (boolean? 1) | ||
9 | (print "(boolean? 5) -> ") (boolean? 5) | ||
10 | (print "(boolean? \"string\") -> ") (boolean? "string") | ||
11 | (print "(boolean? (+ 1 2 3)) -> ") (boolean? (+ 1 2 3)) | ||
12 | (print "(boolean? (not 1)) -> ") (boolean? (not 1)) | ||
13 | |||
14 | ;; Empty list/null. | ||
15 | (print "(nil? true) -> ") (nil? true) | ||
16 | (print "(nil? false) -> ") (nil? false) | ||
17 | (print "(nil? 1) -> ") (nil? 1) | ||
18 | (print "(nil? 5) -> ") (nil? 5) | ||
19 | (print "(nil? \"string\") -> ") (nil? "string") | ||
20 | (print "(nil? (+ 1 2 3)) -> ") (nil? (+ 1 2 3)) | ||
21 | (print "(nil? (not 1)) -> ") (nil? (not 1)) | ||
22 | (print "(nil? ()) -> ") (nil? ()) | ||
23 | |||
24 | ;; String. | ||
25 | (print "(string? true) -> ") (string? true) | ||
26 | (print "(string? false) -> ") (string? false) | ||
27 | (print "(string? 1) -> ") (string? 1) | ||
28 | (print "(string? 5) -> ") (string? 5) | ||
29 | (print "(string? \"string\") -> ") (string? "string") | ||
30 | (print "(string? (+ 1 2 3)) -> ") (string? (+ 1 2 3)) | ||
31 | (print "(string? (not 1)) -> ") (string? (not 1)) | ||
32 | |||
33 | ;; Fixnum. | ||
34 | (print "(fixnum? true) -> ") (fixnum? true) | ||
35 | (print "(fixnum? false) -> ") (fixnum? false) | ||
36 | (print "(fixnum? 1) -> ") (fixnum? 1) | ||
37 | (print "(fixnum? 5) -> ") (fixnum? 5) | ||
38 | (print "(fixnum? \"string\") -> ") (fixnum? "string") | ||
39 | (print "(fixnum? (+ 1 2 3)) -> ") (fixnum? (+ 1 2 3)) | ||
40 | (print "(fixnum? (not 1)) -> ") (fixnum? (not 1)) | ||
41 | |||
42 | ;; Symbol. | ||
43 | (print "(symbol? true) -> ") (symbol? true) | ||
44 | (print "(symbol? false) -> ") (symbol? false) | ||
45 | (print "(symbol? 1) -> ") (symbol? 1) | ||
46 | (print "(symbol? +) -> ") (symbol? +) | ||
47 | (print "(symbol? \"string\") -> ") (symbol? "string") | ||
48 | (print "(symbol? (+ 1 2 3)) -> ") (symbol? (+ 1 2 3)) | ||
49 | (print "(symbol? (not 1)) -> ") (symbol? (not 1)) | ||
50 | (print "(symbol? 'a) -> ") (symbol? 'a) | ||
51 | (print "(symbol? 'c) -> ") (symbol? 'c) | ||
52 | |||
53 | ;; Pair. | ||
54 | (print "(pair? false) -> ") (pair? false) | ||
55 | (print "(pair? 1) -> ") (pair? 1) | ||
56 | (print "(pair? 5) -> ") (pair? 5) | ||
57 | (print "(pair? \"string\") -> ") (pair? "string") | ||
58 | (print "(pair? (+ 1 2 3)) -> ") (pair? (+ 1 2 3)) | ||
59 | (print "(pair? (not 1)) -> ") (pair? (not 1)) | ||
60 | (print "(pair? (cons 1 2)) -> ") (pair? (cons 1 2)) | ||
61 | (print "(pair? (list 1 2 3)) -> ") (pair? (list 1 2 3)) | ||
62 | |||
63 | ; ;; Procedure. | ||
64 | (print "(procedure? false) -> ") (procedure? false) | ||
65 | (print "(procedure? 1) -> ") (procedure? 1) | ||
66 | (print "(procedure? 5) -> ") (procedure? 5) | ||
67 | (print "(procedure? \"string\") -> ") (procedure? "string") | ||
68 | (print "(procedure? (+ 1 2 3)) -> ") (procedure? (+ 1 2 3)) | ||
69 | (print "(procedure? (not 1)) -> ") (procedure? (not 1)) | ||
70 | (print "(procedure? +) -> ") (procedure? +) | ||
71 | (print "(procedure? -) -> ") (procedure? -) | ||
72 | (print "(procedure? procedure?) -> ") (procedure? procedure?) | ||
diff --git a/examples/variables.bdl b/examples/variables.bdl deleted file mode 100644 index a4dea0a..0000000 --- a/examples/variables.bdl +++ /dev/null | |||
@@ -1,84 +0,0 @@ | |||
1 | ;; | ||
2 | ;; Variable declarations and updates | ||
3 | ;; | ||
4 | |||
5 | (print "(def a 20)") | ||
6 | (def a 20) | ||
7 | (newline) | ||
8 | |||
9 | (print "((lambda (a b) (+ 10 a b)) 1 2) -> ") | ||
10 | (display ((lambda (a b) (+ 10 a b)) 1 2)) | ||
11 | (newline) | ||
12 | |||
13 | (print "((lambda (a b) (+ 10 a b)) a 3) -> ") | ||
14 | (display ((lambda (a b) (+ 10 a b)) a 3)) | ||
15 | (newline) | ||
16 | |||
17 | (print "(def myfun (lambda (a b) (+ a b))) (myfun 6 9) -> ") | ||
18 | (def myfun (lambda (a b) (+ a b))) | ||
19 | (display (myfun 6 9)) | ||
20 | (newline) | ||
21 | |||
22 | (print "(fun myfun (a b) (+ a b)) (myfun 6 9) -> ") | ||
23 | (fun myfun (a b) (+ a b)) | ||
24 | (display (myfun 6 9)) | ||
25 | (newline) | ||
26 | |||
27 | (print "(+ 1 (myfun 10 (myfun a a)) 30) -> ") | ||
28 | (display (+ 1 (myfun 10 (myfun a a)) 30)) | ||
29 | (newline) | ||
30 | |||
31 | (print "(myfun 10 (myfun 5 0)) -> ") | ||
32 | (display (myfun 10 (myfun 5 0))) | ||
33 | (newline) | ||
34 | |||
35 | ;; Closures. | ||
36 | (print "(fun make-counter () (def value 0) (def counter (lambda () (set! value (+ value 1)) value)) counter)") | ||
37 | (newline) | ||
38 | (fun make-counter () | ||
39 | (def value 0) | ||
40 | (def counter (lambda () | ||
41 | (set! value (+ value 1)) | ||
42 | value)) | ||
43 | counter) | ||
44 | |||
45 | (print "(def counter-a (make-counter))") (def counter-a (make-counter)) (newline) | ||
46 | (print "(def counter-b (make-counter))") (def counter-b (make-counter)) (newline) | ||
47 | (print "(counter-a) -> ") (display (counter-a))(newline) | ||
48 | (print "(counter-b) -> ") (display (counter-b))(newline) | ||
49 | (print "(counter-a) -> ") (display (counter-a))(newline) | ||
50 | (print "(counter-a) -> ") (display (counter-a))(newline) | ||
51 | (print "(counter-a) -> ") (display (counter-a))(newline) | ||
52 | (print "(counter-b) -> ") (display (counter-b))(newline) | ||
53 | (print "(counter-b) -> ") (display (counter-b))(newline) | ||
54 | (print "(counter-b) -> ") (display (counter-b))(newline) | ||
55 | |||
56 | ;; Fibonacci. | ||
57 | (print "(fun fib (n) (if (<= n 2) 1 (+ (fib (- n 1)) (fib (- n 2)))))") (newline) | ||
58 | (fun fib (n) | ||
59 | (if (<= n 2) | ||
60 | 1 | ||
61 | (+ (fib (- n 1)) (fib (- n 2))))) | ||
62 | |||
63 | (print "(fib 15) -> ") | ||
64 | (display (fib 15))(newline) | ||
65 | |||
66 | ;; Lambda capture. | ||
67 | (print "(fun b () (display a) (print \" --- \") (def a 42) (display a) (newline))") (newline) | ||
68 | (fun b () | ||
69 | (display a) | ||
70 | (print " --- ") | ||
71 | (def a 42) | ||
72 | (display a) | ||
73 | (newline)) | ||
74 | |||
75 | (print "(b) -> ") (b) | ||
76 | (print "(b) -> ") (b) | ||
77 | |||
78 | ;; Infinite loop. (For teseting purposes) | ||
79 | ; (def test (lambda (n) | ||
80 | ; (print "ITER\n") | ||
81 | ; (if (<= n 2) | ||
82 | ; 1 | ||
83 | ; (test (+ n 1))))) | ||
84 | ; (test 3) | ||
@@ -70,6 +70,13 @@ typedef enum NodeKind { | |||
70 | NODE_TRUE, | 70 | NODE_TRUE, |
71 | NODE_FALSE, | 71 | NODE_FALSE, |
72 | NODE_NIL, | 72 | NODE_NIL, |
73 | // Keywords. | ||
74 | NODE_LET, | ||
75 | NODE_SET, | ||
76 | NODE_STRUCT, | ||
77 | // Helpers. | ||
78 | NODE_NODE_LIST, | ||
79 | NODE_NODE_TYPE, | ||
73 | } NodeKind; | 80 | } NodeKind; |
74 | 81 | ||
75 | Str node_str[] = { | 82 | Str node_str[] = { |
@@ -104,6 +111,12 @@ Str node_str[] = { | |||
104 | [NODE_TRUE] = cstr("TRUE"), | 111 | [NODE_TRUE] = cstr("TRUE"), |
105 | [NODE_FALSE] = cstr("FALSE"), | 112 | [NODE_FALSE] = cstr("FALSE"), |
106 | [NODE_NIL] = cstr("NIL"), | 113 | [NODE_NIL] = cstr("NIL"), |
114 | [NODE_LET] = cstr("LET"), | ||
115 | [NODE_SET] = cstr("SET"), | ||
116 | [NODE_STRUCT] = cstr("STRUCT"), | ||
117 | // Helpers. | ||
118 | [NODE_NODE_LIST] = cstr("..."), | ||
119 | [NODE_NODE_TYPE] = cstr("TYPE"), | ||
107 | }; | 120 | }; |
108 | 121 | ||
109 | typedef struct Node { | 122 | typedef struct Node { |
@@ -119,21 +132,17 @@ typedef struct Node { | |||
119 | Str str; | 132 | Str str; |
120 | Str sym; | 133 | Str sym; |
121 | } value; | 134 | } value; |
122 | struct Node *left; | 135 | union { |
123 | struct Node *right; | 136 | struct Node *left; |
137 | struct Node *varname; | ||
138 | }; | ||
139 | union { | ||
140 | struct Node *right; | ||
141 | struct Node *vartype; | ||
142 | struct Node *varvalue; | ||
143 | }; | ||
124 | } Node; | 144 | } Node; |
125 | 145 | ||
126 | Node * | ||
127 | node_alloc(NodeKind kind, Token tok, Arena *a) { | ||
128 | static sz id = 0; | ||
129 | Node *node = arena_calloc((sz)sizeof(Node), a); | ||
130 | node->id = id++; | ||
131 | node->kind = kind; | ||
132 | node->line = tok.line; | ||
133 | node->col = tok.col; | ||
134 | return node; | ||
135 | } | ||
136 | |||
137 | // | 146 | // |
138 | // Parsing. | 147 | // Parsing. |
139 | // | 148 | // |
@@ -179,6 +188,7 @@ typedef struct { | |||
179 | 188 | ||
180 | void parse_expr(Parser *parser, ParsePrecedence precedence); | 189 | void parse_expr(Parser *parser, ParsePrecedence precedence); |
181 | void parse_advance(Parser *parser); | 190 | void parse_advance(Parser *parser); |
191 | bool parse_match(Parser *parser, TokenKind kind); | ||
182 | 192 | ||
183 | void parse_grouping(Parser *parser); | 193 | void parse_grouping(Parser *parser); |
184 | void parse_unary(Parser *parser); | 194 | void parse_unary(Parser *parser); |
@@ -187,6 +197,11 @@ void parse_number(Parser *parser); | |||
187 | void parse_literal(Parser *parser); | 197 | void parse_literal(Parser *parser); |
188 | void parse_string(Parser *parser); | 198 | void parse_string(Parser *parser); |
189 | void parse_symbol(Parser *parser); | 199 | void parse_symbol(Parser *parser); |
200 | void parse_symbol_chain(Parser *parser); | ||
201 | void parse_keyword(Parser *parser); | ||
202 | void parse_struct(Parser *parser); | ||
203 | Node *parse_struct_field(Parser *parser); | ||
204 | Node *parse_type(Parser *parser); | ||
190 | 205 | ||
191 | ParseRule parse_rules[] = { | 206 | ParseRule parse_rules[] = { |
192 | [TOK_LPAREN] = {parse_grouping, NULL, PREC_NONE}, | 207 | [TOK_LPAREN] = {parse_grouping, NULL, PREC_NONE}, |
@@ -196,6 +211,7 @@ ParseRule parse_rules[] = { | |||
196 | [TOK_DIV] = {NULL, parse_binary, PREC_FACTOR}, | 211 | [TOK_DIV] = {NULL, parse_binary, PREC_FACTOR}, |
197 | [TOK_MUL] = {NULL, parse_binary, PREC_FACTOR}, | 212 | [TOK_MUL] = {NULL, parse_binary, PREC_FACTOR}, |
198 | [TOK_MOD] = {NULL, parse_binary, PREC_FACTOR}, | 213 | [TOK_MOD] = {NULL, parse_binary, PREC_FACTOR}, |
214 | |||
199 | // Logical. | 215 | // Logical. |
200 | [TOK_NOT] = {parse_unary, NULL, PREC_NONE}, | 216 | [TOK_NOT] = {parse_unary, NULL, PREC_NONE}, |
201 | [TOK_AND] = {NULL, parse_binary, PREC_AND}, | 217 | [TOK_AND] = {NULL, parse_binary, PREC_AND}, |
@@ -206,23 +222,53 @@ ParseRule parse_rules[] = { | |||
206 | [TOK_GT] = {NULL, parse_binary, PREC_COMPARISON}, | 222 | [TOK_GT] = {NULL, parse_binary, PREC_COMPARISON}, |
207 | [TOK_LE] = {NULL, parse_binary, PREC_COMPARISON}, | 223 | [TOK_LE] = {NULL, parse_binary, PREC_COMPARISON}, |
208 | [TOK_GE] = {NULL, parse_binary, PREC_COMPARISON}, | 224 | [TOK_GE] = {NULL, parse_binary, PREC_COMPARISON}, |
225 | |||
209 | // Bitwise ops. | 226 | // Bitwise ops. |
210 | [TOK_BITNOT] = {parse_unary, NULL, PREC_NONE}, | 227 | [TOK_BITNOT] = {parse_unary, NULL, PREC_NONE}, |
211 | [TOK_BITAND] = {NULL, parse_binary, PREC_BITLOGIC}, | 228 | [TOK_BITAND] = {NULL, parse_binary, PREC_BITLOGIC}, |
212 | [TOK_BITOR] = {NULL, parse_binary, PREC_BITLOGIC}, | 229 | [TOK_BITOR] = {NULL, parse_binary, PREC_BITLOGIC}, |
213 | [TOK_BITLSHIFT] = {NULL, parse_binary, PREC_BITSHIFT}, | 230 | [TOK_BITLSHIFT] = {NULL, parse_binary, PREC_BITSHIFT}, |
214 | [TOK_BITRSHIFT] = {NULL, parse_binary, PREC_BITSHIFT}, | 231 | [TOK_BITRSHIFT] = {NULL, parse_binary, PREC_BITSHIFT}, |
232 | |||
215 | // Literals. | 233 | // Literals. |
216 | [TOK_STRING] = {parse_string, NULL, PREC_NONE}, | 234 | [TOK_STRING] = {parse_string, NULL, PREC_NONE}, |
217 | [TOK_SYMBOL] = {parse_symbol, NULL, PREC_NONE}, | 235 | [TOK_SYMBOL] = {parse_symbol_chain, NULL, PREC_NONE}, |
218 | [TOK_NUM_INT] = {parse_number, NULL, PREC_NONE}, | 236 | [TOK_NUM_INT] = {parse_number, NULL, PREC_NONE}, |
219 | [TOK_NUM_FLOAT] = {parse_number, NULL, PREC_NONE}, | 237 | [TOK_NUM_FLOAT] = {parse_number, NULL, PREC_NONE}, |
220 | [TOK_TRUE] = {parse_literal, NULL, PREC_NONE}, | 238 | [TOK_TRUE] = {parse_literal, NULL, PREC_NONE}, |
221 | [TOK_FALSE] = {parse_literal, NULL, PREC_NONE}, | 239 | [TOK_FALSE] = {parse_literal, NULL, PREC_NONE}, |
222 | [TOK_NIL] = {parse_literal, NULL, PREC_NONE}, | 240 | [TOK_NIL] = {parse_literal, NULL, PREC_NONE}, |
241 | |||
242 | // Statements. | ||
243 | [TOK_LET] = {parse_keyword, NULL, PREC_NONE}, | ||
244 | [TOK_SET] = {parse_keyword, NULL, PREC_NONE}, | ||
245 | [TOK_STRUCT] = {parse_keyword, NULL, PREC_NONE}, | ||
246 | [TOK_IF] = {parse_keyword, NULL, PREC_NONE}, | ||
247 | [TOK_MATCH] = {parse_keyword, NULL, PREC_NONE}, | ||
248 | [TOK_CASE] = {parse_keyword, NULL, PREC_NONE}, | ||
249 | [TOK_WHILE] = {parse_keyword, NULL, PREC_NONE}, | ||
250 | [TOK_CONTINUE] = {parse_keyword, NULL, PREC_NONE}, | ||
251 | [TOK_BREAK] = {parse_keyword, NULL, PREC_NONE}, | ||
252 | [TOK_FUN] = {parse_keyword, NULL, PREC_NONE}, | ||
253 | [TOK_RETURN] = {parse_keyword, NULL, PREC_NONE}, | ||
254 | |||
223 | [TOK_EOF] = {NULL, NULL, PREC_NONE}, | 255 | [TOK_EOF] = {NULL, NULL, PREC_NONE}, |
224 | }; | 256 | }; |
225 | 257 | ||
258 | Node * | ||
259 | node_alloc(NodeKind kind, Token tok, Parser *p) { | ||
260 | if (p->panic) { | ||
261 | return NULL; | ||
262 | } | ||
263 | static sz id = 0; | ||
264 | Node *node = arena_calloc((sz)sizeof(Node), p->storage); | ||
265 | node->id = id++; | ||
266 | node->kind = kind; | ||
267 | node->line = tok.line; | ||
268 | node->col = tok.col; | ||
269 | return node; | ||
270 | } | ||
271 | |||
226 | void | 272 | void |
227 | parse_emit_err(Parser *parser, Token token, Str msg) { | 273 | parse_emit_err(Parser *parser, Token token, Str msg) { |
228 | if (parser->panic) { | 274 | if (parser->panic) { |
@@ -243,9 +289,22 @@ void | |||
243 | parse_advance(Parser *parser) { | 289 | parse_advance(Parser *parser) { |
244 | assert(parser); | 290 | assert(parser); |
245 | parser->previous = parser->current; | 291 | parser->previous = parser->current; |
292 | if (parser->previous.kind == TOK_EOF) { | ||
293 | return; | ||
294 | } | ||
246 | parser->current = parser->tokens[parser->idx++]; | 295 | parser->current = parser->tokens[parser->idx++]; |
247 | } | 296 | } |
248 | 297 | ||
298 | bool | ||
299 | parse_match(Parser *parser, TokenKind kind) { | ||
300 | assert(parser); | ||
301 | if (parser->current.kind != kind) { | ||
302 | return false; | ||
303 | } | ||
304 | parse_advance(parser); | ||
305 | return true; | ||
306 | } | ||
307 | |||
249 | static void | 308 | static void |
250 | parse_consume(Parser *parser, TokenKind kind, Str msg) { | 309 | parse_consume(Parser *parser, TokenKind kind, Str msg) { |
251 | if (parser->current.kind == kind) { | 310 | if (parser->current.kind == kind) { |
@@ -258,6 +317,10 @@ parse_consume(Parser *parser, TokenKind kind, Str msg) { | |||
258 | void | 317 | void |
259 | parse_expr(Parser *parser, ParsePrecedence precedence) { | 318 | parse_expr(Parser *parser, ParsePrecedence precedence) { |
260 | parse_advance(parser); | 319 | parse_advance(parser); |
320 | // TODO: synchronize panic mode on keywords. | ||
321 | if (parser->panic) { | ||
322 | return; | ||
323 | } | ||
261 | ParseFn prefix = parse_rules[parser->previous.kind].prefix; | 324 | ParseFn prefix = parse_rules[parser->previous.kind].prefix; |
262 | if (prefix == NULL) { | 325 | if (prefix == NULL) { |
263 | parse_emit_err(parser, parser->previous, cstr("expected expression")); | 326 | parse_emit_err(parser, parser->previous, cstr("expected expression")); |
@@ -287,12 +350,13 @@ parse_unary(Parser *parser) { | |||
287 | parse_expr(parser, PREC_UNARY); | 350 | parse_expr(parser, PREC_UNARY); |
288 | Node *node = NULL; | 351 | Node *node = NULL; |
289 | switch (prev.kind) { | 352 | switch (prev.kind) { |
290 | case TOK_NOT: node = node_alloc(NODE_NOT, prev, parser->storage); break; | 353 | case TOK_NOT: node = node_alloc(NODE_NOT, prev, parser); break; |
291 | case TOK_BITNOT: { | 354 | case TOK_BITNOT: node = node_alloc(NODE_BITNOT, prev, parser); break; |
292 | node = node_alloc(NODE_BITNOT, prev, parser->storage); | ||
293 | } break; | ||
294 | default: break; // Unreachable. | 355 | default: break; // Unreachable. |
295 | } | 356 | } |
357 | if (!node) { | ||
358 | return; | ||
359 | } | ||
296 | node->left = array_pop(parser->nodes); | 360 | node->left = array_pop(parser->nodes); |
297 | array_push(parser->nodes, node, parser->storage); | 361 | array_push(parser->nodes, node, parser->storage); |
298 | } | 362 | } |
@@ -307,13 +371,142 @@ parse_literal(Parser *parser) { | |||
307 | Node *node = NULL; | 371 | Node *node = NULL; |
308 | switch (prev.kind) { | 372 | switch (prev.kind) { |
309 | case TOK_TRUE: { | 373 | case TOK_TRUE: { |
310 | node = node_alloc(NODE_TRUE, prev, parser->storage); | 374 | node = node_alloc(NODE_TRUE, prev, parser); |
311 | } break; | 375 | } break; |
312 | case TOK_FALSE: { | 376 | case TOK_FALSE: { |
313 | node = node_alloc(NODE_FALSE, prev, parser->storage); | 377 | node = node_alloc(NODE_FALSE, prev, parser); |
314 | } break; | 378 | } break; |
315 | case TOK_NIL: { | 379 | case TOK_NIL: { |
316 | node = node_alloc(NODE_NIL, prev, parser->storage); | 380 | node = node_alloc(NODE_NIL, prev, parser); |
381 | } break; | ||
382 | default: return; // Unreachable. | ||
383 | } | ||
384 | array_push(parser->nodes, node, parser->storage); | ||
385 | } | ||
386 | |||
387 | Node * | ||
388 | parse_type(Parser *parser) { | ||
389 | Token prev = parser->previous; | ||
390 | #if DEBUG == 1 | ||
391 | print("parsing type "); | ||
392 | print_token(prev); | ||
393 | #endif | ||
394 | Node *node = node_alloc(NODE_NODE_TYPE, prev, parser); | ||
395 | if (parse_match(parser, TOK_LCURLY)) { | ||
396 | node->value.sym = cstr("..."); | ||
397 | Node *l = parse_struct_field(parser); | ||
398 | if (!l) { | ||
399 | return NULL; | ||
400 | } | ||
401 | node->vartype = l; | ||
402 | while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { | ||
403 | Node *tmp = parse_struct_field(parser); | ||
404 | if (!tmp) { | ||
405 | return NULL; | ||
406 | } | ||
407 | l->vartype = tmp; | ||
408 | l = tmp; | ||
409 | } | ||
410 | return node; | ||
411 | } | ||
412 | parse_consume(parser, TOK_SYMBOL, cstr("no type given for struct field")); | ||
413 | node->value.sym = parser->previous.val; | ||
414 | return node; | ||
415 | } | ||
416 | |||
417 | Node * | ||
418 | parse_struct_field(Parser *parser) { | ||
419 | #if DEBUG == 1 | ||
420 | println("parsing struct field "); | ||
421 | print_token(parser->previous); | ||
422 | #endif | ||
423 | parse_consume(parser, TOK_SYMBOL, cstr("expected struct field name")); | ||
424 | parse_symbol(parser); | ||
425 | Node *field = array_pop(parser->nodes); | ||
426 | parse_consume(parser, TOK_COLON, | ||
427 | cstr("invalid type name given for struct field")); | ||
428 | field->vartype = parse_type(parser); | ||
429 | if (parse_match(parser, TOK_ASSIGN)) { | ||
430 | parse_expr(parser, PREC_LOW); | ||
431 | field->varname = array_pop(parser->nodes); | ||
432 | } | ||
433 | |||
434 | Node *list = node_alloc(NODE_NODE_LIST, parser->previous, parser); | ||
435 | list->varname = field; | ||
436 | return list; | ||
437 | } | ||
438 | |||
439 | void | ||
440 | parse_keyword(Parser *parser) { | ||
441 | Token prev = parser->previous; | ||
442 | #if DEBUG == 1 | ||
443 | print("parsing keyword "); | ||
444 | print_token(prev); | ||
445 | #endif | ||
446 | Node *node = NULL; | ||
447 | switch (prev.kind) { | ||
448 | case TOK_LET: { | ||
449 | parse_consume(parser, TOK_SYMBOL, | ||
450 | cstr("expected symbol name on let expression")); | ||
451 | parse_symbol(parser); | ||
452 | |||
453 | // Optional type declaration. | ||
454 | Node *type = NULL; | ||
455 | if (parse_match(parser, TOK_COLON)) { | ||
456 | type = parse_type(parser); | ||
457 | } | ||
458 | |||
459 | node = node_alloc(NODE_LET, prev, parser); | ||
460 | if (!node) { | ||
461 | return; | ||
462 | } | ||
463 | |||
464 | // Optional assignment. | ||
465 | if (parse_match(parser, TOK_ASSIGN)) { | ||
466 | parse_expr(parser, PREC_LOW); | ||
467 | node->varvalue = array_pop(parser->nodes); | ||
468 | } | ||
469 | node->varname = array_pop(parser->nodes); | ||
470 | node->varname->vartype = type; | ||
471 | } break; | ||
472 | case TOK_SET: { | ||
473 | parse_consume(parser, TOK_SYMBOL, | ||
474 | cstr("expected symbol name on set expression")); | ||
475 | parse_symbol_chain(parser); | ||
476 | parse_consume(parser, TOK_ASSIGN, | ||
477 | cstr("expected assignment on set expression")); | ||
478 | parse_expr(parser, PREC_LOW); | ||
479 | node = node_alloc(NODE_SET, prev, parser); | ||
480 | if (!node) { | ||
481 | return; | ||
482 | } | ||
483 | node->varvalue = array_pop(parser->nodes); | ||
484 | node->varname = array_pop(parser->nodes); | ||
485 | } break; | ||
486 | case TOK_STRUCT: { | ||
487 | parse_consume(parser, TOK_SYMBOL, | ||
488 | cstr("expected symbol name on struct definition")); | ||
489 | parse_symbol(parser); | ||
490 | parse_consume(parser, TOK_LCURLY, | ||
491 | cstr("expected '{' on struct definition")); | ||
492 | node = node_alloc(NODE_STRUCT, prev, parser); | ||
493 | if (!node) { | ||
494 | return; | ||
495 | } | ||
496 | node->varname = array_pop(parser->nodes); | ||
497 | Node *l = parse_struct_field(parser); | ||
498 | if (!l) { | ||
499 | return; | ||
500 | } | ||
501 | node->vartype = l; | ||
502 | while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { | ||
503 | Node *tmp = parse_struct_field(parser); | ||
504 | if (!tmp) { | ||
505 | return; | ||
506 | } | ||
507 | l->vartype = tmp; | ||
508 | l = tmp; | ||
509 | } | ||
317 | } break; | 510 | } break; |
318 | default: return; // Unreachable. | 511 | default: return; // Unreachable. |
319 | } | 512 | } |
@@ -332,36 +525,39 @@ parse_binary(Parser *parser) { | |||
332 | 525 | ||
333 | Node *node; | 526 | Node *node; |
334 | switch (prev.kind) { | 527 | switch (prev.kind) { |
335 | case TOK_ADD: node = node_alloc(NODE_ADD, prev, parser->storage); break; | 528 | case TOK_ADD: node = node_alloc(NODE_ADD, prev, parser); break; |
336 | case TOK_SUB: node = node_alloc(NODE_SUB, prev, parser->storage); break; | 529 | case TOK_SUB: node = node_alloc(NODE_SUB, prev, parser); break; |
337 | case TOK_MUL: node = node_alloc(NODE_MUL, prev, parser->storage); break; | 530 | case TOK_MUL: node = node_alloc(NODE_MUL, prev, parser); break; |
338 | case TOK_DIV: node = node_alloc(NODE_DIV, prev, parser->storage); break; | 531 | case TOK_DIV: node = node_alloc(NODE_DIV, prev, parser); break; |
339 | case TOK_MOD: node = node_alloc(NODE_MOD, prev, parser->storage); break; | 532 | case TOK_MOD: node = node_alloc(NODE_MOD, prev, parser); break; |
340 | case TOK_AND: node = node_alloc(NODE_AND, prev, parser->storage); break; | 533 | case TOK_AND: node = node_alloc(NODE_AND, prev, parser); break; |
341 | case TOK_OR: node = node_alloc(NODE_OR, prev, parser->storage); break; | 534 | case TOK_OR: node = node_alloc(NODE_OR, prev, parser); break; |
342 | case TOK_EQ: node = node_alloc(NODE_EQ, prev, parser->storage); break; | 535 | case TOK_EQ: node = node_alloc(NODE_EQ, prev, parser); break; |
343 | case TOK_NEQ: node = node_alloc(NODE_NEQ, prev, parser->storage); break; | 536 | case TOK_NEQ: node = node_alloc(NODE_NEQ, prev, parser); break; |
344 | case TOK_LT: node = node_alloc(NODE_LT, prev, parser->storage); break; | 537 | case TOK_LT: node = node_alloc(NODE_LT, prev, parser); break; |
345 | case TOK_GT: node = node_alloc(NODE_GT, prev, parser->storage); break; | 538 | case TOK_GT: node = node_alloc(NODE_GT, prev, parser); break; |
346 | case TOK_LE: node = node_alloc(NODE_LE, prev, parser->storage); break; | 539 | case TOK_LE: node = node_alloc(NODE_LE, prev, parser); break; |
347 | case TOK_GE: node = node_alloc(NODE_GE, prev, parser->storage); break; | 540 | case TOK_GE: node = node_alloc(NODE_GE, prev, parser); break; |
348 | case TOK_BITAND: { | 541 | case TOK_BITAND: { |
349 | node = node_alloc(NODE_BITAND, prev, parser->storage); | 542 | node = node_alloc(NODE_BITAND, prev, parser); |
350 | } break; | 543 | } break; |
351 | case TOK_BITOR: { | 544 | case TOK_BITOR: { |
352 | node = node_alloc(NODE_BITOR, prev, parser->storage); | 545 | node = node_alloc(NODE_BITOR, prev, parser); |
353 | } break; | 546 | } break; |
354 | case TOK_BITLSHIFT: { | 547 | case TOK_BITLSHIFT: { |
355 | node = node_alloc(NODE_BITLSHIFT, prev, parser->storage); | 548 | node = node_alloc(NODE_BITLSHIFT, prev, parser); |
356 | } break; | 549 | } break; |
357 | case TOK_BITRSHIFT: { | 550 | case TOK_BITRSHIFT: { |
358 | node = node_alloc(NODE_BITRSHIFT, prev, parser->storage); | 551 | node = node_alloc(NODE_BITRSHIFT, prev, parser); |
359 | } break; | 552 | } break; |
360 | default: { | 553 | default: { |
361 | parse_emit_err(parser, prev, cstr("unreachable")); | 554 | parse_emit_err(parser, prev, cstr("unreachable")); |
362 | return; | 555 | return; |
363 | } | 556 | } |
364 | } | 557 | } |
558 | if (!node) { | ||
559 | return; | ||
560 | } | ||
365 | node->right = array_pop(parser->nodes); | 561 | node->right = array_pop(parser->nodes); |
366 | node->left = array_pop(parser->nodes); | 562 | node->left = array_pop(parser->nodes); |
367 | array_push(parser->nodes, node, parser->storage); | 563 | array_push(parser->nodes, node, parser->storage); |
@@ -379,15 +575,24 @@ parse_number(Parser *parser) { | |||
379 | case TOK_NUM_INT: { | 575 | case TOK_NUM_INT: { |
380 | if (str_has_prefix(prev.val, cstr("0x")) || | 576 | if (str_has_prefix(prev.val, cstr("0x")) || |
381 | str_has_prefix(prev.val, cstr("0b"))) { | 577 | str_has_prefix(prev.val, cstr("0b"))) { |
382 | node = node_alloc(NODE_NUM_UINT, prev, parser->storage); | 578 | node = node_alloc(NODE_NUM_UINT, prev, parser); |
579 | if (!node) { | ||
580 | return; | ||
581 | } | ||
383 | node->value.u = str_to_uint(prev.val); | 582 | node->value.u = str_to_uint(prev.val); |
384 | } else { | 583 | } else { |
385 | node = node_alloc(NODE_NUM_INT, prev, parser->storage); | 584 | node = node_alloc(NODE_NUM_INT, prev, parser); |
585 | if (!node) { | ||
586 | return; | ||
587 | } | ||
386 | node->value.i = str_to_int(prev.val); | 588 | node->value.i = str_to_int(prev.val); |
387 | } | 589 | } |
388 | } break; | 590 | } break; |
389 | case TOK_NUM_FLOAT: { | 591 | case TOK_NUM_FLOAT: { |
390 | node = node_alloc(NODE_NUM_FLOAT, prev, parser->storage); | 592 | node = node_alloc(NODE_NUM_FLOAT, prev, parser); |
593 | if (!node) { | ||
594 | return; | ||
595 | } | ||
391 | node->value.d = str_to_float(prev.val); | 596 | node->value.d = str_to_float(prev.val); |
392 | } break; | 597 | } break; |
393 | default: break; | 598 | default: break; |
@@ -402,7 +607,10 @@ parse_string(Parser *parser) { | |||
402 | print("parsing string "); | 607 | print("parsing string "); |
403 | print_token(prev); | 608 | print_token(prev); |
404 | #endif | 609 | #endif |
405 | Node *node = node_alloc(NODE_STRING, prev, parser->storage); | 610 | Node *node = node_alloc(NODE_STRING, prev, parser); |
611 | if (!node) { | ||
612 | return; | ||
613 | } | ||
406 | node->value.str = str_remove_prefix(prev.val, cstr("\"")); | 614 | node->value.str = str_remove_prefix(prev.val, cstr("\"")); |
407 | node->value.str = str_remove_suffix(node->value.str, cstr("\"")); | 615 | node->value.str = str_remove_suffix(node->value.str, cstr("\"")); |
408 | array_push(parser->nodes, node, parser->storage); | 616 | array_push(parser->nodes, node, parser->storage); |
@@ -412,15 +620,39 @@ void | |||
412 | parse_symbol(Parser *parser) { | 620 | parse_symbol(Parser *parser) { |
413 | Token prev = parser->previous; | 621 | Token prev = parser->previous; |
414 | #if DEBUG == 1 | 622 | #if DEBUG == 1 |
415 | print("parsing string "); | 623 | print("parsing symbol "); |
416 | print_token(prev); | 624 | print_token(prev); |
417 | #endif | 625 | #endif |
418 | Node *node = node_alloc(NODE_STRING, prev, parser->storage); | 626 | Node *node = node_alloc(NODE_SYMBOL, prev, parser); |
627 | if (!node) { | ||
628 | return; | ||
629 | } | ||
419 | node->value.sym = prev.val; | 630 | node->value.sym = prev.val; |
420 | array_push(parser->nodes, node, parser->storage); | 631 | array_push(parser->nodes, node, parser->storage); |
421 | } | 632 | } |
422 | 633 | ||
423 | void | 634 | void |
635 | parse_symbol_chain(Parser *parser) { | ||
636 | Token prev = parser->previous; | ||
637 | #if DEBUG == 1 | ||
638 | print("parsing symbol "); | ||
639 | print_token(prev); | ||
640 | #endif | ||
641 | Node *node = node_alloc(NODE_SYMBOL, prev, parser); | ||
642 | if (!node) { | ||
643 | return; | ||
644 | } | ||
645 | node->value.sym = prev.val; | ||
646 | if (parse_match(parser, TOK_DOT)) { | ||
647 | parse_consume(parser, TOK_SYMBOL, | ||
648 | cstr("expected symbol after '.' operator")); | ||
649 | parse_symbol_chain(parser); | ||
650 | node->varname = array_pop(parser->nodes); | ||
651 | } | ||
652 | array_push(parser->nodes, node, parser->storage); | ||
653 | } | ||
654 | |||
655 | void | ||
424 | parse_grouping(Parser *parser) { | 656 | parse_grouping(Parser *parser) { |
425 | #if DEBUG == 1 | 657 | #if DEBUG == 1 |
426 | print("parsing group "); | 658 | print("parsing group "); |
@@ -436,23 +668,24 @@ graph_node(Node *node) { | |||
436 | return; | 668 | return; |
437 | } | 669 | } |
438 | print("%d [width=2.5,shape=Mrecord,label=\"", node->id); | 670 | print("%d [width=2.5,shape=Mrecord,label=\"", node->id); |
439 | print("<top> %s ", node_str[node->kind]); | 671 | print("{ %s | { L: %d | C: %d } } ", node_str[node->kind], node->line, |
672 | node->col); | ||
440 | switch (node->kind) { | 673 | switch (node->kind) { |
441 | case NODE_NUM_INT: print("| Value: %d", node->value.i); break; | 674 | case NODE_NUM_INT: print("| Value: %d", node->value.i); break; |
442 | case NODE_NUM_UINT: print("| Value: %x", node->value.u); break; | 675 | case NODE_NUM_UINT: print("| Value: %x", node->value.u); break; |
443 | case NODE_NUM_FLOAT: print("| Value: %f{2}", node->value.d); break; | 676 | case NODE_NUM_FLOAT: print("| Value: %f{2}", node->value.d); break; |
444 | case NODE_STRING: print("| Value: %s", node->value.str); break; | 677 | case NODE_STRING: print("| Value: %s", node->value.str); break; |
445 | case NODE_SYMBOL: print("| Value: %s", node->value.sym); break; | 678 | case NODE_SYMBOL: print("| Value: %s", node->value.sym); break; |
679 | case NODE_NODE_TYPE: print("| Value: %s", node->value.sym); break; | ||
446 | default: break; | 680 | default: break; |
447 | } | 681 | } |
448 | print("| Line: %d | Col: %d ", node->line, node->col); | ||
449 | println("\"];"); | 682 | println("\"];"); |
450 | if (node->left) { | 683 | if (node->left) { |
451 | println("%d:top:e->%d:top:w;", node->id, node->left->id); | 684 | println("%d:e->%d:w;", node->id, node->left->id); |
452 | graph_node(node->left); | 685 | graph_node(node->left); |
453 | } | 686 | } |
454 | if (node->right) { | 687 | if (node->right) { |
455 | println("%d:top:e->%d:top:w;", node->id, node->right->id); | 688 | println("%d:e->%d:w;", node->id, node->right->id); |
456 | graph_node(node->right); | 689 | graph_node(node->right); |
457 | } | 690 | } |
458 | } | 691 | } |
@@ -516,7 +749,14 @@ process_file(Str path) { | |||
516 | array_init(parser.nodes, 256, parser.storage); | 749 | array_init(parser.nodes, 256, parser.storage); |
517 | parse_advance(&parser); | 750 | parse_advance(&parser); |
518 | while (parser.current.kind != TOK_EOF) { | 751 | while (parser.current.kind != TOK_EOF) { |
752 | #if DEBUG == 1 | ||
753 | static sz ctr = 0; | ||
754 | println("parsing root: %d", ctr++); | ||
755 | #endif | ||
519 | parse_expr(&parser, PREC_LOW); | 756 | parse_expr(&parser, PREC_LOW); |
757 | if (parser.panic) { | ||
758 | break; | ||
759 | } | ||
520 | } | 760 | } |
521 | if (parser.err) { | 761 | if (parser.err) { |
522 | goto stop; | 762 | goto stop; |
diff --git a/tests/arithmetic_expected.txt b/tests/arithmetic_expected.txt deleted file mode 100644 index a2a5a83..0000000 --- a/tests/arithmetic_expected.txt +++ /dev/null | |||
@@ -1,13 +0,0 @@ | |||
1 | (+ 10 100) -> 110 | ||
2 | (+ 1 -2 3 4) -> 6 | ||
3 | (- 100 75) -> 25 | ||
4 | (- 10 20 30) -> -40 | ||
5 | (* 10 7) -> 70 | ||
6 | (* -1 66) -> -66 | ||
7 | (/ 45 5) -> 9 | ||
8 | (/ 10 5 2) -> 1 | ||
9 | (% 45 5) -> 0 | ||
10 | (% 45 7) -> 3 | ||
11 | (% 120 45) -> 30 | ||
12 | (% 120 45 8) -> 6 | ||
13 | (* 20 (+ 100 (- 50 30) (/ 300 3)) 10) -> 44000 | ||
diff --git a/tests/booleans_expected.txt b/tests/booleans_expected.txt deleted file mode 100644 index 43f67e5..0000000 --- a/tests/booleans_expected.txt +++ /dev/null | |||
@@ -1,53 +0,0 @@ | |||
1 | (not true) -> false | ||
2 | (not false) -> true | ||
3 | (not (not true)) -> true | ||
4 | (not (not false)) -> false | ||
5 | (not 1) -> false | ||
6 | (not (not 1)) -> true | ||
7 | (not "string") -> false | ||
8 | (not (not "string")) -> true | ||
9 | (and 1 "string" 4 true) -> true | ||
10 | (and true true true) -> true | ||
11 | (and (+ 1 2 3)) -> true | ||
12 | (and false false false) -> false | ||
13 | (and true false false) -> false | ||
14 | (and false true false) -> false | ||
15 | (and false true true) -> false | ||
16 | (and (not false) true true) -> true | ||
17 | (or 1 "string" 4 true) -> true | ||
18 | (or false 1) -> true | ||
19 | (or false "string") -> true | ||
20 | (or false) -> false | ||
21 | (or true true true) -> true | ||
22 | (or false false false) -> false | ||
23 | (or true false false) -> true | ||
24 | (or false true false) -> true | ||
25 | (or false true true) -> true | ||
26 | (or (not false) true true) -> true | ||
27 | (or (not true) false) -> false | ||
28 | (if true true false) -> true | ||
29 | (if false true false) -> false | ||
30 | (if true (+ 1 2 3) 0) -> 6 | ||
31 | (if false (+ 1 2 3) 0) -> 0 | ||
32 | (if (or true false) (+ 1 2 3) (+ 7 8 9)) -> 6 | ||
33 | (if (or false false) (+ 1 2 3) (+ 7 8 9)) -> 24 | ||
34 | (if (or (+ 1 2 3) false) (+ 1 2 3) (+ 7 8 9)) -> 6 | ||
35 | (if true 7) -> 7 | ||
36 | (if false 7) -> | ||
37 | (cond ((and true true true) 1) ((or true true false) 2) (else 3)) -> 1 | ||
38 | (cond ((and true true false) 1) ((or true true false) 2) (else 3)) -> 2 | ||
39 | (cond ((and true true false) 1) ((or false false false) 2) (else 3)) -> 3 | ||
40 | (cond ((and true true true) 1) ((or true true false) 2)) -> | ||
41 | (cond ((and true true true) (+ 1 2 3)) ((or true true false) 2) (else 3)) -> 6 | ||
42 | (< 1 2 3) -> true | ||
43 | (< 3 2 1) -> false | ||
44 | (> 1 2 3) -> false | ||
45 | (> 3 2 1) -> true | ||
46 | (= 1 2 3) -> false | ||
47 | (= 3 2 1) -> false | ||
48 | (= 3 3 3) -> true | ||
49 | (= (+ 1 2) 3 (- 6 3)) -> true | ||
50 | (< 1 1 3) -> false | ||
51 | (<= 1 1 3) -> true | ||
52 | (> 3 3 1) -> false | ||
53 | (>= 3 3 1) -> true | ||
diff --git a/tests/constants/numbers.bdl b/tests/constants/numbers.bdl deleted file mode 100644 index 136b5fb..0000000 --- a/tests/constants/numbers.bdl +++ /dev/null | |||
@@ -1,41 +0,0 @@ | |||
1 | ; Signed integers. | ||
2 | (print 1:s8) | ||
3 | (print 52:s8) | ||
4 | (print -1:s8) | ||
5 | (print 0:s8) | ||
6 | (print 1:s16) | ||
7 | (print 52:s16) | ||
8 | (print -1:s16) | ||
9 | (print 0:s16) | ||
10 | (print 1:s32) | ||
11 | (print 52:s32) | ||
12 | (print -1:s32) | ||
13 | (print 0:s32) | ||
14 | (print 1:s64) | ||
15 | (print 52:s64) | ||
16 | (print -1:s64) | ||
17 | (print 0:s64) | ||
18 | |||
19 | ; Unsigned integers. | ||
20 | (print 1:u8) | ||
21 | (print 52:u8) | ||
22 | (print -1:u8) | ||
23 | (print 0:u8) | ||
24 | (print 1:u16) | ||
25 | (print 52:u16) | ||
26 | (print -1:u16) | ||
27 | (print 0:u16) | ||
28 | (print 1:u32) | ||
29 | (print 52:u32) | ||
30 | (print -1:u32) | ||
31 | (print 0:u32) | ||
32 | (print 1:u64) | ||
33 | (print 52:u64) | ||
34 | (print -1:u64) | ||
35 | (print 0:u64) | ||
36 | |||
37 | ; Type inference. | ||
38 | (print 1) | ||
39 | (print 52) | ||
40 | (print -1) | ||
41 | (print 0) | ||
diff --git a/tests/constants/strings.bdl b/tests/constants/strings.bdl deleted file mode 100644 index 9b1d687..0000000 --- a/tests/constants/strings.bdl +++ /dev/null | |||
@@ -1,5 +0,0 @@ | |||
1 | (print "abc") | ||
2 | (print "test this longer string") | ||
3 | (print "escape\na\nnewline") | ||
4 | (print "escape\ttab\tcharacters") | ||
5 | (print "with type :str":str) | ||
diff --git a/tests/lists_expected.txt b/tests/lists_expected.txt deleted file mode 100644 index 6ddb71b..0000000 --- a/tests/lists_expected.txt +++ /dev/null | |||
@@ -1,15 +0,0 @@ | |||
1 | (list) -> | ||
2 | (list 1) -> (1) | ||
3 | (list 1 2) -> (1 2) | ||
4 | (list 1 2 3) -> (1 2 3) | ||
5 | (list 4 5 (+ 1 2 3)) -> (4 5 6) | ||
6 | (car (list 1 2 3)) -> 1 | ||
7 | (cdr (list 1 2 3)) -> (2 3) | ||
8 | (car (list (* 10 20) (+ 1 2 3) 50 60)) -> 200 | ||
9 | (cdr (list (* 10 20) (+ 1 2 3) 50 60)) -> (6 50 60) | ||
10 | (car (cdr (list (* 10 20) (+ 1 2 3) 50 60))) -> 6 | ||
11 | (cons 1 2) -> (1 . 2) | ||
12 | (cons "a" "b") -> ("a" . "b") | ||
13 | (cons "a" (cons "c" ())) -> ("a" "c") | ||
14 | (cons 1 (cons 2 (cons (+ 1 2) ()))) -> (1 2 3) | ||
15 | (cons 1 (cons 2 (cons (+ 1 2) 4))) -> (1 2 3 . 4) | ||
diff --git a/tests/types_expected.txt b/tests/types_expected.txt deleted file mode 100644 index 58eaa7f..0000000 --- a/tests/types_expected.txt +++ /dev/null | |||
@@ -1,55 +0,0 @@ | |||
1 | (boolean? true) -> true | ||
2 | (boolean? false) -> true | ||
3 | (boolean? 1) -> false | ||
4 | (boolean? 5) -> false | ||
5 | (boolean? "string") -> false | ||
6 | (boolean? (+ 1 2 3)) -> false | ||
7 | (boolean? (not 1)) -> true | ||
8 | (nil? true) -> false | ||
9 | (nil? false) -> false | ||
10 | (nil? 1) -> false | ||
11 | (nil? 5) -> false | ||
12 | (nil? "string") -> false | ||
13 | (nil? (+ 1 2 3)) -> false | ||
14 | (nil? (not 1)) -> false | ||
15 | (nil? ()) -> true | ||
16 | (string? true) -> false | ||
17 | (string? false) -> false | ||
18 | (string? 1) -> false | ||
19 | (string? 5) -> false | ||
20 | (string? "string") -> true | ||
21 | (string? (+ 1 2 3)) -> false | ||
22 | (string? (not 1)) -> false | ||
23 | (fixnum? true) -> false | ||
24 | (fixnum? false) -> false | ||
25 | (fixnum? 1) -> true | ||
26 | (fixnum? 5) -> true | ||
27 | (fixnum? "string") -> false | ||
28 | (fixnum? (+ 1 2 3)) -> true | ||
29 | (fixnum? (not 1)) -> false | ||
30 | (symbol? true) -> false | ||
31 | (symbol? false) -> false | ||
32 | (symbol? 1) -> false | ||
33 | (symbol? +) -> false | ||
34 | (symbol? "string") -> false | ||
35 | (symbol? (+ 1 2 3)) -> false | ||
36 | (symbol? (not 1)) -> false | ||
37 | (symbol? 'a) -> true | ||
38 | (symbol? 'c) -> true | ||
39 | (pair? false) -> false | ||
40 | (pair? 1) -> false | ||
41 | (pair? 5) -> false | ||
42 | (pair? "string") -> false | ||
43 | (pair? (+ 1 2 3)) -> false | ||
44 | (pair? (not 1)) -> false | ||
45 | (pair? (cons 1 2)) -> true | ||
46 | (pair? (list 1 2 3)) -> true | ||
47 | (procedure? false) -> false | ||
48 | (procedure? 1) -> false | ||
49 | (procedure? 5) -> false | ||
50 | (procedure? "string") -> false | ||
51 | (procedure? (+ 1 2 3)) -> false | ||
52 | (procedure? (not 1)) -> false | ||
53 | (procedure? +) -> true | ||
54 | (procedure? -) -> true | ||
55 | (procedure? procedure?) -> true | ||
diff --git a/tests/variables.bad b/tests/variables.bad new file mode 100644 index 0000000..a6f9900 --- /dev/null +++ b/tests/variables.bad | |||
@@ -0,0 +1,57 @@ | |||
1 | ; Basic variable declaration with and without default values. The type could be | ||
2 | ; inferred, but can also be manually specified. | ||
3 | let a | ||
4 | let b: f64 | ||
5 | let c = 10 | ||
6 | let d:u64 = 20 | ||
7 | |||
8 | ; No infix '=', instead we use `set` to bind values. | ||
9 | set a = "hello" | ||
10 | set b = 1.2 | ||
11 | set c = 30 | ||
12 | set d = (1 + 2 - 3) | ||
13 | |||
14 | ; Struct definitions. | ||
15 | struct vec { | ||
16 | x: f32 | ||
17 | y: f32 | ||
18 | z: f32 | ||
19 | } | ||
20 | |||
21 | ; Default values are allowed, including const expressions. | ||
22 | struct person { | ||
23 | name: str = "joe" | ||
24 | age: int = 18 * 2 | ||
25 | } | ||
26 | |||
27 | ; We can use the dot operator to access fields. | ||
28 | let player_a: person | ||
29 | set player_a.name = "alex" | ||
30 | set player_a.age = 32 | ||
31 | let player_b = player_a | ||
32 | |||
33 | ; Anonymous structs can also be declared inline. | ||
34 | let user: { id: u64 name: str } | ||
35 | set user.id = 10 | ||
36 | set user.name = "haxor" | ||
37 | |||
38 | ; We can have anonymous struct fields. | ||
39 | struct entity { | ||
40 | pos: vec | ||
41 | vel: vec | ||
42 | attr: { | ||
43 | id: u64 | ||
44 | name: str | ||
45 | } | ||
46 | } | ||
47 | |||
48 | ; Symbols followed by curly braces output struct literals. | ||
49 | ; let particle = entity { | ||
50 | ; ; Two ways of initializing inner fields. | ||
51 | ; pos = { 1 2 } | ||
52 | ; attr.id = 1 | ||
53 | ; attr.name = "particle" | ||
54 | |||
55 | ; ; Missing initialization fields default to zero. | ||
56 | ; vel = { -3 } | ||
57 | ; } | ||
diff --git a/tests/variables_expected.txt b/tests/variables_expected.txt deleted file mode 100644 index 02a5f7a..0000000 --- a/tests/variables_expected.txt +++ /dev/null | |||
@@ -1,23 +0,0 @@ | |||
1 | (def a 20) | ||
2 | ((lambda (a b) (+ 10 a b)) 1 2) -> 13 | ||
3 | ((lambda (a b) (+ 10 a b)) a 3) -> 33 | ||
4 | (def myfun (lambda (a b) (+ a b))) (myfun 6 9) -> 15 | ||
5 | (fun myfun (a b) (+ a b)) (myfun 6 9) -> 15 | ||
6 | (+ 1 (myfun 10 (myfun a a)) 30) -> 81 | ||
7 | (myfun 10 (myfun 5 0)) -> 15 | ||
8 | (fun make-counter () (def value 0) (def counter (lambda () (set! value (+ value 1)) value)) counter) | ||
9 | (def counter-a (make-counter)) | ||
10 | (def counter-b (make-counter)) | ||
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 | ||