diff options
-rw-r--r-- | src/bootstrap/environment.c | 21 | ||||
-rw-r--r-- | src/bootstrap/environment.h | 34 | ||||
-rw-r--r-- | src/bootstrap/errors.c | 31 | ||||
-rw-r--r-- | src/bootstrap/errors.h | 38 | ||||
-rw-r--r-- | src/bootstrap/gc.c | 67 | ||||
-rw-r--r-- | src/bootstrap/gc.h | 69 | ||||
-rw-r--r-- | src/bootstrap/lexer.c | 38 | ||||
-rw-r--r-- | src/bootstrap/lexer.h | 66 | ||||
-rwxr-xr-x | src/bootstrap/main.c | 22 | ||||
-rw-r--r-- | src/bootstrap/objects.c | 66 | ||||
-rw-r--r-- | src/bootstrap/objects.h | 77 | ||||
-rw-r--r-- | src/bootstrap/parser.c | 9 | ||||
-rw-r--r-- | src/bootstrap/parser.h | 22 | ||||
-rw-r--r-- | src/bootstrap/primitives.c | 4 | ||||
-rw-r--r-- | src/bootstrap/primitives.h | 60 | ||||
-rw-r--r-- | src/bootstrap/read_line.c | 3 | ||||
-rw-r--r-- | src/bootstrap/read_line.h | 10 | ||||
-rw-r--r-- | src/bootstrap/singletons.c | 17 | ||||
-rw-r--r-- | src/bootstrap/string_view.c | 5 | ||||
-rw-r--r-- | src/bootstrap/string_view.h | 21 |
20 files changed, 445 insertions, 235 deletions
diff --git a/src/bootstrap/environment.c b/src/bootstrap/environment.c index d5e954b..3fe8be1 100644 --- a/src/bootstrap/environment.c +++ b/src/bootstrap/environment.c | |||
@@ -1,21 +1,6 @@ | |||
1 | typedef struct EnvEntry { | 1 | #include "environment.h" |
2 | Object *symbol; | 2 | #include "gc.h" |
3 | Object *value; | 3 | #include "errors.h" |
4 | } EnvEntry; | ||
5 | |||
6 | typedef struct Environment { | ||
7 | struct Environment *parent; | ||
8 | EnvEntry *buf; | ||
9 | size_t size; | ||
10 | size_t cap; | ||
11 | bool marked; | ||
12 | } Environment; | ||
13 | |||
14 | static Environment *global_env; | ||
15 | |||
16 | #define ENV_BUF_CAP 8 | ||
17 | |||
18 | Environment *alloc_env(void); | ||
19 | 4 | ||
20 | Environment * | 5 | Environment * |
21 | env_create(Environment *parent) { | 6 | env_create(Environment *parent) { |
diff --git a/src/bootstrap/environment.h b/src/bootstrap/environment.h new file mode 100644 index 0000000..cc13921 --- /dev/null +++ b/src/bootstrap/environment.h | |||
@@ -0,0 +1,34 @@ | |||
1 | #ifndef BDL_ENVIRONMENT_H | ||
2 | #define BDL_ENVIRONMENT_H | ||
3 | |||
4 | #include "objects.h" | ||
5 | |||
6 | typedef struct EnvEntry { | ||
7 | Object *symbol; | ||
8 | Object *value; | ||
9 | } EnvEntry; | ||
10 | |||
11 | typedef struct Environment { | ||
12 | struct Environment *parent; | ||
13 | EnvEntry *buf; | ||
14 | size_t size; | ||
15 | size_t cap; | ||
16 | bool marked; | ||
17 | } Environment; | ||
18 | |||
19 | Environment * env_create(Environment *parent); | ||
20 | void env_add_symbol(Environment *env, Object *symbol, Object *value); | ||
21 | Object * env_lookup(Environment *env, Object *symbol); | ||
22 | Object * env_update(Environment *env, Object *symbol, Object *value); | ||
23 | ssize_t env_index_current(Environment *env, Object *symbol); | ||
24 | void env_add_or_update_current(Environment *env, Object *symbol, Object *value); | ||
25 | Environment * env_extend(Environment *parent, Environment *extra); | ||
26 | |||
27 | #define MAKE_ENV_VAR(ENV,STR,VAR) \ | ||
28 | (env_add_symbol((ENV), MAKE_SYM(STR), (VAR))) | ||
29 | #define MAKE_ENV_PROC(ENV,STR,FUN) \ | ||
30 | (env_add_symbol((ENV), MAKE_SYM(STR), make_procedure(FUN))) | ||
31 | |||
32 | #define ENV_BUF_CAP 8 | ||
33 | |||
34 | #endif // BDL_ENVIRONMENT_H | ||
diff --git a/src/bootstrap/errors.c b/src/bootstrap/errors.c index c1d2879..d957cfa 100644 --- a/src/bootstrap/errors.c +++ b/src/bootstrap/errors.c | |||
@@ -1,32 +1,4 @@ | |||
1 | typedef enum ErrorType { | 1 | #include "errors.h" |
2 | ERR_TYPE_LEXER, | ||
3 | ERR_TYPE_PARSER, | ||
4 | ERR_TYPE_RUNTIME, | ||
5 | } ErrorType; | ||
6 | |||
7 | typedef enum ErrorValue { | ||
8 | ERR_UNKNOWN = 0, | ||
9 | ERR_UNMATCHED_STRING, | ||
10 | ERR_UNBALANCED_PAREN, | ||
11 | ERR_NOT_IMPLEMENTED, | ||
12 | ERR_EOF_REACHED, | ||
13 | ERR_UNKNOWN_TOKEN, | ||
14 | ERR_UNKNOWN_OBJ_TYPE, | ||
15 | ERR_NOT_A_SYMBOL, | ||
16 | ERR_SYMBOL_NOT_FOUND, | ||
17 | ERR_OBJ_NOT_CALLABLE, | ||
18 | ERR_NOT_ENOUGH_ARGS, | ||
19 | ERR_TOO_MANY_ARGS, | ||
20 | ERR_WRONG_ARG_TYPE, | ||
21 | ERR_DIVISION_BY_ZERO, | ||
22 | } ErrorValue; | ||
23 | |||
24 | typedef struct Error { | ||
25 | ErrorType type; | ||
26 | ErrorValue value; | ||
27 | size_t line; | ||
28 | size_t col; | ||
29 | } Error; | ||
30 | 2 | ||
31 | static const char* error_msgs[] = { | 3 | static const char* error_msgs[] = { |
32 | [ERR_UNKNOWN] = "error: something unexpected happened", | 4 | [ERR_UNKNOWN] = "error: something unexpected happened", |
@@ -45,7 +17,6 @@ static const char* error_msgs[] = { | |||
45 | [ERR_DIVISION_BY_ZERO] = "error: division by zero", | 17 | [ERR_DIVISION_BY_ZERO] = "error: division by zero", |
46 | }; | 18 | }; |
47 | 19 | ||
48 | #define ERR_MAX_NUMBER 16 | ||
49 | static Error errors[ERR_MAX_NUMBER]; | 20 | static Error errors[ERR_MAX_NUMBER]; |
50 | static size_t errors_n = 0; | 21 | static size_t errors_n = 0; |
51 | static bool supress_errors = false; | 22 | static bool supress_errors = false; |
diff --git a/src/bootstrap/errors.h b/src/bootstrap/errors.h new file mode 100644 index 0000000..7916f4a --- /dev/null +++ b/src/bootstrap/errors.h | |||
@@ -0,0 +1,38 @@ | |||
1 | #ifndef BDL_ERRORS_H | ||
2 | #define BDL_ERRORS_H | ||
3 | |||
4 | typedef enum ErrorType { | ||
5 | ERR_TYPE_LEXER, | ||
6 | ERR_TYPE_PARSER, | ||
7 | ERR_TYPE_RUNTIME, | ||
8 | } ErrorType; | ||
9 | |||
10 | typedef enum ErrorValue { | ||
11 | ERR_UNKNOWN = 0, | ||
12 | ERR_UNMATCHED_STRING, | ||
13 | ERR_UNBALANCED_PAREN, | ||
14 | ERR_NOT_IMPLEMENTED, | ||
15 | ERR_EOF_REACHED, | ||
16 | ERR_UNKNOWN_TOKEN, | ||
17 | ERR_UNKNOWN_OBJ_TYPE, | ||
18 | ERR_NOT_A_SYMBOL, | ||
19 | ERR_SYMBOL_NOT_FOUND, | ||
20 | ERR_OBJ_NOT_CALLABLE, | ||
21 | ERR_NOT_ENOUGH_ARGS, | ||
22 | ERR_TOO_MANY_ARGS, | ||
23 | ERR_WRONG_ARG_TYPE, | ||
24 | ERR_DIVISION_BY_ZERO, | ||
25 | } ErrorValue; | ||
26 | |||
27 | typedef struct Error { | ||
28 | ErrorType type; | ||
29 | ErrorValue value; | ||
30 | size_t line; | ||
31 | size_t col; | ||
32 | } Error; | ||
33 | |||
34 | void error_push(Error error); | ||
35 | |||
36 | #define ERR_MAX_NUMBER 16 | ||
37 | |||
38 | #endif // BDL_ERRORS_H | ||
diff --git a/src/bootstrap/gc.c b/src/bootstrap/gc.c index 11a1f5a..473930a 100644 --- a/src/bootstrap/gc.c +++ b/src/bootstrap/gc.c | |||
@@ -1,48 +1,4 @@ | |||
1 | // Stack of root nodes. | 1 | #include "gc.h" |
2 | typedef struct RootNodes { | ||
3 | Object **buf; | ||
4 | size_t size; | ||
5 | size_t cap; | ||
6 | } RootNodes; | ||
7 | |||
8 | // Stack of active environments. | ||
9 | typedef struct ActiveEnvs { | ||
10 | Environment **buf; | ||
11 | size_t size; | ||
12 | size_t cap; | ||
13 | } ActiveEnvs; | ||
14 | |||
15 | typedef struct Environments { | ||
16 | Environment *buf; | ||
17 | size_t size; | ||
18 | size_t cap; | ||
19 | } Environments; | ||
20 | |||
21 | typedef struct FreeList { | ||
22 | size_t *buf; | ||
23 | size_t size; | ||
24 | size_t cap; | ||
25 | size_t position; | ||
26 | } FreeList; | ||
27 | |||
28 | typedef struct GC { | ||
29 | RootNodes roots; | ||
30 | Environments envs; | ||
31 | Object *objects; | ||
32 | size_t obj_cap; | ||
33 | FreeList free_objects; | ||
34 | FreeList free_envs; | ||
35 | ActiveEnvs active_envs; | ||
36 | } GC; | ||
37 | |||
38 | #define GC_OBJS_CAP 1024 * 1024 | ||
39 | #define GC_ROOTS_CAP 1024 | ||
40 | #define GC_ENVS_CAP 1024 * 4 | ||
41 | |||
42 | static GC gc; | ||
43 | |||
44 | void mark_and_sweep(void); | ||
45 | void dump_gc(void); | ||
46 | 2 | ||
47 | Environment * | 3 | Environment * |
48 | alloc_env(void) { | 4 | alloc_env(void) { |
@@ -115,9 +71,9 @@ init_gc(void) { | |||
115 | .cap = GC_ENVS_CAP, | 71 | .cap = GC_ENVS_CAP, |
116 | }, | 72 | }, |
117 | .active_envs = (ActiveEnvs){ | 73 | .active_envs = (ActiveEnvs){ |
118 | .buf = malloc(GC_ROOTS_CAP * sizeof(Environment*)), | 74 | .buf = malloc(GC_ACTIVE_ENVS_CAP * sizeof(Environment*)), |
119 | .size = 0, | 75 | .size = 0, |
120 | .cap = GC_ROOTS_CAP, | 76 | .cap = GC_ACTIVE_ENVS_CAP, |
121 | }, | 77 | }, |
122 | }; | 78 | }; |
123 | 79 | ||
@@ -131,13 +87,6 @@ init_gc(void) { | |||
131 | } | 87 | } |
132 | } | 88 | } |
133 | 89 | ||
134 | Object * | ||
135 | get_obj(size_t offset) { | ||
136 | return &gc.objects[offset]; | ||
137 | } | ||
138 | |||
139 | void mark_obj(Object *obj); | ||
140 | |||
141 | void | 90 | void |
142 | mark_environment(Environment *env) { | 91 | mark_environment(Environment *env) { |
143 | if (env == NULL || env->marked) { | 92 | if (env == NULL || env->marked) { |
@@ -190,11 +139,15 @@ mark_and_sweep(void) { | |||
190 | if (!obj->marked) { | 139 | if (!obj->marked) { |
191 | // Free heap allocated memory for this object if needed. | 140 | // Free heap allocated memory for this object if needed. |
192 | if (obj->type == OBJ_TYPE_SYMBOL) { | 141 | if (obj->type == OBJ_TYPE_SYMBOL) { |
193 | free(obj->symbol); | 142 | if (obj->symbol != NULL) { |
143 | free(obj->symbol); | ||
144 | } | ||
194 | obj->symbol = NULL; | 145 | obj->symbol = NULL; |
195 | obj->symbol_n = 0; | 146 | obj->symbol_n = 0; |
196 | } else if (obj->type == OBJ_TYPE_STRING) { | 147 | } else if (obj->type == OBJ_TYPE_STRING) { |
197 | free(obj->string); | 148 | if (obj->symbol != NULL) { |
149 | free(obj->string); | ||
150 | } | ||
198 | obj->string = NULL; | 151 | obj->string = NULL; |
199 | obj->string_n = 0; | 152 | obj->string_n = 0; |
200 | } | 153 | } |
@@ -280,7 +233,7 @@ alloc_object(ObjectType type) { | |||
280 | } | 233 | } |
281 | size_t slot = gc.free_objects.buf[gc.free_objects.position++]; | 234 | size_t slot = gc.free_objects.buf[gc.free_objects.position++]; |
282 | gc.free_objects.size--; | 235 | gc.free_objects.size--; |
283 | Object *obj = get_obj(slot); | 236 | Object *obj = &gc.objects[slot]; |
284 | obj->type = type; | 237 | obj->type = type; |
285 | obj->marked = false; | 238 | obj->marked = false; |
286 | return obj; | 239 | return obj; |
diff --git a/src/bootstrap/gc.h b/src/bootstrap/gc.h new file mode 100644 index 0000000..038c820 --- /dev/null +++ b/src/bootstrap/gc.h | |||
@@ -0,0 +1,69 @@ | |||
1 | #ifndef BDL_GC_H | ||
2 | #define BDL_GC_H | ||
3 | |||
4 | #include "objects.h" | ||
5 | #include "environment.h" | ||
6 | |||
7 | // Stack of root nodes. | ||
8 | typedef struct RootNodes { | ||
9 | Object **buf; | ||
10 | size_t size; | ||
11 | size_t cap; | ||
12 | } RootNodes; | ||
13 | |||
14 | // Stack of active environments. | ||
15 | typedef struct ActiveEnvs { | ||
16 | Environment **buf; | ||
17 | size_t size; | ||
18 | size_t cap; | ||
19 | } ActiveEnvs; | ||
20 | |||
21 | typedef struct Environments { | ||
22 | Environment *buf; | ||
23 | size_t size; | ||
24 | size_t cap; | ||
25 | } Environments; | ||
26 | |||
27 | typedef struct FreeList { | ||
28 | size_t *buf; | ||
29 | size_t size; | ||
30 | size_t cap; | ||
31 | size_t position; | ||
32 | } FreeList; | ||
33 | |||
34 | typedef struct GC { | ||
35 | RootNodes roots; | ||
36 | Environments envs; | ||
37 | Object *objects; | ||
38 | size_t obj_cap; | ||
39 | FreeList free_objects; | ||
40 | FreeList free_envs; | ||
41 | ActiveEnvs active_envs; | ||
42 | } GC; | ||
43 | |||
44 | void init_gc(void); | ||
45 | |||
46 | // Allocation functions for objects and environments. | ||
47 | Object * alloc_object(ObjectType type); | ||
48 | Environment * alloc_env(void); | ||
49 | |||
50 | // Root and environment protector functions. | ||
51 | void push_root(Object *obj); | ||
52 | Object * pop_root(void); | ||
53 | void push_active_env(Environment *env); | ||
54 | Environment * pop_active_env(void); | ||
55 | |||
56 | // Mark and sweep algorithm functions. | ||
57 | void mark_environment(Environment *env); | ||
58 | void mark_obj(Object *obj); | ||
59 | void mark_and_sweep(void); | ||
60 | |||
61 | // Debugging function to print out the contentes of some GC fields. | ||
62 | void dump_gc(void); | ||
63 | |||
64 | #define GC_OBJS_CAP 1024 * 1024 | ||
65 | #define GC_ROOTS_CAP 1024 | ||
66 | #define GC_ACTIVE_ENVS_CAP 2 | ||
67 | #define GC_ENVS_CAP 1024 * 4 | ||
68 | |||
69 | #endif // BDL_GC_H | ||
diff --git a/src/bootstrap/lexer.c b/src/bootstrap/lexer.c index ee387dd..05324eb 100644 --- a/src/bootstrap/lexer.c +++ b/src/bootstrap/lexer.c | |||
@@ -1,29 +1,4 @@ | |||
1 | typedef enum TokenType { | 1 | #include "lexer.h" |
2 | TOKEN_UNKNOWN = 0, | ||
3 | TOKEN_LPAREN, | ||
4 | TOKEN_RPAREN, | ||
5 | TOKEN_QUOTE, | ||
6 | TOKEN_TRUE, | ||
7 | TOKEN_FALSE, | ||
8 | TOKEN_NIL, | ||
9 | TOKEN_FIXNUM, | ||
10 | TOKEN_SYMBOL, | ||
11 | TOKEN_STRING, | ||
12 | TOKEN_EOF, | ||
13 | } TokenType; | ||
14 | |||
15 | typedef struct Token { | ||
16 | TokenType type; | ||
17 | StringView value; | ||
18 | size_t line; | ||
19 | size_t column; | ||
20 | } Token; | ||
21 | |||
22 | typedef struct Tokens { | ||
23 | Token *buf; | ||
24 | size_t size; | ||
25 | size_t cap; | ||
26 | } Tokens; | ||
27 | 2 | ||
28 | void | 3 | void |
29 | print_token(Token tok) { | 4 | print_token(Token tok) { |
@@ -69,8 +44,6 @@ print_token(Token tok) { | |||
69 | printf("\n"); | 44 | printf("\n"); |
70 | } | 45 | } |
71 | 46 | ||
72 | #define TOK_BUF_CAP 256 | ||
73 | |||
74 | void | 47 | void |
75 | push_token(Tokens *tokens, Token tok) { | 48 | push_token(Tokens *tokens, Token tok) { |
76 | if (tokens->buf == NULL) { | 49 | if (tokens->buf == NULL) { |
@@ -84,13 +57,6 @@ push_token(Tokens *tokens, Token tok) { | |||
84 | tokens->buf[tokens->size++] = tok; | 57 | tokens->buf[tokens->size++] = tok; |
85 | } | 58 | } |
86 | 59 | ||
87 | typedef struct Scanner { | ||
88 | StringView current; | ||
89 | size_t line_number; | ||
90 | size_t col_number; | ||
91 | size_t offset; | ||
92 | } Scanner; | ||
93 | |||
94 | char | 60 | char |
95 | scan_next(Scanner *scanner) { | 61 | scan_next(Scanner *scanner) { |
96 | char c = sv_next(&scanner->current); | 62 | char c = sv_next(&scanner->current); |
@@ -157,7 +123,7 @@ is_delimiter(char c) { | |||
157 | } | 123 | } |
158 | 124 | ||
159 | TokenType | 125 | TokenType |
160 | find_primitive_type(StringView value) { | 126 | find_primitive_type(const StringView value) { |
161 | bool is_fixnum = true; | 127 | bool is_fixnum = true; |
162 | for (size_t i = 0; i < value.n; i++) { | 128 | for (size_t i = 0; i < value.n; i++) { |
163 | char c = value.start[i]; | 129 | char c = value.start[i]; |
diff --git a/src/bootstrap/lexer.h b/src/bootstrap/lexer.h new file mode 100644 index 0000000..129fd9a --- /dev/null +++ b/src/bootstrap/lexer.h | |||
@@ -0,0 +1,66 @@ | |||
1 | #ifndef BDL_LEXER_H | ||
2 | #define BDL_LEXER_H | ||
3 | |||
4 | typedef enum TokenType { | ||
5 | TOKEN_UNKNOWN = 0, | ||
6 | TOKEN_LPAREN, | ||
7 | TOKEN_RPAREN, | ||
8 | TOKEN_QUOTE, | ||
9 | TOKEN_TRUE, | ||
10 | TOKEN_FALSE, | ||
11 | TOKEN_NIL, | ||
12 | TOKEN_FIXNUM, | ||
13 | TOKEN_SYMBOL, | ||
14 | TOKEN_STRING, | ||
15 | TOKEN_EOF, | ||
16 | } TokenType; | ||
17 | |||
18 | typedef struct Token { | ||
19 | TokenType type; | ||
20 | StringView value; | ||
21 | size_t line; | ||
22 | size_t column; | ||
23 | } Token; | ||
24 | |||
25 | typedef struct Tokens { | ||
26 | Token *buf; | ||
27 | size_t size; | ||
28 | size_t cap; | ||
29 | } Tokens; | ||
30 | |||
31 | typedef struct Scanner { | ||
32 | StringView current; | ||
33 | size_t line_number; | ||
34 | size_t col_number; | ||
35 | size_t offset; | ||
36 | } Scanner; | ||
37 | |||
38 | // Print a token to standard output for debugging purposes. | ||
39 | void print_token(Token tok); | ||
40 | |||
41 | // Push a token to the token list. | ||
42 | void push_token(Tokens *tokens, Token tok); | ||
43 | |||
44 | // Same functionality as the ScanView pairs, but keeping track of line and | ||
45 | // column numbers. | ||
46 | char scan_next(Scanner *scanner); | ||
47 | char scan_peek(const Scanner *scanner); | ||
48 | |||
49 | // Check if the current scanner still have characters left. | ||
50 | bool scan_has_next(const Scanner *scanner); | ||
51 | |||
52 | // Advance the scanner until we ran out of whitespace. | ||
53 | void skip_whitespace(Scanner *scanner); | ||
54 | |||
55 | // Check if a given character is a delimiter. | ||
56 | bool is_delimiter(char c); | ||
57 | |||
58 | // Extract the token type from the current string. | ||
59 | TokenType find_primitive_type(const StringView value); | ||
60 | |||
61 | // Generate a list of tokens from the given string. | ||
62 | Tokens tokenize(const StringView *sv); | ||
63 | |||
64 | #define TOK_BUF_CAP 256 | ||
65 | |||
66 | #endif // BDL_LEXER_H | ||
diff --git a/src/bootstrap/main.c b/src/bootstrap/main.c index 2d24f92..cfad9f1 100755 --- a/src/bootstrap/main.c +++ b/src/bootstrap/main.c | |||
@@ -6,25 +6,17 @@ | |||
6 | #include <stdlib.h> | 6 | #include <stdlib.h> |
7 | #include <string.h> | 7 | #include <string.h> |
8 | 8 | ||
9 | #include "string_view.c" | 9 | #include "singletons.c" |
10 | #include "read_line.c" | 10 | |
11 | #include "environment.c" | ||
11 | #include "errors.c" | 12 | #include "errors.c" |
13 | #include "gc.c" | ||
12 | #include "lexer.c" | 14 | #include "lexer.c" |
13 | #include "objects.c" | 15 | #include "objects.c" |
14 | #include "parser.c" | 16 | #include "parser.c" |
15 | #include "environment.c" | ||
16 | #include "gc.c" | ||
17 | #include "primitives.c" | 17 | #include "primitives.c" |
18 | 18 | #include "read_line.c" | |
19 | // | 19 | #include "string_view.c" |
20 | // Utility macros. | ||
21 | // | ||
22 | |||
23 | #define MAKE_SYM(STR) make_symbol((StringView){(STR), sizeof(STR) - 1}) | ||
24 | #define MAKE_ENV_VAR(ENV,STR,VAR) \ | ||
25 | (env_add_symbol((ENV), MAKE_SYM(STR), (VAR))) | ||
26 | #define MAKE_ENV_PROC(ENV,STR,FUN) \ | ||
27 | (env_add_symbol((ENV), MAKE_SYM(STR), make_procedure(FUN))) | ||
28 | 20 | ||
29 | void | 21 | void |
30 | init(void) { | 22 | init(void) { |
@@ -113,7 +105,7 @@ process_source(const StringView *source) { | |||
113 | .current = 0, | 105 | .current = 0, |
114 | }; | 106 | }; |
115 | while (has_next_token(&visitor) && peek_token(&visitor).type != TOKEN_EOF) { | 107 | while (has_next_token(&visitor) && peek_token(&visitor).type != TOKEN_EOF) { |
116 | // check the stack before parsing | 108 | // Check the root node stack size before parsing |
117 | size_t root_stack_size = gc.roots.size; | 109 | size_t root_stack_size = gc.roots.size; |
118 | Object *root = parse_tree(&visitor); | 110 | Object *root = parse_tree(&visitor); |
119 | gc.roots.size = root_stack_size; | 111 | gc.roots.size = root_stack_size; |
diff --git a/src/bootstrap/objects.c b/src/bootstrap/objects.c index 09076db..359329b 100644 --- a/src/bootstrap/objects.c +++ b/src/bootstrap/objects.c | |||
@@ -1,70 +1,10 @@ | |||
1 | typedef enum ObjectType { | 1 | #include "gc.h" |
2 | OBJ_TYPE_FIXNUM, | 2 | #include "objects.h" |
3 | OBJ_TYPE_BOOL, | ||
4 | OBJ_TYPE_NIL, | ||
5 | OBJ_TYPE_SYMBOL, | ||
6 | OBJ_TYPE_STRING, | ||
7 | OBJ_TYPE_PAIR, | ||
8 | OBJ_TYPE_PROCEDURE, | ||
9 | OBJ_TYPE_LAMBDA, | ||
10 | OBJ_TYPE_ERR, | ||
11 | } ObjectType; | ||
12 | |||
13 | struct Environment; | ||
14 | |||
15 | typedef struct Object { | ||
16 | ObjectType type; | ||
17 | bool marked; | ||
18 | union { | ||
19 | // OBJ_TYPE_FIXNUM | ||
20 | ssize_t fixnum; | ||
21 | |||
22 | // OBJ_TYPE_STRING | ||
23 | struct { | ||
24 | char *string; | ||
25 | size_t string_n; | ||
26 | }; | ||
27 | |||
28 | // OBJ_TYPE_PAIR | ||
29 | struct { | ||
30 | struct Object *car; | ||
31 | struct Object *cdr; | ||
32 | }; | ||
33 | |||
34 | // OBJ_TYPE_SYMBOL | ||
35 | struct { | ||
36 | char *symbol; | ||
37 | size_t symbol_n; | ||
38 | }; | ||
39 | |||
40 | // OBJ_TYPE_PROCEDURE | ||
41 | struct Object *(*proc)(struct Environment *env, struct Object *args); | ||
42 | |||
43 | // OBJ_TYPE_LAMBDA | ||
44 | struct { | ||
45 | struct Object *params; | ||
46 | struct Object *body; | ||
47 | struct Environment *env; | ||
48 | }; | ||
49 | }; | ||
50 | } Object; | ||
51 | |||
52 | // | ||
53 | // Singletons. | ||
54 | // | ||
55 | |||
56 | static Object *obj_nil; | ||
57 | static Object *obj_true; | ||
58 | static Object *obj_false; | ||
59 | static Object *obj_err; | ||
60 | static Object *obj_quote; | ||
61 | 3 | ||
62 | // | 4 | // |
63 | // Constructors. | 5 | // Constructors. |
64 | // | 6 | // |
65 | 7 | ||
66 | Object * alloc_object(ObjectType); | ||
67 | |||
68 | Object * | 8 | Object * |
69 | make_fixnum(ssize_t num) { | 9 | make_fixnum(ssize_t num) { |
70 | Object *obj = alloc_object(OBJ_TYPE_FIXNUM); | 10 | Object *obj = alloc_object(OBJ_TYPE_FIXNUM); |
@@ -116,8 +56,6 @@ append_string(Object *obj, const StringView sv) { | |||
116 | obj->string_n += sv.n; | 56 | obj->string_n += sv.n; |
117 | } | 57 | } |
118 | 58 | ||
119 | void display(Object *root); | ||
120 | |||
121 | void | 59 | void |
122 | display_pair(Object *root) { | 60 | display_pair(Object *root) { |
123 | display(root->car); | 61 | display(root->car); |
diff --git a/src/bootstrap/objects.h b/src/bootstrap/objects.h new file mode 100644 index 0000000..56821eb --- /dev/null +++ b/src/bootstrap/objects.h | |||
@@ -0,0 +1,77 @@ | |||
1 | #ifndef BDL_OBJECTS_H | ||
2 | #define BDL_OBJECTS_H | ||
3 | |||
4 | #include "string_view.h" | ||
5 | |||
6 | typedef enum ObjectType { | ||
7 | OBJ_TYPE_FIXNUM, | ||
8 | OBJ_TYPE_BOOL, | ||
9 | OBJ_TYPE_NIL, | ||
10 | OBJ_TYPE_SYMBOL, | ||
11 | OBJ_TYPE_STRING, | ||
12 | OBJ_TYPE_PAIR, | ||
13 | OBJ_TYPE_PROCEDURE, | ||
14 | OBJ_TYPE_LAMBDA, | ||
15 | OBJ_TYPE_ERR, | ||
16 | } ObjectType; | ||
17 | |||
18 | struct Environment; | ||
19 | |||
20 | typedef struct Object { | ||
21 | ObjectType type; | ||
22 | bool marked; | ||
23 | union { | ||
24 | // OBJ_TYPE_FIXNUM | ||
25 | ssize_t fixnum; | ||
26 | |||
27 | // OBJ_TYPE_STRING | ||
28 | struct { | ||
29 | char *string; | ||
30 | size_t string_n; | ||
31 | }; | ||
32 | |||
33 | // OBJ_TYPE_PAIR | ||
34 | struct { | ||
35 | struct Object *car; | ||
36 | struct Object *cdr; | ||
37 | }; | ||
38 | |||
39 | // OBJ_TYPE_SYMBOL | ||
40 | struct { | ||
41 | char *symbol; | ||
42 | size_t symbol_n; | ||
43 | }; | ||
44 | |||
45 | // OBJ_TYPE_PROCEDURE | ||
46 | struct Object *(*proc)(struct Environment *env, struct Object *args); | ||
47 | |||
48 | // OBJ_TYPE_LAMBDA | ||
49 | struct { | ||
50 | struct Object *params; | ||
51 | struct Object *body; | ||
52 | struct Environment *env; | ||
53 | }; | ||
54 | }; | ||
55 | } Object; | ||
56 | |||
57 | // Object constructors. | ||
58 | Object * make_fixnum(ssize_t num); | ||
59 | Object * make_procedure(Object *(*proc)(struct Environment *, struct Object *args)); | ||
60 | Object * make_pair(Object *car, Object *cdr); | ||
61 | Object * make_symbol(StringView sv); | ||
62 | Object * make_string(void); | ||
63 | void append_string(Object *obj, const StringView sv); | ||
64 | |||
65 | // Object representation. | ||
66 | void display(Object *root); | ||
67 | void display_pair(Object *root); | ||
68 | |||
69 | // Object comparison. | ||
70 | bool obj_eq(Object *a, Object* b); | ||
71 | |||
72 | // Utility macros. | ||
73 | #define DEBUG_OBJ(MSG,OBJ) printf((MSG)); display(OBJ); printf("\n"); | ||
74 | #define PRINT_OBJ(OBJ) display(OBJ); printf("\n"); | ||
75 | #define MAKE_SYM(STR) make_symbol((StringView){(STR), sizeof(STR) - 1}) | ||
76 | |||
77 | #endif // BDL_OBJECTS_H | ||
diff --git a/src/bootstrap/parser.c b/src/bootstrap/parser.c index 77ece9d..5b0033a 100644 --- a/src/bootstrap/parser.c +++ b/src/bootstrap/parser.c | |||
@@ -1,7 +1,4 @@ | |||
1 | typedef struct Visitor { | 1 | #include "parser.h" |
2 | Tokens tokens; | ||
3 | size_t current; | ||
4 | } Visitor; | ||
5 | 2 | ||
6 | Token | 3 | Token |
7 | peek_token(const Visitor *visitor) { | 4 | peek_token(const Visitor *visitor) { |
@@ -18,8 +15,6 @@ has_next_token(const Visitor *visitor) { | |||
18 | return visitor->current < visitor->tokens.size; | 15 | return visitor->current < visitor->tokens.size; |
19 | } | 16 | } |
20 | 17 | ||
21 | void push_root(Object*); | ||
22 | |||
23 | Object * | 18 | Object * |
24 | parse_fixnum(Token tok) { | 19 | parse_fixnum(Token tok) { |
25 | ssize_t num = 0; | 20 | ssize_t num = 0; |
@@ -38,8 +33,6 @@ parse_fixnum(Token tok) { | |||
38 | return obj; | 33 | return obj; |
39 | } | 34 | } |
40 | 35 | ||
41 | Object * parse_tree(Visitor *vs); | ||
42 | |||
43 | Object * | 36 | Object * |
44 | parse_list(Visitor *vs) { | 37 | parse_list(Visitor *vs) { |
45 | Token tok = peek_token(vs); | 38 | Token tok = peek_token(vs); |
diff --git a/src/bootstrap/parser.h b/src/bootstrap/parser.h new file mode 100644 index 0000000..3bd17ef --- /dev/null +++ b/src/bootstrap/parser.h | |||
@@ -0,0 +1,22 @@ | |||
1 | #ifndef BDL_PARSER_H | ||
2 | #define BDL_PARSER_H | ||
3 | |||
4 | typedef struct Visitor { | ||
5 | Tokens tokens; | ||
6 | size_t current; | ||
7 | } Visitor; | ||
8 | |||
9 | // Mimics the functionality in the Scanner functions, but for entire tokens. | ||
10 | Token next_token(Visitor *visitor); | ||
11 | Token peek_token(const Visitor *visitor); | ||
12 | bool has_next_token(const Visitor *visitor); | ||
13 | |||
14 | // Parse a token into a fixnum object. | ||
15 | Object * parse_fixnum(Token tok); | ||
16 | |||
17 | // Recursive descent parser. If an object is not a list the parsing is handled | ||
18 | // by the parse_tree function. | ||
19 | Object * parse_list(Visitor *vs); | ||
20 | Object * parse_tree(Visitor *vs); | ||
21 | |||
22 | #endif // BDL_PARSER_H | ||
diff --git a/src/bootstrap/primitives.c b/src/bootstrap/primitives.c index 0c2a17d..0f1498d 100644 --- a/src/bootstrap/primitives.c +++ b/src/bootstrap/primitives.c | |||
@@ -1,5 +1,4 @@ | |||
1 | #define DEBUG_OBJ(MSG,OBJ) printf((MSG)); display(OBJ); printf("\n"); | 1 | #include "primitives.h" |
2 | static Object *proc_if; | ||
3 | 2 | ||
4 | Object * | 3 | Object * |
5 | eval(Environment *env, Object *root) { | 4 | eval(Environment *env, Object *root) { |
@@ -153,6 +152,7 @@ eval_lambda: | |||
153 | .value = ERR_UNKNOWN_OBJ_TYPE, | 152 | .value = ERR_UNKNOWN_OBJ_TYPE, |
154 | }); | 153 | }); |
155 | return obj_err; | 154 | return obj_err; |
155 | |||
156 | eval_success: | 156 | eval_success: |
157 | if (recursion_active) { | 157 | if (recursion_active) { |
158 | // Remove stack protector. | 158 | // Remove stack protector. |
diff --git a/src/bootstrap/primitives.h b/src/bootstrap/primitives.h new file mode 100644 index 0000000..f874b17 --- /dev/null +++ b/src/bootstrap/primitives.h | |||
@@ -0,0 +1,60 @@ | |||
1 | #ifndef BDL_PRIMITIVES_H | ||
2 | #define BDL_PRIMITIVES_H | ||
3 | |||
4 | // Function evaluation. | ||
5 | Object * eval(Environment *env, Object *root); | ||
6 | |||
7 | // Evaluation functions. | ||
8 | Object * proc_quote(Environment *env, Object *obj); | ||
9 | Object * proc_eval(Environment *env, Object *obj); | ||
10 | |||
11 | // Arithmetic. | ||
12 | Object * proc_sum(Environment *env, Object *obj); | ||
13 | Object * proc_sub(Environment *env, Object *obj); | ||
14 | Object * proc_mul(Environment *env, Object *obj); | ||
15 | Object * proc_div(Environment *env, Object *obj); | ||
16 | Object * proc_mod(Environment *env, Object *obj); | ||
17 | |||
18 | // Printing. | ||
19 | Object * proc_display(Environment *env, Object *obj); | ||
20 | Object * proc_print(Environment *env, Object *obj); | ||
21 | Object * proc_newline(Environment *env, Object *obj); | ||
22 | |||
23 | // Type checking. | ||
24 | Object * proc_is_boolean(Environment *env, Object *obj); | ||
25 | Object * proc_is_nil(Environment *env, Object *obj); | ||
26 | Object * proc_is_symbol(Environment *env, Object *obj); | ||
27 | Object * proc_is_string(Environment *env, Object *obj); | ||
28 | Object * proc_is_fixnum(Environment *env, Object *obj); | ||
29 | Object * proc_is_pair(Environment *env, Object *obj); | ||
30 | Object * proc_is_procedure(Environment *env, Object *obj); | ||
31 | Object * proc_is_error(Environment *env, Object *obj); | ||
32 | |||
33 | // Logical operations. | ||
34 | Object * proc_not(Environment *env, Object *obj); | ||
35 | Object * proc_and(Environment *env, Object *obj); | ||
36 | Object * proc_or(Environment *env, Object *obj); | ||
37 | Object * proc_cond(Environment *env, Object *obj); | ||
38 | Object * proc_num_less_than(Environment *env, Object *obj); | ||
39 | Object * proc_num_greater_than(Environment *env, Object *obj); | ||
40 | Object * proc_num_lesseq_than(Environment *env, Object *obj); | ||
41 | Object * proc_num_greatereq_than(Environment *env, Object *obj); | ||
42 | Object * proc_num_equal(Environment *env, Object *obj); | ||
43 | Object * proc_equal(Environment *env, Object *obj); | ||
44 | |||
45 | // List operations. | ||
46 | Object * proc_car(Environment *env, Object *obj); | ||
47 | Object * proc_cdr(Environment *env, Object *obj); | ||
48 | Object * proc_cons(Environment *env, Object *obj); | ||
49 | Object * proc_list(Environment *env, Object *obj); | ||
50 | |||
51 | // Environment/variable manipulation. | ||
52 | Object * proc_define(Environment *env, Object *obj); | ||
53 | Object * proc_set(Environment *env, Object *obj); | ||
54 | Object * proc_lambda(Environment *env, Object *obj); | ||
55 | Object * proc_fun(Environment *env, Object *obj); | ||
56 | |||
57 | // Runtinme configuration. | ||
58 | Object * proc_supress_errors(Environment *env, Object *obj); | ||
59 | |||
60 | #endif // BDL_PRIMITIVES_H | ||
diff --git a/src/bootstrap/read_line.c b/src/bootstrap/read_line.c index 603bfee..03146ad 100644 --- a/src/bootstrap/read_line.c +++ b/src/bootstrap/read_line.c | |||
@@ -1,4 +1,5 @@ | |||
1 | #define RL_BUF_SIZE 1024 | 1 | #include "read_line.h" |
2 | |||
2 | static char readline_buf[RL_BUF_SIZE]; | 3 | static char readline_buf[RL_BUF_SIZE]; |
3 | 4 | ||
4 | StringView | 5 | StringView |
diff --git a/src/bootstrap/read_line.h b/src/bootstrap/read_line.h new file mode 100644 index 0000000..160bce0 --- /dev/null +++ b/src/bootstrap/read_line.h | |||
@@ -0,0 +1,10 @@ | |||
1 | #ifndef BDL_READ_LINE_H | ||
2 | #define BDL_READ_LINE_H | ||
3 | |||
4 | #include "string_view.h" | ||
5 | |||
6 | StringView read_line(void); | ||
7 | |||
8 | #define RL_BUF_SIZE 1024 | ||
9 | |||
10 | #endif // BDL_READ_LINE_H | ||
diff --git a/src/bootstrap/singletons.c b/src/bootstrap/singletons.c new file mode 100644 index 0000000..eb9c397 --- /dev/null +++ b/src/bootstrap/singletons.c | |||
@@ -0,0 +1,17 @@ | |||
1 | #include "environment.h" | ||
2 | #include "gc.h" | ||
3 | #include "objects.h" | ||
4 | |||
5 | // Global garbage collector singleton. | ||
6 | static GC gc; | ||
7 | |||
8 | // Special singleton Objects. | ||
9 | static Object *obj_nil; | ||
10 | static Object *obj_true; | ||
11 | static Object *obj_false; | ||
12 | static Object *obj_err; | ||
13 | static Object *obj_quote; | ||
14 | static Object *proc_if; | ||
15 | |||
16 | // Global environment. | ||
17 | static Environment *global_env; | ||
diff --git a/src/bootstrap/string_view.c b/src/bootstrap/string_view.c index 13ba9e0..39fabe9 100644 --- a/src/bootstrap/string_view.c +++ b/src/bootstrap/string_view.c | |||
@@ -1,7 +1,4 @@ | |||
1 | typedef struct StringView { | 1 | #include "string_view.h" |
2 | char *start; | ||
3 | size_t n; | ||
4 | } StringView; | ||
5 | 2 | ||
6 | char | 3 | char |
7 | sv_next(StringView *sv) { | 4 | sv_next(StringView *sv) { |
diff --git a/src/bootstrap/string_view.h b/src/bootstrap/string_view.h new file mode 100644 index 0000000..42273ab --- /dev/null +++ b/src/bootstrap/string_view.h | |||
@@ -0,0 +1,21 @@ | |||
1 | #ifndef BDL_STRINGVIEW_H | ||
2 | #define BDL_STRINGVIEW_H | ||
3 | |||
4 | typedef struct StringView { | ||
5 | char *start; | ||
6 | size_t n; | ||
7 | } StringView; | ||
8 | |||
9 | // Consume a character in the stream. | ||
10 | char sv_next(StringView *sv); | ||
11 | |||
12 | // Check what is the current character in the stream. | ||
13 | char sv_peek(const StringView *sv); | ||
14 | |||
15 | // Compare if the arguments are the same. | ||
16 | bool sv_equal(const StringView *a, const StringView *b); | ||
17 | |||
18 | // Write a character to the given output stream. | ||
19 | void sv_write(const StringView *sv, FILE *file); | ||
20 | |||
21 | #endif // BDL_STRINGVIEW_H | ||