diff options
Diffstat (limited to 'src/semantic.c')
-rw-r--r-- | src/semantic.c | 538 |
1 files changed, 383 insertions, 155 deletions
diff --git a/src/semantic.c b/src/semantic.c index 1b40723..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); |
@@ -146,6 +149,23 @@ find_struct(Scope *scope, Str type) { | |||
146 | return (FindStructResult){0}; | 149 | return (FindStructResult){0}; |
147 | } | 150 | } |
148 | 151 | ||
152 | typedef struct FindSymbolResult { | ||
153 | SymbolMap *map; | ||
154 | Scope *scope; | ||
155 | } FindSymbolResult; | ||
156 | |||
157 | FindSymbolResult | ||
158 | find_symbol(Scope *scope, Str type) { | ||
159 | while (scope != NULL) { | ||
160 | SymbolMap *val = symmap_lookup(&scope->symbols, type); | ||
161 | if (val != NULL) { | ||
162 | return (FindSymbolResult){.map = val, .scope = scope}; | ||
163 | } | ||
164 | scope = scope->parent; | ||
165 | } | ||
166 | return (FindSymbolResult){0}; | ||
167 | } | ||
168 | |||
149 | void | 169 | void |
150 | graph_typescope(Scope *scope, Arena a) { | 170 | graph_typescope(Scope *scope, Arena a) { |
151 | if (!scope->symbols) { | 171 | if (!scope->symbols) { |
@@ -259,7 +279,7 @@ Str type_inference(Analyzer *a, Node *node, Scope *scope); | |||
259 | 279 | ||
260 | void | 280 | void |
261 | typecheck_field(Analyzer *a, Node *node, Scope *scope, Str symbol) { | 281 | typecheck_field(Analyzer *a, Node *node, Scope *scope, Str symbol) { |
262 | if (node->field_type->kind == NODE_COMPOUND_TYPE) { | 282 | if (node->field.type->kind == NODE_COMPOUND_TYPE) { |
263 | Str field_name = str_concat(symbol, cstr("."), a->storage); | 283 | Str field_name = str_concat(symbol, cstr("."), a->storage); |
264 | field_name = str_concat(field_name, node->value.str, a->storage); | 284 | field_name = str_concat(field_name, node->value.str, a->storage); |
265 | if (structmap_lookup(&scope->structs, field_name)) { | 285 | if (structmap_lookup(&scope->structs, field_name)) { |
@@ -268,8 +288,8 @@ typecheck_field(Analyzer *a, Node *node, Scope *scope, Str symbol) { | |||
268 | a->err = true; | 288 | a->err = true; |
269 | } | 289 | } |
270 | Str type = cstr("\\{ "); | 290 | Str type = cstr("\\{ "); |
271 | 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++) { |
272 | Node *field = node->field_type->elements[i]; | 292 | Node *field = node->field.type->elements[i]; |
273 | typecheck_field(a, field, scope, field_name); | 293 | typecheck_field(a, field, scope, field_name); |
274 | type = str_concat(type, field->type, a->storage); | 294 | type = str_concat(type, field->type, a->storage); |
275 | type = str_concat(type, cstr(" "), a->storage); | 295 | type = str_concat(type, cstr(" "), a->storage); |
@@ -279,16 +299,16 @@ typecheck_field(Analyzer *a, Node *node, Scope *scope, Str symbol) { | |||
279 | } else { | 299 | } else { |
280 | Str field_name = str_concat(symbol, cstr("."), a->storage); | 300 | Str field_name = str_concat(symbol, cstr("."), a->storage); |
281 | field_name = str_concat(field_name, node->value.str, a->storage); | 301 | field_name = str_concat(field_name, node->value.str, a->storage); |
282 | Str field_type = node->field_type->value.str; | 302 | Str field_type = node->field.type->value.str; |
283 | if (!find_type(scope, field_type)) { | 303 | if (!find_type(scope, field_type)) { |
284 | eprintln("%s:%d:%d: error: unknown type '%s'", a->file_name, | 304 | eprintln("%s:%d:%d: error: unknown type '%s'", a->file_name, |
285 | node->field_type->line, node->field_type->col, field_type); | 305 | node->field.type->line, node->field.type->col, field_type); |
286 | a->err = true; | 306 | a->err = true; |
287 | } | 307 | } |
288 | if (node->field_type->is_ptr) { | 308 | if (node->field.type->is_ptr) { |
289 | field_type = str_concat(cstr("@"), field_type, a->storage); | 309 | field_type = str_concat(cstr("@"), field_type, a->storage); |
290 | } | 310 | } |
291 | if (node->field_type->kind == NODE_ARR_TYPE) { | 311 | if (node->field.type->kind == NODE_ARR_TYPE) { |
292 | field_type = str_concat(cstr("@"), field_type, a->storage); | 312 | field_type = str_concat(cstr("@"), field_type, a->storage); |
293 | } | 313 | } |
294 | if (structmap_lookup(&scope->structs, field_name)) { | 314 | if (structmap_lookup(&scope->structs, field_name)) { |
@@ -296,8 +316,8 @@ typecheck_field(Analyzer *a, Node *node, Scope *scope, Str symbol) { | |||
296 | a->file_name, node->line, node->col, field_name); | 316 | a->file_name, node->line, node->col, field_name); |
297 | a->err = true; | 317 | a->err = true; |
298 | } | 318 | } |
299 | if (node->field_val) { | 319 | if (node->field.val) { |
300 | Str type = type_inference(a, node->field_val, scope); | 320 | Str type = type_inference(a, node->field.val, scope); |
301 | if (!str_eq(type, field_type)) { | 321 | if (!str_eq(type, field_type)) { |
302 | eprintln( | 322 | eprintln( |
303 | "%s:%d:%d: error: mismatched types in struct " | 323 | "%s:%d:%d: error: mismatched types in struct " |
@@ -312,7 +332,7 @@ typecheck_field(Analyzer *a, Node *node, Scope *scope, Str symbol) { | |||
312 | (Struct){ | 332 | (Struct){ |
313 | .name = field_name, | 333 | .name = field_name, |
314 | .type = field_type, | 334 | .type = field_type, |
315 | .val = node->field_val, | 335 | .val = node->field.val, |
316 | }, | 336 | }, |
317 | a->storage); | 337 | a->storage); |
318 | symmap_insert(&scope->symbols, field_name, | 338 | symmap_insert(&scope->symbols, field_name, |
@@ -324,10 +344,10 @@ typecheck_field(Analyzer *a, Node *node, Scope *scope, Str symbol) { | |||
324 | 344 | ||
325 | void | 345 | void |
326 | typecheck_lit_field(Analyzer *a, Node *node, Scope *scope, Str symbol) { | 346 | typecheck_lit_field(Analyzer *a, Node *node, Scope *scope, Str symbol) { |
327 | if (node->field_val->kind == NODE_COMPOUND_TYPE) { | 347 | if (node->field.val->kind == NODE_COMPOUND_TYPE) { |
328 | Str type = cstr("\\{ "); | 348 | Str type = cstr("\\{ "); |
329 | 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++) { |
330 | Node *field = node->field_val->elements[i]; | 350 | Node *field = node->field.val->elements[i]; |
331 | Str field_name = str_concat(symbol, cstr("."), a->storage); | 351 | Str field_name = str_concat(symbol, cstr("."), a->storage); |
332 | field_name = str_concat(field_name, field->value.str, a->storage); | 352 | field_name = str_concat(field_name, field->value.str, a->storage); |
333 | typecheck_lit_field(a, field, scope, field_name); | 353 | typecheck_lit_field(a, field, scope, field_name); |
@@ -345,7 +365,7 @@ typecheck_lit_field(Analyzer *a, Node *node, Scope *scope, Str symbol) { | |||
345 | return; | 365 | return; |
346 | } | 366 | } |
347 | Str field_type = s->val.type; | 367 | Str field_type = s->val.type; |
348 | Str type = type_inference(a, node->field_val, scope); | 368 | Str type = type_inference(a, node->field.val, scope); |
349 | if (!str_eq(type, field_type)) { | 369 | if (!str_eq(type, field_type)) { |
350 | eprintln( | 370 | eprintln( |
351 | "%s:%d:%d: error: mismatched types in struct " | 371 | "%s:%d:%d: error: mismatched types in struct " |
@@ -367,17 +387,18 @@ typecheck_returns(Analyzer *a, Node *node, Str expected) { | |||
367 | switch (node->kind) { | 387 | switch (node->kind) { |
368 | case NODE_COND: | 388 | case NODE_COND: |
369 | case NODE_MATCH: { | 389 | case NODE_MATCH: { |
370 | for (sz i = 0; i < array_size(node->match_cases); i++) { | 390 | for (sz i = 0; i < array_size(node->match.cases); i++) { |
371 | Node *next = node->match_cases[i]; | 391 | Node *next = node->match.cases[i]; |
372 | typecheck_returns(a, next, expected); | 392 | typecheck_returns(a, next, expected); |
373 | } | 393 | } |
374 | } break; | 394 | } break; |
375 | case NODE_RETURN: { | 395 | case NODE_RETURN: { |
376 | bool err = !str_eq(node->type, expected); | 396 | Str type = str_remove_prefix(node->type, cstr("ret:")); |
397 | bool err = !str_eq(type, expected); | ||
377 | if (err) { | 398 | if (err) { |
378 | eprintln( | 399 | eprintln( |
379 | "%s:%d:%d: error: mismatched return type %s, expected %s", | 400 | "%s:%d:%d: error: mismatched return type %s, expected %s", |
380 | a->file_name, node->line, node->col, node->type, expected); | 401 | a->file_name, node->line, node->col, type, expected); |
381 | a->err = true; | 402 | a->err = true; |
382 | } | 403 | } |
383 | } break; | 404 | } break; |
@@ -388,17 +409,17 @@ typecheck_returns(Analyzer *a, Node *node, Str expected) { | |||
388 | } | 409 | } |
389 | } break; | 410 | } break; |
390 | case NODE_IF: { | 411 | case NODE_IF: { |
391 | if (node->cond_expr) { | 412 | if (node->ifelse.expr_true) { |
392 | typecheck_returns(a, node->cond_expr, expected); | 413 | typecheck_returns(a, node->ifelse.expr_true, expected); |
393 | } | 414 | } |
394 | if (node->cond_else) { | 415 | if (node->ifelse.expr_else) { |
395 | typecheck_returns(a, node->cond_else, expected); | 416 | typecheck_returns(a, node->ifelse.expr_else, expected); |
396 | } | 417 | } |
397 | } break; | 418 | } break; |
398 | case NODE_SET: | 419 | case NODE_SET: |
399 | case NODE_LET: { | 420 | case NODE_LET: { |
400 | if (node->var_val) { | 421 | if (node->var.val) { |
401 | typecheck_returns(a, node->var_val, expected); | 422 | typecheck_returns(a, node->var.val, expected); |
402 | } | 423 | } |
403 | } break; | 424 | } break; |
404 | case NODE_ADD: | 425 | case NODE_ADD: |
@@ -418,13 +439,14 @@ typecheck_returns(Analyzer *a, Node *node, Str expected) { | |||
418 | case NODE_BITNOT: | 439 | case NODE_BITNOT: |
419 | case NODE_BITAND: | 440 | case NODE_BITAND: |
420 | case NODE_BITOR: | 441 | case NODE_BITOR: |
442 | case NODE_BITXOR: | ||
421 | case NODE_BITLSHIFT: | 443 | case NODE_BITLSHIFT: |
422 | case NODE_BITRSHIFT: { | 444 | case NODE_BITRSHIFT: { |
423 | if (node->left) { | 445 | if (node->binary.left) { |
424 | typecheck_returns(a, node->left, expected); | 446 | typecheck_returns(a, node->binary.left, expected); |
425 | } | 447 | } |
426 | if (node->right) { | 448 | if (node->binary.right) { |
427 | typecheck_returns(a, node->right, expected); | 449 | typecheck_returns(a, node->binary.right, expected); |
428 | } | 450 | } |
429 | } break; | 451 | } break; |
430 | default: break; | 452 | default: break; |
@@ -435,66 +457,79 @@ Str | |||
435 | type_inference(Analyzer *a, Node *node, Scope *scope) { | 457 | type_inference(Analyzer *a, Node *node, Scope *scope) { |
436 | assert(a); | 458 | assert(a); |
437 | assert(scope); | 459 | assert(scope); |
438 | if (!node) { | 460 | if (!node || a->err) { |
439 | return cstr(""); | 461 | return cstr(""); |
440 | } | 462 | } |
441 | // 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. |
442 | switch (node->kind) { | 464 | switch (node->kind) { |
443 | case NODE_LET: { | 465 | case NODE_LET: { |
444 | node->type = cstr("nil"); | 466 | node->type = cstr("nil"); |
445 | Str symbol = node->var_name->value.str; | 467 | node->var.name->parent = node; |
468 | Str symbol = node->var.name->value.str; | ||
446 | if (symmap_lookup(&scope->symbols, symbol)) { | 469 | if (symmap_lookup(&scope->symbols, symbol)) { |
447 | eprintln( | 470 | eprintln( |
448 | "%s:%d:%d: error: symbol '%s' already exists in current " | 471 | "%s:%d:%d: error: symbol '%s' already exists in current " |
449 | "scope ", | 472 | "scope ", |
450 | a->file_name, node->var_name->line, node->var_name->col, | 473 | a->file_name, node->var.name->line, node->var.name->col, |
451 | symbol); | 474 | symbol); |
452 | a->err = true; | 475 | a->err = true; |
453 | return cstr(""); | 476 | return cstr(""); |
454 | } | 477 | } |
455 | if (node->var_type) { | 478 | if (node->var.type) { |
456 | Str type_name = node->var_type->value.str; | 479 | node->var.type->parent = node; |
480 | Str type_name = node->var.type->value.str; | ||
457 | SymbolMap *type = find_type(scope, type_name); | 481 | SymbolMap *type = find_type(scope, type_name); |
458 | if (type == NULL) { | 482 | if (type == NULL) { |
459 | eprintln("%s:%d:%d: error: unknown type '%s'", a->file_name, | 483 | eprintln("%s:%d:%d: error: unknown type '%s'", a->file_name, |
460 | node->var_type->line, node->var_type->col, | 484 | node->var.type->line, node->var.type->col, |
461 | type_name); | 485 | type_name); |
462 | a->err = true; | 486 | a->err = true; |
463 | return cstr(""); | 487 | return cstr(""); |
464 | } | 488 | } |
465 | if (node->var_type->is_ptr) { | 489 | if (node->var.type->is_ptr) { |
466 | type_name = str_concat(cstr("@"), type_name, a->storage); | 490 | type_name = str_concat(cstr("@"), type_name, a->storage); |
467 | } | 491 | } |
468 | if (node->var_type->kind == NODE_ARR_TYPE) { | 492 | if (node->var.type->kind == NODE_ARR_TYPE) { |
469 | type_name = str_concat(cstr("@"), type_name, a->storage); | 493 | type_name = str_concat(cstr("@"), type_name, a->storage); |
470 | // 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 | } | ||
471 | // TODO: register array in scope | 501 | // TODO: register array in scope |
472 | } | 502 | } |
473 | if (node->var_val) { | 503 | if (node->var.val) { |
474 | 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); | ||
475 | if (!type.size) { | 506 | if (!type.size) { |
476 | eprintln( | 507 | eprintln( |
477 | "%s:%d:%d: error: can't bind `nil` to variable " | 508 | "%s:%d:%d: error: can't bind `nil` to variable " |
478 | "'%s'", | 509 | "'%s'", |
479 | a->file_name, node->var_type->line, | 510 | a->file_name, node->var.type->line, |
480 | node->var_type->col, symbol); | 511 | node->var.type->col, symbol); |
481 | a->err = true; | 512 | a->err = true; |
482 | return cstr(""); | 513 | return cstr(""); |
483 | } | 514 | } |
484 | // TODO: Consider compatible types. | ||
485 | if (!str_eq(type, type_name)) { | 515 | if (!str_eq(type, type_name)) { |
486 | // Special case, enums can be treated as ints. | 516 | if (!(strset_lookup(&a->integer_types, type) && |
487 | FindEnumResult res = find_enum(scope, type_name); | 517 | strset_lookup(&a->integer_types, type_name)) && |
488 | if (!(res.map && str_eq(type, cstr("int")))) { | 518 | !(strset_lookup(&a->numeric_types, type) && |
489 | eprintln( | 519 | strset_lookup(&a->numeric_types, type_name))) { |
490 | "%s:%d:%d: error: type mismatch, trying to " | 520 | // Special case, enums can be treated as ints. |
491 | "assing " | 521 | FindEnumResult res = find_enum(scope, type_name); |
492 | "%s" | 522 | if (!(res.map && str_eq(type, cstr("int")))) { |
493 | " to a variable of type %s", | 523 | eprintln( |
494 | a->file_name, node->var_type->line, | 524 | "%s:%d:%d: error: type mismatch, trying to " |
495 | node->var_type->col, type, type_name); | 525 | "assing " |
496 | a->err = true; | 526 | "%s" |
497 | 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 | } | ||
498 | } | 533 | } |
499 | } | 534 | } |
500 | } | 535 | } |
@@ -504,17 +539,29 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
504 | .kind = SYM_VAR, | 539 | .kind = SYM_VAR, |
505 | }, | 540 | }, |
506 | 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; | ||
507 | return node->type; | 547 | return node->type; |
508 | } | 548 | } |
509 | 549 | ||
510 | // We don't know the type for this symbol, perform inference. | 550 | // We don't know the type for this symbol, perform inference. |
511 | Str type = type_inference(a, node->var_val, scope); | 551 | node->var.val->parent = node; |
512 | if (type.size) { | 552 | Str type = type_inference(a, node->var.val, scope); |
513 | symmap_insert(&scope->symbols, symbol, | 553 | if (!type.size || str_eq(type, cstr("nil")) || |
514 | (Symbol){.name = type, .kind = SYM_VAR}, | 554 | str_has_prefix(type, cstr("ret:"))) { |
515 | a->storage); | 555 | eprintln( |
516 | 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(""); | ||
517 | } | 561 | } |
562 | symmap_insert(&scope->symbols, symbol, | ||
563 | (Symbol){.name = type, .kind = SYM_VAR}, a->storage); | ||
564 | node->var.name->type = type; | ||
518 | symbol = str_concat(cstr("."), symbol, a->storage); | 565 | symbol = str_concat(cstr("."), symbol, a->storage); |
519 | symbol = str_concat(symbol, str_from_int(scope->id, a->storage), | 566 | symbol = str_concat(symbol, str_from_int(scope->id, a->storage), |
520 | a->storage); | 567 | a->storage); |
@@ -522,8 +569,10 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
522 | return node->type; | 569 | return node->type; |
523 | } break; | 570 | } break; |
524 | case NODE_SET: { | 571 | case NODE_SET: { |
525 | Str name = type_inference(a, node->var_name, scope); | 572 | node->var.name->parent = node; |
526 | 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); | ||
527 | if (!str_eq(name, val)) { | 576 | if (!str_eq(name, val)) { |
528 | eprintln( | 577 | eprintln( |
529 | "%s:%d:%d: error: type mismatch, trying to assing " | 578 | "%s:%d:%d: error: type mismatch, trying to assing " |
@@ -533,6 +582,12 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
533 | a->err = true; | 582 | a->err = true; |
534 | return cstr(""); | 583 | return cstr(""); |
535 | } | 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); | ||
536 | node->type = cstr("nil"); | 591 | node->type = cstr("nil"); |
537 | return node->type; | 592 | return node->type; |
538 | } break; | 593 | } break; |
@@ -551,6 +606,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
551 | a->storage); | 606 | a->storage); |
552 | for (sz i = 0; i < array_size(node->struct_field); i++) { | 607 | for (sz i = 0; i < array_size(node->struct_field); i++) { |
553 | Node *field = node->struct_field[i]; | 608 | Node *field = node->struct_field[i]; |
609 | field->parent = node; | ||
554 | typecheck_field(a, field, scope, symbol); | 610 | typecheck_field(a, field, scope, symbol); |
555 | } | 611 | } |
556 | symmap_insert(&scope->symbols, symbol, | 612 | symmap_insert(&scope->symbols, symbol, |
@@ -572,11 +628,12 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
572 | enummap_insert(&scope->enums, symbol, | 628 | enummap_insert(&scope->enums, symbol, |
573 | (Enum){ | 629 | (Enum){ |
574 | .name = symbol, | 630 | .name = symbol, |
575 | .val = node->field_val, | 631 | .val = node->field.val, |
576 | }, | 632 | }, |
577 | a->storage); | 633 | a->storage); |
578 | for (sz i = 0; i < array_size(node->struct_field); i++) { | 634 | for (sz i = 0; i < array_size(node->struct_field); i++) { |
579 | Node *field = node->struct_field[i]; | 635 | Node *field = node->struct_field[i]; |
636 | field->parent = node; | ||
580 | Str field_name = str_concat(symbol, cstr("."), a->storage); | 637 | Str field_name = str_concat(symbol, cstr("."), a->storage); |
581 | field_name = | 638 | field_name = |
582 | str_concat(field_name, field->value.str, a->storage); | 639 | str_concat(field_name, field->value.str, a->storage); |
@@ -585,8 +642,8 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
585 | a->file_name, field->line, field->col, field_name); | 642 | a->file_name, field->line, field->col, field_name); |
586 | a->err = true; | 643 | a->err = true; |
587 | } | 644 | } |
588 | if (field->field_val) { | 645 | if (field->field.val) { |
589 | Str type = type_inference(a, field->field_val, scope); | 646 | Str type = type_inference(a, field->field.val, scope); |
590 | if (!str_eq(type, cstr("int"))) { | 647 | if (!str_eq(type, cstr("int"))) { |
591 | eprintln( | 648 | eprintln( |
592 | "%s:%d:%d: error: non int enum value for '%s.%s'", | 649 | "%s:%d:%d: error: non int enum value for '%s.%s'", |
@@ -609,26 +666,34 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
609 | return node->type; | 666 | return node->type; |
610 | } break; | 667 | } break; |
611 | case NODE_IF: { | 668 | case NODE_IF: { |
612 | 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); | ||
613 | if (!str_eq(cond_type, cstr("bool"))) { | 672 | if (!str_eq(cond_type, cstr("bool"))) { |
614 | emit_semantic_error( | 673 | emit_semantic_error( |
615 | a, node->cond_if, | 674 | a, node->ifelse.cond, |
616 | cstr("non boolean expression on if condition")); | 675 | cstr("non boolean expression on if condition")); |
617 | return cstr(""); | 676 | return cstr(""); |
618 | } | 677 | } |
619 | if (node->cond_expr->kind == NODE_BLOCK) { | 678 | if (node->ifelse.expr_true->kind == NODE_BLOCK) { |
620 | node->type = type_inference(a, node->cond_expr, scope); | 679 | node->type = type_inference(a, node->ifelse.expr_true, scope); |
621 | } else { | 680 | } else { |
622 | Scope *next = typescope_alloc(a, scope); | 681 | Scope *next = typescope_alloc(a, scope); |
623 | node->type = type_inference(a, node->cond_expr, next); | 682 | node->type = type_inference(a, node->ifelse.expr_true, next); |
624 | } | 683 | } |
625 | 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; | ||
626 | Str else_type; | 690 | Str else_type; |
627 | if (node->cond_else->kind == NODE_BLOCK) { | 691 | if (node->ifelse.expr_else->kind == NODE_BLOCK) { |
628 | else_type = type_inference(a, node->cond_else, scope); | 692 | else_type = |
693 | type_inference(a, node->ifelse.expr_else, scope); | ||
629 | } else { | 694 | } else { |
630 | Scope *next = typescope_alloc(a, scope); | 695 | Scope *next = typescope_alloc(a, scope); |
631 | else_type = type_inference(a, node->cond_else, next); | 696 | else_type = type_inference(a, node->ifelse.expr_else, next); |
632 | } | 697 | } |
633 | if (!str_eq(node->type, else_type)) { | 698 | if (!str_eq(node->type, else_type)) { |
634 | emit_semantic_error( | 699 | emit_semantic_error( |
@@ -636,27 +701,41 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
636 | return cstr(""); | 701 | return cstr(""); |
637 | } | 702 | } |
638 | } | 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 | } | ||
639 | return node->type; | 714 | return node->type; |
640 | } break; | 715 | } break; |
641 | case NODE_WHILE: { | 716 | case NODE_WHILE: { |
642 | 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); | ||
643 | if (!str_eq(cond_type, cstr("bool"))) { | 720 | if (!str_eq(cond_type, cstr("bool"))) { |
644 | emit_semantic_error( | 721 | emit_semantic_error( |
645 | a, node->cond_if, | 722 | a, node->loop.cond, |
646 | cstr("non boolean expression on while condition")); | 723 | cstr("non boolean expression on while condition")); |
647 | return cstr(""); | 724 | return cstr(""); |
648 | } | 725 | } |
649 | if (node->while_expr->kind != NODE_BLOCK) { | 726 | if (node->loop.expr->kind != NODE_BLOCK) { |
650 | scope = typescope_alloc(a, scope); | 727 | scope = typescope_alloc(a, scope); |
651 | } | 728 | } |
652 | type_inference(a, node->while_expr, scope); | 729 | type_inference(a, node->loop.expr, scope); |
653 | node->type = cstr("nil"); | 730 | node->type = cstr("nil"); |
654 | return node->type; | 731 | return node->type; |
655 | } break; | 732 | } break; |
656 | case NODE_COND: { | 733 | case NODE_COND: { |
657 | Str previous = cstr(""); | 734 | Str previous = cstr(""); |
658 | for (sz i = 0; i < array_size(node->match_cases); i++) { | 735 | bool has_else = false; |
659 | 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; | ||
660 | Str next = type_inference(a, expr, scope); | 739 | Str next = type_inference(a, expr, scope); |
661 | if (i != 0 && !str_eq(next, previous)) { | 740 | if (i != 0 && !str_eq(next, previous)) { |
662 | emit_semantic_error( | 741 | emit_semantic_error( |
@@ -664,22 +743,38 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
664 | cstr("non-matching types for cond expressions")); | 743 | cstr("non-matching types for cond expressions")); |
665 | return cstr(""); | 744 | return cstr(""); |
666 | } | 745 | } |
746 | if (!expr->case_entry.cond) { | ||
747 | has_else = true; | ||
748 | } | ||
667 | previous = next; | 749 | previous = next; |
668 | } | 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 | } | ||
669 | node->type = previous; | 762 | node->type = previous; |
670 | return node->type; | 763 | return node->type; |
671 | } break; | 764 | } break; |
672 | case NODE_MATCH: { | 765 | case NODE_MATCH: { |
673 | 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); | ||
674 | if (str_eq(e, cstr("int"))) { | 768 | if (str_eq(e, cstr("int"))) { |
675 | // Integer matching. | 769 | // Integer matching. |
676 | for (sz i = 0; i < array_size(node->match_cases); i++) { | 770 | for (sz i = 0; i < array_size(node->match.cases); i++) { |
677 | Node *field = node->match_cases[i]; | 771 | Node *field = node->match.cases[i]; |
678 | if (field->case_value) { | 772 | field->parent = node; |
679 | if (field->case_value->kind != NODE_NUM_INT && | 773 | if (field->case_entry.cond) { |
680 | 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) { | ||
681 | emit_semantic_error( | 776 | emit_semantic_error( |
682 | a, field->case_value, | 777 | a, field->case_entry.cond, |
683 | cstr( | 778 | cstr( |
684 | "non-integer or enum types on match case")); | 779 | "non-integer or enum types on match case")); |
685 | } | 780 | } |
@@ -690,24 +785,26 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
690 | FindEnumResult res = find_enum(scope, e); | 785 | FindEnumResult res = find_enum(scope, e); |
691 | Str enum_prefix = | 786 | Str enum_prefix = |
692 | str_concat(res.map->val.name, cstr("."), a->storage); | 787 | str_concat(res.map->val.name, cstr("."), a->storage); |
693 | for (sz i = 0; i < array_size(node->match_cases); i++) { | 788 | for (sz i = 0; i < array_size(node->match.cases); i++) { |
694 | Node *field = node->match_cases[i]; | 789 | Node *field = node->match.cases[i]; |
695 | if (field->case_value) { | 790 | field->parent = node; |
791 | if (field->case_entry.cond) { | ||
696 | Str field_name = str_concat( | 792 | Str field_name = str_concat( |
697 | enum_prefix, field->case_value->value.str, | 793 | enum_prefix, field->case_entry.cond->value.str, |
698 | a->storage); | 794 | a->storage); |
699 | if (!enummap_lookup(&res.scope->enums, field_name)) { | 795 | if (!enummap_lookup(&res.scope->enums, field_name)) { |
700 | eprintln("%s:%d:%d: error: unknown enum field '%s'", | 796 | eprintln("%s:%d:%d: error: unknown enum field '%s'", |
701 | a->file_name, field->case_value->line, | 797 | a->file_name, field->case_entry.cond->line, |
702 | field->case_value->col, field_name); | 798 | field->case_entry.cond->col, field_name); |
703 | a->err = true; | 799 | a->err = true; |
704 | } | 800 | } |
705 | } | 801 | } |
706 | } | 802 | } |
707 | } | 803 | } |
708 | Str previous = cstr(""); | 804 | Str previous = cstr(""); |
709 | for (sz i = 0; i < array_size(node->match_cases); i++) { | 805 | for (sz i = 0; i < array_size(node->match.cases); i++) { |
710 | Node *expr = node->match_cases[i]; | 806 | Node *expr = node->match.cases[i]; |
807 | expr->parent = node; | ||
711 | Str next = type_inference(a, expr, scope); | 808 | Str next = type_inference(a, expr, scope); |
712 | if (i != 0 && !str_eq(next, previous)) { | 809 | if (i != 0 && !str_eq(next, previous)) { |
713 | emit_semantic_error( | 810 | emit_semantic_error( |
@@ -721,24 +818,27 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
721 | return node->type; | 818 | return node->type; |
722 | } break; | 819 | } break; |
723 | case NODE_CASE_MATCH: { | 820 | case NODE_CASE_MATCH: { |
724 | if (node->case_expr->kind != NODE_BLOCK) { | 821 | if (node->case_entry.expr->kind != NODE_BLOCK) { |
725 | scope = typescope_alloc(a, scope); | 822 | scope = typescope_alloc(a, scope); |
726 | } | 823 | } |
727 | 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); | ||
728 | return node->type; | 826 | return node->type; |
729 | } break; | 827 | } break; |
730 | case NODE_CASE_COND: { | 828 | case NODE_CASE_COND: { |
731 | if (node->case_value) { | 829 | node->case_entry.expr->parent = node; |
732 | 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); | ||
733 | if (!str_eq(cond, cstr("bool"))) { | 833 | if (!str_eq(cond, cstr("bool"))) { |
734 | emit_semantic_error(a, node, | 834 | emit_semantic_error(a, node, |
735 | cstr("non-boolean case condition")); | 835 | cstr("non-boolean case condition")); |
736 | } | 836 | } |
737 | } | 837 | } |
738 | if (node->case_expr->kind != NODE_BLOCK) { | 838 | if (node->case_entry.expr->kind != NODE_BLOCK) { |
739 | scope = typescope_alloc(a, scope); | 839 | scope = typescope_alloc(a, scope); |
740 | } | 840 | } |
741 | node->type = type_inference(a, node->case_expr, scope); | 841 | node->type = type_inference(a, node->case_entry.expr, scope); |
742 | return node->type; | 842 | return node->type; |
743 | } break; | 843 | } break; |
744 | case NODE_TRUE: | 844 | case NODE_TRUE: |
@@ -753,14 +853,16 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
753 | case NODE_NOT: | 853 | case NODE_NOT: |
754 | case NODE_AND: | 854 | case NODE_AND: |
755 | case NODE_OR: { | 855 | case NODE_OR: { |
756 | Str left = type_inference(a, node->left, scope); | 856 | node->binary.left->parent = node; |
857 | Str left = type_inference(a, node->binary.left, scope); | ||
757 | if (!str_eq(left, cstr("bool"))) { | 858 | if (!str_eq(left, cstr("bool"))) { |
758 | emit_semantic_error(a, node, | 859 | emit_semantic_error(a, node, |
759 | cstr("expected bool on logic expression")); | 860 | cstr("expected bool on logic expression")); |
760 | return cstr(""); | 861 | return cstr(""); |
761 | } | 862 | } |
762 | if (node->right) { | 863 | if (node->binary.right) { |
763 | Str right = type_inference(a, node->right, scope); | 864 | node->binary.right->parent = node; |
865 | Str right = type_inference(a, node->binary.right, scope); | ||
764 | if (!str_eq(right, cstr("bool"))) { | 866 | if (!str_eq(right, cstr("bool"))) { |
765 | emit_semantic_error( | 867 | emit_semantic_error( |
766 | a, node, cstr("expected bool on logic expression")); | 868 | a, node, cstr("expected bool on logic expression")); |
@@ -776,8 +878,10 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
776 | case NODE_GT: | 878 | case NODE_GT: |
777 | case NODE_LE: | 879 | case NODE_LE: |
778 | case NODE_GE: { | 880 | case NODE_GE: { |
779 | Str left = type_inference(a, node->left, scope); | 881 | node->binary.left->parent = node; |
780 | 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); | ||
781 | if (!str_eq(left, right)) { | 885 | if (!str_eq(left, right)) { |
782 | emit_semantic_error( | 886 | emit_semantic_error( |
783 | a, node, cstr("mismatched types on binary expression")); | 887 | a, node, cstr("mismatched types on binary expression")); |
@@ -787,7 +891,8 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
787 | return node->type; | 891 | return node->type; |
788 | } break; | 892 | } break; |
789 | case NODE_BITNOT: { | 893 | case NODE_BITNOT: { |
790 | Str left = type_inference(a, node->left, scope); | 894 | node->binary.left->parent = node; |
895 | Str left = type_inference(a, node->binary.left, scope); | ||
791 | if (!strset_lookup(&a->integer_types, left)) { | 896 | if (!strset_lookup(&a->integer_types, left)) { |
792 | emit_semantic_error( | 897 | emit_semantic_error( |
793 | a, node, cstr("non integer type on bit twiddling expr")); | 898 | a, node, cstr("non integer type on bit twiddling expr")); |
@@ -798,10 +903,13 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
798 | } break; | 903 | } break; |
799 | case NODE_BITAND: | 904 | case NODE_BITAND: |
800 | case NODE_BITOR: | 905 | case NODE_BITOR: |
906 | case NODE_BITXOR: | ||
801 | case NODE_BITLSHIFT: | 907 | case NODE_BITLSHIFT: |
802 | case NODE_BITRSHIFT: { | 908 | case NODE_BITRSHIFT: { |
803 | Str left = type_inference(a, node->left, scope); | 909 | node->binary.left->parent = node; |
804 | 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); | ||
805 | if (!strset_lookup(&a->integer_types, left) || | 913 | if (!strset_lookup(&a->integer_types, left) || |
806 | !strset_lookup(&a->integer_types, right)) { | 914 | !strset_lookup(&a->integer_types, right)) { |
807 | emit_semantic_error( | 915 | emit_semantic_error( |
@@ -816,8 +924,10 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
816 | case NODE_DIV: | 924 | case NODE_DIV: |
817 | case NODE_MUL: | 925 | case NODE_MUL: |
818 | case NODE_MOD: { | 926 | case NODE_MOD: { |
819 | Str left = type_inference(a, node->left, scope); | 927 | node->binary.left->parent = node; |
820 | 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); | ||
821 | if (!strset_lookup(&a->numeric_types, left) || | 931 | if (!strset_lookup(&a->numeric_types, left) || |
822 | !strset_lookup(&a->numeric_types, right)) { | 932 | !strset_lookup(&a->numeric_types, right)) { |
823 | emit_semantic_error( | 933 | emit_semantic_error( |
@@ -833,7 +943,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
833 | return node->type; | 943 | return node->type; |
834 | } break; | 944 | } break; |
835 | case NODE_NUM_UINT: { | 945 | case NODE_NUM_UINT: { |
836 | node->type = cstr("uint"); | 946 | node->type = cstr("int"); |
837 | return node->type; | 947 | return node->type; |
838 | } break; | 948 | } break; |
839 | case NODE_NUM_INT: { | 949 | case NODE_NUM_INT: { |
@@ -868,9 +978,24 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
868 | a->err = true; | 978 | a->err = true; |
869 | return cstr(""); | 979 | return cstr(""); |
870 | } | 980 | } |
981 | |||
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 | } | ||
990 | node->unique_name = str_concat(cstr("."), symbol, a->storage); | ||
991 | node->unique_name = | ||
992 | str_concat(node->unique_name, | ||
993 | str_from_int(sym.scope->id, a->storage), a->storage); | ||
994 | |||
871 | Str type_name = type->val.name; | 995 | Str type_name = type->val.name; |
872 | if (node->kind == NODE_SYMBOL_IDX) { | 996 | if (node->kind == NODE_SYMBOL_IDX) { |
873 | 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); | ||
874 | if (!strset_lookup(&a->integer_types, idx_type)) { | 999 | if (!strset_lookup(&a->integer_types, idx_type)) { |
875 | emit_semantic_error( | 1000 | emit_semantic_error( |
876 | a, node, cstr("can't resolve non integer index")); | 1001 | a, node, cstr("can't resolve non integer index")); |
@@ -884,7 +1009,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
884 | 1009 | ||
885 | FindEnumResult e = find_enum(scope, type_name); | 1010 | FindEnumResult e = find_enum(scope, type_name); |
886 | if (e.map && str_eq(symbol, type_name)) { | 1011 | if (e.map && str_eq(symbol, type_name)) { |
887 | if (!node->next) { | 1012 | if (!node->sym.next) { |
888 | eprintln( | 1013 | eprintln( |
889 | "%s:%d:%d: error: unspecified enum field for symbol " | 1014 | "%s:%d:%d: error: unspecified enum field for symbol " |
890 | "'%s'", | 1015 | "'%s'", |
@@ -894,19 +1019,21 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
894 | } | 1019 | } |
895 | // 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. |
896 | Str field = str_concat(type_name, cstr("."), a->storage); | 1021 | Str field = str_concat(type_name, cstr("."), a->storage); |
897 | field = str_concat(field, node->next->value.str, a->storage); | 1022 | field = |
1023 | str_concat(field, node->sym.next->value.str, a->storage); | ||
898 | if (!enummap_lookup(&e.scope->enums, field)) { | 1024 | if (!enummap_lookup(&e.scope->enums, field)) { |
899 | eprintln( | 1025 | eprintln( |
900 | "%s:%d:%d: error: unknown enum field for " | 1026 | "%s:%d:%d: error: unknown enum field for " |
901 | "'%s': %s", | 1027 | "'%s': %s", |
902 | a->file_name, node->line, node->col, symbol, | 1028 | a->file_name, node->line, node->col, symbol, |
903 | node->next->value.str); | 1029 | node->sym.next->value.str); |
904 | a->err = true; | 1030 | a->err = true; |
905 | return cstr(""); | 1031 | return cstr(""); |
906 | } | 1032 | } |
907 | node->next->type = type_name; | 1033 | |
1034 | node->sym.next->type = type_name; | ||
908 | node->type = type_name; | 1035 | node->type = type_name; |
909 | return node->next->type; | 1036 | return node->sym.next->type; |
910 | } | 1037 | } |
911 | 1038 | ||
912 | FindStructResult s = find_struct(scope, type_name); | 1039 | FindStructResult s = find_struct(scope, type_name); |
@@ -919,11 +1046,11 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
919 | a->err = true; | 1046 | a->err = true; |
920 | return cstr(""); | 1047 | return cstr(""); |
921 | } else { | 1048 | } else { |
922 | if (node->next) { | 1049 | if (node->sym.next) { |
923 | Str chain = type_name; | 1050 | Str chain = type_name; |
924 | Node *next = node; | 1051 | Node *next = node; |
925 | while (next->next) { | 1052 | while (next->sym.next) { |
926 | next = next->next; | 1053 | next = next->sym.next; |
927 | chain = str_concat(chain, cstr("."), a->storage); | 1054 | chain = str_concat(chain, cstr("."), a->storage); |
928 | chain = | 1055 | chain = |
929 | str_concat(chain, next->value.str, a->storage); | 1056 | str_concat(chain, next->value.str, a->storage); |
@@ -939,8 +1066,9 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
939 | } | 1066 | } |
940 | Str field_type = field->val.type; | 1067 | Str field_type = field->val.type; |
941 | if (next->kind == NODE_SYMBOL_IDX) { | 1068 | if (next->kind == NODE_SYMBOL_IDX) { |
1069 | node->sym.arr_size->parent = node; | ||
942 | Str idx_type = | 1070 | Str idx_type = |
943 | type_inference(a, next->arr_size, scope); | 1071 | type_inference(a, next->sym.arr_size, scope); |
944 | if (!strset_lookup(&a->integer_types, idx_type)) { | 1072 | if (!strset_lookup(&a->integer_types, idx_type)) { |
945 | emit_semantic_error( | 1073 | emit_semantic_error( |
946 | a, next, | 1074 | a, next, |
@@ -971,6 +1099,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
971 | StrSet *set = NULL; | 1099 | StrSet *set = NULL; |
972 | for (sz i = 0; i < array_size(node->elements); i++) { | 1100 | for (sz i = 0; i < array_size(node->elements); i++) { |
973 | Node *next = node->elements[i]; | 1101 | Node *next = node->elements[i]; |
1102 | next->parent = node; | ||
974 | Str field_name = str_concat(name, cstr("."), a->storage); | 1103 | Str field_name = str_concat(name, cstr("."), a->storage); |
975 | field_name = | 1104 | field_name = |
976 | str_concat(field_name, next->value.str, a->storage); | 1105 | str_concat(field_name, next->value.str, a->storage); |
@@ -1000,10 +1129,17 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
1000 | a->err = true; | 1129 | a->err = true; |
1001 | return cstr(""); | 1130 | return cstr(""); |
1002 | } | 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 | |||
1003 | // Check that actual parameters typecheck | 1138 | // Check that actual parameters typecheck |
1004 | Str args = cstr(""); | 1139 | Str args = cstr(""); |
1005 | for (sz i = 0; i < array_size(node->elements); i++) { | 1140 | for (sz i = 0; i < array_size(node->elements); i++) { |
1006 | Node *expr = node->elements[i]; | 1141 | Node *expr = node->elements[i]; |
1142 | expr->parent = node; | ||
1007 | Str type = type_inference(a, expr, scope); | 1143 | Str type = type_inference(a, expr, scope); |
1008 | args = str_concat(args, type, a->storage); | 1144 | args = str_concat(args, type, a->storage); |
1009 | if (i != array_size(node->elements) - 1) { | 1145 | if (i != array_size(node->elements) - 1) { |
@@ -1029,15 +1165,27 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
1029 | Str type; | 1165 | Str type; |
1030 | for (sz i = 0; i < array_size(node->elements); i++) { | 1166 | for (sz i = 0; i < array_size(node->elements); i++) { |
1031 | Node *expr = node->elements[i]; | 1167 | Node *expr = node->elements[i]; |
1168 | expr->parent = node; | ||
1032 | 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 | } | ||
1033 | } | 1174 | } |
1034 | node->type = type; | 1175 | node->type = type; |
1035 | return node->type; | 1176 | return node->type; |
1036 | } break; | 1177 | } break; |
1037 | case NODE_RETURN: { | 1178 | case NODE_RETURN: { |
1038 | 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:"); | ||
1039 | for (sz i = 0; i < array_size(node->elements); i++) { | 1186 | for (sz i = 0; i < array_size(node->elements); i++) { |
1040 | Node *expr = node->elements[i]; | 1187 | Node *expr = node->elements[i]; |
1188 | expr->parent = node; | ||
1041 | Str type = type_inference(a, expr, scope); | 1189 | Str type = type_inference(a, expr, scope); |
1042 | ret_type = str_concat(ret_type, type, a->storage); | 1190 | ret_type = str_concat(ret_type, type, a->storage); |
1043 | if (i != array_size(node->elements) - 1) { | 1191 | if (i != array_size(node->elements) - 1) { |
@@ -1050,40 +1198,68 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
1050 | node->type = ret_type; | 1198 | node->type = ret_type; |
1051 | return node->type; | 1199 | return node->type; |
1052 | } 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; | ||
1053 | case NODE_FUN: { | 1223 | case NODE_FUN: { |
1054 | node->type = cstr("nil"); | 1224 | node->type = cstr("nil"); |
1055 | Scope *prev_scope = scope; | 1225 | Scope *prev_scope = scope; |
1056 | scope = typescope_alloc(a, scope); | 1226 | scope = typescope_alloc(a, scope); |
1057 | Str param_type = cstr(""); | 1227 | Str param_type = cstr(""); |
1058 | for (sz i = 0; i < array_size(node->func_params); i++) { | 1228 | for (sz i = 0; i < array_size(node->func.params); i++) { |
1059 | Node *param = node->func_params[i]; | 1229 | Node *param = node->func.params[i]; |
1060 | Str symbol = param->param_name->value.str; | 1230 | param->parent = node; |
1061 | Str type = param->param_type->value.str; | 1231 | Str symbol = param->param.name->value.str; |
1062 | if (param->param_type->is_ptr) { | 1232 | Str type = param->param.type->value.str; |
1233 | if (param->param.type->is_ptr) { | ||
1063 | type = str_concat(cstr("@"), type, a->storage); | 1234 | type = str_concat(cstr("@"), type, a->storage); |
1064 | } | 1235 | } |
1065 | if (param->param_type->kind == NODE_ARR_TYPE) { | 1236 | if (param->param.type->kind == NODE_ARR_TYPE) { |
1066 | type = str_concat(cstr("@"), type, a->storage); | 1237 | type = str_concat(cstr("@"), type, a->storage); |
1067 | } | 1238 | } |
1068 | param->param_name->type = | 1239 | param->param.name->type = |
1069 | type_inference(a, param->param_type, scope); | 1240 | type_inference(a, param->param.type, scope); |
1070 | param->type = type; | 1241 | param->type = type; |
1071 | symmap_insert(&scope->symbols, symbol, | 1242 | symmap_insert(&scope->symbols, symbol, |
1072 | (Symbol){.name = type, .kind = SYM_PARAM}, | 1243 | (Symbol){.name = type, .kind = SYM_PARAM}, |
1073 | a->storage); | 1244 | a->storage); |
1074 | param_type = str_concat(param_type, type, a->storage); | 1245 | param_type = str_concat(param_type, type, a->storage); |
1075 | if (i != array_size(node->func_params) - 1) { | 1246 | if (i != array_size(node->func.params) - 1) { |
1076 | param_type = str_concat(param_type, cstr(","), a->storage); | 1247 | param_type = str_concat(param_type, cstr(","), a->storage); |
1077 | } | 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; | ||
1078 | } | 1253 | } |
1079 | if (!param_type.size) { | 1254 | if (!param_type.size) { |
1080 | param_type = cstr("nil"); | 1255 | param_type = cstr("nil"); |
1081 | } | 1256 | } |
1082 | node->fun_params = param_type; | 1257 | node->type_params = param_type; |
1083 | 1258 | ||
1084 | Str ret_type = cstr(""); | 1259 | Str ret_type = cstr(""); |
1085 | for (sz i = 0; i < array_size(node->func_ret); i++) { | 1260 | for (sz i = 0; i < array_size(node->func.ret); i++) { |
1086 | Node *expr = node->func_ret[i]; | 1261 | Node *expr = node->func.ret[i]; |
1262 | expr->parent = node; | ||
1087 | Str type = type_inference(a, expr, scope); | 1263 | Str type = type_inference(a, expr, scope); |
1088 | if (expr->is_ptr) { | 1264 | if (expr->is_ptr) { |
1089 | type = str_concat(cstr("@"), type, a->storage); | 1265 | type = str_concat(cstr("@"), type, a->storage); |
@@ -1092,28 +1268,28 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
1092 | type = str_concat(cstr("@"), type, a->storage); | 1268 | type = str_concat(cstr("@"), type, a->storage); |
1093 | } | 1269 | } |
1094 | ret_type = str_concat(ret_type, type, a->storage); | 1270 | ret_type = str_concat(ret_type, type, a->storage); |
1095 | if (i != array_size(node->func_ret) - 1) { | 1271 | if (i != array_size(node->func.ret) - 1) { |
1096 | ret_type = str_concat(ret_type, cstr(","), a->storage); | 1272 | ret_type = str_concat(ret_type, cstr(","), a->storage); |
1097 | } | 1273 | } |
1098 | } | 1274 | } |
1099 | if (!ret_type.size) { | 1275 | if (!ret_type.size) { |
1100 | ret_type = cstr("nil"); | 1276 | ret_type = cstr("nil"); |
1101 | } | 1277 | } |
1102 | node->fun_return = ret_type; | 1278 | node->type_returns = ret_type; |
1103 | 1279 | ||
1104 | Str symbol = node->func_name->value.str; | 1280 | Str symbol = node->func.name->value.str; |
1105 | if (prev_scope->parent != NULL) { | 1281 | if (prev_scope->parent != NULL) { |
1106 | if (symmap_lookup(&prev_scope->symbols, symbol)) { | 1282 | if (symmap_lookup(&prev_scope->symbols, symbol)) { |
1107 | eprintln( | 1283 | eprintln( |
1108 | "%s:%d:%d: error: function '%s' already defined in " | 1284 | "%s:%d:%d: error: function '%s' already defined in " |
1109 | "current " | 1285 | "current " |
1110 | "scope ", | 1286 | "scope ", |
1111 | a->file_name, node->var_name->line, node->var_name->col, | 1287 | a->file_name, node->var.name->line, node->var.name->col, |
1112 | symbol); | 1288 | symbol); |
1113 | a->err = true; | 1289 | a->err = true; |
1114 | return cstr(""); | 1290 | return cstr(""); |
1115 | } | 1291 | } |
1116 | symmap_insert(&scope->symbols, symbol, | 1292 | symmap_insert(&prev_scope->symbols, symbol, |
1117 | (Symbol){.name = symbol, .kind = SYM_FUN}, | 1293 | (Symbol){.name = symbol, .kind = SYM_FUN}, |
1118 | a->storage); | 1294 | a->storage); |
1119 | } | 1295 | } |
@@ -1123,41 +1299,50 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
1123 | .param_type = param_type, | 1299 | .param_type = param_type, |
1124 | .return_type = ret_type}, | 1300 | .return_type = ret_type}, |
1125 | 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; | ||
1126 | 1306 | ||
1127 | if (node->func_body->kind == NODE_BLOCK) { | 1307 | if (node->func.body->kind == NODE_BLOCK) { |
1128 | Str type; | 1308 | Str type; |
1129 | 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++) { |
1130 | Node *expr = node->func_body->elements[i]; | 1310 | Node *expr = node->func.body->elements[i]; |
1311 | expr->parent = node; | ||
1312 | // TODO: block early return. | ||
1131 | type = type_inference(a, expr, scope); | 1313 | type = type_inference(a, expr, scope); |
1132 | } | 1314 | } |
1133 | if (!type.size) { | 1315 | if (!type.size) { |
1134 | type = cstr("nil"); | 1316 | type = cstr("nil"); |
1135 | } | 1317 | } |
1136 | node->func_body->type = type; | 1318 | node->func.body->type = type; |
1137 | } else { | 1319 | } else { |
1138 | type_inference(a, node->func_body, scope); | 1320 | node->func.body->parent = node; |
1321 | type_inference(a, node->func.body, scope); | ||
1139 | } | 1322 | } |
1140 | 1323 | ||
1141 | // Ensure main body return matches the prototype. | 1324 | // Ensure main body return matches the prototype. |
1142 | 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)) { | ||
1143 | eprintln( | 1328 | eprintln( |
1144 | "%s:%d:%d: error: mismatched return type %s, expected %s", | 1329 | "%s:%d:%d: error: mismatched return type %s, expected %s", |
1145 | a->file_name, node->line, node->col, node->func_body->type, | 1330 | a->file_name, node->line, node->col, type, ret_type); |
1146 | ret_type); | ||
1147 | a->err = true; | 1331 | a->err = true; |
1148 | } | 1332 | } |
1149 | 1333 | ||
1150 | // Ensure ALL return statements match the function prototype. | 1334 | // Ensure ALL return statements match the function prototype. |
1151 | typecheck_returns(a, node->func_body, ret_type); | 1335 | typecheck_returns(a, node->func.body, ret_type); |
1152 | 1336 | ||
1153 | // TODO: should return statements be allowed on let blocks? | 1337 | // TODO: should return statements be allowed on let blocks? |
1154 | return node->type; | 1338 | return node->type; |
1155 | } break; | 1339 | } break; |
1156 | default: { | 1340 | default: { |
1157 | emit_semantic_error(a, node, | 1341 | eprintln( |
1158 | cstr("type inference not implemented for this " | 1342 | "%s:%d:%d: error: type inference not implemented for node " |
1159 | "kind of expression")); | 1343 | "type: %s", |
1160 | println("KIND: %s", node_str[node->kind]); | 1344 | a->file_name, node->line, node->col, node_str[node->kind]); |
1345 | a->err = true; | ||
1161 | } break; | 1346 | } break; |
1162 | } | 1347 | } |
1163 | return cstr(""); | 1348 | return cstr(""); |
@@ -1218,16 +1403,59 @@ symbolic_analysis(Analyzer *a, Parser *parser) { | |||
1218 | for (sz i = 0; i < array_size(parser->nodes); i++) { | 1403 | for (sz i = 0; i < array_size(parser->nodes); i++) { |
1219 | Node *root = parser->nodes[i]; | 1404 | Node *root = parser->nodes[i]; |
1220 | if (root->kind == NODE_FUN) { | 1405 | if (root->kind == NODE_FUN) { |
1221 | Str symbol = root->func_name->value.str; | 1406 | Str symbol = root->func.name->value.str; |
1222 | if (symmap_lookup(&scope->symbols, symbol)) { | 1407 | if (symmap_lookup(&scope->symbols, symbol)) { |
1223 | eprintln( | 1408 | eprintln( |
1224 | "%s:%d:%d: error: function '%s' already defined in " | 1409 | "%s:%d:%d: error: function '%s' already defined in " |
1225 | "current " | 1410 | "current " |
1226 | "scope ", | 1411 | "scope ", |
1227 | a->file_name, root->var_name->line, root->var_name->col, | 1412 | a->file_name, root->var.name->line, root->var.name->col, |
1228 | symbol); | 1413 | symbol); |
1229 | a->err = true; | 1414 | a->err = true; |
1230 | } | 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); | ||
1231 | symmap_insert(&scope->symbols, symbol, | 1459 | symmap_insert(&scope->symbols, symbol, |
1232 | (Symbol){.name = symbol, .kind = SYM_FUN}, | 1460 | (Symbol){.name = symbol, .kind = SYM_FUN}, |
1233 | a->storage); | 1461 | a->storage); |