diff options
Diffstat (limited to 'src/semantic.c')
-rw-r--r-- | src/semantic.c | 513 |
1 files changed, 358 insertions, 155 deletions
diff --git a/src/semantic.c b/src/semantic.c index d782cac..7c44671 100644 --- a/src/semantic.c +++ b/src/semantic.c | |||
@@ -82,6 +82,9 @@ Scope * | |||
82 | typescope_alloc(Analyzer *a, Scope *parent) { | 82 | typescope_alloc(Analyzer *a, Scope *parent) { |
83 | Scope *scope = arena_calloc(sizeof(Scope), a->storage); | 83 | Scope *scope = arena_calloc(sizeof(Scope), a->storage); |
84 | scope->parent = parent; | 84 | scope->parent = parent; |
85 | if (parent != NULL) { | ||
86 | scope->name = parent->name; | ||
87 | } | ||
85 | scope->id = a->typescope_gen++; | 88 | scope->id = a->typescope_gen++; |
86 | scope->depth = parent == NULL ? 0 : parent->depth + 1; | 89 | scope->depth = parent == NULL ? 0 : parent->depth + 1; |
87 | array_push(a->scopes, scope, a->storage); | 90 | array_push(a->scopes, scope, a->storage); |
@@ -276,7 +279,7 @@ Str type_inference(Analyzer *a, Node *node, Scope *scope); | |||
276 | 279 | ||
277 | void | 280 | void |
278 | typecheck_field(Analyzer *a, Node *node, Scope *scope, Str symbol) { | 281 | typecheck_field(Analyzer *a, Node *node, Scope *scope, Str symbol) { |
279 | if (node->field_type->kind == NODE_COMPOUND_TYPE) { | 282 | if (node->field.type->kind == NODE_COMPOUND_TYPE) { |
280 | Str field_name = str_concat(symbol, cstr("."), a->storage); | 283 | Str field_name = str_concat(symbol, cstr("."), a->storage); |
281 | field_name = str_concat(field_name, node->value.str, a->storage); | 284 | field_name = str_concat(field_name, node->value.str, a->storage); |
282 | if (structmap_lookup(&scope->structs, field_name)) { | 285 | if (structmap_lookup(&scope->structs, field_name)) { |
@@ -285,8 +288,8 @@ typecheck_field(Analyzer *a, Node *node, Scope *scope, Str symbol) { | |||
285 | a->err = true; | 288 | a->err = true; |
286 | } | 289 | } |
287 | Str type = cstr("\\{ "); | 290 | Str type = cstr("\\{ "); |
288 | for (sz i = 0; i < array_size(node->field_type->elements); i++) { | 291 | for (sz i = 0; i < array_size(node->field.type->elements); i++) { |
289 | Node *field = node->field_type->elements[i]; | 292 | Node *field = node->field.type->elements[i]; |
290 | typecheck_field(a, field, scope, field_name); | 293 | typecheck_field(a, field, scope, field_name); |
291 | type = str_concat(type, field->type, a->storage); | 294 | type = str_concat(type, field->type, a->storage); |
292 | type = str_concat(type, cstr(" "), a->storage); | 295 | type = str_concat(type, cstr(" "), a->storage); |
@@ -296,16 +299,16 @@ typecheck_field(Analyzer *a, Node *node, Scope *scope, Str symbol) { | |||
296 | } else { | 299 | } else { |
297 | Str field_name = str_concat(symbol, cstr("."), a->storage); | 300 | Str field_name = str_concat(symbol, cstr("."), a->storage); |
298 | field_name = str_concat(field_name, node->value.str, a->storage); | 301 | field_name = str_concat(field_name, node->value.str, a->storage); |
299 | Str field_type = node->field_type->value.str; | 302 | Str field_type = node->field.type->value.str; |
300 | if (!find_type(scope, field_type)) { | 303 | if (!find_type(scope, field_type)) { |
301 | eprintln("%s:%d:%d: error: unknown type '%s'", a->file_name, | 304 | eprintln("%s:%d:%d: error: unknown type '%s'", a->file_name, |
302 | node->field_type->line, node->field_type->col, field_type); | 305 | node->field.type->line, node->field.type->col, field_type); |
303 | a->err = true; | 306 | a->err = true; |
304 | } | 307 | } |
305 | if (node->field_type->is_ptr) { | 308 | if (node->field.type->is_ptr) { |
306 | field_type = str_concat(cstr("@"), field_type, a->storage); | 309 | field_type = str_concat(cstr("@"), field_type, a->storage); |
307 | } | 310 | } |
308 | if (node->field_type->kind == NODE_ARR_TYPE) { | 311 | if (node->field.type->kind == NODE_ARR_TYPE) { |
309 | field_type = str_concat(cstr("@"), field_type, a->storage); | 312 | field_type = str_concat(cstr("@"), field_type, a->storage); |
310 | } | 313 | } |
311 | if (structmap_lookup(&scope->structs, field_name)) { | 314 | if (structmap_lookup(&scope->structs, field_name)) { |
@@ -313,8 +316,8 @@ typecheck_field(Analyzer *a, Node *node, Scope *scope, Str symbol) { | |||
313 | a->file_name, node->line, node->col, field_name); | 316 | a->file_name, node->line, node->col, field_name); |
314 | a->err = true; | 317 | a->err = true; |
315 | } | 318 | } |
316 | if (node->field_val) { | 319 | if (node->field.val) { |
317 | Str type = type_inference(a, node->field_val, scope); | 320 | Str type = type_inference(a, node->field.val, scope); |
318 | if (!str_eq(type, field_type)) { | 321 | if (!str_eq(type, field_type)) { |
319 | eprintln( | 322 | eprintln( |
320 | "%s:%d:%d: error: mismatched types in struct " | 323 | "%s:%d:%d: error: mismatched types in struct " |
@@ -329,7 +332,7 @@ typecheck_field(Analyzer *a, Node *node, Scope *scope, Str symbol) { | |||
329 | (Struct){ | 332 | (Struct){ |
330 | .name = field_name, | 333 | .name = field_name, |
331 | .type = field_type, | 334 | .type = field_type, |
332 | .val = node->field_val, | 335 | .val = node->field.val, |
333 | }, | 336 | }, |
334 | a->storage); | 337 | a->storage); |
335 | symmap_insert(&scope->symbols, field_name, | 338 | symmap_insert(&scope->symbols, field_name, |
@@ -341,10 +344,10 @@ typecheck_field(Analyzer *a, Node *node, Scope *scope, Str symbol) { | |||
341 | 344 | ||
342 | void | 345 | void |
343 | typecheck_lit_field(Analyzer *a, Node *node, Scope *scope, Str symbol) { | 346 | typecheck_lit_field(Analyzer *a, Node *node, Scope *scope, Str symbol) { |
344 | if (node->field_val->kind == NODE_COMPOUND_TYPE) { | 347 | if (node->field.val->kind == NODE_COMPOUND_TYPE) { |
345 | Str type = cstr("\\{ "); | 348 | Str type = cstr("\\{ "); |
346 | for (sz i = 0; i < array_size(node->field_val->elements); i++) { | 349 | for (sz i = 0; i < array_size(node->field.val->elements); i++) { |
347 | Node *field = node->field_val->elements[i]; | 350 | Node *field = node->field.val->elements[i]; |
348 | Str field_name = str_concat(symbol, cstr("."), a->storage); | 351 | Str field_name = str_concat(symbol, cstr("."), a->storage); |
349 | field_name = str_concat(field_name, field->value.str, a->storage); | 352 | field_name = str_concat(field_name, field->value.str, a->storage); |
350 | typecheck_lit_field(a, field, scope, field_name); | 353 | typecheck_lit_field(a, field, scope, field_name); |
@@ -362,7 +365,7 @@ typecheck_lit_field(Analyzer *a, Node *node, Scope *scope, Str symbol) { | |||
362 | return; | 365 | return; |
363 | } | 366 | } |
364 | Str field_type = s->val.type; | 367 | Str field_type = s->val.type; |
365 | Str type = type_inference(a, node->field_val, scope); | 368 | Str type = type_inference(a, node->field.val, scope); |
366 | if (!str_eq(type, field_type)) { | 369 | if (!str_eq(type, field_type)) { |
367 | eprintln( | 370 | eprintln( |
368 | "%s:%d:%d: error: mismatched types in struct " | 371 | "%s:%d:%d: error: mismatched types in struct " |
@@ -384,17 +387,18 @@ typecheck_returns(Analyzer *a, Node *node, Str expected) { | |||
384 | switch (node->kind) { | 387 | switch (node->kind) { |
385 | case NODE_COND: | 388 | case NODE_COND: |
386 | case NODE_MATCH: { | 389 | case NODE_MATCH: { |
387 | for (sz i = 0; i < array_size(node->match_cases); i++) { | 390 | for (sz i = 0; i < array_size(node->match.cases); i++) { |
388 | Node *next = node->match_cases[i]; | 391 | Node *next = node->match.cases[i]; |
389 | typecheck_returns(a, next, expected); | 392 | typecheck_returns(a, next, expected); |
390 | } | 393 | } |
391 | } break; | 394 | } break; |
392 | case NODE_RETURN: { | 395 | case NODE_RETURN: { |
393 | bool err = !str_eq(node->type, expected); | 396 | Str type = str_remove_prefix(node->type, cstr("ret:")); |
397 | bool err = !str_eq(type, expected); | ||
394 | if (err) { | 398 | if (err) { |
395 | eprintln( | 399 | eprintln( |
396 | "%s:%d:%d: error: mismatched return type %s, expected %s", | 400 | "%s:%d:%d: error: mismatched return type %s, expected %s", |
397 | a->file_name, node->line, node->col, node->type, expected); | 401 | a->file_name, node->line, node->col, type, expected); |
398 | a->err = true; | 402 | a->err = true; |
399 | } | 403 | } |
400 | } break; | 404 | } break; |
@@ -405,17 +409,17 @@ typecheck_returns(Analyzer *a, Node *node, Str expected) { | |||
405 | } | 409 | } |
406 | } break; | 410 | } break; |
407 | case NODE_IF: { | 411 | case NODE_IF: { |
408 | if (node->cond_expr) { | 412 | if (node->ifelse.expr_true) { |
409 | typecheck_returns(a, node->cond_expr, expected); | 413 | typecheck_returns(a, node->ifelse.expr_true, expected); |
410 | } | 414 | } |
411 | if (node->cond_else) { | 415 | if (node->ifelse.expr_else) { |
412 | typecheck_returns(a, node->cond_else, expected); | 416 | typecheck_returns(a, node->ifelse.expr_else, expected); |
413 | } | 417 | } |
414 | } break; | 418 | } break; |
415 | case NODE_SET: | 419 | case NODE_SET: |
416 | case NODE_LET: { | 420 | case NODE_LET: { |
417 | if (node->var_val) { | 421 | if (node->var.val) { |
418 | typecheck_returns(a, node->var_val, expected); | 422 | typecheck_returns(a, node->var.val, expected); |
419 | } | 423 | } |
420 | } break; | 424 | } break; |
421 | case NODE_ADD: | 425 | case NODE_ADD: |
@@ -435,13 +439,14 @@ typecheck_returns(Analyzer *a, Node *node, Str expected) { | |||
435 | case NODE_BITNOT: | 439 | case NODE_BITNOT: |
436 | case NODE_BITAND: | 440 | case NODE_BITAND: |
437 | case NODE_BITOR: | 441 | case NODE_BITOR: |
442 | case NODE_BITXOR: | ||
438 | case NODE_BITLSHIFT: | 443 | case NODE_BITLSHIFT: |
439 | case NODE_BITRSHIFT: { | 444 | case NODE_BITRSHIFT: { |
440 | if (node->left) { | 445 | if (node->binary.left) { |
441 | typecheck_returns(a, node->left, expected); | 446 | typecheck_returns(a, node->binary.left, expected); |
442 | } | 447 | } |
443 | if (node->right) { | 448 | if (node->binary.right) { |
444 | typecheck_returns(a, node->right, expected); | 449 | typecheck_returns(a, node->binary.right, expected); |
445 | } | 450 | } |
446 | } break; | 451 | } break; |
447 | default: break; | 452 | default: break; |
@@ -452,66 +457,79 @@ Str | |||
452 | type_inference(Analyzer *a, Node *node, Scope *scope) { | 457 | type_inference(Analyzer *a, Node *node, Scope *scope) { |
453 | assert(a); | 458 | assert(a); |
454 | assert(scope); | 459 | assert(scope); |
455 | if (!node) { | 460 | if (!node || a->err) { |
456 | return cstr(""); | 461 | return cstr(""); |
457 | } | 462 | } |
458 | // NOTE: For now we are not going to do implicit numeric conversions. | 463 | // NOTE: For now we are not going to do implicit numeric conversions. |
459 | switch (node->kind) { | 464 | switch (node->kind) { |
460 | case NODE_LET: { | 465 | case NODE_LET: { |
461 | node->type = cstr("nil"); | 466 | node->type = cstr("nil"); |
462 | Str symbol = node->var_name->value.str; | 467 | node->var.name->parent = node; |
468 | Str symbol = node->var.name->value.str; | ||
463 | if (symmap_lookup(&scope->symbols, symbol)) { | 469 | if (symmap_lookup(&scope->symbols, symbol)) { |
464 | eprintln( | 470 | eprintln( |
465 | "%s:%d:%d: error: symbol '%s' already exists in current " | 471 | "%s:%d:%d: error: symbol '%s' already exists in current " |
466 | "scope ", | 472 | "scope ", |
467 | a->file_name, node->var_name->line, node->var_name->col, | 473 | a->file_name, node->var.name->line, node->var.name->col, |
468 | symbol); | 474 | symbol); |
469 | a->err = true; | 475 | a->err = true; |
470 | return cstr(""); | 476 | return cstr(""); |
471 | } | 477 | } |
472 | if (node->var_type) { | 478 | if (node->var.type) { |
473 | Str type_name = node->var_type->value.str; | 479 | node->var.type->parent = node; |
480 | Str type_name = node->var.type->value.str; | ||
474 | SymbolMap *type = find_type(scope, type_name); | 481 | SymbolMap *type = find_type(scope, type_name); |
475 | if (type == NULL) { | 482 | if (type == NULL) { |
476 | eprintln("%s:%d:%d: error: unknown type '%s'", a->file_name, | 483 | eprintln("%s:%d:%d: error: unknown type '%s'", a->file_name, |
477 | node->var_type->line, node->var_type->col, | 484 | node->var.type->line, node->var.type->col, |
478 | type_name); | 485 | type_name); |
479 | a->err = true; | 486 | a->err = true; |
480 | return cstr(""); | 487 | return cstr(""); |
481 | } | 488 | } |
482 | if (node->var_type->is_ptr) { | 489 | if (node->var.type->is_ptr) { |
483 | type_name = str_concat(cstr("@"), type_name, a->storage); | 490 | type_name = str_concat(cstr("@"), type_name, a->storage); |
484 | } | 491 | } |
485 | if (node->var_type->kind == NODE_ARR_TYPE) { | 492 | if (node->var.type->kind == NODE_ARR_TYPE) { |
486 | type_name = str_concat(cstr("@"), type_name, a->storage); | 493 | type_name = str_concat(cstr("@"), type_name, a->storage); |
487 | // TODO: typecheck size | 494 | if (node->var.type->sym.arr_size->value.i == 0) { |
495 | eprintln("%s:%d:%d: error: zero sized array '%s'", | ||
496 | a->file_name, node->var.type->line, | ||
497 | node->var.type->col, symbol); | ||
498 | a->err = true; | ||
499 | return cstr(""); | ||
500 | } | ||
488 | // TODO: register array in scope | 501 | // TODO: register array in scope |
489 | } | 502 | } |
490 | if (node->var_val) { | 503 | if (node->var.val) { |
491 | Str type = type_inference(a, node->var_val, scope); | 504 | node->var.val->parent = node; |
505 | Str type = type_inference(a, node->var.val, scope); | ||
492 | if (!type.size) { | 506 | if (!type.size) { |
493 | eprintln( | 507 | eprintln( |
494 | "%s:%d:%d: error: can't bind `nil` to variable " | 508 | "%s:%d:%d: error: can't bind `nil` to variable " |
495 | "'%s'", | 509 | "'%s'", |
496 | a->file_name, node->var_type->line, | 510 | a->file_name, node->var.type->line, |
497 | node->var_type->col, symbol); | 511 | node->var.type->col, symbol); |
498 | a->err = true; | 512 | a->err = true; |
499 | return cstr(""); | 513 | return cstr(""); |
500 | } | 514 | } |
501 | // TODO: Consider compatible types. | ||
502 | if (!str_eq(type, type_name)) { | 515 | if (!str_eq(type, type_name)) { |
503 | // Special case, enums can be treated as ints. | 516 | if (!(strset_lookup(&a->integer_types, type) && |
504 | FindEnumResult res = find_enum(scope, type_name); | 517 | strset_lookup(&a->integer_types, type_name)) && |
505 | if (!(res.map && str_eq(type, cstr("int")))) { | 518 | !(strset_lookup(&a->numeric_types, type) && |
506 | eprintln( | 519 | strset_lookup(&a->numeric_types, type_name))) { |
507 | "%s:%d:%d: error: type mismatch, trying to " | 520 | // Special case, enums can be treated as ints. |
508 | "assing " | 521 | FindEnumResult res = find_enum(scope, type_name); |
509 | "%s" | 522 | if (!(res.map && str_eq(type, cstr("int")))) { |
510 | " to a variable of type %s", | 523 | eprintln( |
511 | a->file_name, node->var_type->line, | 524 | "%s:%d:%d: error: type mismatch, trying to " |
512 | node->var_type->col, type, type_name); | 525 | "assing " |
513 | a->err = true; | 526 | "%s" |
514 | return cstr(""); | 527 | " to a variable of type %s", |
528 | a->file_name, node->var.type->line, | ||
529 | node->var.type->col, type, type_name); | ||
530 | a->err = true; | ||
531 | return cstr(""); | ||
532 | } | ||
515 | } | 533 | } |
516 | } | 534 | } |
517 | } | 535 | } |
@@ -521,17 +539,29 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
521 | .kind = SYM_VAR, | 539 | .kind = SYM_VAR, |
522 | }, | 540 | }, |
523 | a->storage); | 541 | a->storage); |
542 | node->var.name->type = type_name; | ||
543 | symbol = str_concat(cstr("."), symbol, a->storage); | ||
544 | symbol = str_concat(symbol, str_from_int(scope->id, a->storage), | ||
545 | a->storage); | ||
546 | node->unique_name = symbol; | ||
524 | return node->type; | 547 | return node->type; |
525 | } | 548 | } |
526 | 549 | ||
527 | // We don't know the type for this symbol, perform inference. | 550 | // We don't know the type for this symbol, perform inference. |
528 | Str type = type_inference(a, node->var_val, scope); | 551 | node->var.val->parent = node; |
529 | if (type.size) { | 552 | Str type = type_inference(a, node->var.val, scope); |
530 | symmap_insert(&scope->symbols, symbol, | 553 | if (!type.size || str_eq(type, cstr("nil")) || |
531 | (Symbol){.name = type, .kind = SYM_VAR}, | 554 | str_has_prefix(type, cstr("ret:"))) { |
532 | a->storage); | 555 | eprintln( |
533 | node->var_name->type = type; | 556 | "%s:%d:%d: error: can't bind `nil` to variable " |
557 | "'%s'", | ||
558 | a->file_name, node->line, node->col, symbol); | ||
559 | a->err = true; | ||
560 | return cstr(""); | ||
534 | } | 561 | } |
562 | symmap_insert(&scope->symbols, symbol, | ||
563 | (Symbol){.name = type, .kind = SYM_VAR}, a->storage); | ||
564 | node->var.name->type = type; | ||
535 | symbol = str_concat(cstr("."), symbol, a->storage); | 565 | symbol = str_concat(cstr("."), symbol, a->storage); |
536 | symbol = str_concat(symbol, str_from_int(scope->id, a->storage), | 566 | symbol = str_concat(symbol, str_from_int(scope->id, a->storage), |
537 | a->storage); | 567 | a->storage); |
@@ -539,8 +569,10 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
539 | return node->type; | 569 | return node->type; |
540 | } break; | 570 | } break; |
541 | case NODE_SET: { | 571 | case NODE_SET: { |
542 | Str name = type_inference(a, node->var_name, scope); | 572 | node->var.name->parent = node; |
543 | Str val = type_inference(a, node->var_val, scope); | 573 | node->var.val->parent = node; |
574 | Str name = type_inference(a, node->var.name, scope); | ||
575 | Str val = type_inference(a, node->var.val, scope); | ||
544 | if (!str_eq(name, val)) { | 576 | if (!str_eq(name, val)) { |
545 | eprintln( | 577 | eprintln( |
546 | "%s:%d:%d: error: type mismatch, trying to assing " | 578 | "%s:%d:%d: error: type mismatch, trying to assing " |
@@ -550,6 +582,12 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
550 | a->err = true; | 582 | a->err = true; |
551 | return cstr(""); | 583 | return cstr(""); |
552 | } | 584 | } |
585 | Str symbol = node->var.name->value.str; | ||
586 | FindSymbolResult sym = find_symbol(scope, symbol); | ||
587 | node->unique_name = str_concat(cstr("."), symbol, a->storage); | ||
588 | node->unique_name = | ||
589 | str_concat(node->unique_name, | ||
590 | str_from_int(sym.scope->id, a->storage), a->storage); | ||
553 | node->type = cstr("nil"); | 591 | node->type = cstr("nil"); |
554 | return node->type; | 592 | return node->type; |
555 | } break; | 593 | } break; |
@@ -568,6 +606,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
568 | a->storage); | 606 | a->storage); |
569 | for (sz i = 0; i < array_size(node->struct_field); i++) { | 607 | for (sz i = 0; i < array_size(node->struct_field); i++) { |
570 | Node *field = node->struct_field[i]; | 608 | Node *field = node->struct_field[i]; |
609 | field->parent = node; | ||
571 | typecheck_field(a, field, scope, symbol); | 610 | typecheck_field(a, field, scope, symbol); |
572 | } | 611 | } |
573 | symmap_insert(&scope->symbols, symbol, | 612 | symmap_insert(&scope->symbols, symbol, |
@@ -589,11 +628,12 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
589 | enummap_insert(&scope->enums, symbol, | 628 | enummap_insert(&scope->enums, symbol, |
590 | (Enum){ | 629 | (Enum){ |
591 | .name = symbol, | 630 | .name = symbol, |
592 | .val = node->field_val, | 631 | .val = node->field.val, |
593 | }, | 632 | }, |
594 | a->storage); | 633 | a->storage); |
595 | for (sz i = 0; i < array_size(node->struct_field); i++) { | 634 | for (sz i = 0; i < array_size(node->struct_field); i++) { |
596 | Node *field = node->struct_field[i]; | 635 | Node *field = node->struct_field[i]; |
636 | field->parent = node; | ||
597 | Str field_name = str_concat(symbol, cstr("."), a->storage); | 637 | Str field_name = str_concat(symbol, cstr("."), a->storage); |
598 | field_name = | 638 | field_name = |
599 | str_concat(field_name, field->value.str, a->storage); | 639 | str_concat(field_name, field->value.str, a->storage); |
@@ -602,8 +642,8 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
602 | a->file_name, field->line, field->col, field_name); | 642 | a->file_name, field->line, field->col, field_name); |
603 | a->err = true; | 643 | a->err = true; |
604 | } | 644 | } |
605 | if (field->field_val) { | 645 | if (field->field.val) { |
606 | Str type = type_inference(a, field->field_val, scope); | 646 | Str type = type_inference(a, field->field.val, scope); |
607 | if (!str_eq(type, cstr("int"))) { | 647 | if (!str_eq(type, cstr("int"))) { |
608 | eprintln( | 648 | eprintln( |
609 | "%s:%d:%d: error: non int enum value for '%s.%s'", | 649 | "%s:%d:%d: error: non int enum value for '%s.%s'", |
@@ -626,26 +666,34 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
626 | return node->type; | 666 | return node->type; |
627 | } break; | 667 | } break; |
628 | case NODE_IF: { | 668 | case NODE_IF: { |
629 | Str cond_type = type_inference(a, node->cond_if, scope); | 669 | node->ifelse.cond->parent = node; |
670 | node->ifelse.expr_true->parent = node; | ||
671 | Str cond_type = type_inference(a, node->ifelse.cond, scope); | ||
630 | if (!str_eq(cond_type, cstr("bool"))) { | 672 | if (!str_eq(cond_type, cstr("bool"))) { |
631 | emit_semantic_error( | 673 | emit_semantic_error( |
632 | a, node->cond_if, | 674 | a, node->ifelse.cond, |
633 | cstr("non boolean expression on if condition")); | 675 | cstr("non boolean expression on if condition")); |
634 | return cstr(""); | 676 | return cstr(""); |
635 | } | 677 | } |
636 | if (node->cond_expr->kind == NODE_BLOCK) { | 678 | if (node->ifelse.expr_true->kind == NODE_BLOCK) { |
637 | node->type = type_inference(a, node->cond_expr, scope); | 679 | node->type = type_inference(a, node->ifelse.expr_true, scope); |
638 | } else { | 680 | } else { |
639 | Scope *next = typescope_alloc(a, scope); | 681 | Scope *next = typescope_alloc(a, scope); |
640 | node->type = type_inference(a, node->cond_expr, next); | 682 | node->type = type_inference(a, node->ifelse.expr_true, next); |
641 | } | 683 | } |
642 | if (node->cond_else) { | 684 | if (str_has_prefix(node->type, cstr("ret:")) || |
685 | str_has_prefix(node->type, cstr("flow:"))) { | ||
686 | node->type = cstr("nil"); | ||
687 | } | ||
688 | if (node->ifelse.expr_else) { | ||
689 | node->ifelse.expr_else->parent = node; | ||
643 | Str else_type; | 690 | Str else_type; |
644 | if (node->cond_else->kind == NODE_BLOCK) { | 691 | if (node->ifelse.expr_else->kind == NODE_BLOCK) { |
645 | else_type = type_inference(a, node->cond_else, scope); | 692 | else_type = |
693 | type_inference(a, node->ifelse.expr_else, scope); | ||
646 | } else { | 694 | } else { |
647 | Scope *next = typescope_alloc(a, scope); | 695 | Scope *next = typescope_alloc(a, scope); |
648 | else_type = type_inference(a, node->cond_else, next); | 696 | else_type = type_inference(a, node->ifelse.expr_else, next); |
649 | } | 697 | } |
650 | if (!str_eq(node->type, else_type)) { | 698 | if (!str_eq(node->type, else_type)) { |
651 | emit_semantic_error( | 699 | emit_semantic_error( |
@@ -653,27 +701,41 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
653 | return cstr(""); | 701 | return cstr(""); |
654 | } | 702 | } |
655 | } | 703 | } |
704 | |||
705 | // If it returns a value, verify it contains an `else` statement. | ||
706 | if (!str_eq(node->type, cstr("nil"))) { | ||
707 | if (!node->ifelse.expr_else) { | ||
708 | emit_semantic_error( | ||
709 | a, node, | ||
710 | cstr("missing else statement in if expression")); | ||
711 | return cstr(""); | ||
712 | } | ||
713 | } | ||
656 | return node->type; | 714 | return node->type; |
657 | } break; | 715 | } break; |
658 | case NODE_WHILE: { | 716 | case NODE_WHILE: { |
659 | Str cond_type = type_inference(a, node->while_cond, scope); | 717 | node->loop.cond->parent = node; |
718 | node->loop.expr->parent = node; | ||
719 | Str cond_type = type_inference(a, node->loop.cond, scope); | ||
660 | if (!str_eq(cond_type, cstr("bool"))) { | 720 | if (!str_eq(cond_type, cstr("bool"))) { |
661 | emit_semantic_error( | 721 | emit_semantic_error( |
662 | a, node->cond_if, | 722 | a, node->loop.cond, |
663 | cstr("non boolean expression on while condition")); | 723 | cstr("non boolean expression on while condition")); |
664 | return cstr(""); | 724 | return cstr(""); |
665 | } | 725 | } |
666 | if (node->while_expr->kind != NODE_BLOCK) { | 726 | if (node->loop.expr->kind != NODE_BLOCK) { |
667 | scope = typescope_alloc(a, scope); | 727 | scope = typescope_alloc(a, scope); |
668 | } | 728 | } |
669 | type_inference(a, node->while_expr, scope); | 729 | type_inference(a, node->loop.expr, scope); |
670 | node->type = cstr("nil"); | 730 | node->type = cstr("nil"); |
671 | return node->type; | 731 | return node->type; |
672 | } break; | 732 | } break; |
673 | case NODE_COND: { | 733 | case NODE_COND: { |
674 | Str previous = cstr(""); | 734 | Str previous = cstr(""); |
675 | for (sz i = 0; i < array_size(node->match_cases); i++) { | 735 | bool has_else = false; |
676 | Node *expr = node->match_cases[i]; | 736 | for (sz i = 0; i < array_size(node->match.cases); i++) { |
737 | Node *expr = node->match.cases[i]; | ||
738 | expr->parent = node; | ||
677 | Str next = type_inference(a, expr, scope); | 739 | Str next = type_inference(a, expr, scope); |
678 | if (i != 0 && !str_eq(next, previous)) { | 740 | if (i != 0 && !str_eq(next, previous)) { |
679 | emit_semantic_error( | 741 | emit_semantic_error( |
@@ -681,22 +743,38 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
681 | cstr("non-matching types for cond expressions")); | 743 | cstr("non-matching types for cond expressions")); |
682 | return cstr(""); | 744 | return cstr(""); |
683 | } | 745 | } |
746 | if (!expr->case_entry.cond) { | ||
747 | has_else = true; | ||
748 | } | ||
684 | previous = next; | 749 | previous = next; |
685 | } | 750 | } |
751 | // If it returns a value, verify it contains an `else` statement. | ||
752 | if (!str_eq(node->type, cstr("nil")) && | ||
753 | !str_has_prefix(node->type, cstr("ret:")) && | ||
754 | !str_has_prefix(node->type, cstr("flow:"))) { | ||
755 | if (!has_else) { | ||
756 | emit_semantic_error( | ||
757 | a, node, | ||
758 | cstr("missing else statement in cond expression")); | ||
759 | return cstr(""); | ||
760 | } | ||
761 | } | ||
686 | node->type = previous; | 762 | node->type = previous; |
687 | return node->type; | 763 | return node->type; |
688 | } break; | 764 | } break; |
689 | case NODE_MATCH: { | 765 | case NODE_MATCH: { |
690 | Str e = type_inference(a, node->match_expr, scope); | 766 | node->match.expr->parent = node; |
767 | Str e = type_inference(a, node->match.expr, scope); | ||
691 | if (str_eq(e, cstr("int"))) { | 768 | if (str_eq(e, cstr("int"))) { |
692 | // Integer matching. | 769 | // Integer matching. |
693 | for (sz i = 0; i < array_size(node->match_cases); i++) { | 770 | for (sz i = 0; i < array_size(node->match.cases); i++) { |
694 | Node *field = node->match_cases[i]; | 771 | Node *field = node->match.cases[i]; |
695 | if (field->case_value) { | 772 | field->parent = node; |
696 | if (field->case_value->kind != NODE_NUM_INT && | 773 | if (field->case_entry.cond) { |
697 | field->case_value->kind != NODE_NUM_UINT) { | 774 | if (field->case_entry.cond->kind != NODE_NUM_INT && |
775 | field->case_entry.cond->kind != NODE_NUM_UINT) { | ||
698 | emit_semantic_error( | 776 | emit_semantic_error( |
699 | a, field->case_value, | 777 | a, field->case_entry.cond, |
700 | cstr( | 778 | cstr( |
701 | "non-integer or enum types on match case")); | 779 | "non-integer or enum types on match case")); |
702 | } | 780 | } |
@@ -707,24 +785,26 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
707 | FindEnumResult res = find_enum(scope, e); | 785 | FindEnumResult res = find_enum(scope, e); |
708 | Str enum_prefix = | 786 | Str enum_prefix = |
709 | str_concat(res.map->val.name, cstr("."), a->storage); | 787 | str_concat(res.map->val.name, cstr("."), a->storage); |
710 | for (sz i = 0; i < array_size(node->match_cases); i++) { | 788 | for (sz i = 0; i < array_size(node->match.cases); i++) { |
711 | Node *field = node->match_cases[i]; | 789 | Node *field = node->match.cases[i]; |
712 | if (field->case_value) { | 790 | field->parent = node; |
791 | if (field->case_entry.cond) { | ||
713 | Str field_name = str_concat( | 792 | Str field_name = str_concat( |
714 | enum_prefix, field->case_value->value.str, | 793 | enum_prefix, field->case_entry.cond->value.str, |
715 | a->storage); | 794 | a->storage); |
716 | if (!enummap_lookup(&res.scope->enums, field_name)) { | 795 | if (!enummap_lookup(&res.scope->enums, field_name)) { |
717 | eprintln("%s:%d:%d: error: unknown enum field '%s'", | 796 | eprintln("%s:%d:%d: error: unknown enum field '%s'", |
718 | a->file_name, field->case_value->line, | 797 | a->file_name, field->case_entry.cond->line, |
719 | field->case_value->col, field_name); | 798 | field->case_entry.cond->col, field_name); |
720 | a->err = true; | 799 | a->err = true; |
721 | } | 800 | } |
722 | } | 801 | } |
723 | } | 802 | } |
724 | } | 803 | } |
725 | Str previous = cstr(""); | 804 | Str previous = cstr(""); |
726 | for (sz i = 0; i < array_size(node->match_cases); i++) { | 805 | for (sz i = 0; i < array_size(node->match.cases); i++) { |
727 | Node *expr = node->match_cases[i]; | 806 | Node *expr = node->match.cases[i]; |
807 | expr->parent = node; | ||
728 | Str next = type_inference(a, expr, scope); | 808 | Str next = type_inference(a, expr, scope); |
729 | if (i != 0 && !str_eq(next, previous)) { | 809 | if (i != 0 && !str_eq(next, previous)) { |
730 | emit_semantic_error( | 810 | emit_semantic_error( |
@@ -738,24 +818,27 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
738 | return node->type; | 818 | return node->type; |
739 | } break; | 819 | } break; |
740 | case NODE_CASE_MATCH: { | 820 | case NODE_CASE_MATCH: { |
741 | if (node->case_expr->kind != NODE_BLOCK) { | 821 | if (node->case_entry.expr->kind != NODE_BLOCK) { |
742 | scope = typescope_alloc(a, scope); | 822 | scope = typescope_alloc(a, scope); |
743 | } | 823 | } |
744 | node->type = type_inference(a, node->case_expr, scope); | 824 | node->case_entry.expr->parent = node; |
825 | node->type = type_inference(a, node->case_entry.expr, scope); | ||
745 | return node->type; | 826 | return node->type; |
746 | } break; | 827 | } break; |
747 | case NODE_CASE_COND: { | 828 | case NODE_CASE_COND: { |
748 | if (node->case_value) { | 829 | node->case_entry.expr->parent = node; |
749 | Str cond = type_inference(a, node->case_value, scope); | 830 | if (node->case_entry.cond) { |
831 | node->case_entry.cond->parent = node; | ||
832 | Str cond = type_inference(a, node->case_entry.cond, scope); | ||
750 | if (!str_eq(cond, cstr("bool"))) { | 833 | if (!str_eq(cond, cstr("bool"))) { |
751 | emit_semantic_error(a, node, | 834 | emit_semantic_error(a, node, |
752 | cstr("non-boolean case condition")); | 835 | cstr("non-boolean case condition")); |
753 | } | 836 | } |
754 | } | 837 | } |
755 | if (node->case_expr->kind != NODE_BLOCK) { | 838 | if (node->case_entry.expr->kind != NODE_BLOCK) { |
756 | scope = typescope_alloc(a, scope); | 839 | scope = typescope_alloc(a, scope); |
757 | } | 840 | } |
758 | node->type = type_inference(a, node->case_expr, scope); | 841 | node->type = type_inference(a, node->case_entry.expr, scope); |
759 | return node->type; | 842 | return node->type; |
760 | } break; | 843 | } break; |
761 | case NODE_TRUE: | 844 | case NODE_TRUE: |
@@ -770,14 +853,16 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
770 | case NODE_NOT: | 853 | case NODE_NOT: |
771 | case NODE_AND: | 854 | case NODE_AND: |
772 | case NODE_OR: { | 855 | case NODE_OR: { |
773 | Str left = type_inference(a, node->left, scope); | 856 | node->binary.left->parent = node; |
857 | Str left = type_inference(a, node->binary.left, scope); | ||
774 | if (!str_eq(left, cstr("bool"))) { | 858 | if (!str_eq(left, cstr("bool"))) { |
775 | emit_semantic_error(a, node, | 859 | emit_semantic_error(a, node, |
776 | cstr("expected bool on logic expression")); | 860 | cstr("expected bool on logic expression")); |
777 | return cstr(""); | 861 | return cstr(""); |
778 | } | 862 | } |
779 | if (node->right) { | 863 | if (node->binary.right) { |
780 | Str right = type_inference(a, node->right, scope); | 864 | node->binary.right->parent = node; |
865 | Str right = type_inference(a, node->binary.right, scope); | ||
781 | if (!str_eq(right, cstr("bool"))) { | 866 | if (!str_eq(right, cstr("bool"))) { |
782 | emit_semantic_error( | 867 | emit_semantic_error( |
783 | a, node, cstr("expected bool on logic expression")); | 868 | a, node, cstr("expected bool on logic expression")); |
@@ -793,8 +878,10 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
793 | case NODE_GT: | 878 | case NODE_GT: |
794 | case NODE_LE: | 879 | case NODE_LE: |
795 | case NODE_GE: { | 880 | case NODE_GE: { |
796 | Str left = type_inference(a, node->left, scope); | 881 | node->binary.left->parent = node; |
797 | Str right = type_inference(a, node->right, scope); | 882 | node->binary.right->parent = node; |
883 | Str left = type_inference(a, node->binary.left, scope); | ||
884 | Str right = type_inference(a, node->binary.right, scope); | ||
798 | if (!str_eq(left, right)) { | 885 | if (!str_eq(left, right)) { |
799 | emit_semantic_error( | 886 | emit_semantic_error( |
800 | a, node, cstr("mismatched types on binary expression")); | 887 | a, node, cstr("mismatched types on binary expression")); |
@@ -804,7 +891,8 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
804 | return node->type; | 891 | return node->type; |
805 | } break; | 892 | } break; |
806 | case NODE_BITNOT: { | 893 | case NODE_BITNOT: { |
807 | Str left = type_inference(a, node->left, scope); | 894 | node->binary.left->parent = node; |
895 | Str left = type_inference(a, node->binary.left, scope); | ||
808 | if (!strset_lookup(&a->integer_types, left)) { | 896 | if (!strset_lookup(&a->integer_types, left)) { |
809 | emit_semantic_error( | 897 | emit_semantic_error( |
810 | a, node, cstr("non integer type on bit twiddling expr")); | 898 | a, node, cstr("non integer type on bit twiddling expr")); |
@@ -815,10 +903,13 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
815 | } break; | 903 | } break; |
816 | case NODE_BITAND: | 904 | case NODE_BITAND: |
817 | case NODE_BITOR: | 905 | case NODE_BITOR: |
906 | case NODE_BITXOR: | ||
818 | case NODE_BITLSHIFT: | 907 | case NODE_BITLSHIFT: |
819 | case NODE_BITRSHIFT: { | 908 | case NODE_BITRSHIFT: { |
820 | Str left = type_inference(a, node->left, scope); | 909 | node->binary.left->parent = node; |
821 | Str right = type_inference(a, node->right, scope); | 910 | node->binary.right->parent = node; |
911 | Str left = type_inference(a, node->binary.left, scope); | ||
912 | Str right = type_inference(a, node->binary.right, scope); | ||
822 | if (!strset_lookup(&a->integer_types, left) || | 913 | if (!strset_lookup(&a->integer_types, left) || |
823 | !strset_lookup(&a->integer_types, right)) { | 914 | !strset_lookup(&a->integer_types, right)) { |
824 | emit_semantic_error( | 915 | emit_semantic_error( |
@@ -833,8 +924,10 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
833 | case NODE_DIV: | 924 | case NODE_DIV: |
834 | case NODE_MUL: | 925 | case NODE_MUL: |
835 | case NODE_MOD: { | 926 | case NODE_MOD: { |
836 | Str left = type_inference(a, node->left, scope); | 927 | node->binary.left->parent = node; |
837 | Str right = type_inference(a, node->right, scope); | 928 | node->binary.right->parent = node; |
929 | Str left = type_inference(a, node->binary.left, scope); | ||
930 | Str right = type_inference(a, node->binary.right, scope); | ||
838 | if (!strset_lookup(&a->numeric_types, left) || | 931 | if (!strset_lookup(&a->numeric_types, left) || |
839 | !strset_lookup(&a->numeric_types, right)) { | 932 | !strset_lookup(&a->numeric_types, right)) { |
840 | emit_semantic_error( | 933 | emit_semantic_error( |
@@ -850,7 +943,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
850 | return node->type; | 943 | return node->type; |
851 | } break; | 944 | } break; |
852 | case NODE_NUM_UINT: { | 945 | case NODE_NUM_UINT: { |
853 | node->type = cstr("uint"); | 946 | node->type = cstr("int"); |
854 | return node->type; | 947 | return node->type; |
855 | } break; | 948 | } break; |
856 | case NODE_NUM_INT: { | 949 | case NODE_NUM_INT: { |
@@ -887,6 +980,13 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
887 | } | 980 | } |
888 | 981 | ||
889 | FindSymbolResult sym = find_symbol(scope, symbol); | 982 | FindSymbolResult sym = find_symbol(scope, symbol); |
983 | if (!str_eq(sym.scope->name, scope->name) && sym.scope->name.size) { | ||
984 | eprintln( | ||
985 | "%s:%d:%d: error: can't capture external local symbol '%s'", | ||
986 | a->file_name, node->line, node->col, symbol); | ||
987 | a->err = true; | ||
988 | return cstr(""); | ||
989 | } | ||
890 | node->unique_name = str_concat(cstr("."), symbol, a->storage); | 990 | node->unique_name = str_concat(cstr("."), symbol, a->storage); |
891 | node->unique_name = | 991 | node->unique_name = |
892 | str_concat(node->unique_name, | 992 | str_concat(node->unique_name, |
@@ -894,7 +994,8 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
894 | 994 | ||
895 | Str type_name = type->val.name; | 995 | Str type_name = type->val.name; |
896 | if (node->kind == NODE_SYMBOL_IDX) { | 996 | if (node->kind == NODE_SYMBOL_IDX) { |
897 | Str idx_type = type_inference(a, node->arr_size, scope); | 997 | node->sym.arr_size->parent = node; |
998 | Str idx_type = type_inference(a, node->sym.arr_size, scope); | ||
898 | if (!strset_lookup(&a->integer_types, idx_type)) { | 999 | if (!strset_lookup(&a->integer_types, idx_type)) { |
899 | emit_semantic_error( | 1000 | emit_semantic_error( |
900 | a, node, cstr("can't resolve non integer index")); | 1001 | a, node, cstr("can't resolve non integer index")); |
@@ -908,7 +1009,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
908 | 1009 | ||
909 | FindEnumResult e = find_enum(scope, type_name); | 1010 | FindEnumResult e = find_enum(scope, type_name); |
910 | if (e.map && str_eq(symbol, type_name)) { | 1011 | if (e.map && str_eq(symbol, type_name)) { |
911 | if (!node->next) { | 1012 | if (!node->sym.next) { |
912 | eprintln( | 1013 | eprintln( |
913 | "%s:%d:%d: error: unspecified enum field for symbol " | 1014 | "%s:%d:%d: error: unspecified enum field for symbol " |
914 | "'%s'", | 1015 | "'%s'", |
@@ -918,20 +1019,21 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
918 | } | 1019 | } |
919 | // Check if there is a next and it matches the enum field. | 1020 | // Check if there is a next and it matches the enum field. |
920 | Str field = str_concat(type_name, cstr("."), a->storage); | 1021 | Str field = str_concat(type_name, cstr("."), a->storage); |
921 | field = str_concat(field, node->next->value.str, a->storage); | 1022 | field = |
1023 | str_concat(field, node->sym.next->value.str, a->storage); | ||
922 | if (!enummap_lookup(&e.scope->enums, field)) { | 1024 | if (!enummap_lookup(&e.scope->enums, field)) { |
923 | eprintln( | 1025 | eprintln( |
924 | "%s:%d:%d: error: unknown enum field for " | 1026 | "%s:%d:%d: error: unknown enum field for " |
925 | "'%s': %s", | 1027 | "'%s': %s", |
926 | a->file_name, node->line, node->col, symbol, | 1028 | a->file_name, node->line, node->col, symbol, |
927 | node->next->value.str); | 1029 | node->sym.next->value.str); |
928 | a->err = true; | 1030 | a->err = true; |
929 | return cstr(""); | 1031 | return cstr(""); |
930 | } | 1032 | } |
931 | 1033 | ||
932 | node->next->type = type_name; | 1034 | node->sym.next->type = type_name; |
933 | node->type = type_name; | 1035 | node->type = type_name; |
934 | return node->next->type; | 1036 | return node->sym.next->type; |
935 | } | 1037 | } |
936 | 1038 | ||
937 | FindStructResult s = find_struct(scope, type_name); | 1039 | FindStructResult s = find_struct(scope, type_name); |
@@ -944,11 +1046,11 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
944 | a->err = true; | 1046 | a->err = true; |
945 | return cstr(""); | 1047 | return cstr(""); |
946 | } else { | 1048 | } else { |
947 | if (node->next) { | 1049 | if (node->sym.next) { |
948 | Str chain = type_name; | 1050 | Str chain = type_name; |
949 | Node *next = node; | 1051 | Node *next = node; |
950 | while (next->next) { | 1052 | while (next->sym.next) { |
951 | next = next->next; | 1053 | next = next->sym.next; |
952 | chain = str_concat(chain, cstr("."), a->storage); | 1054 | chain = str_concat(chain, cstr("."), a->storage); |
953 | chain = | 1055 | chain = |
954 | str_concat(chain, next->value.str, a->storage); | 1056 | str_concat(chain, next->value.str, a->storage); |
@@ -964,8 +1066,9 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
964 | } | 1066 | } |
965 | Str field_type = field->val.type; | 1067 | Str field_type = field->val.type; |
966 | if (next->kind == NODE_SYMBOL_IDX) { | 1068 | if (next->kind == NODE_SYMBOL_IDX) { |
1069 | node->sym.arr_size->parent = node; | ||
967 | Str idx_type = | 1070 | Str idx_type = |
968 | type_inference(a, next->arr_size, scope); | 1071 | type_inference(a, next->sym.arr_size, scope); |
969 | if (!strset_lookup(&a->integer_types, idx_type)) { | 1072 | if (!strset_lookup(&a->integer_types, idx_type)) { |
970 | emit_semantic_error( | 1073 | emit_semantic_error( |
971 | a, next, | 1074 | a, next, |
@@ -996,6 +1099,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
996 | StrSet *set = NULL; | 1099 | StrSet *set = NULL; |
997 | for (sz i = 0; i < array_size(node->elements); i++) { | 1100 | for (sz i = 0; i < array_size(node->elements); i++) { |
998 | Node *next = node->elements[i]; | 1101 | Node *next = node->elements[i]; |
1102 | next->parent = node; | ||
999 | Str field_name = str_concat(name, cstr("."), a->storage); | 1103 | Str field_name = str_concat(name, cstr("."), a->storage); |
1000 | field_name = | 1104 | field_name = |
1001 | str_concat(field_name, next->value.str, a->storage); | 1105 | str_concat(field_name, next->value.str, a->storage); |
@@ -1025,10 +1129,17 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
1025 | a->err = true; | 1129 | a->err = true; |
1026 | return cstr(""); | 1130 | return cstr(""); |
1027 | } | 1131 | } |
1132 | FindSymbolResult sym = find_symbol(scope, symbol); | ||
1133 | node->unique_name = str_concat(cstr("."), symbol, a->storage); | ||
1134 | node->unique_name = | ||
1135 | str_concat(node->unique_name, | ||
1136 | str_from_int(sym.scope->id, a->storage), a->storage); | ||
1137 | |||
1028 | // Check that actual parameters typecheck | 1138 | // Check that actual parameters typecheck |
1029 | Str args = cstr(""); | 1139 | Str args = cstr(""); |
1030 | for (sz i = 0; i < array_size(node->elements); i++) { | 1140 | for (sz i = 0; i < array_size(node->elements); i++) { |
1031 | Node *expr = node->elements[i]; | 1141 | Node *expr = node->elements[i]; |
1142 | expr->parent = node; | ||
1032 | Str type = type_inference(a, expr, scope); | 1143 | Str type = type_inference(a, expr, scope); |
1033 | args = str_concat(args, type, a->storage); | 1144 | args = str_concat(args, type, a->storage); |
1034 | if (i != array_size(node->elements) - 1) { | 1145 | if (i != array_size(node->elements) - 1) { |
@@ -1054,15 +1165,27 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
1054 | Str type; | 1165 | Str type; |
1055 | for (sz i = 0; i < array_size(node->elements); i++) { | 1166 | for (sz i = 0; i < array_size(node->elements); i++) { |
1056 | Node *expr = node->elements[i]; | 1167 | Node *expr = node->elements[i]; |
1168 | expr->parent = node; | ||
1057 | type = type_inference(a, expr, scope); | 1169 | type = type_inference(a, expr, scope); |
1170 | if (str_has_prefix(type, cstr("ret:")) || | ||
1171 | str_has_prefix(type, cstr("flow:"))) { | ||
1172 | break; | ||
1173 | } | ||
1058 | } | 1174 | } |
1059 | node->type = type; | 1175 | node->type = type; |
1060 | return node->type; | 1176 | return node->type; |
1061 | } break; | 1177 | } break; |
1062 | case NODE_RETURN: { | 1178 | case NODE_RETURN: { |
1063 | Str ret_type = cstr(""); | 1179 | if (!scope->name.size) { |
1180 | emit_semantic_error( | ||
1181 | a, node, cstr("return statement outside a function")); | ||
1182 | a->err = true; | ||
1183 | return cstr(""); | ||
1184 | } | ||
1185 | Str ret_type = cstr("ret:"); | ||
1064 | for (sz i = 0; i < array_size(node->elements); i++) { | 1186 | for (sz i = 0; i < array_size(node->elements); i++) { |
1065 | Node *expr = node->elements[i]; | 1187 | Node *expr = node->elements[i]; |
1188 | expr->parent = node; | ||
1066 | Str type = type_inference(a, expr, scope); | 1189 | Str type = type_inference(a, expr, scope); |
1067 | ret_type = str_concat(ret_type, type, a->storage); | 1190 | ret_type = str_concat(ret_type, type, a->storage); |
1068 | if (i != array_size(node->elements) - 1) { | 1191 | if (i != array_size(node->elements) - 1) { |
@@ -1075,40 +1198,68 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
1075 | node->type = ret_type; | 1198 | node->type = ret_type; |
1076 | return node->type; | 1199 | return node->type; |
1077 | } break; | 1200 | } break; |
1201 | case NODE_CONTINUE: | ||
1202 | case NODE_BREAK: { | ||
1203 | // Check if we are inside a loop. | ||
1204 | Node *parent = node->parent; | ||
1205 | bool inside_loop = false; | ||
1206 | while (parent != NULL) { | ||
1207 | if (parent->kind == NODE_WHILE) { | ||
1208 | inside_loop = true; | ||
1209 | break; | ||
1210 | } | ||
1211 | parent = parent->parent; | ||
1212 | } | ||
1213 | if (!inside_loop) { | ||
1214 | eprintln( | ||
1215 | "%s:%d:%d: error: control flow statement outside a loop", | ||
1216 | a->file_name, node->line, node->col); | ||
1217 | a->err = true; | ||
1218 | return cstr(""); | ||
1219 | } | ||
1220 | node->type = cstr("flow:"); | ||
1221 | return node->type; | ||
1222 | } break; | ||
1078 | case NODE_FUN: { | 1223 | case NODE_FUN: { |
1079 | node->type = cstr("nil"); | 1224 | node->type = cstr("nil"); |
1080 | Scope *prev_scope = scope; | 1225 | Scope *prev_scope = scope; |
1081 | scope = typescope_alloc(a, scope); | 1226 | scope = typescope_alloc(a, scope); |
1082 | Str param_type = cstr(""); | 1227 | Str param_type = cstr(""); |
1083 | for (sz i = 0; i < array_size(node->func_params); i++) { | 1228 | for (sz i = 0; i < array_size(node->func.params); i++) { |
1084 | Node *param = node->func_params[i]; | 1229 | Node *param = node->func.params[i]; |
1085 | Str symbol = param->param_name->value.str; | 1230 | param->parent = node; |
1086 | Str type = param->param_type->value.str; | 1231 | Str symbol = param->param.name->value.str; |
1087 | if (param->param_type->is_ptr) { | 1232 | Str type = param->param.type->value.str; |
1233 | if (param->param.type->is_ptr) { | ||
1088 | type = str_concat(cstr("@"), type, a->storage); | 1234 | type = str_concat(cstr("@"), type, a->storage); |
1089 | } | 1235 | } |
1090 | if (param->param_type->kind == NODE_ARR_TYPE) { | 1236 | if (param->param.type->kind == NODE_ARR_TYPE) { |
1091 | type = str_concat(cstr("@"), type, a->storage); | 1237 | type = str_concat(cstr("@"), type, a->storage); |
1092 | } | 1238 | } |
1093 | param->param_name->type = | 1239 | param->param.name->type = |
1094 | type_inference(a, param->param_type, scope); | 1240 | type_inference(a, param->param.type, scope); |
1095 | param->type = type; | 1241 | param->type = type; |
1096 | symmap_insert(&scope->symbols, symbol, | 1242 | symmap_insert(&scope->symbols, symbol, |
1097 | (Symbol){.name = type, .kind = SYM_PARAM}, | 1243 | (Symbol){.name = type, .kind = SYM_PARAM}, |
1098 | a->storage); | 1244 | a->storage); |
1099 | param_type = str_concat(param_type, type, a->storage); | 1245 | param_type = str_concat(param_type, type, a->storage); |
1100 | if (i != array_size(node->func_params) - 1) { | 1246 | if (i != array_size(node->func.params) - 1) { |
1101 | param_type = str_concat(param_type, cstr(","), a->storage); | 1247 | param_type = str_concat(param_type, cstr(","), a->storage); |
1102 | } | 1248 | } |
1249 | symbol = str_concat(cstr("."), symbol, a->storage); | ||
1250 | symbol = str_concat(symbol, str_from_int(scope->id, a->storage), | ||
1251 | a->storage); | ||
1252 | param->unique_name = symbol; | ||
1103 | } | 1253 | } |
1104 | if (!param_type.size) { | 1254 | if (!param_type.size) { |
1105 | param_type = cstr("nil"); | 1255 | param_type = cstr("nil"); |
1106 | } | 1256 | } |
1107 | node->fun_params = param_type; | 1257 | node->type_params = param_type; |
1108 | 1258 | ||
1109 | Str ret_type = cstr(""); | 1259 | Str ret_type = cstr(""); |
1110 | for (sz i = 0; i < array_size(node->func_ret); i++) { | 1260 | for (sz i = 0; i < array_size(node->func.ret); i++) { |
1111 | Node *expr = node->func_ret[i]; | 1261 | Node *expr = node->func.ret[i]; |
1262 | expr->parent = node; | ||
1112 | Str type = type_inference(a, expr, scope); | 1263 | Str type = type_inference(a, expr, scope); |
1113 | if (expr->is_ptr) { | 1264 | if (expr->is_ptr) { |
1114 | type = str_concat(cstr("@"), type, a->storage); | 1265 | type = str_concat(cstr("@"), type, a->storage); |
@@ -1117,28 +1268,28 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
1117 | type = str_concat(cstr("@"), type, a->storage); | 1268 | type = str_concat(cstr("@"), type, a->storage); |
1118 | } | 1269 | } |
1119 | ret_type = str_concat(ret_type, type, a->storage); | 1270 | ret_type = str_concat(ret_type, type, a->storage); |
1120 | if (i != array_size(node->func_ret) - 1) { | 1271 | if (i != array_size(node->func.ret) - 1) { |
1121 | ret_type = str_concat(ret_type, cstr(","), a->storage); | 1272 | ret_type = str_concat(ret_type, cstr(","), a->storage); |
1122 | } | 1273 | } |
1123 | } | 1274 | } |
1124 | if (!ret_type.size) { | 1275 | if (!ret_type.size) { |
1125 | ret_type = cstr("nil"); | 1276 | ret_type = cstr("nil"); |
1126 | } | 1277 | } |
1127 | node->fun_return = ret_type; | 1278 | node->type_returns = ret_type; |
1128 | 1279 | ||
1129 | Str symbol = node->func_name->value.str; | 1280 | Str symbol = node->func.name->value.str; |
1130 | if (prev_scope->parent != NULL) { | 1281 | if (prev_scope->parent != NULL) { |
1131 | if (symmap_lookup(&prev_scope->symbols, symbol)) { | 1282 | if (symmap_lookup(&prev_scope->symbols, symbol)) { |
1132 | eprintln( | 1283 | eprintln( |
1133 | "%s:%d:%d: error: function '%s' already defined in " | 1284 | "%s:%d:%d: error: function '%s' already defined in " |
1134 | "current " | 1285 | "current " |
1135 | "scope ", | 1286 | "scope ", |
1136 | a->file_name, node->var_name->line, node->var_name->col, | 1287 | a->file_name, node->var.name->line, node->var.name->col, |
1137 | symbol); | 1288 | symbol); |
1138 | a->err = true; | 1289 | a->err = true; |
1139 | return cstr(""); | 1290 | return cstr(""); |
1140 | } | 1291 | } |
1141 | symmap_insert(&scope->symbols, symbol, | 1292 | symmap_insert(&prev_scope->symbols, symbol, |
1142 | (Symbol){.name = symbol, .kind = SYM_FUN}, | 1293 | (Symbol){.name = symbol, .kind = SYM_FUN}, |
1143 | a->storage); | 1294 | a->storage); |
1144 | } | 1295 | } |
@@ -1148,41 +1299,50 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
1148 | .param_type = param_type, | 1299 | .param_type = param_type, |
1149 | .return_type = ret_type}, | 1300 | .return_type = ret_type}, |
1150 | a->storage); | 1301 | a->storage); |
1302 | symbol = str_concat(cstr("."), symbol, a->storage); | ||
1303 | symbol = str_concat( | ||
1304 | symbol, str_from_int(prev_scope->id, a->storage), a->storage); | ||
1305 | node->unique_name = symbol; | ||
1151 | 1306 | ||
1152 | if (node->func_body->kind == NODE_BLOCK) { | 1307 | if (node->func.body->kind == NODE_BLOCK) { |
1153 | Str type; | 1308 | Str type; |
1154 | for (sz i = 0; i < array_size(node->func_body->elements); i++) { | 1309 | for (sz i = 0; i < array_size(node->func.body->elements); i++) { |
1155 | Node *expr = node->func_body->elements[i]; | 1310 | Node *expr = node->func.body->elements[i]; |
1311 | expr->parent = node; | ||
1312 | // TODO: block early return. | ||
1156 | type = type_inference(a, expr, scope); | 1313 | type = type_inference(a, expr, scope); |
1157 | } | 1314 | } |
1158 | if (!type.size) { | 1315 | if (!type.size) { |
1159 | type = cstr("nil"); | 1316 | type = cstr("nil"); |
1160 | } | 1317 | } |
1161 | node->func_body->type = type; | 1318 | node->func.body->type = type; |
1162 | } else { | 1319 | } else { |
1163 | type_inference(a, node->func_body, scope); | 1320 | node->func.body->parent = node; |
1321 | type_inference(a, node->func.body, scope); | ||
1164 | } | 1322 | } |
1165 | 1323 | ||
1166 | // Ensure main body return matches the prototype. | 1324 | // Ensure main body return matches the prototype. |
1167 | if (!str_eq(node->func_body->type, ret_type)) { | 1325 | Str type = str_remove_prefix(node->func.body->type, cstr("ret:")); |
1326 | node->func.body->type = type; | ||
1327 | if (!str_eq(type, ret_type)) { | ||
1168 | eprintln( | 1328 | eprintln( |
1169 | "%s:%d:%d: error: mismatched return type %s, expected %s", | 1329 | "%s:%d:%d: error: mismatched return type %s, expected %s", |
1170 | a->file_name, node->line, node->col, node->func_body->type, | 1330 | a->file_name, node->line, node->col, type, ret_type); |
1171 | ret_type); | ||
1172 | a->err = true; | 1331 | a->err = true; |
1173 | } | 1332 | } |
1174 | 1333 | ||
1175 | // Ensure ALL return statements match the function prototype. | 1334 | // Ensure ALL return statements match the function prototype. |
1176 | typecheck_returns(a, node->func_body, ret_type); | 1335 | typecheck_returns(a, node->func.body, ret_type); |
1177 | 1336 | ||
1178 | // TODO: should return statements be allowed on let blocks? | 1337 | // TODO: should return statements be allowed on let blocks? |
1179 | return node->type; | 1338 | return node->type; |
1180 | } break; | 1339 | } break; |
1181 | default: { | 1340 | default: { |
1182 | emit_semantic_error(a, node, | 1341 | eprintln( |
1183 | cstr("type inference not implemented for this " | 1342 | "%s:%d:%d: error: type inference not implemented for node " |
1184 | "kind of expression")); | 1343 | "type: %s", |
1185 | println("KIND: %s", node_str[node->kind]); | 1344 | a->file_name, node->line, node->col, node_str[node->kind]); |
1345 | a->err = true; | ||
1186 | } break; | 1346 | } break; |
1187 | } | 1347 | } |
1188 | return cstr(""); | 1348 | return cstr(""); |
@@ -1243,16 +1403,59 @@ symbolic_analysis(Analyzer *a, Parser *parser) { | |||
1243 | for (sz i = 0; i < array_size(parser->nodes); i++) { | 1403 | for (sz i = 0; i < array_size(parser->nodes); i++) { |
1244 | Node *root = parser->nodes[i]; | 1404 | Node *root = parser->nodes[i]; |
1245 | if (root->kind == NODE_FUN) { | 1405 | if (root->kind == NODE_FUN) { |
1246 | Str symbol = root->func_name->value.str; | 1406 | Str symbol = root->func.name->value.str; |
1247 | if (symmap_lookup(&scope->symbols, symbol)) { | 1407 | if (symmap_lookup(&scope->symbols, symbol)) { |
1248 | eprintln( | 1408 | eprintln( |
1249 | "%s:%d:%d: error: function '%s' already defined in " | 1409 | "%s:%d:%d: error: function '%s' already defined in " |
1250 | "current " | 1410 | "current " |
1251 | "scope ", | 1411 | "scope ", |
1252 | a->file_name, root->var_name->line, root->var_name->col, | 1412 | a->file_name, root->var.name->line, root->var.name->col, |
1253 | symbol); | 1413 | symbol); |
1254 | a->err = true; | 1414 | a->err = true; |
1255 | } | 1415 | } |
1416 | Str param_type = cstr(""); | ||
1417 | for (sz i = 0; i < array_size(root->func.params); i++) { | ||
1418 | Node *param = root->func.params[i]; | ||
1419 | Str type = param->param.type->value.str; | ||
1420 | if (param->param.type->is_ptr) { | ||
1421 | type = str_concat(cstr("@"), type, a->storage); | ||
1422 | } | ||
1423 | if (param->param.type->kind == NODE_ARR_TYPE) { | ||
1424 | type = str_concat(cstr("@"), type, a->storage); | ||
1425 | } | ||
1426 | param_type = str_concat(param_type, type, a->storage); | ||
1427 | if (i != array_size(root->func.params) - 1) { | ||
1428 | param_type = str_concat(param_type, cstr(","), a->storage); | ||
1429 | } | ||
1430 | } | ||
1431 | if (!param_type.size) { | ||
1432 | param_type = cstr("nil"); | ||
1433 | } | ||
1434 | root->type_params = param_type; | ||
1435 | |||
1436 | Str ret_type = cstr(""); | ||
1437 | for (sz i = 0; i < array_size(root->func.ret); i++) { | ||
1438 | Node *expr = root->func.ret[i]; | ||
1439 | Str type = expr->value.str; | ||
1440 | if (expr->is_ptr) { | ||
1441 | type = str_concat(cstr("@"), type, a->storage); | ||
1442 | } | ||
1443 | if (expr->kind == NODE_ARR_TYPE) { | ||
1444 | type = str_concat(cstr("@"), type, a->storage); | ||
1445 | } | ||
1446 | ret_type = str_concat(ret_type, type, a->storage); | ||
1447 | if (i != array_size(root->func.ret) - 1) { | ||
1448 | ret_type = str_concat(ret_type, cstr(","), a->storage); | ||
1449 | } | ||
1450 | } | ||
1451 | if (!ret_type.size) { | ||
1452 | ret_type = cstr("nil"); | ||
1453 | } | ||
1454 | funmap_insert(&scope->funcs, symbol, | ||
1455 | (Fun){.name = symbol, | ||
1456 | .param_type = param_type, | ||
1457 | .return_type = ret_type}, | ||
1458 | a->storage); | ||
1256 | symmap_insert(&scope->symbols, symbol, | 1459 | symmap_insert(&scope->symbols, symbol, |
1257 | (Symbol){.name = symbol, .kind = SYM_FUN}, | 1460 | (Symbol){.name = symbol, .kind = SYM_FUN}, |
1258 | a->storage); | 1461 | a->storage); |