| ... | ... | @@ -13,8 +13,8 @@ |
| 13 | 13 | |
| 14 | 14 | static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 15 | 15 | TypeTableEntry *expected_type, AstNode *node); |
| 16 | | static TypeTableEntry *eval_const_expr(CodeGen *g, BlockContext *context, |
| 17 | | AstNode *node, AstNodeNumberLiteral *out_number_literal); |
| 16 | static void eval_const_expr(CodeGen *g, BlockContext *context, |
| 17 | AstNode *node, ConstExprValue *out_val); |
| 18 | 18 | static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableEntry *import, |
| 19 | 19 | BlockContext *context, TypeTableEntry *expected_type, AstNode *node); |
| 20 | 20 | static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *struct_type); |
| ... | ... | @@ -32,8 +32,6 @@ static AstNode *first_executing_node(AstNode *node) { |
| 32 | 32 | return first_executing_node(node->data.slice_expr.array_ref_expr); |
| 33 | 33 | case NodeTypeFieldAccessExpr: |
| 34 | 34 | return first_executing_node(node->data.field_access_expr.struct_expr); |
| 35 | | case NodeTypeCastExpr: |
| 36 | | return first_executing_node(node->data.cast_expr.expr); |
| 37 | 35 | case NodeTypeRoot: |
| 38 | 36 | case NodeTypeRootExportDecl: |
| 39 | 37 | case NodeTypeFnProto: |
| ... | ... | @@ -125,6 +123,7 @@ TypeTableEntry *new_type_table_entry(TypeTableEntryId id) { |
| 125 | 123 | case TypeTableEntryIdArray: |
| 126 | 124 | case TypeTableEntryIdNumberLiteral: |
| 127 | 125 | case TypeTableEntryIdMaybe: |
| 126 | case TypeTableEntryIdFn: |
| 128 | 127 | // nothing to init |
| 129 | 128 | break; |
| 130 | 129 | case TypeTableEntryIdStruct: |
| ... | ... | @@ -357,63 +356,74 @@ static TypeTableEntry *analyze_type_expr(CodeGen *g, ImportTableEntry *import, B |
| 357 | 356 | } |
| 358 | 357 | } |
| 359 | 358 | |
| 360 | | |
| 361 | | static TypeTableEntry *eval_const_expr_bin_op(CodeGen *g, BlockContext *context, |
| 362 | | AstNode *node, AstNodeNumberLiteral *out_number_literal) |
| 359 | static void eval_const_expr_bin_op(CodeGen *g, BlockContext *context, |
| 360 | AstNode *node, ConstExprValue *out_val) |
| 363 | 361 | { |
| 364 | | AstNodeNumberLiteral op1_lit; |
| 365 | | AstNodeNumberLiteral op2_lit; |
| 366 | | TypeTableEntry *op1_type = eval_const_expr(g, context, node->data.bin_op_expr.op1, &op1_lit); |
| 367 | | TypeTableEntry *op2_type = eval_const_expr(g, context, node->data.bin_op_expr.op1, &op2_lit); |
| 368 | | |
| 369 | | if (op1_type->id == TypeTableEntryIdInvalid || |
| 370 | | op2_type->id == TypeTableEntryIdInvalid) |
| 371 | | { |
| 372 | | return g->builtin_types.entry_invalid; |
| 362 | AstNode *op1_node = node->data.bin_op_expr.op1; |
| 363 | AstNode *op2_node = node->data.bin_op_expr.op2; |
| 364 | ConstExprValue op1_val = {0}; |
| 365 | ConstExprValue op2_val = {0}; |
| 366 | eval_const_expr(g, context, op1_node, &op1_val); |
| 367 | eval_const_expr(g, context, op2_node, &op2_val); |
| 368 | |
| 369 | if (!op1_val.ok || !op2_val.ok) { |
| 370 | return; |
| 373 | 371 | } |
| 374 | 372 | |
| 373 | TypeTableEntry *op1_type = get_resolved_expr(op1_node)->type_entry; |
| 374 | TypeTableEntry *op2_type = get_resolved_expr(op2_node)->type_entry; |
| 375 | |
| 375 | 376 | // TODO complete more of this function instead of returning invalid |
| 376 | 377 | // returning invalid makes the "unable to evaluate constant expression" error |
| 377 | 378 | |
| 378 | 379 | switch (node->data.bin_op_expr.bin_op) { |
| 379 | 380 | case BinOpTypeCmpNotEq: |
| 380 | 381 | { |
| 381 | | if (is_num_lit_unsigned(op1_lit.kind) && |
| 382 | | is_num_lit_unsigned(op2_lit.kind)) |
| 382 | if (op1_type->id == TypeTableEntryIdInt && |
| 383 | op2_type->id == TypeTableEntryIdInt) |
| 383 | 384 | { |
| 384 | | out_number_literal->kind = NumLitU8; |
| 385 | | out_number_literal->overflow = false; |
| 386 | | out_number_literal->data.x_uint = (op1_lit.data.x_uint != op2_lit.data.x_uint); |
| 387 | | return get_resolved_expr(node)->type_entry; |
| 388 | | } else { |
| 389 | | return g->builtin_types.entry_invalid; |
| 385 | out_val->data.x_bool = (op1_val.data.x_uint == op2_val.data.x_uint); |
| 386 | out_val->ok = true; |
| 390 | 387 | } |
| 388 | break; |
| 391 | 389 | } |
| 392 | 390 | case BinOpTypeCmpLessThan: |
| 393 | 391 | { |
| 394 | | if (is_num_lit_unsigned(op1_lit.kind) && |
| 395 | | is_num_lit_unsigned(op2_lit.kind)) |
| 392 | if (op1_type->id == TypeTableEntryIdInt && |
| 393 | op2_type->id == TypeTableEntryIdInt) |
| 396 | 394 | { |
| 397 | | out_number_literal->kind = NumLitU8; |
| 398 | | out_number_literal->overflow = false; |
| 399 | | out_number_literal->data.x_uint = (op1_lit.data.x_uint < op2_lit.data.x_uint); |
| 400 | | return get_resolved_expr(node)->type_entry; |
| 401 | | } else { |
| 402 | | return g->builtin_types.entry_invalid; |
| 395 | if (op1_type->data.integral.is_signed && |
| 396 | op2_type->data.integral.is_signed) |
| 397 | { |
| 398 | out_val->data.x_bool = (op1_val.data.x_int < op2_val.data.x_int); |
| 399 | out_val->ok = true; |
| 400 | } else if (!op1_type->data.integral.is_signed && |
| 401 | !op2_type->data.integral.is_signed) |
| 402 | { |
| 403 | out_val->data.x_bool = (op1_val.data.x_uint < op2_val.data.x_uint); |
| 404 | out_val->ok = true; |
| 405 | } |
| 403 | 406 | } |
| 407 | break; |
| 404 | 408 | } |
| 405 | 409 | case BinOpTypeMod: |
| 406 | 410 | { |
| 407 | | if (is_num_lit_unsigned(op1_lit.kind) && |
| 408 | | is_num_lit_unsigned(op2_lit.kind)) |
| 411 | if (op1_type->id == TypeTableEntryIdInt && |
| 412 | op2_type->id == TypeTableEntryIdInt) |
| 409 | 413 | { |
| 410 | | out_number_literal->kind = NumLitU64; |
| 411 | | out_number_literal->overflow = false; |
| 412 | | out_number_literal->data.x_uint = (op1_lit.data.x_uint % op2_lit.data.x_uint); |
| 413 | | return get_resolved_expr(node)->type_entry; |
| 414 | | } else { |
| 415 | | return g->builtin_types.entry_invalid; |
| 414 | if (op1_type->data.integral.is_signed && |
| 415 | op2_type->data.integral.is_signed) |
| 416 | { |
| 417 | out_val->data.x_int = op1_val.data.x_int % op2_val.data.x_int; |
| 418 | out_val->ok = true; |
| 419 | } else if (!op1_type->data.integral.is_signed && |
| 420 | !op2_type->data.integral.is_signed) |
| 421 | { |
| 422 | out_val->data.x_uint = op1_val.data.x_uint % op2_val.data.x_uint; |
| 423 | out_val->ok = true; |
| 424 | } |
| 416 | 425 | } |
| 426 | break; |
| 417 | 427 | } |
| 418 | 428 | case BinOpTypeBoolOr: |
| 419 | 429 | case BinOpTypeBoolAnd: |
| ... | ... | @@ -431,7 +441,7 @@ static TypeTableEntry *eval_const_expr_bin_op(CodeGen *g, BlockContext *context, |
| 431 | 441 | case BinOpTypeMult: |
| 432 | 442 | case BinOpTypeDiv: |
| 433 | 443 | case BinOpTypeUnwrapMaybe: |
| 434 | | return g->builtin_types.entry_invalid; |
| 444 | break; |
| 435 | 445 | case BinOpTypeInvalid: |
| 436 | 446 | case BinOpTypeAssign: |
| 437 | 447 | case BinOpTypeAssignTimes: |
| ... | ... | @@ -448,31 +458,23 @@ static TypeTableEntry *eval_const_expr_bin_op(CodeGen *g, BlockContext *context, |
| 448 | 458 | case BinOpTypeAssignBoolOr: |
| 449 | 459 | zig_unreachable(); |
| 450 | 460 | } |
| 451 | | zig_unreachable(); |
| 452 | 461 | } |
| 453 | 462 | |
| 454 | | static TypeTableEntry *eval_const_expr_fn_call(CodeGen *g, BlockContext *context, |
| 455 | | AstNode *node, AstNodeNumberLiteral *out_number_literal) |
| 456 | | { |
| 457 | | if (!node->data.fn_call_expr.is_builtin) { |
| 458 | | return g->builtin_types.entry_invalid; |
| 459 | | } |
| 460 | | |
| 463 | static void eval_const_expr_builtin(CodeGen *g, BlockContext *context, AstNode *node, ConstExprValue *out_val) { |
| 461 | 464 | switch (node->data.fn_call_expr.builtin_fn->id) { |
| 462 | 465 | case BuiltinFnIdInvalid: |
| 463 | 466 | zig_unreachable(); |
| 464 | 467 | case BuiltinFnIdArithmeticWithOverflow: |
| 465 | 468 | case BuiltinFnIdMemcpy: |
| 466 | 469 | case BuiltinFnIdMemset: |
| 467 | | return g->builtin_types.entry_invalid; |
| 470 | break; |
| 468 | 471 | case BuiltinFnIdSizeof: |
| 469 | 472 | { |
| 470 | 473 | AstNode *type_node = node->data.fn_call_expr.params.at(0); |
| 471 | 474 | TypeTableEntry *target_type = unwrapped_node_type(type_node); |
| 472 | | out_number_literal->overflow = false; |
| 473 | | out_number_literal->data.x_uint = target_type->size_in_bits / 8; |
| 474 | | out_number_literal->kind = get_number_literal_kind_unsigned(out_number_literal->data.x_uint); |
| 475 | | return get_resolved_expr(node)->type_entry; |
| 475 | out_val->data.x_uint = target_type->size_in_bits / 8; |
| 476 | out_val->ok = true; |
| 477 | break; |
| 476 | 478 | } |
| 477 | 479 | case BuiltinFnIdMaxValue: |
| 478 | 480 | case BuiltinFnIdMinValue: |
| ... | ... | @@ -480,43 +482,154 @@ static TypeTableEntry *eval_const_expr_fn_call(CodeGen *g, BlockContext *context |
| 480 | 482 | case BuiltinFnIdValueCount: |
| 481 | 483 | zig_panic("TODO eval_const_expr_fn_call value_count"); |
| 482 | 484 | case BuiltinFnIdTypeof: |
| 483 | | return get_resolved_expr(node)->type_entry; |
| 485 | // TODO |
| 486 | out_val->ok = true; |
| 487 | break; |
| 484 | 488 | } |
| 485 | | zig_unreachable(); |
| 486 | 489 | } |
| 487 | 490 | |
| 488 | | static TypeTableEntry *eval_const_expr(CodeGen *g, BlockContext *context, |
| 489 | | AstNode *node, AstNodeNumberLiteral *out_number_literal) |
| 491 | static void eval_const_expr_fn_call_known(CodeGen *g, BlockContext *context, |
| 492 | AstNode *node, ConstExprValue *out_val) |
| 493 | { |
| 494 | // currently no functions can be constant expression evaluated, |
| 495 | // so we do nothing |
| 496 | } |
| 497 | |
| 498 | static void eval_const_expr_fn_call_cast(CodeGen *g, BlockContext *context, |
| 499 | AstNode *node, ConstExprValue *out_val) |
| 500 | { |
| 501 | assert(node->type == NodeTypeFnCallExpr); |
| 502 | AstNode *expr_node = node->data.fn_call_expr.params.at(0); |
| 503 | Cast *cast = &node->data.fn_call_expr.cast; |
| 504 | switch (cast->op) { |
| 505 | case CastOpNothing: |
| 506 | case CastOpPtrToInt: |
| 507 | case CastOpPointerReinterpret: |
| 508 | case CastOpIntWidenOrShorten: |
| 509 | { |
| 510 | eval_const_expr(g, context, expr_node, out_val); |
| 511 | break; |
| 512 | } |
| 513 | case CastOpMaybeWrap: |
| 514 | { |
| 515 | ConstExprValue *child_val = allocate<ConstExprValue>(1); |
| 516 | eval_const_expr(g, context, expr_node, child_val); |
| 517 | if (!child_val->ok) { |
| 518 | return; |
| 519 | } |
| 520 | out_val->data.x_maybe.child_val = child_val; |
| 521 | out_val->data.x_maybe.is_null = false; |
| 522 | out_val->ok = true; |
| 523 | break; |
| 524 | } |
| 525 | case CastOpToUnknownSizeArray: |
| 526 | zig_panic("TODO eval_const_expr CastOpToUnknownSizeArray"); |
| 527 | } |
| 528 | } |
| 529 | |
| 530 | static void eval_const_expr_fn_call(CodeGen *g, BlockContext *context, |
| 531 | AstNode *node, ConstExprValue *out_val) |
| 532 | { |
| 533 | if (node->data.fn_call_expr.is_builtin) { |
| 534 | return eval_const_expr_builtin(g, context, node, out_val); |
| 535 | } |
| 536 | if (node->data.fn_call_expr.fn_entry) { |
| 537 | return eval_const_expr_fn_call_known(g, context, node, out_val); |
| 538 | } |
| 539 | return eval_const_expr_fn_call_cast(g, context, node, out_val); |
| 540 | } |
| 541 | |
| 542 | static void eval_const_expr_prefix_op_expr(CodeGen *g, BlockContext *context, AstNode *node, |
| 543 | ConstExprValue *out_val) |
| 490 | 544 | { |
| 545 | AstNode *expr_node = node->data.prefix_op_expr.primary_expr; |
| 546 | switch (node->data.prefix_op_expr.prefix_op) { |
| 547 | case PrefixOpInvalid: |
| 548 | zig_unreachable(); |
| 549 | case PrefixOpBoolNot: |
| 550 | { |
| 551 | eval_const_expr(g, context, expr_node, out_val); |
| 552 | if (out_val->ok) { |
| 553 | out_val->data.x_bool = !out_val->data.x_bool; |
| 554 | } |
| 555 | break; |
| 556 | } |
| 557 | case PrefixOpBinNot: |
| 558 | break; |
| 559 | case PrefixOpNegation: |
| 560 | break; |
| 561 | case PrefixOpAddressOf: |
| 562 | { |
| 563 | if (get_resolved_expr(node)->type_entry->id == TypeTableEntryIdMetaType) { |
| 564 | eval_const_expr(g, context, expr_node, out_val); |
| 565 | } |
| 566 | break; |
| 567 | } |
| 568 | case PrefixOpConstAddressOf: |
| 569 | break; |
| 570 | case PrefixOpDereference: |
| 571 | break; |
| 572 | case PrefixOpMaybe: |
| 573 | break; |
| 574 | } |
| 575 | } |
| 576 | |
| 577 | static void eval_const_expr(CodeGen *g, BlockContext *context, AstNode *node, ConstExprValue *out_val) { |
| 491 | 578 | switch (node->type) { |
| 492 | 579 | case NodeTypeNumberLiteral: |
| 493 | | *out_number_literal = node->data.number_literal; |
| 494 | | return get_resolved_expr(node)->type_entry; |
| 580 | { |
| 581 | if (is_num_lit_unsigned(node->data.number_literal.kind)) { |
| 582 | out_val->data.x_uint = node->data.number_literal.data.x_uint; |
| 583 | out_val->ok = true; |
| 584 | } else if (is_num_lit_float(node->data.number_literal.kind)) { |
| 585 | out_val->data.x_uint = node->data.number_literal.data.x_float; |
| 586 | out_val->ok = true; |
| 587 | } |
| 588 | break; |
| 589 | } |
| 495 | 590 | case NodeTypeBoolLiteral: |
| 496 | | out_number_literal->data.x_uint = node->data.bool_literal.value ? 1 : 0; |
| 497 | | return get_resolved_expr(node)->type_entry; |
| 591 | out_val->data.x_uint = node->data.bool_literal.value ? 1 : 0; |
| 592 | out_val->ok = true; |
| 593 | break; |
| 498 | 594 | case NodeTypeNullLiteral: |
| 499 | | return get_resolved_expr(node)->type_entry; |
| 595 | out_val->data.x_maybe.is_null = true; |
| 596 | out_val->ok = true; |
| 597 | break; |
| 500 | 598 | case NodeTypeBinOpExpr: |
| 501 | | return eval_const_expr_bin_op(g, context, node, out_number_literal); |
| 599 | eval_const_expr_bin_op(g, context, node, out_val); |
| 600 | break; |
| 502 | 601 | case NodeTypeSymbol: |
| 503 | 602 | { |
| 504 | | VariableTableEntry *var = find_variable(context, &node->data.symbol_expr.symbol); |
| 505 | | assert(var); |
| 506 | | AstNode *decl_node = var->decl_node; |
| 507 | | AstNode *expr_node = decl_node->data.variable_declaration.expr; |
| 508 | | if (expr_node) { |
| 509 | | BlockContext *next_context = get_resolved_expr(expr_node)->block_context; |
| 510 | | return eval_const_expr(g, next_context, expr_node, out_number_literal); |
| 603 | VariableTableEntry *var = node->data.symbol_expr.variable; |
| 604 | if (var) { |
| 605 | if (var->is_const) { |
| 606 | AstNode *decl_node = var->decl_node; |
| 607 | if (decl_node->type == NodeTypeVariableDeclaration) { |
| 608 | AstNode *expr_node = decl_node->data.variable_declaration.expr; |
| 609 | if (expr_node) { |
| 610 | BlockContext *next_context = get_resolved_expr(expr_node)->block_context; |
| 611 | eval_const_expr(g, next_context, expr_node, out_val); |
| 612 | } |
| 613 | } |
| 614 | } |
| 615 | } else if (node->data.symbol_expr.meta_type) { |
| 616 | out_val->ok = true; |
| 617 | } else if (node->data.symbol_expr.fn_entry) { |
| 618 | out_val->ok = true; |
| 619 | out_val->data.x_fn = node->data.symbol_expr.fn_entry; |
| 511 | 620 | } else { |
| 512 | | // can't eval it |
| 513 | | return g->builtin_types.entry_invalid; |
| 621 | zig_unreachable(); |
| 514 | 622 | } |
| 623 | break; |
| 515 | 624 | } |
| 516 | 625 | case NodeTypeFnCallExpr: |
| 517 | | return eval_const_expr_fn_call(g, context, node, out_number_literal); |
| 626 | eval_const_expr_fn_call(g, context, node, out_val); |
| 627 | break; |
| 628 | case NodeTypePrefixOpExpr: |
| 629 | eval_const_expr_prefix_op_expr(g, context, node, out_val); |
| 630 | break; |
| 518 | 631 | default: |
| 519 | | return g->builtin_types.entry_invalid; |
| 632 | break; |
| 520 | 633 | } |
| 521 | 634 | } |
| 522 | 635 | |
| ... | ... | @@ -550,11 +663,30 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t |
| 550 | 663 | } |
| 551 | 664 | } |
| 552 | 665 | |
| 553 | | for (int i = 0; i < node->data.fn_proto.params.length; i += 1) { |
| 666 | int param_count = node->data.fn_proto.params.length; |
| 667 | |
| 668 | TypeTableEntry *fn_type = new_type_table_entry(TypeTableEntryIdFn); |
| 669 | fn_type->data.fn.param_count = param_count; |
| 670 | fn_type->data.fn.param_types = allocate<TypeTableEntry*>(param_count); |
| 671 | |
| 672 | fn_table_entry->type_entry = fn_type; |
| 673 | |
| 674 | Buf *name = &node->data.fn_proto.name; |
| 675 | buf_resize(&fn_type->name, 0); |
| 676 | buf_appendf(&fn_type->name, "fn %s(", buf_ptr(name)); |
| 677 | for (int i = 0; i < param_count; i += 1) { |
| 554 | 678 | AstNode *child = node->data.fn_proto.params.at(i); |
| 555 | 679 | assert(child->type == NodeTypeParamDecl); |
| 556 | 680 | TypeTableEntry *type_entry = analyze_type_expr(g, import, import->block_context, |
| 557 | 681 | child->data.param_decl.type); |
| 682 | fn_table_entry->type_entry->data.fn.param_types[i] = type_entry; |
| 683 | |
| 684 | buf_appendf(&fn_type->name, "%s : %s", |
| 685 | buf_ptr(&child->data.param_decl.name), buf_ptr(&type_entry->name)); |
| 686 | |
| 687 | if (i + 1 < param_count) { |
| 688 | buf_appendf(&fn_type->name, ", "); |
| 689 | } |
| 558 | 690 | |
| 559 | 691 | if (type_entry->id == TypeTableEntryIdUnreachable) { |
| 560 | 692 | add_node_error(g, child->data.param_decl.type, |
| ... | ... | @@ -567,7 +699,14 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t |
| 567 | 699 | } |
| 568 | 700 | } |
| 569 | 701 | |
| 570 | | analyze_type_expr(g, import, import->block_context, node->data.fn_proto.return_type); |
| 702 | TypeTableEntry *return_type = analyze_type_expr(g, import, import->block_context, |
| 703 | node->data.fn_proto.return_type); |
| 704 | fn_table_entry->type_entry->data.fn.return_type = return_type; |
| 705 | |
| 706 | buf_appendf(&fn_type->name, ")"); |
| 707 | if (return_type->id != TypeTableEntryIdVoid) { |
| 708 | buf_appendf(&fn_type->name, " %s", buf_ptr(&return_type->name)); |
| 709 | } |
| 571 | 710 | } |
| 572 | 711 | |
| 573 | 712 | static void preview_function_labels(CodeGen *g, AstNode *node, FnTableEntry *fn_table_entry) { |
| ... | ... | @@ -1058,7 +1197,6 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode |
| 1058 | 1197 | case NodeTypeBoolLiteral: |
| 1059 | 1198 | case NodeTypeNullLiteral: |
| 1060 | 1199 | case NodeTypeSymbol: |
| 1061 | | case NodeTypeCastExpr: |
| 1062 | 1200 | case NodeTypePrefixOpExpr: |
| 1063 | 1201 | case NodeTypeIfBoolExpr: |
| 1064 | 1202 | case NodeTypeIfVarExpr: |
| ... | ... | @@ -1116,6 +1254,7 @@ static bool num_lit_fits_in_other_type(CodeGen *g, TypeTableEntry *literal_type, |
| 1116 | 1254 | case TypeTableEntryIdStruct: |
| 1117 | 1255 | case TypeTableEntryIdEnum: |
| 1118 | 1256 | case TypeTableEntryIdMetaType: |
| 1257 | case TypeTableEntryIdFn: |
| 1119 | 1258 | return false; |
| 1120 | 1259 | case TypeTableEntryIdInt: |
| 1121 | 1260 | if (is_num_lit_unsigned(num_lit)) { |
| ... | ... | @@ -1703,17 +1842,28 @@ static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import, |
| 1703 | 1842 | |
| 1704 | 1843 | auto primitive_table_entry = g->primitive_type_table.maybe_get(variable_name); |
| 1705 | 1844 | if (primitive_table_entry) { |
| 1706 | | return get_meta_type(g, primitive_table_entry->value); |
| 1845 | TypeTableEntry *meta_type = get_meta_type(g, primitive_table_entry->value); |
| 1846 | node->data.symbol_expr.meta_type = meta_type; |
| 1847 | return meta_type; |
| 1707 | 1848 | } |
| 1708 | 1849 | |
| 1709 | 1850 | VariableTableEntry *var = find_variable(context, variable_name); |
| 1710 | 1851 | if (var) { |
| 1852 | node->data.symbol_expr.variable = var; |
| 1711 | 1853 | return var->type; |
| 1712 | 1854 | } |
| 1713 | 1855 | |
| 1714 | 1856 | TypeTableEntry *container_type = find_container(context, variable_name); |
| 1715 | 1857 | if (container_type) { |
| 1716 | | return get_meta_type(g, container_type); |
| 1858 | TypeTableEntry *meta_type = get_meta_type(g, container_type); |
| 1859 | node->data.symbol_expr.meta_type = meta_type; |
| 1860 | return meta_type; |
| 1861 | } |
| 1862 | |
| 1863 | auto fn_table_entry = import->fn_table.maybe_get(variable_name); |
| 1864 | if (fn_table_entry) { |
| 1865 | node->data.symbol_expr.fn_entry = fn_table_entry->value; |
| 1866 | return node->data.symbol_expr.fn_entry->type_entry; |
| 1717 | 1867 | } |
| 1718 | 1868 | |
| 1719 | 1869 | add_node_error(g, node, buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name))); |
| ... | ... | @@ -1781,65 +1931,6 @@ static bool is_op_allowed(TypeTableEntry *type, BinOpType op) { |
| 1781 | 1931 | zig_unreachable(); |
| 1782 | 1932 | } |
| 1783 | 1933 | |
| 1784 | | static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 1785 | | TypeTableEntry *expected_type, AstNode *node) |
| 1786 | | { |
| 1787 | | assert(node->type == NodeTypeCastExpr); |
| 1788 | | |
| 1789 | | TypeTableEntry *wanted_type = analyze_type_expr(g, import, context, node->data.cast_expr.type); |
| 1790 | | TypeTableEntry *actual_type = analyze_expression(g, import, context, nullptr, node->data.cast_expr.expr); |
| 1791 | | |
| 1792 | | if (wanted_type->id == TypeTableEntryIdInvalid || |
| 1793 | | actual_type->id == TypeTableEntryIdInvalid) |
| 1794 | | { |
| 1795 | | return g->builtin_types.entry_invalid; |
| 1796 | | } |
| 1797 | | |
| 1798 | | Cast *cast = &node->data.cast_expr.cast; |
| 1799 | | cast->source_node = node; |
| 1800 | | cast->after_type = wanted_type; |
| 1801 | | |
| 1802 | | if ((wanted_type == g->builtin_types.entry_isize || wanted_type == g->builtin_types.entry_usize) && |
| 1803 | | actual_type->id == TypeTableEntryIdPointer) |
| 1804 | | { |
| 1805 | | cast->op = CastOpPtrToInt; |
| 1806 | | return wanted_type; |
| 1807 | | } else if (wanted_type->id == TypeTableEntryIdInt && |
| 1808 | | actual_type->id == TypeTableEntryIdInt) |
| 1809 | | { |
| 1810 | | cast->op = CastOpIntWidenOrShorten; |
| 1811 | | return wanted_type; |
| 1812 | | } else if (wanted_type->id == TypeTableEntryIdStruct && |
| 1813 | | wanted_type->data.structure.is_unknown_size_array && |
| 1814 | | actual_type->id == TypeTableEntryIdArray && |
| 1815 | | actual_type->data.array.child_type == wanted_type->data.structure.fields[0].type_entry) |
| 1816 | | { |
| 1817 | | cast->op = CastOpToUnknownSizeArray; |
| 1818 | | context->cast_expr_alloca_list.append(cast); |
| 1819 | | return wanted_type; |
| 1820 | | } else if (actual_type->id == TypeTableEntryIdNumberLiteral && |
| 1821 | | num_lit_fits_in_other_type(g, actual_type, wanted_type)) |
| 1822 | | { |
| 1823 | | AstNode *literal_node = node->data.cast_expr.expr; |
| 1824 | | NumLitCodeGen *codegen_num_lit = get_resolved_num_lit(literal_node); |
| 1825 | | assert(!codegen_num_lit->resolved_type); |
| 1826 | | codegen_num_lit->resolved_type = wanted_type; |
| 1827 | | cast->op = CastOpNothing; |
| 1828 | | return wanted_type; |
| 1829 | | } else if (actual_type->id == TypeTableEntryIdPointer && |
| 1830 | | wanted_type->id == TypeTableEntryIdPointer) |
| 1831 | | { |
| 1832 | | cast->op = CastOpPointerReinterpret; |
| 1833 | | return wanted_type; |
| 1834 | | } else { |
| 1835 | | add_node_error(g, node, |
| 1836 | | buf_sprintf("invalid cast from type '%s' to '%s'", |
| 1837 | | buf_ptr(&actual_type->name), |
| 1838 | | buf_ptr(&wanted_type->name))); |
| 1839 | | return g->builtin_types.entry_invalid; |
| 1840 | | } |
| 1841 | | } |
| 1842 | | |
| 1843 | 1934 | enum LValPurpose { |
| 1844 | 1935 | LValPurposeAssign, |
| 1845 | 1936 | LValPurposeAddressOf, |
| ... | ... | @@ -2153,17 +2244,11 @@ static TypeTableEntry *analyze_array_type(CodeGen *g, ImportTableEntry *import, |
| 2153 | 2244 | return g->builtin_types.entry_invalid; |
| 2154 | 2245 | } |
| 2155 | 2246 | |
| 2156 | | AstNodeNumberLiteral number_literal; |
| 2157 | | TypeTableEntry *resolved_type = eval_const_expr(g, context, size_node, &number_literal); |
| 2247 | ConstExprValue const_val = {0}; |
| 2248 | eval_const_expr(g, context, size_node, &const_val); |
| 2158 | 2249 | |
| 2159 | | if (resolved_type->id == TypeTableEntryIdInt) { |
| 2160 | | if (resolved_type->data.integral.is_signed) { |
| 2161 | | add_node_error(g, size_node, |
| 2162 | | buf_create_from_str("array size must be unsigned integer")); |
| 2163 | | return g->builtin_types.entry_invalid; |
| 2164 | | } else { |
| 2165 | | return get_meta_type(g, get_array_type(g, import, child_type, number_literal.data.x_uint)); |
| 2166 | | } |
| 2250 | if (const_val.ok) { |
| 2251 | return get_meta_type(g, get_array_type(g, import, child_type, const_val.data.x_uint)); |
| 2167 | 2252 | } else { |
| 2168 | 2253 | add_node_error(g, size_node, |
| 2169 | 2254 | buf_create_from_str("unable to resolve constant expression")); |
| ... | ... | @@ -2195,12 +2280,11 @@ static TypeTableEntry *analyze_while_expr(CodeGen *g, ImportTableEntry *import, |
| 2195 | 2280 | } else { |
| 2196 | 2281 | // if the condition is a simple constant expression and there are no break statements |
| 2197 | 2282 | // then the return type is unreachable |
| 2198 | | AstNodeNumberLiteral number_literal; |
| 2199 | | TypeTableEntry *resolved_type = eval_const_expr(g, context, condition_node, &number_literal); |
| 2200 | | if (resolved_type->id != TypeTableEntryIdInvalid) { |
| 2201 | | assert(resolved_type->id == TypeTableEntryIdBool); |
| 2202 | | bool constant_cond_value = number_literal.data.x_uint; |
| 2203 | | if (constant_cond_value) { |
| 2283 | ConstExprValue const_val = {0}; |
| 2284 | eval_const_expr(g, context, condition_node, &const_val); |
| 2285 | |
| 2286 | if (const_val.ok) { |
| 2287 | if (const_val.data.x_bool) { |
| 2204 | 2288 | node->data.while_expr.condition_always_true = true; |
| 2205 | 2289 | if (!node->data.while_expr.contains_break) { |
| 2206 | 2290 | expr_return_type = g->builtin_types.entry_unreachable; |
| ... | ... | @@ -2305,6 +2389,73 @@ static TypeTableEntry *analyze_min_max_value(CodeGen *g, ImportTableEntry *impor |
| 2305 | 2389 | } |
| 2306 | 2390 | } |
| 2307 | 2391 | |
| 2392 | static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 2393 | AstNode *node, TypeTableEntry *invoke_type_entry) |
| 2394 | { |
| 2395 | assert(node->type == NodeTypeFnCallExpr); |
| 2396 | |
| 2397 | AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr; |
| 2398 | int actual_param_count = node->data.fn_call_expr.params.length; |
| 2399 | |
| 2400 | if (actual_param_count != 1) { |
| 2401 | add_node_error(g, fn_ref_expr, buf_sprintf("cast expression expects exactly one parameter")); |
| 2402 | return g->builtin_types.entry_invalid; |
| 2403 | } |
| 2404 | |
| 2405 | AstNode *expr_node = node->data.fn_call_expr.params.at(0); |
| 2406 | TypeTableEntry *wanted_type = invoke_type_entry->data.meta_type.child_type; |
| 2407 | TypeTableEntry *actual_type = analyze_expression(g, import, context, nullptr, expr_node); |
| 2408 | |
| 2409 | if (wanted_type->id == TypeTableEntryIdInvalid || |
| 2410 | actual_type->id == TypeTableEntryIdInvalid) |
| 2411 | { |
| 2412 | return g->builtin_types.entry_invalid; |
| 2413 | } |
| 2414 | |
| 2415 | Cast *cast = &node->data.fn_call_expr.cast; |
| 2416 | cast->source_node = node; |
| 2417 | cast->after_type = wanted_type; |
| 2418 | |
| 2419 | if ((wanted_type == g->builtin_types.entry_isize || wanted_type == g->builtin_types.entry_usize) && |
| 2420 | actual_type->id == TypeTableEntryIdPointer) |
| 2421 | { |
| 2422 | cast->op = CastOpPtrToInt; |
| 2423 | return wanted_type; |
| 2424 | } else if (wanted_type->id == TypeTableEntryIdInt && |
| 2425 | actual_type->id == TypeTableEntryIdInt) |
| 2426 | { |
| 2427 | cast->op = CastOpIntWidenOrShorten; |
| 2428 | return wanted_type; |
| 2429 | } else if (wanted_type->id == TypeTableEntryIdStruct && |
| 2430 | wanted_type->data.structure.is_unknown_size_array && |
| 2431 | actual_type->id == TypeTableEntryIdArray && |
| 2432 | actual_type->data.array.child_type == wanted_type->data.structure.fields[0].type_entry) |
| 2433 | { |
| 2434 | cast->op = CastOpToUnknownSizeArray; |
| 2435 | context->cast_expr_alloca_list.append(cast); |
| 2436 | return wanted_type; |
| 2437 | } else if (actual_type->id == TypeTableEntryIdNumberLiteral && |
| 2438 | num_lit_fits_in_other_type(g, actual_type, wanted_type)) |
| 2439 | { |
| 2440 | NumLitCodeGen *codegen_num_lit = get_resolved_num_lit(expr_node); |
| 2441 | assert(!codegen_num_lit->resolved_type); |
| 2442 | codegen_num_lit->resolved_type = wanted_type; |
| 2443 | cast->op = CastOpNothing; |
| 2444 | return wanted_type; |
| 2445 | } else if (actual_type->id == TypeTableEntryIdPointer && |
| 2446 | wanted_type->id == TypeTableEntryIdPointer) |
| 2447 | { |
| 2448 | cast->op = CastOpPointerReinterpret; |
| 2449 | return wanted_type; |
| 2450 | } else { |
| 2451 | add_node_error(g, node, |
| 2452 | buf_sprintf("invalid cast from type '%s' to '%s'", |
| 2453 | buf_ptr(&actual_type->name), |
| 2454 | buf_ptr(&wanted_type->name))); |
| 2455 | return g->builtin_types.entry_invalid; |
| 2456 | } |
| 2457 | } |
| 2458 | |
| 2308 | 2459 | static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 2309 | 2460 | TypeTableEntry *expected_type, AstNode *node) |
| 2310 | 2461 | { |
| ... | ... | @@ -2458,25 +2609,93 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry |
| 2458 | 2609 | } |
| 2459 | 2610 | } |
| 2460 | 2611 | |
| 2612 | static TypeTableEntry *analyze_fn_call_raw(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 2613 | TypeTableEntry *expected_type, AstNode *node, FnTableEntry *fn_table_entry, TypeTableEntry *struct_type) |
| 2614 | { |
| 2615 | assert(node->type == NodeTypeFnCallExpr); |
| 2616 | |
| 2617 | node->data.fn_call_expr.fn_entry = fn_table_entry; |
| 2618 | assert(fn_table_entry->proto_node->type == NodeTypeFnProto); |
| 2619 | AstNodeFnProto *fn_proto = &fn_table_entry->proto_node->data.fn_proto; |
| 2620 | |
| 2621 | // count parameters |
| 2622 | int expected_param_count = fn_proto->params.length; |
| 2623 | int actual_param_count = node->data.fn_call_expr.params.length; |
| 2624 | |
| 2625 | if (struct_type) { |
| 2626 | actual_param_count += 1; |
| 2627 | } |
| 2628 | |
| 2629 | if (fn_proto->is_var_args) { |
| 2630 | if (actual_param_count < expected_param_count) { |
| 2631 | add_node_error(g, node, |
| 2632 | buf_sprintf("expected at least %d arguments, got %d", |
| 2633 | expected_param_count, actual_param_count)); |
| 2634 | } |
| 2635 | } else if (expected_param_count != actual_param_count) { |
| 2636 | add_node_error(g, node, |
| 2637 | buf_sprintf("expected %d arguments, got %d", |
| 2638 | expected_param_count, actual_param_count)); |
| 2639 | } |
| 2640 | |
| 2641 | // analyze each parameter. in the case of a method, we already analyzed the |
| 2642 | // first parameter in order to figure out which struct we were calling a method on. |
| 2643 | for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) { |
| 2644 | AstNode *child = node->data.fn_call_expr.params.at(i); |
| 2645 | // determine the expected type for each parameter |
| 2646 | TypeTableEntry *expected_param_type = nullptr; |
| 2647 | int fn_proto_i = i + (struct_type ? 1 : 0); |
| 2648 | if (fn_proto_i < fn_proto->params.length) { |
| 2649 | AstNode *param_decl_node = fn_proto->params.at(fn_proto_i); |
| 2650 | assert(param_decl_node->type == NodeTypeParamDecl); |
| 2651 | AstNode *param_type_node = param_decl_node->data.param_decl.type; |
| 2652 | TypeTableEntry *param_type_entry = get_resolved_expr(param_type_node)->type_entry; |
| 2653 | if (param_type_entry) { |
| 2654 | expected_param_type = unwrapped_node_type(param_type_node); |
| 2655 | } |
| 2656 | } |
| 2657 | analyze_expression(g, import, context, expected_param_type, child); |
| 2658 | } |
| 2659 | |
| 2660 | return unwrapped_node_type(fn_proto->return_type); |
| 2661 | } |
| 2662 | |
| 2461 | 2663 | static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 2462 | 2664 | TypeTableEntry *expected_type, AstNode *node) |
| 2463 | 2665 | { |
| 2464 | 2666 | AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr; |
| 2465 | | TypeTableEntry *struct_type = nullptr; |
| 2466 | | HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> *fn_table = &import->fn_table; |
| 2467 | | AstNode *first_param_expr = nullptr; |
| 2468 | | Buf *name; |
| 2667 | |
| 2668 | if (node->data.fn_call_expr.is_builtin) { |
| 2669 | return analyze_builtin_fn_call_expr(g, import, context, expected_type, node); |
| 2670 | } |
| 2469 | 2671 | |
| 2470 | 2672 | if (fn_ref_expr->type == NodeTypeFieldAccessExpr) { |
| 2471 | | first_param_expr = fn_ref_expr->data.field_access_expr.struct_expr; |
| 2472 | | struct_type = analyze_expression(g, import, context, nullptr, first_param_expr); |
| 2473 | | name = &fn_ref_expr->data.field_access_expr.field_name; |
| 2474 | | if (struct_type->id == TypeTableEntryIdStruct) { |
| 2475 | | fn_table = &struct_type->data.structure.fn_table; |
| 2476 | | } else if (struct_type->id == TypeTableEntryIdPointer && |
| 2477 | | struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct) |
| 2673 | AstNode *first_param_expr = fn_ref_expr->data.field_access_expr.struct_expr; |
| 2674 | TypeTableEntry *struct_type = analyze_expression(g, import, context, nullptr, first_param_expr); |
| 2675 | Buf *name = &fn_ref_expr->data.field_access_expr.field_name; |
| 2676 | if (struct_type->id == TypeTableEntryIdStruct || |
| 2677 | (struct_type->id == TypeTableEntryIdPointer && |
| 2678 | struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct)) |
| 2478 | 2679 | { |
| 2479 | | fn_table = &struct_type->data.pointer.child_type->data.structure.fn_table; |
| 2680 | TypeTableEntry *bare_struct_type = (struct_type->id == TypeTableEntryIdStruct) ? |
| 2681 | struct_type : struct_type->data.pointer.child_type; |
| 2682 | |
| 2683 | auto table_entry = bare_struct_type->data.structure.fn_table.maybe_get(name); |
| 2684 | if (table_entry) { |
| 2685 | return analyze_fn_call_raw(g, import, context, expected_type, node, |
| 2686 | table_entry->value, bare_struct_type); |
| 2687 | } else { |
| 2688 | add_node_error(g, fn_ref_expr, |
| 2689 | buf_sprintf("no function named '%s' in '%s'", |
| 2690 | buf_ptr(name), buf_ptr(&bare_struct_type->name))); |
| 2691 | // still analyze the parameters, even though we don't know what to expect |
| 2692 | for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) { |
| 2693 | AstNode *child = node->data.fn_call_expr.params.at(i); |
| 2694 | analyze_expression(g, import, context, nullptr, child); |
| 2695 | } |
| 2696 | |
| 2697 | return g->builtin_types.entry_invalid; |
| 2698 | } |
| 2480 | 2699 | } else if (struct_type->id == TypeTableEntryIdInvalid) { |
| 2481 | 2700 | return struct_type; |
| 2482 | 2701 | } else if (struct_type->id == TypeTableEntryIdMetaType && |
| ... | ... | @@ -2505,74 +2724,31 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import |
| 2505 | 2724 | buf_sprintf("member reference base type not struct or enum")); |
| 2506 | 2725 | return g->builtin_types.entry_invalid; |
| 2507 | 2726 | } |
| 2508 | | } else if (fn_ref_expr->type == NodeTypeSymbol) { |
| 2509 | | if (node->data.fn_call_expr.is_builtin) { |
| 2510 | | return analyze_builtin_fn_call_expr(g, import, context, expected_type, node); |
| 2511 | | } |
| 2512 | | name = &fn_ref_expr->data.symbol_expr.symbol; |
| 2513 | | } else { |
| 2514 | | add_node_error(g, node, |
| 2515 | | buf_sprintf("function pointers not yet supported")); |
| 2516 | | return g->builtin_types.entry_invalid; |
| 2517 | 2727 | } |
| 2518 | 2728 | |
| 2519 | | auto entry = fn_table->maybe_get(name); |
| 2520 | | |
| 2521 | | if (!entry) { |
| 2522 | | add_node_error(g, fn_ref_expr, |
| 2523 | | buf_sprintf("undefined function: '%s'", buf_ptr(name))); |
| 2524 | | // still analyze the parameters, even though we don't know what to expect |
| 2525 | | for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) { |
| 2526 | | AstNode *child = node->data.fn_call_expr.params.at(i); |
| 2527 | | analyze_expression(g, import, context, nullptr, child); |
| 2528 | | } |
| 2529 | | |
| 2729 | TypeTableEntry *invoke_type_entry = analyze_expression(g, import, context, nullptr, fn_ref_expr); |
| 2730 | if (invoke_type_entry->id == TypeTableEntryIdInvalid) { |
| 2530 | 2731 | return g->builtin_types.entry_invalid; |
| 2531 | | } else { |
| 2532 | | FnTableEntry *fn_table_entry = entry->value; |
| 2533 | | assert(fn_table_entry->proto_node->type == NodeTypeFnProto); |
| 2534 | | AstNodeFnProto *fn_proto = &fn_table_entry->proto_node->data.fn_proto; |
| 2535 | | |
| 2536 | | // count parameters |
| 2537 | | int expected_param_count = fn_proto->params.length; |
| 2538 | | int actual_param_count = node->data.fn_call_expr.params.length; |
| 2539 | | |
| 2540 | | if (struct_type) { |
| 2541 | | actual_param_count += 1; |
| 2542 | | } |
| 2732 | } |
| 2543 | 2733 | |
| 2544 | | if (fn_proto->is_var_args) { |
| 2545 | | if (actual_param_count < expected_param_count) { |
| 2546 | | add_node_error(g, node, |
| 2547 | | buf_sprintf("expected at least %d arguments, got %d", |
| 2548 | | expected_param_count, actual_param_count)); |
| 2549 | | } |
| 2550 | | } else if (expected_param_count != actual_param_count) { |
| 2551 | | add_node_error(g, node, |
| 2552 | | buf_sprintf("expected %d arguments, got %d", |
| 2553 | | expected_param_count, actual_param_count)); |
| 2554 | | } |
| 2734 | // use constant expression evaluator to figure out the function at compile time. |
| 2735 | // otherwise we treat this as a function pointer. |
| 2736 | ConstExprValue const_val = {0}; |
| 2737 | eval_const_expr(g, context, fn_ref_expr, &const_val); |
| 2555 | 2738 | |
| 2556 | | // analyze each parameter. in the case of a method, we already analyzed the |
| 2557 | | // first parameter in order to figure out which struct we were calling a method on. |
| 2558 | | for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) { |
| 2559 | | AstNode *child = node->data.fn_call_expr.params.at(i); |
| 2560 | | // determine the expected type for each parameter |
| 2561 | | TypeTableEntry *expected_param_type = nullptr; |
| 2562 | | int fn_proto_i = i + (struct_type ? 1 : 0); |
| 2563 | | if (fn_proto_i < fn_proto->params.length) { |
| 2564 | | AstNode *param_decl_node = fn_proto->params.at(fn_proto_i); |
| 2565 | | assert(param_decl_node->type == NodeTypeParamDecl); |
| 2566 | | AstNode *param_type_node = param_decl_node->data.param_decl.type; |
| 2567 | | TypeTableEntry *param_type_entry = get_resolved_expr(param_type_node)->type_entry; |
| 2568 | | if (param_type_entry) { |
| 2569 | | expected_param_type = unwrapped_node_type(param_type_node); |
| 2570 | | } |
| 2571 | | } |
| 2572 | | analyze_expression(g, import, context, expected_param_type, child); |
| 2573 | | } |
| 2739 | if (!const_val.ok) { |
| 2740 | add_node_error(g, node, buf_sprintf("function pointers not yet supported")); |
| 2741 | return g->builtin_types.entry_invalid; |
| 2742 | } |
| 2574 | 2743 | |
| 2575 | | return unwrapped_node_type(fn_proto->return_type); |
| 2744 | if (invoke_type_entry->id == TypeTableEntryIdMetaType) { |
| 2745 | return analyze_cast_expr(g, import, context, node, invoke_type_entry); |
| 2746 | } else if (invoke_type_entry->id == TypeTableEntryIdFn) { |
| 2747 | return analyze_fn_call_raw(g, import, context, expected_type, node, const_val.data.x_fn, nullptr); |
| 2748 | } else { |
| 2749 | add_node_error(g, fn_ref_expr, |
| 2750 | buf_sprintf("type '%s' not a function", buf_ptr(&invoke_type_entry->name))); |
| 2751 | return g->builtin_types.entry_invalid; |
| 2576 | 2752 | } |
| 2577 | 2753 | } |
| 2578 | 2754 | |
| ... | ... | @@ -2847,9 +3023,6 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, |
| 2847 | 3023 | case NodeTypeSymbol: |
| 2848 | 3024 | return_type = analyze_symbol_expr(g, import, context, expected_type, node); |
| 2849 | 3025 | break; |
| 2850 | | case NodeTypeCastExpr: |
| 2851 | | return_type = analyze_cast_expr(g, import, context, expected_type, node); |
| 2852 | | break; |
| 2853 | 3026 | case NodeTypePrefixOpExpr: |
| 2854 | 3027 | return_type = analyze_prefix_op_expr(g, import, context, expected_type, node); |
| 2855 | 3028 | break; |
| ... | ... | @@ -3008,7 +3181,6 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode |
| 3008 | 3181 | case NodeTypeBoolLiteral: |
| 3009 | 3182 | case NodeTypeNullLiteral: |
| 3010 | 3183 | case NodeTypeSymbol: |
| 3011 | | case NodeTypeCastExpr: |
| 3012 | 3184 | case NodeTypePrefixOpExpr: |
| 3013 | 3185 | case NodeTypeIfBoolExpr: |
| 3014 | 3186 | case NodeTypeIfVarExpr: |
| ... | ... | @@ -3060,10 +3232,6 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode |
| 3060 | 3232 | case NodeTypeReturnExpr: |
| 3061 | 3233 | collect_expr_decl_deps(g, import, node->data.return_expr.expr, decl_node); |
| 3062 | 3234 | break; |
| 3063 | | case NodeTypeCastExpr: |
| 3064 | | collect_expr_decl_deps(g, import, node->data.cast_expr.expr, decl_node); |
| 3065 | | collect_expr_decl_deps(g, import, node->data.cast_expr.type, decl_node); |
| 3066 | | break; |
| 3067 | 3235 | case NodeTypePrefixOpExpr: |
| 3068 | 3236 | collect_expr_decl_deps(g, import, node->data.prefix_op_expr.primary_expr, decl_node); |
| 3069 | 3237 | break; |
| ... | ... | @@ -3331,7 +3499,6 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast |
| 3331 | 3499 | case NodeTypeBoolLiteral: |
| 3332 | 3500 | case NodeTypeNullLiteral: |
| 3333 | 3501 | case NodeTypeSymbol: |
| 3334 | | case NodeTypeCastExpr: |
| 3335 | 3502 | case NodeTypePrefixOpExpr: |
| 3336 | 3503 | case NodeTypeIfBoolExpr: |
| 3337 | 3504 | case NodeTypeIfVarExpr: |
| ... | ... | @@ -3504,8 +3671,6 @@ Expr *get_resolved_expr(AstNode *node) { |
| 3504 | 3671 | return &node->data.return_expr.resolved_expr; |
| 3505 | 3672 | case NodeTypeBinOpExpr: |
| 3506 | 3673 | return &node->data.bin_op_expr.resolved_expr; |
| 3507 | | case NodeTypeCastExpr: |
| 3508 | | return &node->data.cast_expr.resolved_expr; |
| 3509 | 3674 | case NodeTypePrefixOpExpr: |
| 3510 | 3675 | return &node->data.prefix_op_expr.resolved_expr; |
| 3511 | 3676 | case NodeTypeFnCallExpr: |
| ... | ... | @@ -3577,7 +3742,6 @@ NumLitCodeGen *get_resolved_num_lit(AstNode *node) { |
| 3577 | 3742 | return &node->data.fn_call_expr.resolved_num_lit; |
| 3578 | 3743 | case NodeTypeReturnExpr: |
| 3579 | 3744 | case NodeTypeBinOpExpr: |
| 3580 | | case NodeTypeCastExpr: |
| 3581 | 3745 | case NodeTypePrefixOpExpr: |
| 3582 | 3746 | case NodeTypeArrayAccessExpr: |
| 3583 | 3747 | case NodeTypeSliceExpr: |
| ... | ... | @@ -3627,7 +3791,6 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) { |
| 3627 | 3791 | case NodeTypeNumberLiteral: |
| 3628 | 3792 | case NodeTypeReturnExpr: |
| 3629 | 3793 | case NodeTypeBinOpExpr: |
| 3630 | | case NodeTypeCastExpr: |
| 3631 | 3794 | case NodeTypePrefixOpExpr: |
| 3632 | 3795 | case NodeTypeFnCallExpr: |
| 3633 | 3796 | case NodeTypeArrayAccessExpr: |