diff options
Diffstat (limited to 'src/semantic.c')
-rw-r--r-- | src/semantic.c | 868 |
1 files changed, 578 insertions, 290 deletions
diff --git a/src/semantic.c b/src/semantic.c index 9b119df..2e2735f 100644 --- a/src/semantic.c +++ b/src/semantic.c | |||
@@ -39,6 +39,10 @@ typedef struct Fun { | |||
39 | Str name; | 39 | Str name; |
40 | Str param_type; | 40 | Str param_type; |
41 | Str return_type; | 41 | Str return_type; |
42 | Str *param_types; | ||
43 | Str *return_types; | ||
44 | sz param_arity; | ||
45 | sz return_arity; | ||
42 | } Fun; | 46 | } Fun; |
43 | 47 | ||
44 | typedef struct Enum { | 48 | typedef struct Enum { |
@@ -62,6 +66,7 @@ typedef struct Scope { | |||
62 | sz depth; | 66 | sz depth; |
63 | Str name; | 67 | Str name; |
64 | SymbolMap *symbols; | 68 | SymbolMap *symbols; |
69 | StrSet *types; | ||
65 | FunMap *funcs; | 70 | FunMap *funcs; |
66 | EnumMap *enums; | 71 | EnumMap *enums; |
67 | StructMap *structs; | 72 | StructMap *structs; |
@@ -75,6 +80,7 @@ typedef struct Analyzer { | |||
75 | Scope **scopes; | 80 | Scope **scopes; |
76 | StrSet *numeric_types; | 81 | StrSet *numeric_types; |
77 | StrSet *integer_types; | 82 | StrSet *integer_types; |
83 | StrSet *float_types; | ||
78 | bool err; | 84 | bool err; |
79 | } Analyzer; | 85 | } Analyzer; |
80 | 86 | ||
@@ -82,16 +88,19 @@ Scope * | |||
82 | typescope_alloc(Analyzer *a, Scope *parent) { | 88 | typescope_alloc(Analyzer *a, Scope *parent) { |
83 | Scope *scope = arena_calloc(sizeof(Scope), a->storage); | 89 | Scope *scope = arena_calloc(sizeof(Scope), a->storage); |
84 | scope->parent = parent; | 90 | scope->parent = parent; |
91 | if (parent != NULL) { | ||
92 | scope->name = parent->name; | ||
93 | } | ||
85 | scope->id = a->typescope_gen++; | 94 | scope->id = a->typescope_gen++; |
86 | scope->depth = parent == NULL ? 0 : parent->depth + 1; | 95 | scope->depth = parent == NULL ? 0 : parent->depth + 1; |
87 | array_push(a->scopes, scope, a->storage); | 96 | array_push(a->scopes, scope, a->storage); |
88 | return scope; | 97 | return scope; |
89 | } | 98 | } |
90 | 99 | ||
91 | SymbolMap * | 100 | StrSet * |
92 | find_type(Scope *scope, Str type) { | 101 | find_type(Scope *scope, Str type) { |
93 | while (scope != NULL) { | 102 | while (scope != NULL) { |
94 | SymbolMap *val = symmap_lookup(&scope->symbols, type); | 103 | StrSet *val = strset_lookup(&scope->types, type); |
95 | if (val != NULL) { | 104 | if (val != NULL) { |
96 | return val; | 105 | return val; |
97 | } | 106 | } |
@@ -276,7 +285,7 @@ Str type_inference(Analyzer *a, Node *node, Scope *scope); | |||
276 | 285 | ||
277 | void | 286 | void |
278 | typecheck_field(Analyzer *a, Node *node, Scope *scope, Str symbol) { | 287 | typecheck_field(Analyzer *a, Node *node, Scope *scope, Str symbol) { |
279 | if (node->field_type->kind == NODE_COMPOUND_TYPE) { | 288 | if (node->field.type->kind == NODE_COMPOUND_TYPE) { |
280 | Str field_name = str_concat(symbol, cstr("."), a->storage); | 289 | Str field_name = str_concat(symbol, cstr("."), a->storage); |
281 | field_name = str_concat(field_name, node->value.str, a->storage); | 290 | field_name = str_concat(field_name, node->value.str, a->storage); |
282 | if (structmap_lookup(&scope->structs, field_name)) { | 291 | if (structmap_lookup(&scope->structs, field_name)) { |
@@ -285,8 +294,8 @@ typecheck_field(Analyzer *a, Node *node, Scope *scope, Str symbol) { | |||
285 | a->err = true; | 294 | a->err = true; |
286 | } | 295 | } |
287 | Str type = cstr("\\{ "); | 296 | Str type = cstr("\\{ "); |
288 | for (sz i = 0; i < array_size(node->field_type->elements); i++) { | 297 | for (sz i = 0; i < array_size(node->field.type->elements); i++) { |
289 | Node *field = node->field_type->elements[i]; | 298 | Node *field = node->field.type->elements[i]; |
290 | typecheck_field(a, field, scope, field_name); | 299 | typecheck_field(a, field, scope, field_name); |
291 | type = str_concat(type, field->type, a->storage); | 300 | type = str_concat(type, field->type, a->storage); |
292 | type = str_concat(type, cstr(" "), a->storage); | 301 | type = str_concat(type, cstr(" "), a->storage); |
@@ -296,25 +305,19 @@ typecheck_field(Analyzer *a, Node *node, Scope *scope, Str symbol) { | |||
296 | } else { | 305 | } else { |
297 | Str field_name = str_concat(symbol, cstr("."), a->storage); | 306 | Str field_name = str_concat(symbol, cstr("."), a->storage); |
298 | field_name = str_concat(field_name, node->value.str, a->storage); | 307 | field_name = str_concat(field_name, node->value.str, a->storage); |
299 | Str field_type = node->field_type->value.str; | 308 | Str field_type = node->field.type->value.str; |
300 | if (!find_type(scope, field_type)) { | 309 | if (!find_type(scope, field_type)) { |
301 | eprintln("%s:%d:%d: error: unknown type '%s'", a->file_name, | 310 | eprintln("%s:%d:%d: error: unknown type '%s'", a->file_name, |
302 | node->field_type->line, node->field_type->col, field_type); | 311 | node->field.type->line, node->field.type->col, field_type); |
303 | a->err = true; | 312 | a->err = true; |
304 | } | 313 | } |
305 | if (node->field_type->is_ptr) { | ||
306 | field_type = str_concat(cstr("@"), field_type, a->storage); | ||
307 | } | ||
308 | if (node->field_type->kind == NODE_ARR_TYPE) { | ||
309 | field_type = str_concat(cstr("@"), field_type, a->storage); | ||
310 | } | ||
311 | if (structmap_lookup(&scope->structs, field_name)) { | 314 | if (structmap_lookup(&scope->structs, field_name)) { |
312 | eprintln("%s:%d:%d: error: struct field '%s' already exists", | 315 | eprintln("%s:%d:%d: error: struct field '%s' already exists", |
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,65 @@ 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. | ||
459 | switch (node->kind) { | 463 | switch (node->kind) { |
460 | case NODE_LET: { | 464 | case NODE_LET: { |
461 | node->type = cstr("nil"); | 465 | node->type = cstr("nil"); |
462 | Str symbol = node->var_name->value.str; | 466 | Str symbol = node->var.name->value.str; |
463 | if (symmap_lookup(&scope->symbols, symbol)) { | 467 | if (symmap_lookup(&scope->symbols, symbol)) { |
464 | eprintln( | 468 | eprintln( |
465 | "%s:%d:%d: error: symbol '%s' already exists in current " | 469 | "%s:%d:%d: error: symbol '%s' already exists in current " |
466 | "scope ", | 470 | "scope ", |
467 | a->file_name, node->var_name->line, node->var_name->col, | 471 | a->file_name, node->var.name->line, node->var.name->col, |
468 | symbol); | 472 | symbol); |
469 | a->err = true; | 473 | a->err = true; |
470 | return cstr(""); | 474 | return cstr(""); |
471 | } | 475 | } |
472 | if (node->var_type) { | 476 | if (node->var.type) { |
473 | Str type_name = node->var_type->value.str; | 477 | Str type_name = type_inference(a, node->var.type, scope); |
474 | SymbolMap *type = find_type(scope, type_name); | 478 | if (node->var.val) { |
475 | if (type == NULL) { | 479 | Str type = type_inference(a, node->var.val, scope); |
476 | eprintln("%s:%d:%d: error: unknown type '%s'", a->file_name, | ||
477 | node->var_type->line, node->var_type->col, | ||
478 | type_name); | ||
479 | a->err = true; | ||
480 | return cstr(""); | ||
481 | } | ||
482 | if (node->var_type->is_ptr) { | ||
483 | type_name = str_concat(cstr("@"), type_name, a->storage); | ||
484 | } | ||
485 | if (node->var_type->kind == NODE_ARR_TYPE) { | ||
486 | type_name = str_concat(cstr("@"), type_name, a->storage); | ||
487 | // TODO: typecheck size | ||
488 | // TODO: register array in scope | ||
489 | } | ||
490 | if (node->var_val) { | ||
491 | Str type = type_inference(a, node->var_val, scope); | ||
492 | if (!type.size) { | 480 | if (!type.size) { |
493 | eprintln( | 481 | eprintln( |
494 | "%s:%d:%d: error: can't bind `nil` to variable " | 482 | "%s:%d:%d: error: can't bind `nil` to variable " |
495 | "'%s'", | 483 | "'%s'", |
496 | a->file_name, node->var_type->line, | 484 | a->file_name, node->var.type->line, |
497 | node->var_type->col, symbol); | 485 | node->var.type->col, symbol); |
498 | a->err = true; | 486 | a->err = true; |
499 | return cstr(""); | 487 | return cstr(""); |
500 | } | 488 | } |
501 | // TODO: Consider compatible types. | ||
502 | if (!str_eq(type, type_name)) { | 489 | if (!str_eq(type, type_name)) { |
503 | // Special case, enums can be treated as ints. | 490 | // TODO: ensure that we only assign compatible arrays, |
504 | FindEnumResult res = find_enum(scope, type_name); | 491 | // for pointers this was ok but not anymore. |
505 | if (!(res.map && str_eq(type, cstr("int")))) { | 492 | Str type_a = type; |
506 | eprintln( | 493 | Str type_b = type_name; |
507 | "%s:%d:%d: error: type mismatch, trying to " | 494 | if (str_has_prefix(type_a, cstr("@")) || |
508 | "assing " | 495 | str_has_prefix(type_a, cstr("["))) { |
509 | "%s" | 496 | type_a = cstr("Ptr"); |
510 | " to a variable of type %s", | 497 | } |
511 | a->file_name, node->var_type->line, | 498 | if (str_has_prefix(type_b, cstr("@")) || |
512 | node->var_type->col, type, type_name); | 499 | str_has_prefix(type_b, cstr("["))) { |
513 | a->err = true; | 500 | type_b = cstr("Ptr"); |
514 | return cstr(""); | 501 | } |
502 | if (!(strset_lookup(&a->integer_types, type_a) && | ||
503 | strset_lookup(&a->integer_types, type_b)) || | ||
504 | !(strset_lookup(&a->numeric_types, type_a) && | ||
505 | strset_lookup(&a->numeric_types, type_b))) { | ||
506 | // Special case, enums can be treated as ints. | ||
507 | FindEnumResult res = find_enum(scope, type_name); | ||
508 | if (!(res.map && str_eq(type, cstr("Int")))) { | ||
509 | eprintln( | ||
510 | "%s:%d:%d: error: type mismatch, trying to " | ||
511 | "assing " | ||
512 | "%s" | ||
513 | " to a variable of type %s", | ||
514 | a->file_name, node->var.type->line, | ||
515 | node->var.type->col, type, type_name); | ||
516 | a->err = true; | ||
517 | return cstr(""); | ||
518 | } | ||
515 | } | 519 | } |
516 | } | 520 | } |
517 | } | 521 | } |
@@ -521,17 +525,28 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
521 | .kind = SYM_VAR, | 525 | .kind = SYM_VAR, |
522 | }, | 526 | }, |
523 | a->storage); | 527 | a->storage); |
528 | node->var.name->type = type_name; | ||
529 | symbol = str_concat(cstr("."), symbol, a->storage); | ||
530 | symbol = str_concat(symbol, str_from_int(scope->id, a->storage), | ||
531 | a->storage); | ||
532 | node->unique_name = symbol; | ||
524 | return node->type; | 533 | return node->type; |
525 | } | 534 | } |
526 | 535 | ||
527 | // We don't know the type for this symbol, perform inference. | 536 | // We don't know the type for this symbol, perform inference. |
528 | Str type = type_inference(a, node->var_val, scope); | 537 | Str type = type_inference(a, node->var.val, scope); |
529 | if (type.size) { | 538 | if (!type.size || str_eq(type, cstr("nil")) || |
530 | symmap_insert(&scope->symbols, symbol, | 539 | str_has_prefix(type, cstr("ret:"))) { |
531 | (Symbol){.name = type, .kind = SYM_VAR}, | 540 | eprintln( |
532 | a->storage); | 541 | "%s:%d:%d: error: can't bind `nil` to variable " |
533 | node->var_name->type = type; | 542 | "'%s'", |
543 | a->file_name, node->line, node->col, symbol); | ||
544 | a->err = true; | ||
545 | return cstr(""); | ||
534 | } | 546 | } |
547 | symmap_insert(&scope->symbols, symbol, | ||
548 | (Symbol){.name = type, .kind = SYM_VAR}, a->storage); | ||
549 | node->var.name->type = type; | ||
535 | symbol = str_concat(cstr("."), symbol, a->storage); | 550 | symbol = str_concat(cstr("."), symbol, a->storage); |
536 | symbol = str_concat(symbol, str_from_int(scope->id, a->storage), | 551 | symbol = str_concat(symbol, str_from_int(scope->id, a->storage), |
537 | a->storage); | 552 | a->storage); |
@@ -539,23 +554,38 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
539 | return node->type; | 554 | return node->type; |
540 | } break; | 555 | } break; |
541 | case NODE_SET: { | 556 | case NODE_SET: { |
542 | Str name = type_inference(a, node->var_name, scope); | 557 | Str name = type_inference(a, node->var.name, scope); |
543 | Str val = type_inference(a, node->var_val, scope); | 558 | Str val = type_inference(a, node->var.val, scope); |
559 | if (str_has_prefix(name, cstr("@")) || | ||
560 | str_has_prefix(name, cstr("["))) { | ||
561 | name = cstr("Ptr"); | ||
562 | } | ||
563 | if (str_has_prefix(val, cstr("@")) || | ||
564 | str_has_prefix(val, cstr("["))) { | ||
565 | val = cstr("Ptr"); | ||
566 | } | ||
544 | if (!str_eq(name, val)) { | 567 | if (!str_eq(name, val)) { |
545 | eprintln( | 568 | if (!(strset_lookup(&a->integer_types, name) && |
546 | "%s:%d:%d: error: type mismatch, trying to assing " | 569 | strset_lookup(&a->integer_types, val)) || |
547 | "%s" | 570 | !(strset_lookup(&a->numeric_types, name) && |
548 | " to a variable of type %s", | 571 | strset_lookup(&a->numeric_types, val))) { |
549 | a->file_name, node->line, node->col, val, name); | 572 | eprintln( |
550 | a->err = true; | 573 | "%s:%d:%d: error: type mismatch, trying to assing " |
551 | return cstr(""); | 574 | "%s" |
575 | " to a variable of type %s", | ||
576 | a->file_name, node->line, node->col, val, name); | ||
577 | a->err = true; | ||
578 | return cstr(""); | ||
579 | } | ||
552 | } | 580 | } |
553 | Str symbol = node->var_name->value.str; | 581 | Str symbol = node->var.name->value.str; |
554 | FindSymbolResult sym = find_symbol(scope, symbol); | 582 | FindSymbolResult sym = find_symbol(scope, symbol); |
555 | node->unique_name = str_concat(cstr("."), symbol, a->storage); | 583 | if (sym.map) { |
556 | node->unique_name = | 584 | node->unique_name = str_concat(cstr("."), symbol, a->storage); |
557 | str_concat(node->unique_name, | 585 | node->unique_name = str_concat( |
558 | str_from_int(sym.scope->id, a->storage), a->storage); | 586 | node->unique_name, str_from_int(sym.scope->id, a->storage), |
587 | a->storage); | ||
588 | } | ||
559 | node->type = cstr("nil"); | 589 | node->type = cstr("nil"); |
560 | return node->type; | 590 | return node->type; |
561 | } break; | 591 | } break; |
@@ -595,7 +625,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
595 | enummap_insert(&scope->enums, symbol, | 625 | enummap_insert(&scope->enums, symbol, |
596 | (Enum){ | 626 | (Enum){ |
597 | .name = symbol, | 627 | .name = symbol, |
598 | .val = node->field_val, | 628 | .val = node->field.val, |
599 | }, | 629 | }, |
600 | a->storage); | 630 | a->storage); |
601 | for (sz i = 0; i < array_size(node->struct_field); i++) { | 631 | for (sz i = 0; i < array_size(node->struct_field); i++) { |
@@ -608,9 +638,9 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
608 | a->file_name, field->line, field->col, field_name); | 638 | a->file_name, field->line, field->col, field_name); |
609 | a->err = true; | 639 | a->err = true; |
610 | } | 640 | } |
611 | if (field->field_val) { | 641 | if (field->field.val) { |
612 | Str type = type_inference(a, field->field_val, scope); | 642 | Str type = type_inference(a, field->field.val, scope); |
613 | if (!str_eq(type, cstr("int"))) { | 643 | if (!str_eq(type, cstr("Int"))) { |
614 | eprintln( | 644 | eprintln( |
615 | "%s:%d:%d: error: non int enum value for '%s.%s'", | 645 | "%s:%d:%d: error: non int enum value for '%s.%s'", |
616 | a->file_name, field->line, field->col, symbol, | 646 | a->file_name, field->line, field->col, symbol, |
@@ -632,26 +662,31 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
632 | return node->type; | 662 | return node->type; |
633 | } break; | 663 | } break; |
634 | case NODE_IF: { | 664 | case NODE_IF: { |
635 | Str cond_type = type_inference(a, node->cond_if, scope); | 665 | Str cond_type = type_inference(a, node->ifelse.cond, scope); |
636 | if (!str_eq(cond_type, cstr("bool"))) { | 666 | if (!str_eq(cond_type, cstr("Bool"))) { |
637 | emit_semantic_error( | 667 | emit_semantic_error( |
638 | a, node->cond_if, | 668 | a, node->ifelse.cond, |
639 | cstr("non boolean expression on if condition")); | 669 | cstr("non boolean expression on if condition")); |
640 | return cstr(""); | 670 | return cstr(""); |
641 | } | 671 | } |
642 | if (node->cond_expr->kind == NODE_BLOCK) { | 672 | if (node->ifelse.expr_true->kind == NODE_BLOCK) { |
643 | node->type = type_inference(a, node->cond_expr, scope); | 673 | node->type = type_inference(a, node->ifelse.expr_true, scope); |
644 | } else { | 674 | } else { |
645 | Scope *next = typescope_alloc(a, scope); | 675 | Scope *next = typescope_alloc(a, scope); |
646 | node->type = type_inference(a, node->cond_expr, next); | 676 | node->type = type_inference(a, node->ifelse.expr_true, next); |
677 | } | ||
678 | if (str_has_prefix(node->type, cstr("ret:")) || | ||
679 | str_has_prefix(node->type, cstr("flow:"))) { | ||
680 | node->type = cstr("nil"); | ||
647 | } | 681 | } |
648 | if (node->cond_else) { | 682 | if (node->ifelse.expr_else) { |
649 | Str else_type; | 683 | Str else_type; |
650 | if (node->cond_else->kind == NODE_BLOCK) { | 684 | if (node->ifelse.expr_else->kind == NODE_BLOCK) { |
651 | else_type = type_inference(a, node->cond_else, scope); | 685 | else_type = |
686 | type_inference(a, node->ifelse.expr_else, scope); | ||
652 | } else { | 687 | } else { |
653 | Scope *next = typescope_alloc(a, scope); | 688 | Scope *next = typescope_alloc(a, scope); |
654 | else_type = type_inference(a, node->cond_else, next); | 689 | else_type = type_inference(a, node->ifelse.expr_else, next); |
655 | } | 690 | } |
656 | if (!str_eq(node->type, else_type)) { | 691 | if (!str_eq(node->type, else_type)) { |
657 | emit_semantic_error( | 692 | emit_semantic_error( |
@@ -659,27 +694,38 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
659 | return cstr(""); | 694 | return cstr(""); |
660 | } | 695 | } |
661 | } | 696 | } |
697 | |||
698 | // If it returns a value, verify it contains an `else` statement. | ||
699 | if (!str_eq(node->type, cstr("nil"))) { | ||
700 | if (!node->ifelse.expr_else) { | ||
701 | emit_semantic_error( | ||
702 | a, node, | ||
703 | cstr("missing else statement in if expression")); | ||
704 | return cstr(""); | ||
705 | } | ||
706 | } | ||
662 | return node->type; | 707 | return node->type; |
663 | } break; | 708 | } break; |
664 | case NODE_WHILE: { | 709 | case NODE_WHILE: { |
665 | Str cond_type = type_inference(a, node->while_cond, scope); | 710 | Str cond_type = type_inference(a, node->loop.cond, scope); |
666 | if (!str_eq(cond_type, cstr("bool"))) { | 711 | if (!str_eq(cond_type, cstr("Bool"))) { |
667 | emit_semantic_error( | 712 | emit_semantic_error( |
668 | a, node->cond_if, | 713 | a, node->loop.cond, |
669 | cstr("non boolean expression on while condition")); | 714 | cstr("non boolean expression on while condition")); |
670 | return cstr(""); | 715 | return cstr(""); |
671 | } | 716 | } |
672 | if (node->while_expr->kind != NODE_BLOCK) { | 717 | if (node->loop.expr->kind != NODE_BLOCK) { |
673 | scope = typescope_alloc(a, scope); | 718 | scope = typescope_alloc(a, scope); |
674 | } | 719 | } |
675 | type_inference(a, node->while_expr, scope); | 720 | type_inference(a, node->loop.expr, scope); |
676 | node->type = cstr("nil"); | 721 | node->type = cstr("nil"); |
677 | return node->type; | 722 | return node->type; |
678 | } break; | 723 | } break; |
679 | case NODE_COND: { | 724 | case NODE_COND: { |
680 | Str previous = cstr(""); | 725 | Str previous = cstr(""); |
681 | for (sz i = 0; i < array_size(node->match_cases); i++) { | 726 | bool has_else = false; |
682 | Node *expr = node->match_cases[i]; | 727 | for (sz i = 0; i < array_size(node->match.cases); i++) { |
728 | Node *expr = node->match.cases[i]; | ||
683 | Str next = type_inference(a, expr, scope); | 729 | Str next = type_inference(a, expr, scope); |
684 | if (i != 0 && !str_eq(next, previous)) { | 730 | if (i != 0 && !str_eq(next, previous)) { |
685 | emit_semantic_error( | 731 | emit_semantic_error( |
@@ -687,22 +733,36 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
687 | cstr("non-matching types for cond expressions")); | 733 | cstr("non-matching types for cond expressions")); |
688 | return cstr(""); | 734 | return cstr(""); |
689 | } | 735 | } |
736 | if (!expr->case_entry.cond) { | ||
737 | has_else = true; | ||
738 | } | ||
690 | previous = next; | 739 | previous = next; |
691 | } | 740 | } |
741 | // If it returns a value, verify it contains an `else` statement. | ||
742 | if (!str_eq(node->type, cstr("nil")) && | ||
743 | !str_has_prefix(node->type, cstr("ret:")) && | ||
744 | !str_has_prefix(node->type, cstr("flow:"))) { | ||
745 | if (!has_else) { | ||
746 | emit_semantic_error( | ||
747 | a, node, | ||
748 | cstr("missing else statement in cond expression")); | ||
749 | return cstr(""); | ||
750 | } | ||
751 | } | ||
692 | node->type = previous; | 752 | node->type = previous; |
693 | return node->type; | 753 | return node->type; |
694 | } break; | 754 | } break; |
695 | case NODE_MATCH: { | 755 | case NODE_MATCH: { |
696 | Str e = type_inference(a, node->match_expr, scope); | 756 | Str e = type_inference(a, node->match.expr, scope); |
697 | if (str_eq(e, cstr("int"))) { | 757 | if (str_eq(e, cstr("Int"))) { |
698 | // Integer matching. | 758 | // Integer matching. |
699 | for (sz i = 0; i < array_size(node->match_cases); i++) { | 759 | for (sz i = 0; i < array_size(node->match.cases); i++) { |
700 | Node *field = node->match_cases[i]; | 760 | Node *field = node->match.cases[i]; |
701 | if (field->case_value) { | 761 | if (field->case_entry.cond) { |
702 | if (field->case_value->kind != NODE_NUM_INT && | 762 | if (field->case_entry.cond->kind != NODE_NUM_INT && |
703 | field->case_value->kind != NODE_NUM_UINT) { | 763 | field->case_entry.cond->kind != NODE_NUM_UINT) { |
704 | emit_semantic_error( | 764 | emit_semantic_error( |
705 | a, field->case_value, | 765 | a, field->case_entry.cond, |
706 | cstr( | 766 | cstr( |
707 | "non-integer or enum types on match case")); | 767 | "non-integer or enum types on match case")); |
708 | } | 768 | } |
@@ -713,24 +773,24 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
713 | FindEnumResult res = find_enum(scope, e); | 773 | FindEnumResult res = find_enum(scope, e); |
714 | Str enum_prefix = | 774 | Str enum_prefix = |
715 | str_concat(res.map->val.name, cstr("."), a->storage); | 775 | str_concat(res.map->val.name, cstr("."), a->storage); |
716 | for (sz i = 0; i < array_size(node->match_cases); i++) { | 776 | for (sz i = 0; i < array_size(node->match.cases); i++) { |
717 | Node *field = node->match_cases[i]; | 777 | Node *field = node->match.cases[i]; |
718 | if (field->case_value) { | 778 | if (field->case_entry.cond) { |
719 | Str field_name = str_concat( | 779 | Str field_name = str_concat( |
720 | enum_prefix, field->case_value->value.str, | 780 | enum_prefix, field->case_entry.cond->value.str, |
721 | a->storage); | 781 | a->storage); |
722 | if (!enummap_lookup(&res.scope->enums, field_name)) { | 782 | if (!enummap_lookup(&res.scope->enums, field_name)) { |
723 | eprintln("%s:%d:%d: error: unknown enum field '%s'", | 783 | eprintln("%s:%d:%d: error: unknown enum field '%s'", |
724 | a->file_name, field->case_value->line, | 784 | a->file_name, field->case_entry.cond->line, |
725 | field->case_value->col, field_name); | 785 | field->case_entry.cond->col, field_name); |
726 | a->err = true; | 786 | a->err = true; |
727 | } | 787 | } |
728 | } | 788 | } |
729 | } | 789 | } |
730 | } | 790 | } |
731 | Str previous = cstr(""); | 791 | Str previous = cstr(""); |
732 | for (sz i = 0; i < array_size(node->match_cases); i++) { | 792 | for (sz i = 0; i < array_size(node->match.cases); i++) { |
733 | Node *expr = node->match_cases[i]; | 793 | Node *expr = node->match.cases[i]; |
734 | Str next = type_inference(a, expr, scope); | 794 | Str next = type_inference(a, expr, scope); |
735 | if (i != 0 && !str_eq(next, previous)) { | 795 | if (i != 0 && !str_eq(next, previous)) { |
736 | emit_semantic_error( | 796 | emit_semantic_error( |
@@ -744,29 +804,29 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
744 | return node->type; | 804 | return node->type; |
745 | } break; | 805 | } break; |
746 | case NODE_CASE_MATCH: { | 806 | case NODE_CASE_MATCH: { |
747 | if (node->case_expr->kind != NODE_BLOCK) { | 807 | if (node->case_entry.expr->kind != NODE_BLOCK) { |
748 | scope = typescope_alloc(a, scope); | 808 | scope = typescope_alloc(a, scope); |
749 | } | 809 | } |
750 | node->type = type_inference(a, node->case_expr, scope); | 810 | node->type = type_inference(a, node->case_entry.expr, scope); |
751 | return node->type; | 811 | return node->type; |
752 | } break; | 812 | } break; |
753 | case NODE_CASE_COND: { | 813 | case NODE_CASE_COND: { |
754 | if (node->case_value) { | 814 | if (node->case_entry.cond) { |
755 | Str cond = type_inference(a, node->case_value, scope); | 815 | Str cond = type_inference(a, node->case_entry.cond, scope); |
756 | if (!str_eq(cond, cstr("bool"))) { | 816 | if (!str_eq(cond, cstr("Bool"))) { |
757 | emit_semantic_error(a, node, | 817 | emit_semantic_error(a, node, |
758 | cstr("non-boolean case condition")); | 818 | cstr("non-boolean case condition")); |
759 | } | 819 | } |
760 | } | 820 | } |
761 | if (node->case_expr->kind != NODE_BLOCK) { | 821 | if (node->case_entry.expr->kind != NODE_BLOCK) { |
762 | scope = typescope_alloc(a, scope); | 822 | scope = typescope_alloc(a, scope); |
763 | } | 823 | } |
764 | node->type = type_inference(a, node->case_expr, scope); | 824 | node->type = type_inference(a, node->case_entry.expr, scope); |
765 | return node->type; | 825 | return node->type; |
766 | } break; | 826 | } break; |
767 | case NODE_TRUE: | 827 | case NODE_TRUE: |
768 | case NODE_FALSE: { | 828 | case NODE_FALSE: { |
769 | node->type = cstr("bool"); | 829 | node->type = cstr("Bool"); |
770 | return node->type; | 830 | return node->type; |
771 | } break; | 831 | } break; |
772 | case NODE_NIL: { | 832 | case NODE_NIL: { |
@@ -776,21 +836,21 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
776 | case NODE_NOT: | 836 | case NODE_NOT: |
777 | case NODE_AND: | 837 | case NODE_AND: |
778 | case NODE_OR: { | 838 | case NODE_OR: { |
779 | Str left = type_inference(a, node->left, scope); | 839 | Str left = type_inference(a, node->binary.left, scope); |
780 | if (!str_eq(left, cstr("bool"))) { | 840 | if (!str_eq(left, cstr("Bool"))) { |
781 | emit_semantic_error(a, node, | 841 | emit_semantic_error(a, node, |
782 | cstr("expected bool on logic expression")); | 842 | cstr("expected bool on logic expression")); |
783 | return cstr(""); | 843 | return cstr(""); |
784 | } | 844 | } |
785 | if (node->right) { | 845 | if (node->binary.right) { |
786 | Str right = type_inference(a, node->right, scope); | 846 | Str right = type_inference(a, node->binary.right, scope); |
787 | if (!str_eq(right, cstr("bool"))) { | 847 | if (!str_eq(right, cstr("Bool"))) { |
788 | emit_semantic_error( | 848 | emit_semantic_error( |
789 | a, node, cstr("expected bool on logic expression")); | 849 | a, node, cstr("expected bool on logic expression")); |
790 | return cstr(""); | 850 | return cstr(""); |
791 | } | 851 | } |
792 | } | 852 | } |
793 | node->type = cstr("bool"); | 853 | node->type = cstr("Bool"); |
794 | return node->type; | 854 | return node->type; |
795 | } break; | 855 | } break; |
796 | case NODE_EQ: | 856 | case NODE_EQ: |
@@ -799,18 +859,23 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
799 | case NODE_GT: | 859 | case NODE_GT: |
800 | case NODE_LE: | 860 | case NODE_LE: |
801 | case NODE_GE: { | 861 | case NODE_GE: { |
802 | Str left = type_inference(a, node->left, scope); | 862 | Str left = type_inference(a, node->binary.left, scope); |
803 | Str right = type_inference(a, node->right, scope); | 863 | Str right = type_inference(a, node->binary.right, scope); |
804 | if (!str_eq(left, right)) { | 864 | if (!str_eq(left, right)) { |
805 | emit_semantic_error( | 865 | if (!(strset_lookup(&a->integer_types, left) && |
806 | a, node, cstr("mismatched types on binary expression")); | 866 | strset_lookup(&a->integer_types, right)) || |
807 | return cstr(""); | 867 | !(strset_lookup(&a->numeric_types, left) && |
868 | strset_lookup(&a->numeric_types, right))) { | ||
869 | emit_semantic_error( | ||
870 | a, node, cstr("mismatched types on binary expression")); | ||
871 | return cstr(""); | ||
872 | } | ||
808 | } | 873 | } |
809 | node->type = cstr("bool"); | 874 | node->type = cstr("Bool"); |
810 | return node->type; | 875 | return node->type; |
811 | } break; | 876 | } break; |
812 | case NODE_BITNOT: { | 877 | case NODE_BITNOT: { |
813 | Str left = type_inference(a, node->left, scope); | 878 | Str left = type_inference(a, node->binary.left, scope); |
814 | if (!strset_lookup(&a->integer_types, left)) { | 879 | if (!strset_lookup(&a->integer_types, left)) { |
815 | emit_semantic_error( | 880 | emit_semantic_error( |
816 | a, node, cstr("non integer type on bit twiddling expr")); | 881 | a, node, cstr("non integer type on bit twiddling expr")); |
@@ -821,10 +886,11 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
821 | } break; | 886 | } break; |
822 | case NODE_BITAND: | 887 | case NODE_BITAND: |
823 | case NODE_BITOR: | 888 | case NODE_BITOR: |
889 | case NODE_BITXOR: | ||
824 | case NODE_BITLSHIFT: | 890 | case NODE_BITLSHIFT: |
825 | case NODE_BITRSHIFT: { | 891 | case NODE_BITRSHIFT: { |
826 | Str left = type_inference(a, node->left, scope); | 892 | Str left = type_inference(a, node->binary.left, scope); |
827 | Str right = type_inference(a, node->right, scope); | 893 | Str right = type_inference(a, node->binary.right, scope); |
828 | if (!strset_lookup(&a->integer_types, left) || | 894 | if (!strset_lookup(&a->integer_types, left) || |
829 | !strset_lookup(&a->integer_types, right)) { | 895 | !strset_lookup(&a->integer_types, right)) { |
830 | emit_semantic_error( | 896 | emit_semantic_error( |
@@ -839,8 +905,15 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
839 | case NODE_DIV: | 905 | case NODE_DIV: |
840 | case NODE_MUL: | 906 | case NODE_MUL: |
841 | case NODE_MOD: { | 907 | case NODE_MOD: { |
842 | Str left = type_inference(a, node->left, scope); | 908 | Str left = type_inference(a, node->binary.left, scope); |
843 | Str right = type_inference(a, node->right, scope); | 909 | Str right = type_inference(a, node->binary.right, scope); |
910 | // Enable pointer arithmetic. | ||
911 | if (str_has_prefix(left, cstr("@"))) { | ||
912 | left = cstr("Ptr"); | ||
913 | } | ||
914 | if (str_has_prefix(right, cstr("@"))) { | ||
915 | right = cstr("Ptr"); | ||
916 | } | ||
844 | if (!strset_lookup(&a->numeric_types, left) || | 917 | if (!strset_lookup(&a->numeric_types, left) || |
845 | !strset_lookup(&a->numeric_types, right)) { | 918 | !strset_lookup(&a->numeric_types, right)) { |
846 | emit_semantic_error( | 919 | emit_semantic_error( |
@@ -848,73 +921,149 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
848 | return cstr(""); | 921 | return cstr(""); |
849 | } | 922 | } |
850 | if (!str_eq(left, right)) { | 923 | if (!str_eq(left, right)) { |
851 | emit_semantic_error( | 924 | if (!((strset_lookup(&a->integer_types, left) && |
852 | a, node, cstr("mismatched types on binary expression")); | 925 | strset_lookup(&a->integer_types, right)) || |
853 | return cstr(""); | 926 | (strset_lookup(&a->float_types, left) && |
927 | strset_lookup(&a->float_types, right)))) { | ||
928 | emit_semantic_error( | ||
929 | a, node, cstr("mismatched types on binary expression")); | ||
930 | return cstr(""); | ||
931 | } | ||
854 | } | 932 | } |
855 | node->type = left; | 933 | node->type = left; |
856 | return node->type; | 934 | return node->type; |
857 | } break; | 935 | } break; |
858 | case NODE_NUM_UINT: { | 936 | case NODE_NUM_UINT: { |
859 | node->type = cstr("uint"); | 937 | node->type = cstr("UInt"); |
860 | return node->type; | 938 | return node->type; |
861 | } break; | 939 | } break; |
862 | case NODE_NUM_INT: { | 940 | case NODE_NUM_INT: { |
863 | node->type = cstr("int"); | 941 | node->type = cstr("Int"); |
864 | return node->type; | 942 | return node->type; |
865 | } break; | 943 | } break; |
866 | case NODE_NUM_FLOAT: { | 944 | case NODE_NUM_FLOAT: { |
867 | node->type = cstr("f64"); | 945 | node->type = cstr("F64"); |
868 | return node->type; | 946 | return node->type; |
869 | } break; | 947 | } break; |
870 | case NODE_STRING: { | 948 | case NODE_STRING: { |
871 | node->type = cstr("str"); | 949 | node->type = cstr("Str"); |
872 | return node->type; | 950 | return node->type; |
873 | } break; | 951 | } break; |
874 | case NODE_ARR_TYPE: | ||
875 | case NODE_TYPE: { | 952 | case NODE_TYPE: { |
876 | SymbolMap *type = find_type(scope, node->value.str); | 953 | Str base_type = node->value.str; |
877 | if (!type) { | 954 | StrSet *set = find_type(scope, node->value.str); |
955 | if (!set) { | ||
878 | emit_semantic_error(a, node, cstr("unknown type")); | 956 | emit_semantic_error(a, node, cstr("unknown type")); |
879 | return cstr(""); | 957 | return cstr(""); |
880 | } | 958 | } |
881 | node->type = type->val.name; | 959 | Node *next = node->t.next; |
960 | Str type = cstr(""); | ||
961 | while (next) { | ||
962 | switch (next->kind) { | ||
963 | case NODE_PTR: { | ||
964 | Str suffix = cstr("@"); | ||
965 | type = str_concat(type, suffix, a->storage); | ||
966 | } break; | ||
967 | case NODE_ARR: { | ||
968 | Str suffix = cstr("["); | ||
969 | switch (next->array.kind) { | ||
970 | case NODE_ARR_STATIC: { | ||
971 | suffix = str_concat( | ||
972 | suffix, | ||
973 | str_from_int(next->array.size->value.i, | ||
974 | a->storage), | ||
975 | a->storage); | ||
976 | suffix = | ||
977 | str_concat(suffix, cstr("]"), a->storage); | ||
978 | } break; | ||
979 | default: { | ||
980 | emit_semantic_error(a, node, | ||
981 | cstr("unimplemented")); | ||
982 | return cstr(""); | ||
983 | } break; | ||
984 | } | ||
985 | type = str_concat(type, suffix, a->storage); | ||
986 | } break; | ||
987 | default: break; | ||
988 | } | ||
989 | next = next->t.next; | ||
990 | } | ||
991 | type = str_concat(type, base_type, a->storage); | ||
992 | node->type = type; | ||
993 | return node->type; | ||
994 | } break; | ||
995 | case NODE_DEREF: { | ||
996 | Node *next = node->deref.next; | ||
997 | Str amount = cstr("@"); | ||
998 | while (next) { | ||
999 | if (next->kind == NODE_SYMBOL) { | ||
1000 | break; | ||
1001 | } | ||
1002 | next = next->deref.next; | ||
1003 | amount = str_concat(cstr("@"), amount, a->storage); | ||
1004 | } | ||
1005 | Str symbol = next->value.str; | ||
1006 | Str type = type_inference(a, next, scope); | ||
1007 | if (str_has_prefix(type, cstr("["))) { | ||
1008 | str_split(&type, cstr("]")); | ||
1009 | type = str_concat(cstr("@"), type, a->storage); | ||
1010 | } | ||
1011 | if (!str_has_prefix(type, amount)) { | ||
1012 | eprintln( | ||
1013 | "%s:%d:%d: error: invalid type dereference %s from type %s", | ||
1014 | a->file_name, node->line, node->col, | ||
1015 | str_concat(symbol, amount, a->storage), type); | ||
1016 | a->err = true; | ||
1017 | return cstr(""); | ||
1018 | } | ||
1019 | type = str_remove_prefix(type, amount); | ||
1020 | node->value.str = next->value.str; | ||
1021 | node->unique_name = next->unique_name; | ||
1022 | node->type = type; | ||
882 | return node->type; | 1023 | return node->type; |
883 | } break; | 1024 | } break; |
884 | case NODE_SYMBOL_IDX: | ||
885 | case NODE_SYMBOL: { | 1025 | case NODE_SYMBOL: { |
886 | Str symbol = node->value.str; | 1026 | Str symbol = node->value.str; |
887 | SymbolMap *type = find_type(scope, symbol); | 1027 | |
888 | if (!type) { | 1028 | FindSymbolResult sym = find_symbol(scope, symbol); |
1029 | if (!sym.map) { | ||
889 | eprintln("%s:%d:%d: error: couldn't resolve symbol '%s'", | 1030 | eprintln("%s:%d:%d: error: couldn't resolve symbol '%s'", |
890 | a->file_name, node->line, node->col, symbol); | 1031 | a->file_name, node->line, node->col, symbol); |
891 | a->err = true; | 1032 | a->err = true; |
892 | return cstr(""); | 1033 | return cstr(""); |
893 | } | 1034 | } |
894 | 1035 | ||
895 | FindSymbolResult sym = find_symbol(scope, symbol); | 1036 | if (!str_eq(sym.scope->name, scope->name) && sym.scope->name.size) { |
1037 | eprintln( | ||
1038 | "%s:%d:%d: error: can't capture external local symbol '%s'", | ||
1039 | a->file_name, node->line, node->col, symbol); | ||
1040 | a->err = true; | ||
1041 | return cstr(""); | ||
1042 | } | ||
896 | node->unique_name = str_concat(cstr("."), symbol, a->storage); | 1043 | node->unique_name = str_concat(cstr("."), symbol, a->storage); |
897 | node->unique_name = | 1044 | node->unique_name = |
898 | str_concat(node->unique_name, | 1045 | str_concat(node->unique_name, |
899 | str_from_int(sym.scope->id, a->storage), a->storage); | 1046 | str_from_int(sym.scope->id, a->storage), a->storage); |
900 | 1047 | ||
901 | Str type_name = type->val.name; | 1048 | Str type_name = sym.map->val.name; |
902 | if (node->kind == NODE_SYMBOL_IDX) { | 1049 | // if (node->kind == NODE_SYMBOL_IDX) { |
903 | Str idx_type = type_inference(a, node->arr_size, scope); | 1050 | // // TODO: get rid of NODE_SYMBOL_IDX, use deref instead |
904 | if (!strset_lookup(&a->integer_types, idx_type)) { | 1051 | // Str idx_type = type_inference(a, node->sym.arr_size, scope); |
905 | emit_semantic_error( | 1052 | // if (!strset_lookup(&a->integer_types, idx_type)) { |
906 | a, node, cstr("can't resolve non integer index")); | 1053 | // emit_semantic_error( |
907 | return cstr(""); | 1054 | // a, node, cstr("can't resolve non integer index")); |
908 | } | 1055 | // return cstr(""); |
909 | type_name = str_remove_prefix(type_name, cstr("@")); | 1056 | // } |
910 | } | 1057 | // if (str_has_prefix(type_name, cstr("@"))) { |
911 | if (node->is_ptr) { | 1058 | // type_name = str_remove_prefix(type_name, cstr("@")); |
912 | type_name = str_concat(cstr("@"), type_name, a->storage); | 1059 | // } else if (str_has_prefix(type_name, cstr("["))) { |
913 | } | 1060 | // str_split(&type_name, cstr("]")); |
1061 | // } | ||
1062 | // } | ||
914 | 1063 | ||
915 | FindEnumResult e = find_enum(scope, type_name); | 1064 | FindEnumResult e = find_enum(scope, type_name); |
916 | if (e.map && str_eq(symbol, type_name)) { | 1065 | if (e.map && str_eq(symbol, type_name)) { |
917 | if (!node->next) { | 1066 | if (!node->sym.next) { |
918 | eprintln( | 1067 | eprintln( |
919 | "%s:%d:%d: error: unspecified enum field for symbol " | 1068 | "%s:%d:%d: error: unspecified enum field for symbol " |
920 | "'%s'", | 1069 | "'%s'", |
@@ -924,20 +1073,21 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
924 | } | 1073 | } |
925 | // Check if there is a next and it matches the enum field. | 1074 | // Check if there is a next and it matches the enum field. |
926 | Str field = str_concat(type_name, cstr("."), a->storage); | 1075 | Str field = str_concat(type_name, cstr("."), a->storage); |
927 | field = str_concat(field, node->next->value.str, a->storage); | 1076 | field = |
1077 | str_concat(field, node->sym.next->value.str, a->storage); | ||
928 | if (!enummap_lookup(&e.scope->enums, field)) { | 1078 | if (!enummap_lookup(&e.scope->enums, field)) { |
929 | eprintln( | 1079 | eprintln( |
930 | "%s:%d:%d: error: unknown enum field for " | 1080 | "%s:%d:%d: error: unknown enum field for " |
931 | "'%s': %s", | 1081 | "'%s': %s", |
932 | a->file_name, node->line, node->col, symbol, | 1082 | a->file_name, node->line, node->col, symbol, |
933 | node->next->value.str); | 1083 | node->sym.next->value.str); |
934 | a->err = true; | 1084 | a->err = true; |
935 | return cstr(""); | 1085 | return cstr(""); |
936 | } | 1086 | } |
937 | 1087 | ||
938 | node->next->type = type_name; | 1088 | node->sym.next->type = type_name; |
939 | node->type = type_name; | 1089 | node->type = type_name; |
940 | return node->next->type; | 1090 | return node->sym.next->type; |
941 | } | 1091 | } |
942 | 1092 | ||
943 | FindStructResult s = find_struct(scope, type_name); | 1093 | FindStructResult s = find_struct(scope, type_name); |
@@ -950,11 +1100,11 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
950 | a->err = true; | 1100 | a->err = true; |
951 | return cstr(""); | 1101 | return cstr(""); |
952 | } else { | 1102 | } else { |
953 | if (node->next) { | 1103 | if (node->sym.next) { |
954 | Str chain = type_name; | 1104 | Str chain = type_name; |
955 | Node *next = node; | 1105 | Node *next = node; |
956 | while (next->next) { | 1106 | while (next->sym.next) { |
957 | next = next->next; | 1107 | next = next->sym.next; |
958 | chain = str_concat(chain, cstr("."), a->storage); | 1108 | chain = str_concat(chain, cstr("."), a->storage); |
959 | chain = | 1109 | chain = |
960 | str_concat(chain, next->value.str, a->storage); | 1110 | str_concat(chain, next->value.str, a->storage); |
@@ -969,18 +1119,18 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
969 | return cstr(""); | 1119 | return cstr(""); |
970 | } | 1120 | } |
971 | Str field_type = field->val.type; | 1121 | Str field_type = field->val.type; |
972 | if (next->kind == NODE_SYMBOL_IDX) { | 1122 | // if (next->kind == NODE_SYMBOL_IDX) { |
973 | Str idx_type = | 1123 | // Str idx_type = |
974 | type_inference(a, next->arr_size, scope); | 1124 | // type_inference(a, next->sym.arr_size, scope); |
975 | if (!strset_lookup(&a->integer_types, idx_type)) { | 1125 | // if (!strset_lookup(&a->integer_types, idx_type)) { |
976 | emit_semantic_error( | 1126 | // emit_semantic_error( |
977 | a, next, | 1127 | // a, next, |
978 | cstr("can't resolve non integer index")); | 1128 | // cstr("can't resolve non integer index")); |
979 | return cstr(""); | 1129 | // return cstr(""); |
980 | } | 1130 | // } |
981 | field_type = | 1131 | // field_type = |
982 | str_remove_prefix(field_type, cstr("@")); | 1132 | // str_remove_prefix(field_type, cstr("@")); |
983 | } | 1133 | // } |
984 | node->type = field_type; | 1134 | node->type = field_type; |
985 | return node->type; | 1135 | return node->type; |
986 | } | 1136 | } |
@@ -989,6 +1139,12 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
989 | node->type = type_name; | 1139 | node->type = type_name; |
990 | return node->type; | 1140 | return node->type; |
991 | } break; | 1141 | } break; |
1142 | case NODE_PTR: { | ||
1143 | Str type = type_inference(a, node->t.next, scope); | ||
1144 | type = str_concat(cstr("@"), type, a->storage); | ||
1145 | node->type = type; | ||
1146 | return node->type; | ||
1147 | } break; | ||
992 | case NODE_STRUCT_LIT: { | 1148 | case NODE_STRUCT_LIT: { |
993 | Str name = node->value.str; | 1149 | Str name = node->value.str; |
994 | FindStructResult s = find_struct(scope, name); | 1150 | FindStructResult s = find_struct(scope, name); |
@@ -1031,27 +1187,62 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
1031 | a->err = true; | 1187 | a->err = true; |
1032 | return cstr(""); | 1188 | return cstr(""); |
1033 | } | 1189 | } |
1034 | // Check that actual parameters typecheck | 1190 | FindSymbolResult sym = find_symbol(scope, symbol); |
1035 | Str args = cstr(""); | 1191 | node->unique_name = str_concat(cstr("."), symbol, a->storage); |
1192 | node->unique_name = | ||
1193 | str_concat(node->unique_name, | ||
1194 | str_from_int(sym.scope->id, a->storage), a->storage); | ||
1195 | |||
1196 | // Check function aritiy. | ||
1197 | sz arity_fun = fun->val.param_arity; | ||
1198 | sz arity_call = array_size(node->elements); | ||
1199 | if (arity_fun != -1) { | ||
1200 | if (arity_fun != arity_call) { | ||
1201 | eprintln( | ||
1202 | "%s:%d:%d: error: wrong number of parameters for " | ||
1203 | "funcall: " | ||
1204 | "%s " | ||
1205 | "expected " | ||
1206 | "%d" | ||
1207 | " got %d", | ||
1208 | a->file_name, node->line, node->col, symbol, arity_fun, | ||
1209 | arity_call); | ||
1210 | a->err = true; | ||
1211 | return cstr(""); | ||
1212 | } | ||
1213 | } | ||
1214 | |||
1215 | if (sym.map->val.kind == SYM_BUILTIN_FUN && | ||
1216 | str_eq(fun->key, cstr("sizeof"))) { | ||
1217 | // Node *expr = node->elements[0]; | ||
1218 | // Str type = type_inference(a, expr, scope); | ||
1219 | node->type = fun->val.return_type; | ||
1220 | return node->type; | ||
1221 | } | ||
1222 | |||
1036 | for (sz i = 0; i < array_size(node->elements); i++) { | 1223 | for (sz i = 0; i < array_size(node->elements); i++) { |
1037 | Node *expr = node->elements[i]; | 1224 | Node *expr = node->elements[i]; |
1038 | Str type = type_inference(a, expr, scope); | 1225 | Str type = type_inference(a, expr, scope); |
1039 | args = str_concat(args, type, a->storage); | 1226 | if (!str_eq(fun->val.param_type, cstr("..."))) { |
1040 | if (i != array_size(node->elements) - 1) { | 1227 | Str expected = fun->val.param_types[i]; |
1041 | args = str_concat(args, cstr(","), a->storage); | 1228 | if (!str_eq(type, expected)) { |
1229 | if (!(strset_lookup(&a->integer_types, type) && | ||
1230 | strset_lookup(&a->integer_types, expected)) || | ||
1231 | !(strset_lookup(&a->numeric_types, type) && | ||
1232 | strset_lookup(&a->numeric_types, expected))) { | ||
1233 | eprintln( | ||
1234 | "%s:%d:%d: error: mismatched parameter types: " | ||
1235 | "%s " | ||
1236 | "expected " | ||
1237 | "%s", | ||
1238 | a->file_name, node->line, node->col, type, | ||
1239 | expected); | ||
1240 | a->err = true; | ||
1241 | return cstr(""); | ||
1242 | } | ||
1243 | } | ||
1042 | } | 1244 | } |
1043 | } | 1245 | } |
1044 | if (!args.size) { | ||
1045 | args = cstr("nil"); | ||
1046 | } | ||
1047 | Str expected = fun->val.param_type; | ||
1048 | if (!str_eq(args, expected) && !str_eq(expected, cstr("..."))) { | ||
1049 | eprintln( | ||
1050 | "%s:%d:%d: error: mismatched parameter types: %s expected " | ||
1051 | "%s", | ||
1052 | a->file_name, node->line, node->col, args, expected); | ||
1053 | a->err = true; | ||
1054 | } | ||
1055 | node->type = fun->val.return_type; | 1246 | node->type = fun->val.return_type; |
1056 | return node->type; | 1247 | return node->type; |
1057 | } break; | 1248 | } break; |
@@ -1061,12 +1252,22 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
1061 | for (sz i = 0; i < array_size(node->elements); i++) { | 1252 | for (sz i = 0; i < array_size(node->elements); i++) { |
1062 | Node *expr = node->elements[i]; | 1253 | Node *expr = node->elements[i]; |
1063 | type = type_inference(a, expr, scope); | 1254 | type = type_inference(a, expr, scope); |
1255 | if (str_has_prefix(type, cstr("ret:")) || | ||
1256 | str_has_prefix(type, cstr("flow:"))) { | ||
1257 | break; | ||
1258 | } | ||
1064 | } | 1259 | } |
1065 | node->type = type; | 1260 | node->type = type; |
1066 | return node->type; | 1261 | return node->type; |
1067 | } break; | 1262 | } break; |
1068 | case NODE_RETURN: { | 1263 | case NODE_RETURN: { |
1069 | Str ret_type = cstr(""); | 1264 | if (!scope->name.size) { |
1265 | emit_semantic_error( | ||
1266 | a, node, cstr("return statement outside a function")); | ||
1267 | a->err = true; | ||
1268 | return cstr(""); | ||
1269 | } | ||
1270 | Str ret_type = cstr("ret:"); | ||
1070 | for (sz i = 0; i < array_size(node->elements); i++) { | 1271 | for (sz i = 0; i < array_size(node->elements); i++) { |
1071 | Node *expr = node->elements[i]; | 1272 | Node *expr = node->elements[i]; |
1072 | Str type = type_inference(a, expr, scope); | 1273 | Str type = type_inference(a, expr, scope); |
@@ -1081,119 +1282,156 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
1081 | node->type = ret_type; | 1282 | node->type = ret_type; |
1082 | return node->type; | 1283 | return node->type; |
1083 | } break; | 1284 | } break; |
1285 | case NODE_CONTINUE: | ||
1286 | case NODE_BREAK: { | ||
1287 | // Check if we are inside a loop. | ||
1288 | Node *parent = node->parent; | ||
1289 | bool inside_loop = false; | ||
1290 | while (parent != NULL) { | ||
1291 | if (parent->kind == NODE_WHILE) { | ||
1292 | inside_loop = true; | ||
1293 | break; | ||
1294 | } | ||
1295 | parent = parent->parent; | ||
1296 | } | ||
1297 | if (!inside_loop) { | ||
1298 | eprintln( | ||
1299 | "%s:%d:%d: error: control flow statement outside a " | ||
1300 | "loop", | ||
1301 | a->file_name, node->line, node->col); | ||
1302 | a->err = true; | ||
1303 | return cstr(""); | ||
1304 | } | ||
1305 | node->type = cstr("flow:"); | ||
1306 | return node->type; | ||
1307 | } break; | ||
1084 | case NODE_FUN: { | 1308 | case NODE_FUN: { |
1085 | node->type = cstr("nil"); | 1309 | node->type = cstr("nil"); |
1086 | Scope *prev_scope = scope; | 1310 | Scope *prev_scope = scope; |
1087 | scope = typescope_alloc(a, scope); | 1311 | scope = typescope_alloc(a, scope); |
1088 | Str param_type = cstr(""); | 1312 | Str param_type = cstr(""); |
1089 | for (sz i = 0; i < array_size(node->func_params); i++) { | 1313 | Str symbol = node->func.name->value.str; |
1090 | Node *param = node->func_params[i]; | 1314 | Fun fun = (Fun){.name = symbol}; |
1091 | Str symbol = param->param_name->value.str; | 1315 | for (sz i = 0; i < array_size(node->func.params); i++) { |
1092 | Str type = param->param_type->value.str; | 1316 | Node *param = node->func.params[i]; |
1093 | if (param->param_type->is_ptr) { | 1317 | Str symbol = param->param.name->value.str; |
1094 | type = str_concat(cstr("@"), type, a->storage); | 1318 | Str type = param->param.type->value.str; |
1095 | } | 1319 | param->param.name->type = |
1096 | if (param->param_type->kind == NODE_ARR_TYPE) { | 1320 | type_inference(a, param->param.type, scope); |
1097 | type = str_concat(cstr("@"), type, a->storage); | ||
1098 | } | ||
1099 | param->param_name->type = | ||
1100 | type_inference(a, param->param_type, scope); | ||
1101 | param->type = type; | 1321 | param->type = type; |
1322 | array_push(fun.param_types, type, a->storage); | ||
1102 | symmap_insert(&scope->symbols, symbol, | 1323 | symmap_insert(&scope->symbols, symbol, |
1103 | (Symbol){.name = type, .kind = SYM_PARAM}, | 1324 | (Symbol){.name = type, .kind = SYM_PARAM}, |
1104 | a->storage); | 1325 | a->storage); |
1105 | param_type = str_concat(param_type, type, a->storage); | 1326 | param_type = str_concat(param_type, type, a->storage); |
1106 | if (i != array_size(node->func_params) - 1) { | 1327 | if (i != array_size(node->func.params) - 1) { |
1107 | param_type = str_concat(param_type, cstr(","), a->storage); | 1328 | param_type = str_concat(param_type, cstr(","), a->storage); |
1108 | } | 1329 | } |
1330 | symbol = str_concat(cstr("."), symbol, a->storage); | ||
1331 | symbol = str_concat(symbol, str_from_int(scope->id, a->storage), | ||
1332 | a->storage); | ||
1333 | param->unique_name = symbol; | ||
1109 | } | 1334 | } |
1110 | if (!param_type.size) { | 1335 | if (!param_type.size) { |
1111 | param_type = cstr("nil"); | 1336 | param_type = cstr("nil"); |
1112 | } | 1337 | } |
1113 | node->fun_params = param_type; | 1338 | node->type_params = param_type; |
1339 | fun.param_arity = array_size(node->func.params); | ||
1114 | 1340 | ||
1115 | Str ret_type = cstr(""); | 1341 | Str ret_type = cstr(""); |
1116 | for (sz i = 0; i < array_size(node->func_ret); i++) { | 1342 | for (sz i = 0; i < array_size(node->func.ret); i++) { |
1117 | Node *expr = node->func_ret[i]; | 1343 | Node *expr = node->func.ret[i]; |
1118 | Str type = type_inference(a, expr, scope); | 1344 | Str type = type_inference(a, expr, scope); |
1119 | if (expr->is_ptr) { | ||
1120 | type = str_concat(cstr("@"), type, a->storage); | ||
1121 | } | ||
1122 | if (expr->kind == NODE_ARR_TYPE) { | ||
1123 | type = str_concat(cstr("@"), type, a->storage); | ||
1124 | } | ||
1125 | ret_type = str_concat(ret_type, type, a->storage); | 1345 | ret_type = str_concat(ret_type, type, a->storage); |
1126 | if (i != array_size(node->func_ret) - 1) { | 1346 | array_push(fun.return_types, ret_type, a->storage); |
1347 | if (i != array_size(node->func.ret) - 1) { | ||
1127 | ret_type = str_concat(ret_type, cstr(","), a->storage); | 1348 | ret_type = str_concat(ret_type, cstr(","), a->storage); |
1128 | } | 1349 | } |
1129 | } | 1350 | } |
1351 | fun.return_arity = array_size(node->func.ret); | ||
1130 | if (!ret_type.size) { | 1352 | if (!ret_type.size) { |
1131 | ret_type = cstr("nil"); | 1353 | ret_type = cstr("nil"); |
1132 | } | 1354 | } |
1133 | node->fun_return = ret_type; | 1355 | node->type_returns = ret_type; |
1134 | 1356 | ||
1135 | Str symbol = node->func_name->value.str; | ||
1136 | if (prev_scope->parent != NULL) { | 1357 | if (prev_scope->parent != NULL) { |
1137 | if (symmap_lookup(&prev_scope->symbols, symbol)) { | 1358 | if (symmap_lookup(&prev_scope->symbols, symbol)) { |
1138 | eprintln( | 1359 | eprintln( |
1139 | "%s:%d:%d: error: function '%s' already defined in " | 1360 | "%s:%d:%d: error: function '%s' already defined in " |
1140 | "current " | 1361 | "current " |
1141 | "scope ", | 1362 | "scope ", |
1142 | a->file_name, node->var_name->line, node->var_name->col, | 1363 | a->file_name, node->var.name->line, node->var.name->col, |
1143 | symbol); | 1364 | symbol); |
1144 | a->err = true; | 1365 | a->err = true; |
1145 | return cstr(""); | 1366 | return cstr(""); |
1146 | } | 1367 | } |
1147 | symmap_insert(&scope->symbols, symbol, | 1368 | symmap_insert(&prev_scope->symbols, symbol, |
1148 | (Symbol){.name = symbol, .kind = SYM_FUN}, | 1369 | (Symbol){.name = symbol, .kind = SYM_FUN}, |
1149 | a->storage); | 1370 | a->storage); |
1150 | } | 1371 | } |
1151 | scope->name = symbol; | 1372 | scope->name = symbol; |
1152 | funmap_insert(&prev_scope->funcs, symbol, | 1373 | fun.param_type = param_type; |
1153 | (Fun){.name = symbol, | 1374 | fun.return_type = ret_type; |
1154 | .param_type = param_type, | 1375 | funmap_insert(&prev_scope->funcs, symbol, fun, a->storage); |
1155 | .return_type = ret_type}, | 1376 | symbol = str_concat(cstr("."), symbol, a->storage); |
1156 | a->storage); | 1377 | symbol = str_concat( |
1378 | symbol, str_from_int(prev_scope->id, a->storage), a->storage); | ||
1379 | node->unique_name = symbol; | ||
1157 | 1380 | ||
1158 | if (node->func_body->kind == NODE_BLOCK) { | 1381 | if (node->func.body->kind == NODE_BLOCK) { |
1159 | Str type; | 1382 | Str type; |
1160 | for (sz i = 0; i < array_size(node->func_body->elements); i++) { | 1383 | for (sz i = 0; i < array_size(node->func.body->elements); i++) { |
1161 | Node *expr = node->func_body->elements[i]; | 1384 | Node *expr = node->func.body->elements[i]; |
1162 | type = type_inference(a, expr, scope); | 1385 | type = type_inference(a, expr, scope); |
1163 | } | 1386 | } |
1164 | if (!type.size) { | 1387 | if (!type.size) { |
1165 | type = cstr("nil"); | 1388 | type = cstr("nil"); |
1166 | } | 1389 | } |
1167 | node->func_body->type = type; | 1390 | node->func.body->type = type; |
1168 | } else { | 1391 | } else { |
1169 | type_inference(a, node->func_body, scope); | 1392 | type_inference(a, node->func.body, scope); |
1170 | } | 1393 | } |
1171 | 1394 | ||
1172 | // Ensure main body return matches the prototype. | 1395 | // Ensure main body return matches the prototype. |
1173 | if (!str_eq(node->func_body->type, ret_type)) { | 1396 | Str type = str_remove_prefix(node->func.body->type, cstr("ret:")); |
1174 | eprintln( | 1397 | node->func.body->type = type; |
1175 | "%s:%d:%d: error: mismatched return type %s, expected %s", | 1398 | if (!str_eq(type, ret_type)) { |
1176 | a->file_name, node->line, node->col, node->func_body->type, | 1399 | if (!(strset_lookup(&a->integer_types, type) && |
1177 | ret_type); | 1400 | strset_lookup(&a->integer_types, ret_type)) || |
1178 | a->err = true; | 1401 | !(strset_lookup(&a->numeric_types, type) && |
1402 | strset_lookup(&a->numeric_types, ret_type))) { | ||
1403 | eprintln( | ||
1404 | "%s:%d:%d: error: mismatched return type %s, " | ||
1405 | "expected " | ||
1406 | "%s", | ||
1407 | a->file_name, node->line, node->col, type, ret_type); | ||
1408 | a->err = true; | ||
1409 | } | ||
1179 | } | 1410 | } |
1180 | 1411 | ||
1181 | // Ensure ALL return statements match the function prototype. | 1412 | // Ensure ALL return statements match the function prototype. |
1182 | typecheck_returns(a, node->func_body, ret_type); | 1413 | typecheck_returns(a, node->func.body, ret_type); |
1183 | |||
1184 | // TODO: should return statements be allowed on let blocks? | ||
1185 | return node->type; | 1414 | return node->type; |
1186 | } break; | 1415 | } break; |
1187 | default: { | 1416 | default: { |
1188 | emit_semantic_error(a, node, | 1417 | eprintln( |
1189 | cstr("type inference not implemented for this " | 1418 | "%s:%d:%d: error: type inference not implemented for node " |
1190 | "kind of expression")); | 1419 | "type: %s", |
1191 | println("KIND: %s", node_str[node->kind]); | 1420 | a->file_name, node->line, node->col, node_str[node->kind]); |
1421 | a->err = true; | ||
1192 | } break; | 1422 | } break; |
1193 | } | 1423 | } |
1194 | return cstr(""); | 1424 | return cstr(""); |
1195 | } | 1425 | } |
1196 | 1426 | ||
1427 | typedef struct BuiltinFun { | ||
1428 | Str name; | ||
1429 | Str param_type; | ||
1430 | Str return_type; | ||
1431 | sz param_arity; | ||
1432 | sz return_arity; | ||
1433 | } BuiltinFun; | ||
1434 | |||
1197 | void | 1435 | void |
1198 | symbolic_analysis(Analyzer *a, Parser *parser) { | 1436 | symbolic_analysis(Analyzer *a, Parser *parser) { |
1199 | Scope *scope = typescope_alloc(a, NULL); | 1437 | Scope *scope = typescope_alloc(a, NULL); |
@@ -1201,64 +1439,114 @@ symbolic_analysis(Analyzer *a, Parser *parser) { | |||
1201 | assert(parser); | 1439 | assert(parser); |
1202 | 1440 | ||
1203 | // Fill builtin tables. | 1441 | // Fill builtin tables. |
1204 | Str builtin_functions[] = { | 1442 | BuiltinFun builtin_functions[] = { |
1205 | cstr("print"), | 1443 | {cstr("print"), cstr("..."), cstr("nil"), -1, 0}, |
1206 | cstr("println"), | 1444 | {cstr("println"), cstr("..."), cstr("nil"), -1, 0}, |
1445 | {cstr("sizeof"), cstr(":"), cstr("Int"), 1, 1}, | ||
1207 | }; | 1446 | }; |
1208 | for (sz i = 0; i < LEN(builtin_functions); i++) { | 1447 | for (sz i = 0; i < LEN(builtin_functions); i++) { |
1209 | Str symbol = builtin_functions[i]; | 1448 | Str symbol = builtin_functions[i].name; |
1449 | Str param_type = builtin_functions[i].param_type; | ||
1450 | Str return_type = builtin_functions[i].return_type; | ||
1451 | sz param_arity = builtin_functions[i].param_arity; | ||
1452 | sz return_arity = builtin_functions[i].return_arity; | ||
1210 | symmap_insert(&scope->symbols, symbol, | 1453 | symmap_insert(&scope->symbols, symbol, |
1211 | (Symbol){.name = symbol, .kind = SYM_BUILTIN_FUN}, | 1454 | (Symbol){.name = symbol, .kind = SYM_BUILTIN_FUN}, |
1212 | a->storage); | 1455 | a->storage); |
1213 | funmap_insert(&scope->funcs, symbol, | 1456 | funmap_insert(&scope->funcs, symbol, |
1214 | (Fun){.name = symbol, | 1457 | (Fun){ |
1215 | .param_type = cstr("..."), | 1458 | .name = symbol, |
1216 | .return_type = cstr("nil")}, | 1459 | .param_type = param_type, |
1460 | .return_type = return_type, | ||
1461 | .param_arity = param_arity, | ||
1462 | .return_arity = return_arity, | ||
1463 | }, | ||
1217 | a->storage); | 1464 | a->storage); |
1218 | } | 1465 | } |
1219 | Str builtin_types[] = { | 1466 | Str builtin_types[] = { |
1220 | cstr("u8"), cstr("s8"), cstr("u16"), cstr("s16"), | 1467 | cstr("U8"), cstr("S8"), cstr("U16"), cstr("S16"), |
1221 | cstr("u32"), cstr("s32"), cstr("u64"), cstr("s64"), | 1468 | cstr("U32"), cstr("S32"), cstr("U64"), cstr("S64"), |
1222 | cstr("f32"), cstr("f64"), cstr("ptr"), cstr("int"), | 1469 | cstr("F32"), cstr("F64"), cstr("Ptr"), cstr("Int"), |
1223 | cstr("uint"), cstr("str"), cstr("bool"), cstr("nil")}; | 1470 | cstr("UInt"), cstr("Str"), cstr("Bool"), cstr("Nil")}; |
1224 | for (sz i = 0; i < LEN(builtin_types); i++) { | 1471 | for (sz i = 0; i < LEN(builtin_types); i++) { |
1225 | Str type = builtin_types[i]; | 1472 | Str type = builtin_types[i]; |
1226 | symmap_insert(&scope->symbols, type, | 1473 | symmap_insert(&scope->symbols, type, |
1227 | (Symbol){.name = type, .kind = SYM_BUILTIN_TYPE}, | 1474 | (Symbol){.name = cstr("nil"), .kind = SYM_BUILTIN_TYPE}, |
1228 | a->storage); | 1475 | a->storage); |
1476 | strset_insert(&scope->types, type, a->storage); | ||
1229 | } | 1477 | } |
1230 | Str numeric_types[] = { | 1478 | Str numeric_types[] = { |
1231 | cstr("u8"), cstr("s8"), cstr("u16"), cstr("s16"), cstr("u32"), | 1479 | cstr("U8"), cstr("S8"), cstr("U16"), cstr("S16"), cstr("U32"), |
1232 | cstr("s32"), cstr("u64"), cstr("s64"), cstr("f32"), cstr("f64"), | 1480 | cstr("S32"), cstr("U64"), cstr("S64"), cstr("F32"), cstr("F64"), |
1233 | cstr("ptr"), cstr("int"), cstr("uint"), | 1481 | cstr("Ptr"), cstr("Int"), cstr("UInt"), |
1234 | }; | 1482 | }; |
1235 | for (sz i = 0; i < LEN(numeric_types); i++) { | 1483 | for (sz i = 0; i < LEN(numeric_types); i++) { |
1236 | Str type = numeric_types[i]; | 1484 | Str type = numeric_types[i]; |
1237 | strset_insert(&a->numeric_types, type, a->storage); | 1485 | strset_insert(&a->numeric_types, type, a->storage); |
1238 | } | 1486 | } |
1239 | Str integer_types[] = { | 1487 | Str integer_types[] = { |
1240 | cstr("u8"), cstr("s8"), cstr("u16"), cstr("s16"), | 1488 | cstr("U8"), cstr("S8"), cstr("U16"), cstr("S16"), |
1241 | cstr("u32"), cstr("s32"), cstr("u64"), cstr("s64"), | 1489 | cstr("U32"), cstr("S32"), cstr("U64"), cstr("S64"), |
1242 | cstr("ptr"), cstr("int"), cstr("uint"), | 1490 | cstr("Ptr"), cstr("Int"), cstr("UInt"), |
1243 | }; | 1491 | }; |
1244 | for (sz i = 0; i < LEN(integer_types); i++) { | 1492 | for (sz i = 0; i < LEN(integer_types); i++) { |
1245 | Str type = integer_types[i]; | 1493 | Str type = integer_types[i]; |
1246 | strset_insert(&a->integer_types, type, a->storage); | 1494 | strset_insert(&a->integer_types, type, a->storage); |
1247 | } | 1495 | } |
1496 | Str float_types[] = { | ||
1497 | cstr("F32"), | ||
1498 | cstr("F64"), | ||
1499 | }; | ||
1500 | for (sz i = 0; i < LEN(float_types); i++) { | ||
1501 | Str type = float_types[i]; | ||
1502 | strset_insert(&a->float_types, type, a->storage); | ||
1503 | } | ||
1248 | // Find top level function declarations. | 1504 | // Find top level function declarations. |
1249 | for (sz i = 0; i < array_size(parser->nodes); i++) { | 1505 | for (sz i = 0; i < array_size(parser->nodes); i++) { |
1250 | Node *root = parser->nodes[i]; | 1506 | Node *root = parser->nodes[i]; |
1251 | if (root->kind == NODE_FUN) { | 1507 | if (root->kind == NODE_FUN) { |
1252 | Str symbol = root->func_name->value.str; | 1508 | Str symbol = root->func.name->value.str; |
1253 | if (symmap_lookup(&scope->symbols, symbol)) { | 1509 | if (symmap_lookup(&scope->symbols, symbol)) { |
1254 | eprintln( | 1510 | eprintln( |
1255 | "%s:%d:%d: error: function '%s' already defined in " | 1511 | "%s:%d:%d: error: function '%s' already defined in " |
1256 | "current " | 1512 | "current " |
1257 | "scope ", | 1513 | "scope ", |
1258 | a->file_name, root->var_name->line, root->var_name->col, | 1514 | a->file_name, root->var.name->line, root->var.name->col, |
1259 | symbol); | 1515 | symbol); |
1260 | a->err = true; | 1516 | a->err = true; |
1261 | } | 1517 | } |
1518 | Fun fun = (Fun){.name = symbol}; | ||
1519 | Str param_type = cstr(""); | ||
1520 | for (sz i = 0; i < array_size(root->func.params); i++) { | ||
1521 | Node *param = root->func.params[i]; | ||
1522 | Str type = param->param.type->value.str; | ||
1523 | array_push(fun.param_types, type, a->storage); | ||
1524 | param_type = str_concat(param_type, type, a->storage); | ||
1525 | if (i != array_size(root->func.params) - 1) { | ||
1526 | param_type = str_concat(param_type, cstr(","), a->storage); | ||
1527 | } | ||
1528 | } | ||
1529 | if (!param_type.size) { | ||
1530 | param_type = cstr("nil"); | ||
1531 | } | ||
1532 | root->type_params = param_type; | ||
1533 | |||
1534 | Str ret_type = cstr(""); | ||
1535 | for (sz i = 0; i < array_size(root->func.ret); i++) { | ||
1536 | Node *expr = root->func.ret[i]; | ||
1537 | Str type = expr->value.str; | ||
1538 | array_push(fun.return_types, ret_type, a->storage); | ||
1539 | ret_type = str_concat(ret_type, type, a->storage); | ||
1540 | if (i != array_size(root->func.ret) - 1) { | ||
1541 | ret_type = str_concat(ret_type, cstr(","), a->storage); | ||
1542 | } | ||
1543 | } | ||
1544 | if (!ret_type.size) { | ||
1545 | ret_type = cstr("nil"); | ||
1546 | } | ||
1547 | fun.param_type = param_type; | ||
1548 | fun.return_type = ret_type; | ||
1549 | funmap_insert(&scope->funcs, symbol, fun, a->storage); | ||
1262 | symmap_insert(&scope->symbols, symbol, | 1550 | symmap_insert(&scope->symbols, symbol, |
1263 | (Symbol){.name = symbol, .kind = SYM_FUN}, | 1551 | (Symbol){.name = symbol, .kind = SYM_FUN}, |
1264 | a->storage); | 1552 | a->storage); |