diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bootstrap/darray.h | 55 | ||||
-rw-r--r-- | src/bootstrap/lexer.c | 32 | ||||
-rw-r--r-- | src/bootstrap/lexer.h | 11 | ||||
-rwxr-xr-x | src/bootstrap/main.c | 12 | ||||
-rw-r--r-- | src/bootstrap/parser.c | 6 | ||||
-rw-r--r-- | src/bootstrap/parser.h | 2 |
6 files changed, 77 insertions, 41 deletions
diff --git a/src/bootstrap/darray.h b/src/bootstrap/darray.h new file mode 100644 index 0000000..bb49cdd --- /dev/null +++ b/src/bootstrap/darray.h | |||
@@ -0,0 +1,55 @@ | |||
1 | #ifndef BDL_DARRAY_H | ||
2 | #define BDL_DARRAY_H | ||
3 | |||
4 | #include <string.h> | ||
5 | |||
6 | typedef struct ArrayHeader { | ||
7 | size_t size; | ||
8 | size_t cap; | ||
9 | } ArrayHeader; | ||
10 | |||
11 | // Header/Size/capacity accessors. | ||
12 | #define array_head(ARR) ((ArrayHeader *)((char *)(ARR) - sizeof(ArrayHeader))) | ||
13 | #define array_size(ARR) ((ARR) ? array_head(ARR)->size : 0) | ||
14 | #define array_cap(ARR) ((ARR) ? array_head(ARR)->cap : 0) | ||
15 | |||
16 | // Initialize a dynamic array ARR with N elements. The initialization doesn't | ||
17 | // zero out the data, so thread carefully.. | ||
18 | #define array_init(ARR,N) ((ARR) = _array_reserve(N, sizeof(*(ARR)))) | ||
19 | |||
20 | // Push a given element T to the dynamic array ARR. | ||
21 | #define array_push(ARR, T) \ | ||
22 | ((ARR) = _array_maybe_grow(ARR, sizeof(T)), \ | ||
23 | (ARR)[array_head(ARR)->size++] = (T)) | ||
24 | |||
25 | // Return the last element of the array. Can be used to build stacks. | ||
26 | #define array_pop(ARR) (ARR)[--array_head(ARR)->size] | ||
27 | |||
28 | // Free the memory from the original allocated position. | ||
29 | #define array_free(ARR) ((ARR) ? free(array_head(ARR)), (ARR) = NULL : 0) | ||
30 | |||
31 | static inline void * | ||
32 | _array_reserve(size_t num_elem, size_t type_size) { | ||
33 | char *p = malloc(num_elem * type_size + sizeof(ArrayHeader)); | ||
34 | p += sizeof(ArrayHeader); | ||
35 | array_head(p)->size = 0; | ||
36 | array_head(p)->cap = num_elem; | ||
37 | return p; | ||
38 | } | ||
39 | |||
40 | static inline void * | ||
41 | _array_maybe_grow(void *arr, size_t type_size) { | ||
42 | ArrayHeader *head = array_head(arr); | ||
43 | if (head->cap == head->size) { | ||
44 | if (head->cap == 0) { | ||
45 | head->cap++; | ||
46 | } else { | ||
47 | head->cap *= 2; | ||
48 | } | ||
49 | head = realloc(head, head->cap * type_size + sizeof(ArrayHeader)); | ||
50 | } | ||
51 | arr = (char *)head + sizeof(ArrayHeader); | ||
52 | return arr; | ||
53 | } | ||
54 | |||
55 | #endif // BDL_DARRAY_H | ||
diff --git a/src/bootstrap/lexer.c b/src/bootstrap/lexer.c index 05324eb..38ca37c 100644 --- a/src/bootstrap/lexer.c +++ b/src/bootstrap/lexer.c | |||
@@ -44,19 +44,6 @@ print_token(Token tok) { | |||
44 | printf("\n"); | 44 | printf("\n"); |
45 | } | 45 | } |
46 | 46 | ||
47 | void | ||
48 | push_token(Tokens *tokens, Token tok) { | ||
49 | if (tokens->buf == NULL) { | ||
50 | tokens->size = 0; | ||
51 | tokens->cap = TOK_BUF_CAP; | ||
52 | tokens->buf = malloc(tokens->cap * sizeof(Token)); | ||
53 | } else if (tokens->size == tokens->cap) { | ||
54 | tokens->cap *= 2; | ||
55 | tokens->buf = realloc(tokens->buf, tokens->cap * sizeof(Token)); | ||
56 | } | ||
57 | tokens->buf[tokens->size++] = tok; | ||
58 | } | ||
59 | |||
60 | char | 47 | char |
61 | scan_next(Scanner *scanner) { | 48 | scan_next(Scanner *scanner) { |
62 | char c = sv_next(&scanner->current); | 49 | char c = sv_next(&scanner->current); |
@@ -147,9 +134,10 @@ find_primitive_type(const StringView value) { | |||
147 | return TOKEN_SYMBOL; | 134 | return TOKEN_SYMBOL; |
148 | } | 135 | } |
149 | 136 | ||
150 | Tokens | 137 | Token * |
151 | tokenize(const StringView *sv) { | 138 | tokenize(const StringView *sv) { |
152 | Tokens tokens = (Tokens){0}; | 139 | Token *tokens = NULL; |
140 | array_init(tokens, 1); | ||
153 | Scanner scanner = (Scanner){ | 141 | Scanner scanner = (Scanner){ |
154 | .current = *sv, | 142 | .current = *sv, |
155 | .line_number = 1, | 143 | .line_number = 1, |
@@ -197,7 +185,7 @@ tokenize(const StringView *sv) { | |||
197 | .line = line, | 185 | .line = line, |
198 | .column = col, | 186 | .column = col, |
199 | }; | 187 | }; |
200 | push_token(&tokens, token); | 188 | array_push(tokens, token); |
201 | } break; | 189 | } break; |
202 | case '\'': { | 190 | case '\'': { |
203 | Token token = (Token){ | 191 | Token token = (Token){ |
@@ -205,7 +193,7 @@ tokenize(const StringView *sv) { | |||
205 | .line = line, | 193 | .line = line, |
206 | .column = col, | 194 | .column = col, |
207 | }; | 195 | }; |
208 | push_token(&tokens, token); | 196 | array_push(tokens, token); |
209 | } break; | 197 | } break; |
210 | case '(': { | 198 | case '(': { |
211 | if (scan_peek(&scanner) == ')') { | 199 | if (scan_peek(&scanner) == ')') { |
@@ -215,14 +203,14 @@ tokenize(const StringView *sv) { | |||
215 | .line = line, | 203 | .line = line, |
216 | .column = col, | 204 | .column = col, |
217 | }; | 205 | }; |
218 | push_token(&tokens, token); | 206 | array_push(tokens, token); |
219 | } else { | 207 | } else { |
220 | Token token = (Token){ | 208 | Token token = (Token){ |
221 | .type = TOKEN_LPAREN, | 209 | .type = TOKEN_LPAREN, |
222 | .line = line, | 210 | .line = line, |
223 | .column = col, | 211 | .column = col, |
224 | }; | 212 | }; |
225 | push_token(&tokens, token); | 213 | array_push(tokens, token); |
226 | } | 214 | } |
227 | } break; | 215 | } break; |
228 | case ')': { | 216 | case ')': { |
@@ -231,7 +219,7 @@ tokenize(const StringView *sv) { | |||
231 | .line = line, | 219 | .line = line, |
232 | .column = col, | 220 | .column = col, |
233 | }; | 221 | }; |
234 | push_token(&tokens, token); | 222 | array_push(tokens, token); |
235 | } break; | 223 | } break; |
236 | default: { | 224 | default: { |
237 | size_t n = 1; | 225 | size_t n = 1; |
@@ -252,7 +240,7 @@ tokenize(const StringView *sv) { | |||
252 | .column = col, | 240 | .column = col, |
253 | }; | 241 | }; |
254 | token.type = find_primitive_type(token.value); | 242 | token.type = find_primitive_type(token.value); |
255 | push_token(&tokens, token); | 243 | array_push(tokens, token); |
256 | } break; | 244 | } break; |
257 | } | 245 | } |
258 | } | 246 | } |
@@ -263,7 +251,7 @@ tokenize(const StringView *sv) { | |||
263 | .line = scanner.line_number, | 251 | .line = scanner.line_number, |
264 | .column = 1, | 252 | .column = 1, |
265 | }; | 253 | }; |
266 | push_token(&tokens, token); | 254 | array_push(tokens, token); |
267 | 255 | ||
268 | return tokens; | 256 | return tokens; |
269 | } | 257 | } |
diff --git a/src/bootstrap/lexer.h b/src/bootstrap/lexer.h index 129fd9a..2b2789f 100644 --- a/src/bootstrap/lexer.h +++ b/src/bootstrap/lexer.h | |||
@@ -22,12 +22,6 @@ typedef struct Token { | |||
22 | size_t column; | 22 | size_t column; |
23 | } Token; | 23 | } Token; |
24 | 24 | ||
25 | typedef struct Tokens { | ||
26 | Token *buf; | ||
27 | size_t size; | ||
28 | size_t cap; | ||
29 | } Tokens; | ||
30 | |||
31 | typedef struct Scanner { | 25 | typedef struct Scanner { |
32 | StringView current; | 26 | StringView current; |
33 | size_t line_number; | 27 | size_t line_number; |
@@ -38,9 +32,6 @@ typedef struct Scanner { | |||
38 | // Print a token to standard output for debugging purposes. | 32 | // Print a token to standard output for debugging purposes. |
39 | void print_token(Token tok); | 33 | void print_token(Token tok); |
40 | 34 | ||
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 | 35 | // Same functionality as the ScanView pairs, but keeping track of line and |
45 | // column numbers. | 36 | // column numbers. |
46 | char scan_next(Scanner *scanner); | 37 | char scan_next(Scanner *scanner); |
@@ -59,7 +50,7 @@ bool is_delimiter(char c); | |||
59 | TokenType find_primitive_type(const StringView value); | 50 | TokenType find_primitive_type(const StringView value); |
60 | 51 | ||
61 | // Generate a list of tokens from the given string. | 52 | // Generate a list of tokens from the given string. |
62 | Tokens tokenize(const StringView *sv); | 53 | Token * tokenize(const StringView *sv); |
63 | 54 | ||
64 | #define TOK_BUF_CAP 256 | 55 | #define TOK_BUF_CAP 256 |
65 | 56 | ||
diff --git a/src/bootstrap/main.c b/src/bootstrap/main.c index cfad9f1..22332af 100755 --- a/src/bootstrap/main.c +++ b/src/bootstrap/main.c | |||
@@ -6,6 +6,8 @@ | |||
6 | #include <stdlib.h> | 6 | #include <stdlib.h> |
7 | #include <string.h> | 7 | #include <string.h> |
8 | 8 | ||
9 | #include "darray.h" | ||
10 | |||
9 | #include "singletons.c" | 11 | #include "singletons.c" |
10 | 12 | ||
11 | #include "environment.c" | 13 | #include "environment.c" |
@@ -92,10 +94,10 @@ init(void) { | |||
92 | 94 | ||
93 | void | 95 | void |
94 | process_source(const StringView *source) { | 96 | process_source(const StringView *source) { |
95 | Tokens tokens = tokenize(source); | 97 | Token *tokens = tokenize(source); |
96 | if (errors_n != 0) { | 98 | if (errors_n != 0) { |
97 | if (tokens.buf != NULL) { | 99 | if (tokens != NULL) { |
98 | free(tokens.buf); | 100 | array_free(tokens); |
99 | } | 101 | } |
100 | return; | 102 | return; |
101 | } | 103 | } |
@@ -122,8 +124,8 @@ process_source(const StringView *source) { | |||
122 | pop_root(); | 124 | pop_root(); |
123 | } | 125 | } |
124 | 126 | ||
125 | if (tokens.buf != NULL) { | 127 | if (tokens != NULL) { |
126 | free(tokens.buf); | 128 | array_free(tokens); |
127 | } | 129 | } |
128 | } | 130 | } |
129 | 131 | ||
diff --git a/src/bootstrap/parser.c b/src/bootstrap/parser.c index 5b0033a..a2f0f71 100644 --- a/src/bootstrap/parser.c +++ b/src/bootstrap/parser.c | |||
@@ -2,17 +2,17 @@ | |||
2 | 2 | ||
3 | Token | 3 | Token |
4 | peek_token(const Visitor *visitor) { | 4 | peek_token(const Visitor *visitor) { |
5 | return visitor->tokens.buf[visitor->current]; | 5 | return visitor->tokens[visitor->current]; |
6 | } | 6 | } |
7 | 7 | ||
8 | Token | 8 | Token |
9 | next_token(Visitor *visitor) { | 9 | next_token(Visitor *visitor) { |
10 | return visitor->tokens.buf[visitor->current++]; | 10 | return visitor->tokens[visitor->current++]; |
11 | } | 11 | } |
12 | 12 | ||
13 | bool | 13 | bool |
14 | has_next_token(const Visitor *visitor) { | 14 | has_next_token(const Visitor *visitor) { |
15 | return visitor->current < visitor->tokens.size; | 15 | return visitor->current < array_size(visitor->tokens); |
16 | } | 16 | } |
17 | 17 | ||
18 | Object * | 18 | Object * |
diff --git a/src/bootstrap/parser.h b/src/bootstrap/parser.h index 3bd17ef..3834c75 100644 --- a/src/bootstrap/parser.h +++ b/src/bootstrap/parser.h | |||
@@ -2,7 +2,7 @@ | |||
2 | #define BDL_PARSER_H | 2 | #define BDL_PARSER_H |
3 | 3 | ||
4 | typedef struct Visitor { | 4 | typedef struct Visitor { |
5 | Tokens tokens; | 5 | Token *tokens; |
6 | size_t current; | 6 | size_t current; |
7 | } Visitor; | 7 | } Visitor; |
8 | 8 | ||