| author | |
| committer | |
| log | c1d77f2a231461d88ad493c92079cc571e565f87 |
| tree | 8a85649f49e567f796445d751052fbd4b105fa7c |
| parent | 918e7641fcaa79f75a365751de571807578ae503 |
4 files changed, 99 insertions(+), 96 deletions(-)
README.md+4-4| ... | ... | @@ -88,6 +88,8 @@ ExternBlock : many(Directive) token(Extern) token(LBrace) many(FnDecl) token(RBr |
| 88 | 88 | |
| 89 | 89 | FnProto : many(Directive) option(FnVisibleMod) token(Fn) token(Symbol) ParamDeclList option(token(Arrow) Type) |
| 90 | 90 | |
| 91 | Directive : token(NumberSign) token(Symbol) token(LParen) token(String) token(RParen) | |
| 92 | ||
| 91 | 93 | FnVisibleMod : token(Pub) | token(Export) |
| 92 | 94 | |
| 93 | 95 | FnDecl : FnProto token(Semicolon) |
| ... | ... | @@ -142,15 +144,13 @@ CastExpression : PrefixOpExpression token(as) Type | PrefixOpExpression |
| 142 | 144 | |
| 143 | 145 | PrefixOpExpression : PrefixOp FnCallExpression | FnCallExpression |
| 144 | 146 | |
| 145 | FnCallExpression : PrimaryExpression token(LParen) list(Expression, token(Comma)) token(RParen) | |
| 147 | FnCallExpression : PrimaryExpression token(LParen) list(Expression, token(Comma)) token(RParen) | PrimaryExpression | |
| 146 | 148 | |
| 147 | 149 | PrefixOp : token(Not) | token(Dash) | token(Tilde) |
| 148 | 150 | |
| 149 | PrimaryExpression : token(Number) | token(String) | token(Unreachable) | GroupedExpression | Block | |
| 151 | PrimaryExpression : token(Number) | token(String) | token(Unreachable) | GroupedExpression | Block | token(Symbol) | |
| 150 | 152 | |
| 151 | 153 | GroupedExpression : token(LParen) Expression token(RParen) |
| 152 | ||
| 153 | Directive : token(NumberSign) token(Symbol) token(LParen) token(String) token(RParen) | |
| 154 | 154 | ``` |
| 155 | 155 | |
| 156 | 156 | ### Operator Precedence |
src/codegen.cpp+49-39| ... | ... | @@ -306,7 +306,7 @@ static void find_declarations(CodeGen *g, AstNode *node) { |
| 306 | 306 | case NodeTypeRoot: |
| 307 | 307 | case NodeTypeBlock: |
| 308 | 308 | case NodeTypeBoolOrExpr: |
| 309 | case NodeTypeFnCall: | |
| 309 | case NodeTypeFnCallExpr: | |
| 310 | 310 | case NodeTypeRootExportDecl: |
| 311 | 311 | case NodeTypeBoolAndExpr: |
| 312 | 312 | case NodeTypeComparisonExpr: |
| ... | ... | @@ -378,6 +378,14 @@ static void check_fn_def_control_flow(CodeGen *g, AstNode *node) { |
| 378 | 378 | } |
| 379 | 379 | } |
| 380 | 380 | |
| 381 | static Buf *hack_get_fn_call_name(CodeGen *g, AstNode *node) { | |
| 382 | // Assume that the expression evaluates to a simple name and return the buf | |
| 383 | // TODO after type checking works we should be able to remove this hack | |
| 384 | assert(node->type == NodeTypePrimaryExpr); | |
| 385 | assert(node->data.primary_expr.type == PrimaryExprTypeSymbol); | |
| 386 | return &node->data.primary_expr.data.symbol; | |
| 387 | } | |
| 388 | ||
| 381 | 389 | static void analyze_node(CodeGen *g, AstNode *node) { |
| 382 | 390 | switch (node->type) { |
| 383 | 391 | case NodeTypeRoot: |
| ... | ... | @@ -487,9 +495,9 @@ static void analyze_node(CodeGen *g, AstNode *node) { |
| 487 | 495 | if (node->data.bool_or_expr.op2) |
| 488 | 496 | analyze_node(g, node->data.bool_or_expr.op2); |
| 489 | 497 | break; |
| 490 | case NodeTypeFnCall: | |
| 498 | case NodeTypeFnCallExpr: | |
| 491 | 499 | { |
| 492 | Buf *name = &node->data.fn_call.name; | |
| 500 | Buf *name = hack_get_fn_call_name(g, node->data.fn_call_expr.fn_ref_expr); | |
| 493 | 501 | |
| 494 | 502 | auto entry = g->fn_table.maybe_get(name); |
| 495 | 503 | if (!entry) { |
| ... | ... | @@ -499,7 +507,7 @@ static void analyze_node(CodeGen *g, AstNode *node) { |
| 499 | 507 | FnTableEntry *fn_table_entry = entry->value; |
| 500 | 508 | assert(fn_table_entry->proto_node->type == NodeTypeFnProto); |
| 501 | 509 | int expected_param_count = fn_table_entry->proto_node->data.fn_proto.params.length; |
| 502 | int actual_param_count = node->data.fn_call.params.length; | |
| 510 | int actual_param_count = node->data.fn_call_expr.params.length; | |
| 503 | 511 | if (expected_param_count != actual_param_count) { |
| 504 | 512 | add_node_error(g, node, |
| 505 | 513 | buf_sprintf("wrong number of arguments. Expected %d, got %d.", |
| ... | ... | @@ -507,8 +515,8 @@ static void analyze_node(CodeGen *g, AstNode *node) { |
| 507 | 515 | } |
| 508 | 516 | } |
| 509 | 517 | |
| 510 | for (int i = 0; i < node->data.fn_call.params.length; i += 1) { | |
| 511 | AstNode *child = node->data.fn_call.params.at(i); | |
| 518 | for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) { | |
| 519 | AstNode *child = node->data.fn_call_expr.params.at(i); | |
| 512 | 520 | analyze_node(g, child); |
| 513 | 521 | } |
| 514 | 522 | break; |
| ... | ... | @@ -551,11 +559,9 @@ static void analyze_node(CodeGen *g, AstNode *node) { |
| 551 | 559 | case PrimaryExprTypeNumber: |
| 552 | 560 | case PrimaryExprTypeString: |
| 553 | 561 | case PrimaryExprTypeUnreachable: |
| 562 | case PrimaryExprTypeSymbol: | |
| 554 | 563 | // nothing to do |
| 555 | 564 | break; |
| 556 | case PrimaryExprTypeFnCall: | |
| 557 | analyze_node(g, node->data.primary_expr.data.fn_call); | |
| 558 | break; | |
| 559 | 565 | case PrimaryExprTypeGroupedExpr: |
| 560 | 566 | analyze_node(g, node->data.primary_expr.data.grouped_expr); |
| 561 | 567 | break; |
| ... | ... | @@ -662,33 +668,6 @@ static void add_debug_source_node(CodeGen *g, AstNode *node) { |
| 662 | 668 | g->block_scopes.last())); |
| 663 | 669 | } |
| 664 | 670 | |
| 665 | static LLVMValueRef gen_fn_call(CodeGen *g, AstNode *fn_call_node) { | |
| 666 | assert(fn_call_node->type == NodeTypeFnCall); | |
| 667 | ||
| 668 | Buf *name = &fn_call_node->data.fn_call.name; | |
| 669 | FnTableEntry *fn_table_entry = g->fn_table.get(name); | |
| 670 | assert(fn_table_entry->proto_node->type == NodeTypeFnProto); | |
| 671 | int expected_param_count = fn_table_entry->proto_node->data.fn_proto.params.length; | |
| 672 | int actual_param_count = fn_call_node->data.fn_call.params.length; | |
| 673 | assert(expected_param_count == actual_param_count); | |
| 674 | ||
| 675 | LLVMValueRef *param_values = allocate<LLVMValueRef>(actual_param_count); | |
| 676 | for (int i = 0; i < actual_param_count; i += 1) { | |
| 677 | AstNode *expr_node = fn_call_node->data.fn_call.params.at(i); | |
| 678 | param_values[i] = gen_expr(g, expr_node); | |
| 679 | } | |
| 680 | ||
| 681 | add_debug_source_node(g, fn_call_node); | |
| 682 | LLVMValueRef result = LLVMZigBuildCall(g->builder, fn_table_entry->fn_value, | |
| 683 | param_values, actual_param_count, fn_table_entry->calling_convention, ""); | |
| 684 | ||
| 685 | if (type_is_unreachable(fn_table_entry->proto_node->data.fn_proto.return_type)) { | |
| 686 | return LLVMBuildUnreachable(g->builder); | |
| 687 | } else { | |
| 688 | return result; | |
| 689 | } | |
| 690 | } | |
| 691 | ||
| 692 | 671 | static LLVMValueRef find_or_create_string(CodeGen *g, Buf *str) { |
| 693 | 672 | auto entry = g->str_table.maybe_get(str); |
| 694 | 673 | if (entry) { |
| ... | ... | @@ -733,17 +712,47 @@ static LLVMValueRef gen_primary_expr(CodeGen *g, AstNode *node) { |
| 733 | 712 | case PrimaryExprTypeUnreachable: |
| 734 | 713 | add_debug_source_node(g, node); |
| 735 | 714 | return LLVMBuildUnreachable(g->builder); |
| 736 | case PrimaryExprTypeFnCall: | |
| 737 | return gen_fn_call(g, prim_expr->data.fn_call); | |
| 738 | 715 | case PrimaryExprTypeGroupedExpr: |
| 739 | 716 | return gen_expr(g, prim_expr->data.grouped_expr); |
| 740 | 717 | case PrimaryExprTypeBlock: |
| 718 | zig_panic("TODO block in expression"); | |
| 719 | break; | |
| 720 | case PrimaryExprTypeSymbol: | |
| 721 | zig_panic("TODO variable reference"); | |
| 741 | 722 | break; |
| 742 | 723 | } |
| 743 | 724 | |
| 744 | 725 | zig_unreachable(); |
| 745 | 726 | } |
| 746 | 727 | |
| 728 | static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) { | |
| 729 | assert(node->type == NodeTypeFnCallExpr); | |
| 730 | ||
| 731 | Buf *name = hack_get_fn_call_name(g, node->data.fn_call_expr.fn_ref_expr); | |
| 732 | ||
| 733 | FnTableEntry *fn_table_entry = g->fn_table.get(name); | |
| 734 | assert(fn_table_entry->proto_node->type == NodeTypeFnProto); | |
| 735 | int expected_param_count = fn_table_entry->proto_node->data.fn_proto.params.length; | |
| 736 | int actual_param_count = node->data.fn_call_expr.params.length; | |
| 737 | assert(expected_param_count == actual_param_count); | |
| 738 | ||
| 739 | LLVMValueRef *param_values = allocate<LLVMValueRef>(actual_param_count); | |
| 740 | for (int i = 0; i < actual_param_count; i += 1) { | |
| 741 | AstNode *expr_node = node->data.fn_call_expr.params.at(i); | |
| 742 | param_values[i] = gen_expr(g, expr_node); | |
| 743 | } | |
| 744 | ||
| 745 | add_debug_source_node(g, node); | |
| 746 | LLVMValueRef result = LLVMZigBuildCall(g->builder, fn_table_entry->fn_value, | |
| 747 | param_values, actual_param_count, fn_table_entry->calling_convention, ""); | |
| 748 | ||
| 749 | if (type_is_unreachable(fn_table_entry->proto_node->data.fn_proto.return_type)) { | |
| 750 | return LLVMBuildUnreachable(g->builder); | |
| 751 | } else { | |
| 752 | return result; | |
| 753 | } | |
| 754 | } | |
| 755 | ||
| 747 | 756 | static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) { |
| 748 | 757 | assert(node->type == NodeTypePrefixOpExpr); |
| 749 | 758 | assert(node->data.prefix_op_expr.primary_expr); |
| ... | ... | @@ -1028,6 +1037,8 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) { |
| 1028 | 1037 | return gen_return_expr(g, node); |
| 1029 | 1038 | case NodeTypePrefixOpExpr: |
| 1030 | 1039 | return gen_prefix_op_expr(g, node); |
| 1040 | case NodeTypeFnCallExpr: | |
| 1041 | return gen_fn_call_expr(g, node); | |
| 1031 | 1042 | case NodeTypeRoot: |
| 1032 | 1043 | case NodeTypeRootExportDecl: |
| 1033 | 1044 | case NodeTypeFnProto: |
| ... | ... | @@ -1036,7 +1047,6 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) { |
| 1036 | 1047 | case NodeTypeParamDecl: |
| 1037 | 1048 | case NodeTypeType: |
| 1038 | 1049 | case NodeTypeBlock: |
| 1039 | case NodeTypeFnCall: | |
| 1040 | 1050 | case NodeTypeExternBlock: |
| 1041 | 1051 | case NodeTypeDirective: |
| 1042 | 1052 | case NodeTypeBoolAndExpr: |
src/parser.cpp+40-47| ... | ... | @@ -96,8 +96,8 @@ const char *node_type_str(NodeType node_type) { |
| 96 | 96 | return "Block"; |
| 97 | 97 | case NodeTypeBoolOrExpr: |
| 98 | 98 | return "BoolOrExpr"; |
| 99 | case NodeTypeFnCall: | |
| 100 | return "FnCall"; | |
| 99 | case NodeTypeFnCallExpr: | |
| 100 | return "FnCallExpr"; | |
| 101 | 101 | case NodeTypeExternBlock: |
| 102 | 102 | return "ExternBlock"; |
| 103 | 103 | case NodeTypeDirective: |
| ... | ... | @@ -232,10 +232,11 @@ void ast_print(AstNode *node, int indent) { |
| 232 | 232 | if (node->data.bool_or_expr.op2) |
| 233 | 233 | ast_print(node->data.bool_or_expr.op2, indent + 2); |
| 234 | 234 | break; |
| 235 | case NodeTypeFnCall: | |
| 236 | fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.fn_call.name)); | |
| 237 | for (int i = 0; i < node->data.fn_call.params.length; i += 1) { | |
| 238 | AstNode *child = node->data.fn_call.params.at(i); | |
| 235 | case NodeTypeFnCallExpr: | |
| 236 | fprintf(stderr, "%s\n", node_type_str(node->type)); | |
| 237 | ast_print(node->data.fn_call_expr.fn_ref_expr, indent + 2); | |
| 238 | for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) { | |
| 239 | AstNode *child = node->data.fn_call_expr.params.at(i); | |
| 239 | 240 | ast_print(child, indent + 2); |
| 240 | 241 | } |
| 241 | 242 | break; |
| ... | ... | @@ -318,10 +319,6 @@ void ast_print(AstNode *node, int indent) { |
| 318 | 319 | case PrimaryExprTypeUnreachable: |
| 319 | 320 | fprintf(stderr, "PrimaryExpr Unreachable\n"); |
| 320 | 321 | break; |
| 321 | case PrimaryExprTypeFnCall: | |
| 322 | fprintf(stderr, "PrimaryExpr FnCall\n"); | |
| 323 | ast_print(node->data.primary_expr.data.fn_call, indent + 2); | |
| 324 | break; | |
| 325 | 322 | case PrimaryExprTypeGroupedExpr: |
| 326 | 323 | fprintf(stderr, "PrimaryExpr GroupedExpr\n"); |
| 327 | 324 | ast_print(node->data.primary_expr.data.grouped_expr, indent + 2); |
| ... | ... | @@ -330,6 +327,10 @@ void ast_print(AstNode *node, int indent) { |
| 330 | 327 | fprintf(stderr, "PrimaryExpr Block\n"); |
| 331 | 328 | ast_print(node->data.primary_expr.data.block, indent + 2); |
| 332 | 329 | break; |
| 330 | case PrimaryExprTypeSymbol: | |
| 331 | fprintf(stderr, "PrimaryExpr Symbol %s\n", | |
| 332 | buf_ptr(&node->data.primary_expr.data.symbol)); | |
| 333 | break; | |
| 333 | 334 | } |
| 334 | 335 | break; |
| 335 | 336 | case NodeTypeGroupedExpr: |
| ... | ... | @@ -626,32 +627,7 @@ static AstNode *ast_parse_grouped_expr(ParseContext *pc, int *token_index, bool |
| 626 | 627 | } |
| 627 | 628 | |
| 628 | 629 | /* |
| 629 | FnCall : token(Symbol) token(LParen) list(Expression, token(Comma)) token(RParen) ; | |
| 630 | */ | |
| 631 | static AstNode *ast_parse_fn_call(ParseContext *pc, int *token_index, bool mandatory) { | |
| 632 | Token *fn_name = &pc->tokens->at(*token_index); | |
| 633 | if (fn_name->id != TokenIdSymbol) { | |
| 634 | if (mandatory) { | |
| 635 | ast_invalid_token_error(pc, fn_name); | |
| 636 | } else { | |
| 637 | return nullptr; | |
| 638 | } | |
| 639 | } | |
| 640 | ||
| 641 | *token_index += 1; | |
| 642 | ||
| 643 | AstNode *node = ast_create_node(NodeTypeFnCall, fn_name); | |
| 644 | ||
| 645 | ||
| 646 | ast_buf_from_token(pc, fn_name, &node->data.fn_call.name); | |
| 647 | ||
| 648 | ast_parse_fn_call_param_list(pc, *token_index, token_index, &node->data.fn_call.params); | |
| 649 | ||
| 650 | return node; | |
| 651 | } | |
| 652 | ||
| 653 | /* | |
| 654 | PrimaryExpression : token(Number) | token(String) | token(Unreachable) | FnCall | GroupedExpression | Block | |
| 630 | PrimaryExpression : token(Number) | token(String) | token(Unreachable) | GroupedExpression | Block | token(Symbol) | |
| 655 | 631 | */ |
| 656 | 632 | static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool mandatory) { |
| 657 | 633 | Token *token = &pc->tokens->at(*token_index); |
| ... | ... | @@ -673,6 +649,12 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool |
| 673 | 649 | node->data.primary_expr.type = PrimaryExprTypeUnreachable; |
| 674 | 650 | *token_index += 1; |
| 675 | 651 | return node; |
| 652 | } else if (token->id == TokenIdSymbol) { | |
| 653 | AstNode *node = ast_create_node(NodeTypePrimaryExpr, token); | |
| 654 | node->data.primary_expr.type = PrimaryExprTypeSymbol; | |
| 655 | ast_buf_from_token(pc, token, &node->data.primary_expr.data.symbol); | |
| 656 | *token_index += 1; | |
| 657 | return node; | |
| 676 | 658 | } |
| 677 | 659 | |
| 678 | 660 | AstNode *block_node = ast_parse_block(pc, token_index, false); |
| ... | ... | @@ -691,20 +673,31 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool |
| 691 | 673 | return node; |
| 692 | 674 | } |
| 693 | 675 | |
| 694 | AstNode *fn_call_node = ast_parse_fn_call(pc, token_index, false); | |
| 695 | if (fn_call_node) { | |
| 696 | AstNode *node = ast_create_node(NodeTypePrimaryExpr, token); | |
| 697 | node->data.primary_expr.type = PrimaryExprTypeFnCall; | |
| 698 | node->data.primary_expr.data.fn_call = fn_call_node; | |
| 699 | return node; | |
| 700 | } | |
| 701 | ||
| 702 | 676 | if (!mandatory) |
| 703 | 677 | return nullptr; |
| 704 | 678 | |
| 705 | 679 | ast_invalid_token_error(pc, token); |
| 706 | 680 | } |
| 707 | 681 | |
| 682 | /* | |
| 683 | FnCallExpression : PrimaryExpression token(LParen) list(Expression, token(Comma)) token(RParen) | PrimaryExpression | |
| 684 | */ | |
| 685 | static AstNode *ast_parse_fn_call_expr(ParseContext *pc, int *token_index, bool mandatory) { | |
| 686 | AstNode *primary_expr = ast_parse_primary_expr(pc, token_index, mandatory); | |
| 687 | if (!primary_expr) | |
| 688 | return nullptr; | |
| 689 | ||
| 690 | Token *l_paren = &pc->tokens->at(*token_index); | |
| 691 | if (l_paren->id != TokenIdLParen) | |
| 692 | return primary_expr; | |
| 693 | ||
| 694 | AstNode *node = ast_create_node_with_node(NodeTypeFnCallExpr, primary_expr); | |
| 695 | node->data.fn_call_expr.fn_ref_expr = primary_expr; | |
| 696 | ast_parse_fn_call_param_list(pc, *token_index, token_index, &node->data.fn_call_expr.params); | |
| 697 | ||
| 698 | return node; | |
| 699 | } | |
| 700 | ||
| 708 | 701 | static PrefixOp tok_to_prefix_op(Token *token) { |
| 709 | 702 | switch (token->id) { |
| 710 | 703 | case TokenIdBang: return PrefixOpBoolNot; |
| ... | ... | @@ -732,15 +725,15 @@ static PrefixOp ast_parse_prefix_op(ParseContext *pc, int *token_index, bool man |
| 732 | 725 | } |
| 733 | 726 | |
| 734 | 727 | /* |
| 735 | PrefixOpExpression : PrefixOp PrimaryExpression | PrimaryExpression | |
| 728 | PrefixOpExpression : PrefixOp FnCallExpression | FnCallExpression | |
| 736 | 729 | */ |
| 737 | 730 | static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, int *token_index, bool mandatory) { |
| 738 | 731 | Token *token = &pc->tokens->at(*token_index); |
| 739 | 732 | PrefixOp prefix_op = ast_parse_prefix_op(pc, token_index, false); |
| 740 | 733 | if (prefix_op == PrefixOpInvalid) |
| 741 | return ast_parse_primary_expr(pc, token_index, mandatory); | |
| 734 | return ast_parse_fn_call_expr(pc, token_index, mandatory); | |
| 742 | 735 | |
| 743 | AstNode *primary_expr = ast_parse_primary_expr(pc, token_index, true); | |
| 736 | AstNode *primary_expr = ast_parse_fn_call_expr(pc, token_index, true); | |
| 744 | 737 | AstNode *node = ast_create_node(NodeTypePrefixOpExpr, token); |
| 745 | 738 | node->data.prefix_op_expr.primary_expr = primary_expr; |
| 746 | 739 | node->data.prefix_op_expr.prefix_op = prefix_op; |
src/parser.hpp+6-6| ... | ... | @@ -24,7 +24,6 @@ enum NodeType { |
| 24 | 24 | NodeTypeParamDecl, |
| 25 | 25 | NodeTypeType, |
| 26 | 26 | NodeTypeBlock, |
| 27 | NodeTypeFnCall, | |
| 28 | 27 | NodeTypeExternBlock, |
| 29 | 28 | NodeTypeDirective, |
| 30 | 29 | NodeTypeReturnExpr, |
| ... | ... | @@ -41,6 +40,7 @@ enum NodeType { |
| 41 | 40 | NodeTypePrimaryExpr, |
| 42 | 41 | NodeTypeGroupedExpr, |
| 43 | 42 | NodeTypePrefixOpExpr, |
| 43 | NodeTypeFnCallExpr, | |
| 44 | 44 | }; |
| 45 | 45 | |
| 46 | 46 | struct AstNodeRoot { |
| ... | ... | @@ -103,8 +103,8 @@ struct AstNodeBoolOrExpr { |
| 103 | 103 | AstNode *op2; |
| 104 | 104 | }; |
| 105 | 105 | |
| 106 | struct AstNodeFnCall { | |
| 107 | Buf name; | |
| 106 | struct AstNodeFnCallExpr { | |
| 107 | AstNode *fn_ref_expr; | |
| 108 | 108 | ZigList<AstNode *> params; |
| 109 | 109 | }; |
| 110 | 110 | |
| ... | ... | @@ -214,9 +214,9 @@ enum PrimaryExprType { |
| 214 | 214 | PrimaryExprTypeNumber, |
| 215 | 215 | PrimaryExprTypeString, |
| 216 | 216 | PrimaryExprTypeUnreachable, |
| 217 | PrimaryExprTypeFnCall, | |
| 218 | 217 | PrimaryExprTypeGroupedExpr, |
| 219 | 218 | PrimaryExprTypeBlock, |
| 219 | PrimaryExprTypeSymbol, | |
| 220 | 220 | }; |
| 221 | 221 | |
| 222 | 222 | struct AstNodePrimaryExpr { |
| ... | ... | @@ -224,7 +224,7 @@ struct AstNodePrimaryExpr { |
| 224 | 224 | union { |
| 225 | 225 | Buf number; |
| 226 | 226 | Buf string; |
| 227 | AstNode *fn_call; | |
| 227 | Buf symbol; | |
| 228 | 228 | AstNode *grouped_expr; |
| 229 | 229 | AstNode *block; |
| 230 | 230 | } data; |
| ... | ... | @@ -263,7 +263,6 @@ struct AstNode { |
| 263 | 263 | AstNodeBlock block; |
| 264 | 264 | AstNodeReturnExpr return_expr; |
| 265 | 265 | AstNodeBoolOrExpr bool_or_expr; |
| 266 | AstNodeFnCall fn_call; | |
| 267 | 266 | AstNodeExternBlock extern_block; |
| 268 | 267 | AstNodeDirective directive; |
| 269 | 268 | AstNodeBoolAndExpr bool_and_expr; |
| ... | ... | @@ -278,6 +277,7 @@ struct AstNode { |
| 278 | 277 | AstNodePrimaryExpr primary_expr; |
| 279 | 278 | AstNodeGroupedExpr grouped_expr; |
| 280 | 279 | AstNodePrefixOpExpr prefix_op_expr; |
| 280 | AstNodeFnCallExpr fn_call_expr; | |
| 281 | 281 | } data; |
| 282 | 282 | }; |
| 283 | 283 |