aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2024-06-23 20:46:51 +0200
committerBad Diode <bd@badd10de.dev>2024-06-23 20:46:51 +0200
commita52097738e663f8bfea9b771c6f839f3dea9d901 (patch)
tree15bca360082a1aef2f85166096d26716e4f7eb93
parentcaf4d4c7dd0fff6cdf69bf8cb27f3bbb6d02a366 (diff)
downloadbdl-a52097738e663f8bfea9b771c6f839f3dea9d901.tar.gz
bdl-a52097738e663f8bfea9b771c6f839f3dea9d901.zip
Add typechecking for if expressions
-rw-r--r--src/main.c30
-rw-r--r--tests/semantics.bad30
2 files changed, 50 insertions, 10 deletions
diff --git a/src/main.c b/src/main.c
index a66a40c..df2f687 100644
--- a/src/main.c
+++ b/src/main.c
@@ -253,6 +253,36 @@ type_inference(Analyzer *a, Node *node, TypeScope *scope) {
253 } 253 }
254 return node->type; 254 return node->type;
255 } break; 255 } break;
256 case NODE_IF: {
257 Type type = type_inference(a, node->cond_if, scope);
258 if (!str_eq(type, cstr("bool"))) {
259 emit_semantic_error(
260 a, node->cond_if,
261 cstr("non boolean expression on if condition"));
262 return cstr("");
263 }
264 if (node->cond_expr->kind == NODE_BLOCK) {
265 node->type = type_inference(a, node->cond_expr, scope);
266 } else {
267 TypeScope *next = typescope_alloc(a, scope);
268 node->type = type_inference(a, node->cond_expr, next);
269 }
270 if (node->cond_else) {
271 Type else_type;
272 if (node->cond_else->kind == NODE_BLOCK) {
273 else_type = type_inference(a, node->cond_else, scope);
274 } else {
275 TypeScope *next = typescope_alloc(a, scope);
276 else_type = type_inference(a, node->cond_else, next);
277 }
278 if (!str_eq(node->type, else_type)) {
279 emit_semantic_error(
280 a, node,
281 cstr("mismatch types for if/else branches"));
282 return cstr("");
283 }
284 }
285 } break;
256 case NODE_TRUE: 286 case NODE_TRUE:
257 case NODE_FALSE: { 287 case NODE_FALSE: {
258 node->type = cstr("bool"); 288 node->type = cstr("bool");
diff --git a/tests/semantics.bad b/tests/semantics.bad
index 158cec6..c316a3c 100644
--- a/tests/semantics.bad
+++ b/tests/semantics.bad
@@ -1,15 +1,25 @@
1; let a:f32 = (1.0 + 2.0 * 2.0) / 2.0 1; let a:f32 = (1.0 + 2.0 * 2.0) / 2.0
2 2
3let annotated:int = (1 + 2 * 2) / 2 3; let annotated:int = (1 + 2 * 2) / 2
4let numbers = 1 4; let numbers = 1
5let symbols = numbers 5; let symbols = numbers
6let arith = 1 + 2 * 4 6; let arith = 1 + 2 * 4
7let cmp = 1 <= 2 7; let cmp = 1 <= 2
8let logic = !true && false || (1 <= 2) 8; let logic = !true && false || (1 <= 2)
9let bits = 0xff & 0b00001111 9; let bits = 0xff & 0b00001111
10let block = { 10; let block = {
11 let a = 1 + 2 11; let a = 1 + 2
12 a + 3 12; a + 3
13; }
14
15let maybe = if (1 == 2) {
16 32
17} else {
18 44
19}
20
21let single = if (true) {
22 123
13} 23}
14 24
15; enum test { 25; enum test {