| ... | ... | @@ -955,6 +955,66 @@ static AstNode *ast_parse_curly_suffix_expr(ParseContext *pc, size_t *token_inde |
| 955 | 955 | } |
| 956 | 956 | } |
| 957 | 957 | |
| 958 | static AstNode *ast_parse_fn_proto_partial(ParseContext *pc, size_t *token_index, Token *fn_token, |
| 959 | AstNode *async_allocator_type_node, CallingConvention cc, bool is_extern, VisibMod visib_mod) |
| 960 | { |
| 961 | AstNode *node = ast_create_node(pc, NodeTypeFnProto, fn_token); |
| 962 | node->data.fn_proto.visib_mod = visib_mod; |
| 963 | node->data.fn_proto.cc = cc; |
| 964 | node->data.fn_proto.is_extern = is_extern; |
| 965 | node->data.fn_proto.async_allocator_type = async_allocator_type_node; |
| 966 | |
| 967 | Token *fn_name = &pc->tokens->at(*token_index); |
| 968 | |
| 969 | if (fn_name->id == TokenIdSymbol) { |
| 970 | *token_index += 1; |
| 971 | node->data.fn_proto.name = token_buf(fn_name); |
| 972 | } else { |
| 973 | node->data.fn_proto.name = nullptr; |
| 974 | } |
| 975 | |
| 976 | ast_parse_param_decl_list(pc, token_index, &node->data.fn_proto.params, &node->data.fn_proto.is_var_args); |
| 977 | |
| 978 | Token *next_token = &pc->tokens->at(*token_index); |
| 979 | if (next_token->id == TokenIdKeywordAlign) { |
| 980 | *token_index += 1; |
| 981 | ast_eat_token(pc, token_index, TokenIdLParen); |
| 982 | |
| 983 | node->data.fn_proto.align_expr = ast_parse_expression(pc, token_index, true); |
| 984 | ast_eat_token(pc, token_index, TokenIdRParen); |
| 985 | next_token = &pc->tokens->at(*token_index); |
| 986 | } |
| 987 | if (next_token->id == TokenIdKeywordSection) { |
| 988 | *token_index += 1; |
| 989 | ast_eat_token(pc, token_index, TokenIdLParen); |
| 990 | |
| 991 | node->data.fn_proto.section_expr = ast_parse_expression(pc, token_index, true); |
| 992 | ast_eat_token(pc, token_index, TokenIdRParen); |
| 993 | next_token = &pc->tokens->at(*token_index); |
| 994 | } |
| 995 | if (next_token->id == TokenIdKeywordVar) { |
| 996 | node->data.fn_proto.return_var_token = next_token; |
| 997 | *token_index += 1; |
| 998 | next_token = &pc->tokens->at(*token_index); |
| 999 | } else { |
| 1000 | if (next_token->id == TokenIdKeywordError) { |
| 1001 | Token *maybe_lbrace_tok = &pc->tokens->at(*token_index + 1); |
| 1002 | if (maybe_lbrace_tok->id == TokenIdLBrace) { |
| 1003 | *token_index += 1; |
| 1004 | node->data.fn_proto.return_type = ast_create_node(pc, NodeTypeErrorType, next_token); |
| 1005 | return node; |
| 1006 | } |
| 1007 | } else if (next_token->id == TokenIdBang) { |
| 1008 | *token_index += 1; |
| 1009 | node->data.fn_proto.auto_err_set = true; |
| 1010 | next_token = &pc->tokens->at(*token_index); |
| 1011 | } |
| 1012 | node->data.fn_proto.return_type = ast_parse_type_expr(pc, token_index, true); |
| 1013 | } |
| 1014 | |
| 1015 | return node; |
| 1016 | } |
| 1017 | |
| 958 | 1018 | /* |
| 959 | 1019 | SuffixOpExpression = ("async" option("<" SuffixOpExpression ">") SuffixOpExpression FnCallExpression) | PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression) |
| 960 | 1020 | FnCallExpression : token(LParen) list(Expression, token(Comma)) token(RParen) |
| ... | ... | @@ -979,6 +1039,11 @@ static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, size_t *token_index, |
| 979 | 1039 | } |
| 980 | 1040 | |
| 981 | 1041 | Token *fncall_token = &pc->tokens->at(*token_index); |
| 1042 | if (fncall_token->id == TokenIdKeywordFn) { |
| 1043 | *token_index += 1; |
| 1044 | return ast_parse_fn_proto_partial(pc, token_index, fncall_token, allocator_expr_node, CallingConventionAsync, |
| 1045 | false, VisibModPrivate); |
| 1046 | } |
| 982 | 1047 | AstNode *node = ast_parse_suffix_op_expr(pc, token_index, true); |
| 983 | 1048 | if (node->type != NodeTypeFnCallExpr) { |
| 984 | 1049 | ast_error(pc, fncall_token, "expected function call, found '%s'", token_name(fncall_token->id)); |
| ... | ... | @@ -2434,9 +2499,10 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m |
| 2434 | 2499 | } else if (first_token->id == TokenIdKeywordAsync) { |
| 2435 | 2500 | *token_index += 1; |
| 2436 | 2501 | Token *next_token = &pc->tokens->at(*token_index); |
| 2437 | | if (next_token->id == TokenIdLParen) { |
| 2502 | if (next_token->id == TokenIdCmpLessThan) { |
| 2503 | *token_index += 1; |
| 2438 | 2504 | async_allocator_type_node = ast_parse_type_expr(pc, token_index, true); |
| 2439 | | ast_eat_token(pc, token_index, TokenIdRParen); |
| 2505 | ast_eat_token(pc, token_index, TokenIdCmpGreaterThan); |
| 2440 | 2506 | } |
| 2441 | 2507 | fn_token = ast_eat_token(pc, token_index, TokenIdKeywordFn); |
| 2442 | 2508 | cc = CallingConventionAsync; |
| ... | ... | @@ -2470,61 +2536,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m |
| 2470 | 2536 | return nullptr; |
| 2471 | 2537 | } |
| 2472 | 2538 | |
| 2473 | | AstNode *node = ast_create_node(pc, NodeTypeFnProto, fn_token); |
| 2474 | | node->data.fn_proto.visib_mod = visib_mod; |
| 2475 | | node->data.fn_proto.cc = cc; |
| 2476 | | node->data.fn_proto.is_extern = is_extern; |
| 2477 | | node->data.fn_proto.async_allocator_type = async_allocator_type_node; |
| 2478 | | |
| 2479 | | Token *fn_name = &pc->tokens->at(*token_index); |
| 2480 | | |
| 2481 | | if (fn_name->id == TokenIdSymbol) { |
| 2482 | | *token_index += 1; |
| 2483 | | node->data.fn_proto.name = token_buf(fn_name); |
| 2484 | | } else { |
| 2485 | | node->data.fn_proto.name = nullptr; |
| 2486 | | } |
| 2487 | | |
| 2488 | | ast_parse_param_decl_list(pc, token_index, &node->data.fn_proto.params, &node->data.fn_proto.is_var_args); |
| 2489 | | |
| 2490 | | Token *next_token = &pc->tokens->at(*token_index); |
| 2491 | | if (next_token->id == TokenIdKeywordAlign) { |
| 2492 | | *token_index += 1; |
| 2493 | | ast_eat_token(pc, token_index, TokenIdLParen); |
| 2494 | | |
| 2495 | | node->data.fn_proto.align_expr = ast_parse_expression(pc, token_index, true); |
| 2496 | | ast_eat_token(pc, token_index, TokenIdRParen); |
| 2497 | | next_token = &pc->tokens->at(*token_index); |
| 2498 | | } |
| 2499 | | if (next_token->id == TokenIdKeywordSection) { |
| 2500 | | *token_index += 1; |
| 2501 | | ast_eat_token(pc, token_index, TokenIdLParen); |
| 2502 | | |
| 2503 | | node->data.fn_proto.section_expr = ast_parse_expression(pc, token_index, true); |
| 2504 | | ast_eat_token(pc, token_index, TokenIdRParen); |
| 2505 | | next_token = &pc->tokens->at(*token_index); |
| 2506 | | } |
| 2507 | | if (next_token->id == TokenIdKeywordVar) { |
| 2508 | | node->data.fn_proto.return_var_token = next_token; |
| 2509 | | *token_index += 1; |
| 2510 | | next_token = &pc->tokens->at(*token_index); |
| 2511 | | } else { |
| 2512 | | if (next_token->id == TokenIdKeywordError) { |
| 2513 | | Token *maybe_lbrace_tok = &pc->tokens->at(*token_index + 1); |
| 2514 | | if (maybe_lbrace_tok->id == TokenIdLBrace) { |
| 2515 | | *token_index += 1; |
| 2516 | | node->data.fn_proto.return_type = ast_create_node(pc, NodeTypeErrorType, next_token); |
| 2517 | | return node; |
| 2518 | | } |
| 2519 | | } else if (next_token->id == TokenIdBang) { |
| 2520 | | *token_index += 1; |
| 2521 | | node->data.fn_proto.auto_err_set = true; |
| 2522 | | next_token = &pc->tokens->at(*token_index); |
| 2523 | | } |
| 2524 | | node->data.fn_proto.return_type = ast_parse_type_expr(pc, token_index, true); |
| 2525 | | } |
| 2526 | | |
| 2527 | | return node; |
| 2539 | return ast_parse_fn_proto_partial(pc, token_index, fn_token, async_allocator_type_node, cc, is_extern, visib_mod); |
| 2528 | 2540 | } |
| 2529 | 2541 | |
| 2530 | 2542 | /* |