aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2024-06-18 19:54:56 +0200
committerBad Diode <bd@badd10de.dev>2024-06-18 19:54:56 +0200
commit3d88e46dd0d1b54bc0a414b5db42ed76ddc08363 (patch)
tree5eed2d95bdc017ef28d603ff1f49b96640929013
parentf9d0fe5ad641e453724dabc2b17634a44e198ce0 (diff)
downloadbdl-3d88e46dd0d1b54bc0a414b5db42ed76ddc08363.tar.gz
bdl-3d88e46dd0d1b54bc0a414b5db42ed76ddc08363.zip
Add `cond` conditionals
-rw-r--r--src/main.c23
-rw-r--r--tests/conditionals.bad68
2 files changed, 58 insertions, 33 deletions
diff --git a/src/main.c b/src/main.c
index f73c7cc..68ad857 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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" 2if 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 5let 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" 8let 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 11if 1 < 2 6
12; else if 1 > 2 7 12else if 1 > 2 7
13; else 8 13else 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 { 17if 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 = { 23match 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.
48let msg:str = cond {
49 case a == b = "hello"
50 case a != c = "world"
51 else = "what"
52}