diff options
author | Bad Diode <bd@badd10de.dev> | 2022-03-31 08:18:36 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2022-03-31 08:18:36 +0200 |
commit | 483a64aa0c5ee8dc925b7957e39c42744b892288 (patch) | |
tree | 86564a19bfc3255a04872815f7e1ac76d3b19cdc | |
parent | 4d5d49b0d1282df08e3dc7dec3c550c544fbfccb (diff) | |
download | bdl-483a64aa0c5ee8dc925b7957e39c42744b892288.tar.gz bdl-483a64aa0c5ee8dc925b7957e39c42744b892288.zip |
Add type signature to def statements
Currently mandatory, may be optional once we have type inference.
-rw-r--r-- | src/main.c | 1 | ||||
-rw-r--r-- | src/nodes.c | 61 | ||||
-rw-r--r-- | src/nodes.h | 45 | ||||
-rw-r--r-- | src/parser.c | 75 | ||||
-rw-r--r-- | src/parser.h | 42 |
5 files changed, 121 insertions, 103 deletions
@@ -7,6 +7,7 @@ | |||
7 | #include "string_view.c" | 7 | #include "string_view.c" |
8 | #include "errors.c" | 8 | #include "errors.c" |
9 | #include "lexer.c" | 9 | #include "lexer.c" |
10 | #include "nodes.c" | ||
10 | #include "parser.c" | 11 | #include "parser.c" |
11 | // #include "ir.h" | 12 | // #include "ir.h" |
12 | // #include "compiler.h" | 13 | // #include "compiler.h" |
diff --git a/src/nodes.c b/src/nodes.c new file mode 100644 index 0000000..63e9b1f --- /dev/null +++ b/src/nodes.c | |||
@@ -0,0 +1,61 @@ | |||
1 | #include "nodes.h" | ||
2 | |||
3 | Node * | ||
4 | alloc_node(NodeType type) { | ||
5 | // TODO: Use a bump allocator? | ||
6 | // TODO: Free memory! | ||
7 | Node *node = malloc(sizeof(Node)); | ||
8 | node->type = type; | ||
9 | return node; | ||
10 | } | ||
11 | |||
12 | void | ||
13 | print_node(Node *node) { | ||
14 | switch (node->type) { | ||
15 | case NODE_NUMBER: { | ||
16 | if (node->number.negative) { | ||
17 | printf("-"); | ||
18 | } | ||
19 | if (node->number.fractional != 0) { | ||
20 | printf("%zu.%zu", node->number.integral, node->number.fractional); | ||
21 | } else { | ||
22 | printf("%zu", node->number.integral); | ||
23 | } | ||
24 | } break; | ||
25 | case NODE_SYMBOL: | ||
26 | case NODE_STRING: { | ||
27 | sv_write(&node->string); | ||
28 | } break; | ||
29 | case NODE_BOOL: { | ||
30 | if (node->boolean) { | ||
31 | printf("true"); | ||
32 | } else { | ||
33 | printf("false"); | ||
34 | } | ||
35 | } break; | ||
36 | case NODE_BUILTIN: { | ||
37 | printf("({%s}", token_str[node->builtin.type]); | ||
38 | size_t n_args = array_size(node->builtin.args); | ||
39 | if (n_args != 0) { | ||
40 | printf(" "); | ||
41 | } | ||
42 | for (size_t i = 0; i < n_args; ++i) { | ||
43 | print_node(node->builtin.args[i]); | ||
44 | if (i < n_args - 1) { | ||
45 | printf(" "); | ||
46 | } | ||
47 | } | ||
48 | printf(")"); | ||
49 | } break; | ||
50 | case NODE_DEF: { | ||
51 | printf("(def "); | ||
52 | print_node(node->def.symbol); | ||
53 | printf(":"); | ||
54 | sv_write(&node->def.type); | ||
55 | printf(" "); | ||
56 | print_node(node->def.value); | ||
57 | printf(")"); | ||
58 | } break; | ||
59 | default: { printf("{#unknown#}"); } break; | ||
60 | } | ||
61 | } | ||
diff --git a/src/nodes.h b/src/nodes.h new file mode 100644 index 0000000..e6ceb50 --- /dev/null +++ b/src/nodes.h | |||
@@ -0,0 +1,45 @@ | |||
1 | #ifndef BDL_NODES_H | ||
2 | #define BDL_NODES_H | ||
3 | |||
4 | typedef enum NodeType { | ||
5 | NODE_BUILTIN, | ||
6 | NODE_NUMBER, | ||
7 | NODE_BOOL, | ||
8 | NODE_STRING, | ||
9 | NODE_SYMBOL, | ||
10 | NODE_DEF, | ||
11 | } NodeType; | ||
12 | |||
13 | typedef struct Node { | ||
14 | NodeType type; | ||
15 | |||
16 | union { | ||
17 | // Numbers. | ||
18 | struct { | ||
19 | bool negative; | ||
20 | size_t integral; | ||
21 | size_t fractional; | ||
22 | } number; | ||
23 | |||
24 | // String/symbol. | ||
25 | StringView string; | ||
26 | |||
27 | // Boolean. | ||
28 | bool boolean; | ||
29 | |||
30 | // Builtin primitive. | ||
31 | struct { | ||
32 | TokenType type; | ||
33 | struct Node **args; | ||
34 | } builtin; | ||
35 | |||
36 | // Variable definition. | ||
37 | struct { | ||
38 | struct Node *symbol; | ||
39 | struct Node *value; | ||
40 | StringView type; | ||
41 | } def; | ||
42 | }; | ||
43 | } Node; | ||
44 | |||
45 | #endif // BDL_NODES_H | ||
diff --git a/src/parser.c b/src/parser.c index 434ae98..cc94fd2 100644 --- a/src/parser.c +++ b/src/parser.c | |||
@@ -1,15 +1,6 @@ | |||
1 | #include "parser.h" | 1 | #include "parser.h" |
2 | #include "darray.h" | 2 | #include "darray.h" |
3 | 3 | ||
4 | Node * | ||
5 | alloc_node(NodeType type) { | ||
6 | // TODO: Use a bump allocator? | ||
7 | // TODO: Free memory! | ||
8 | Node *node = malloc(sizeof(Node)); | ||
9 | node->type = type; | ||
10 | return node; | ||
11 | } | ||
12 | |||
13 | Token | 4 | Token |
14 | next_token(Parser *parser) { | 5 | next_token(Parser *parser) { |
15 | return parser->tokens[parser->current++]; | 6 | return parser->tokens[parser->current++]; |
@@ -154,7 +145,18 @@ parse_def(Parser *parser) { | |||
154 | return NULL; | 145 | return NULL; |
155 | } | 146 | } |
156 | 147 | ||
157 | // TODO: Check if it has type annotation. | 148 | // TODO: Making type checking mandatory for now until we introduce |
149 | // type inference. | ||
150 | Token next = next_token(parser); | ||
151 | if (next.type != TOKEN_COLON) { | ||
152 | push_error(ERR_TYPE_PARSER, ERR_MALFORMED_EXPR, op.line, op.col); | ||
153 | return NULL; | ||
154 | } | ||
155 | Token type_name = next_token(parser); | ||
156 | if (type_name.type != TOKEN_SYMBOL) { | ||
157 | push_error(ERR_TYPE_PARSER, ERR_MALFORMED_EXPR, op.line, op.col); | ||
158 | return NULL; | ||
159 | } | ||
158 | 160 | ||
159 | Node *value = parse_next(parser); | 161 | Node *value = parse_next(parser); |
160 | if (value == NULL) { | 162 | if (value == NULL) { |
@@ -171,9 +173,7 @@ parse_def(Parser *parser) { | |||
171 | Node *node = alloc_node(NODE_DEF); | 173 | Node *node = alloc_node(NODE_DEF); |
172 | node->def.symbol = symbol; | 174 | node->def.symbol = symbol; |
173 | node->def.value = value; | 175 | node->def.value = value; |
174 | 176 | node->def.type = type_name.value; | |
175 | // TODO: Register variable in symbol table. | ||
176 | |||
177 | return node; | 177 | return node; |
178 | } | 178 | } |
179 | 179 | ||
@@ -221,55 +221,6 @@ parse_next(Parser *parser) { | |||
221 | } | 221 | } |
222 | 222 | ||
223 | void | 223 | void |
224 | print_node(Node *node) { | ||
225 | switch (node->type) { | ||
226 | case NODE_NUMBER: { | ||
227 | if (node->number.negative) { | ||
228 | printf("-"); | ||
229 | } | ||
230 | if (node->number.fractional != 0) { | ||
231 | printf("%zu.%zu", node->number.integral, node->number.fractional); | ||
232 | } else { | ||
233 | printf("%zu", node->number.integral); | ||
234 | } | ||
235 | } break; | ||
236 | case NODE_SYMBOL: | ||
237 | case NODE_STRING: { | ||
238 | sv_write(&node->string); | ||
239 | } break; | ||
240 | case NODE_BOOL: { | ||
241 | if (node->boolean) { | ||
242 | printf("true"); | ||
243 | } else { | ||
244 | printf("false"); | ||
245 | } | ||
246 | } break; | ||
247 | case NODE_BUILTIN: { | ||
248 | printf("({%s}", token_str[node->builtin.type]); | ||
249 | size_t n_args = array_size(node->builtin.args); | ||
250 | if (n_args != 0) { | ||
251 | printf(" "); | ||
252 | } | ||
253 | for (size_t i = 0; i < n_args; ++i) { | ||
254 | print_node(node->builtin.args[i]); | ||
255 | if (i < n_args - 1) { | ||
256 | printf(" "); | ||
257 | } | ||
258 | } | ||
259 | printf(")"); | ||
260 | } break; | ||
261 | case NODE_DEF: { | ||
262 | printf("(def "); | ||
263 | print_node(node->def.symbol); | ||
264 | printf(" "); | ||
265 | print_node(node->def.value); | ||
266 | printf(")"); | ||
267 | } break; | ||
268 | default: { printf("{#unknown#}"); } break; | ||
269 | } | ||
270 | } | ||
271 | |||
272 | void | ||
273 | parse(Token *tokens) { | 224 | parse(Token *tokens) { |
274 | Parser parser = { | 225 | Parser parser = { |
275 | .tokens = tokens, | 226 | .tokens = tokens, |
diff --git a/src/parser.h b/src/parser.h index 6a4401e..47316b9 100644 --- a/src/parser.h +++ b/src/parser.h | |||
@@ -2,53 +2,13 @@ | |||
2 | #define BDL_PARSER_H | 2 | #define BDL_PARSER_H |
3 | 3 | ||
4 | #include "lexer.h" | 4 | #include "lexer.h" |
5 | #include "nodes.h" | ||
5 | 6 | ||
6 | typedef struct Parser { | 7 | typedef struct Parser { |
7 | Token *tokens; | 8 | Token *tokens; |
8 | size_t current; | 9 | size_t current; |
9 | } Parser; | 10 | } Parser; |
10 | 11 | ||
11 | typedef enum NodeType { | ||
12 | NODE_BUILTIN, | ||
13 | NODE_NUMBER, | ||
14 | NODE_BOOL, | ||
15 | NODE_STRING, | ||
16 | NODE_SYMBOL, | ||
17 | NODE_DEF, | ||
18 | } NodeType; | ||
19 | |||
20 | typedef struct Node { | ||
21 | NodeType type; | ||
22 | |||
23 | union { | ||
24 | // Numbers. | ||
25 | struct { | ||
26 | bool negative; | ||
27 | size_t integral; | ||
28 | size_t fractional; | ||
29 | } number; | ||
30 | |||
31 | // String/symbol. | ||
32 | StringView string; | ||
33 | |||
34 | // Boolean. | ||
35 | bool boolean; | ||
36 | |||
37 | // Builtin primitive. | ||
38 | struct { | ||
39 | TokenType type; | ||
40 | struct Node **args; | ||
41 | } builtin; | ||
42 | |||
43 | // Variable definition. | ||
44 | struct { | ||
45 | struct Node *symbol; | ||
46 | struct Node *value; | ||
47 | // TODO: type information | ||
48 | } def; | ||
49 | }; | ||
50 | } Node; | ||
51 | |||
52 | void parse(Token *tokens); | 12 | void parse(Token *tokens); |
53 | Node * parse_next(Parser *parser); | 13 | Node * parse_next(Parser *parser); |
54 | 14 | ||