diff options
author | Bad Diode <bd@badd10de.dev> | 2024-06-18 19:54:56 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2024-06-18 19:54:56 +0200 |
commit | 3d88e46dd0d1b54bc0a414b5db42ed76ddc08363 (patch) | |
tree | 5eed2d95bdc017ef28d603ff1f49b96640929013 | |
parent | f9d0fe5ad641e453724dabc2b17634a44e198ce0 (diff) | |
download | bdl-3d88e46dd0d1b54bc0a414b5db42ed76ddc08363.tar.gz bdl-3d88e46dd0d1b54bc0a414b5db42ed76ddc08363.zip |
Add `cond` conditionals
-rw-r--r-- | src/main.c | 23 | ||||
-rw-r--r-- | tests/conditionals.bad | 68 |
2 files changed, 58 insertions, 33 deletions
@@ -641,6 +641,28 @@ parse_keyword(Parser *parser) { | |||
641 | array_push(node->struct_field, field, parser->storage); | 641 | array_push(node->struct_field, field, parser->storage); |
642 | } | 642 | } |
643 | } break; | 643 | } break; |
644 | case TOK_COND: { | ||
645 | node = node_alloc(parser, NODE_COND, prev); | ||
646 | if (!node) return; | ||
647 | parse_consume(parser, TOK_LCURLY, | ||
648 | cstr("expected '{' on cond expression")); | ||
649 | while (!parse_match(parser, TOK_RCURLY) && !parser->panic) { | ||
650 | Node *tmp = node_alloc(parser, NODE_CASE, parser->previous); | ||
651 | if (!tmp) return; | ||
652 | // Are we on the default case. | ||
653 | if (!parse_match(parser, TOK_ELSE)) { | ||
654 | parse_consume(parser, TOK_CASE, | ||
655 | cstr("expected case statement")); | ||
656 | parse_expr(parser, PREC_LOW); | ||
657 | tmp->case_value = array_pop(parser->nodes); | ||
658 | } | ||
659 | parse_consume(parser, TOK_ASSIGN, | ||
660 | cstr("malformed case statement")); | ||
661 | parse_expr(parser, PREC_LOW); | ||
662 | tmp->case_expr = array_pop(parser->nodes); | ||
663 | array_push(node->match_cases, tmp, parser->storage); | ||
664 | } | ||
665 | } break; | ||
644 | default: return; // Unreachable. | 666 | default: return; // Unreachable. |
645 | } | 667 | } |
646 | array_push(parser->nodes, node, parser->storage); | 668 | array_push(parser->nodes, node, parser->storage); |
@@ -847,6 +869,7 @@ graph_node(Node *node) { | |||
847 | println("\"];"); | 869 | println("\"];"); |
848 | 870 | ||
849 | switch (node->kind) { | 871 | switch (node->kind) { |
872 | case NODE_COND: | ||
850 | case NODE_MATCH: { | 873 | case NODE_MATCH: { |
851 | if (node->match_expr) { | 874 | if (node->match_expr) { |
852 | println("%d:e->%d:w;", node->id, node->match_expr->id); | 875 | println("%d:e->%d:w;", node->id, node->match_expr->id); |
diff --git a/tests/conditionals.bad b/tests/conditionals.bad index 44467a8..856ac8a 100644 --- a/tests/conditionals.bad +++ b/tests/conditionals.bad | |||
@@ -1,36 +1,30 @@ | |||
1 | ; ; Basic if expressions. | 1 | ; Basic if expressions. |
2 | ; if true "hello" | 2 | if true "hello" |
3 | 3 | ||
4 | ; ; These can produce values and the result bound to a name. | 4 | ; These can produce values and the result bound to a name. |
5 | ; let a = if (2 + 2 >= 4) 42 | 5 | let a = if (2 + 2 >= 4) 42 |
6 | 6 | ||
7 | ; ; We support a single if expression. | 7 | ; We support a single if expression. |
8 | ; let b = if 0xff == 255 "hello" else "world" | 8 | let b = if 0xff == 255 "hello" else "world" |
9 | 9 | ||
10 | ; ; ... but these can compound on each other | 10 | ; ... but these can compound on each other |
11 | ; if 1 < 2 6 | 11 | if 1 < 2 6 |
12 | ; else if 1 > 2 7 | 12 | else if 1 > 2 7 |
13 | ; else 8 | 13 | else 8 |
14 | 14 | ||
15 | ; ; A block is an expression, and if raise the scope level regardless if a block | 15 | ; A block is an expression, and if raise the scope level regardless if a block |
16 | ; ; is used or not. | 16 | ; is used or not. |
17 | ; if true != false { | 17 | if true != false { |
18 | ; let a = "yo" | 18 | let a = "yo" |
19 | ; } | 19 | } |
20 | 20 | ||
21 | ; ; Match cases should only apply to literal values, for example `case 1 + 2` | 21 | ; Match cases should only apply to literal values, for example `case 1 + 2` |
22 | ; ; isn't allowed. They should generally convert to a lookup table. | 22 | ; isn't allowed. They should generally convert to a lookup table. |
23 | ; match a = { | 23 | match a = { |
24 | ; case 8 = "hello" | 24 | case 8 = "hello" |
25 | ; case 9 = "world" | 25 | case 9 = "world" |
26 | ; else = "what" | 26 | else = "what" |
27 | ; } | 27 | } |
28 | |||
29 | ; cond { | ||
30 | ; case a == b = "hello" | ||
31 | ; case a != c = "world" | ||
32 | ; else = "what" | ||
33 | ; } | ||
34 | 28 | ||
35 | ; Enums are integers with values that increase automatically or that can be set | 29 | ; Enums are integers with values that increase automatically or that can be set |
36 | ; with a constexpr. | 30 | ; with a constexpr. |
@@ -48,3 +42,11 @@ match a = { | |||
48 | case node_add = "subbing something..." | 42 | case node_add = "subbing something..." |
49 | else = "default case" | 43 | else = "default case" |
50 | } | 44 | } |
45 | |||
46 | ; Conditional `cond` statements are syntactic sugar for a chain of if-else | ||
47 | ; statements. | ||
48 | let msg:str = cond { | ||
49 | case a == b = "hello" | ||
50 | case a != c = "world" | ||
51 | else = "what" | ||
52 | } | ||