aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2022-04-06 07:30:43 -0300
committerBad Diode <bd@badd10de.dev>2022-04-06 07:30:43 -0300
commit77b309ba82d090094f5f753342c3aa401cbf657d (patch)
tree2ead2ad4a87b6ba14c766a62b2a82e7005fb03c1 /src
parentc8b53cb4590d8d6cbfc5cbf891809ddd99e33fe5 (diff)
downloadbdl-77b309ba82d090094f5f753342c3aa401cbf657d.tar.gz
bdl-77b309ba82d090094f5f753342c3aa401cbf657d.zip
Add NODE_BLOCK for scoped expressions
Diffstat (limited to 'src')
-rw-r--r--src/nodes.c18
-rw-r--r--src/nodes.h8
-rw-r--r--src/parser.c42
3 files changed, 43 insertions, 25 deletions
diff --git a/src/nodes.c b/src/nodes.c
index fc39d8e..3a63246 100644
--- a/src/nodes.c
+++ b/src/nodes.c
@@ -64,6 +64,15 @@ print_node(Node *node) {
64 print_node(node->def.value); 64 print_node(node->def.value);
65 printf(")"); 65 printf(")");
66 } break; 66 } break;
67 case NODE_BLOCK: {
68 size_t n_expr = array_size(node->block.expr);
69 printf("{");
70 for (size_t i = 0; i < n_expr; ++i) {
71 printf(" ");
72 print_node(node->block.expr[i]);
73 }
74 printf(" }");
75 } break;
67 case NODE_FUN: { 76 case NODE_FUN: {
68 printf("(fun "); 77 printf("(fun ");
69 print_node(node->fun.name); 78 print_node(node->fun.name);
@@ -80,13 +89,8 @@ print_node(Node *node) {
80 printf(")"); 89 printf(")");
81 printf(": "); 90 printf(": ");
82 print_node(node->fun.return_type); 91 print_node(node->fun.return_type);
83 92 printf(" ");
84 size_t n_expr = array_size(node->fun.body); 93 print_node(node->fun.body);
85 for (size_t i = 0; i < n_expr; ++i) {
86 printf(" ");
87 print_node(node->fun.body[i]);
88 }
89
90 printf(")"); 94 printf(")");
91 } break; 95 } break;
92 default: { printf("{#unknown#}"); } break; 96 default: { printf("{#unknown#}"); } break;
diff --git a/src/nodes.h b/src/nodes.h
index 2e24ea5..c1520b3 100644
--- a/src/nodes.h
+++ b/src/nodes.h
@@ -11,6 +11,7 @@ typedef enum NodeType {
11 NODE_DEF, 11 NODE_DEF,
12 NODE_SET, 12 NODE_SET,
13 NODE_FUN, 13 NODE_FUN,
14 NODE_BLOCK,
14} NodeType; 15} NodeType;
15 16
16typedef struct Node { 17typedef struct Node {
@@ -55,8 +56,13 @@ typedef struct Node {
55 struct Node **param_names; 56 struct Node **param_names;
56 struct Node **param_types; 57 struct Node **param_types;
57 struct Node *return_type; 58 struct Node *return_type;
58 struct Node **body; 59 struct Node *body;
59 } fun; 60 } fun;
61
62 // Block statements.
63 struct {
64 struct Node **expr;
65 } block;
60 }; 66 };
61} Node; 67} Node;
62 68
diff --git a/src/parser.c b/src/parser.c
index cfbefaf..58ad722 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -258,7 +258,6 @@ parse_fun(Parser *parser) {
258 node->fun.name = name; 258 node->fun.name = name;
259 array_init(node->fun.param_names, 0); 259 array_init(node->fun.param_names, 0);
260 array_init(node->fun.param_types, 0); 260 array_init(node->fun.param_types, 0);
261 array_init(node->fun.body, 0);
262 261
263 // Parse parameter list and return type. 262 // Parse parameter list and return type.
264 if (!consume_lparen(parser)) { 263 if (!consume_lparen(parser)) {
@@ -287,19 +286,12 @@ parse_fun(Parser *parser) {
287 } 286 }
288 node->fun.return_type = ret_type; 287 node->fun.return_type = ret_type;
289 288
290 // Parse body. 289 Node *body = parse_next(parser);
291 while (true) { 290 if (body == NULL) {
292 Token next = peek_token(parser); 291 return NULL;
293 if (next.type == TOKEN_RPAREN) {
294 next_token(parser);
295 break;
296 }
297 Node *expr = parse_next(parser);
298 if (expr == NULL) {
299 return NULL;
300 }
301 array_push(node->fun.body, expr);
302 } 292 }
293 node->fun.body = body;
294 consume_rparen(parser);
303 295
304 return node; 296 return node;
305} 297}
@@ -331,10 +323,25 @@ parse_paren(Parser *parser) {
331 return NULL; 323 return NULL;
332} 324}
333 325
334 326Node *
335// TODO: Parse if: (def ...) shouldn't be allowed for now on if statements. In 327parse_block(Parser *parser) {
336// the future, an if can create a new block and thus a fresh scope which would 328 next_token(parser); // Skip paren.
337// make the decision of what variables are active trivial. 329 Node *node = alloc_node(NODE_BLOCK);
330 array_init(node->block.expr, 0);
331 while (true) {
332 Token next = peek_token(parser);
333 if (next.type == TOKEN_RCURLY) {
334 next_token(parser);
335 break;
336 }
337 Node *expr = parse_next(parser);
338 if (expr == NULL) {
339 return NULL;
340 }
341 array_push(node->block.expr, expr);
342 }
343 return node;
344}
338 345
339Node * 346Node *
340parse_next(Parser *parser) { 347parse_next(Parser *parser) {
@@ -347,6 +354,7 @@ parse_next(Parser *parser) {
347 case TOKEN_FALSE: { return parse_bool(parser); } break; 354 case TOKEN_FALSE: { return parse_bool(parser); } break;
348 case TOKEN_LPAREN: { return parse_paren(parser); } break; 355 case TOKEN_LPAREN: { return parse_paren(parser); } break;
349 case TOKEN_EOF: { return NULL; } break; 356 case TOKEN_EOF: { return NULL; } break;
357 case TOKEN_LCURLY: { return parse_block(parser); } break;
350 default: { 358 default: {
351 push_error(ERR_TYPE_PARSER, ERR_UNKNOWN_TOK_TYPE, tok.line, tok.col); 359 push_error(ERR_TYPE_PARSER, ERR_UNKNOWN_TOK_TYPE, tok.line, tok.col);
352 return NULL; 360 return NULL;