| author | |
| committer | |
| log | 897e783763d60449ad1b9514cb5ba86a38f7ae4a |
| tree | 1f1603884432590aba99c7d2edd0d035548c5286 |
| parent | 18af2f9a2764cc340571578d58cb2575faeccdc6 |
closes #85711 files changed, 111 insertions(+), 2 deletions(-)
doc/langref.html.in+3-1| ... | ... | @@ -5863,7 +5863,9 @@ StructLiteralField = "." Symbol "=" Expression |
| 5863 | 5863 | |
| 5864 | 5864 | PrefixOp = "!" | "-" | "~" | "*" | ("&" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "??" | "-%" | "try" | "await" |
| 5865 | 5865 | |
| 5866 | PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ContainerDecl | ("continue" option(":" Symbol)) | ErrorSetDecl | |
| 5866 | PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ContainerDecl | ("continue" option(":" Symbol)) | ErrorSetDecl | PromiseType | |
| 5867 | ||
| 5868 | PromiseType = "promise" option("->" TypeExpr) | |
| 5867 | 5869 | |
| 5868 | 5870 | ArrayType : "[" option(Expression) "]" option("align" "(" Expression option(":" Integer ":" Integer) ")")) option("const") option("volatile") TypeExpr |
| 5869 | 5871 |
src/all_types.hpp+13| ... | ... | @@ -409,6 +409,7 @@ enum NodeType { |
| 409 | 409 | NodeTypeResume, |
| 410 | 410 | NodeTypeAwaitExpr, |
| 411 | 411 | NodeTypeSuspend, |
| 412 | NodeTypePromiseType, | |
| 412 | 413 | }; |
| 413 | 414 | |
| 414 | 415 | struct AstNodeRoot { |
| ... | ... | @@ -879,6 +880,10 @@ struct AstNodeSuspend { |
| 879 | 880 | AstNode *promise_symbol; |
| 880 | 881 | }; |
| 881 | 882 | |
| 883 | struct AstNodePromiseType { | |
| 884 | AstNode *payload_type; // can be NULL | |
| 885 | }; | |
| 886 | ||
| 882 | 887 | struct AstNode { |
| 883 | 888 | enum NodeType type; |
| 884 | 889 | size_t line; |
| ... | ... | @@ -939,6 +944,7 @@ struct AstNode { |
| 939 | 944 | AstNodeResumeExpr resume_expr; |
| 940 | 945 | AstNodeAwaitExpr await_expr; |
| 941 | 946 | AstNodeSuspend suspend; |
| 947 | AstNodePromiseType promise_type; | |
| 942 | 948 | } data; |
| 943 | 949 | }; |
| 944 | 950 | |
| ... | ... | @@ -1947,6 +1953,7 @@ enum IrInstructionId { |
| 1947 | 1953 | IrInstructionIdSetRuntimeSafety, |
| 1948 | 1954 | IrInstructionIdSetFloatMode, |
| 1949 | 1955 | IrInstructionIdArrayType, |
| 1956 | IrInstructionIdPromiseType, | |
| 1950 | 1957 | IrInstructionIdSliceType, |
| 1951 | 1958 | IrInstructionIdAsm, |
| 1952 | 1959 | IrInstructionIdSizeOf, |
| ... | ... | @@ -2365,6 +2372,12 @@ struct IrInstructionArrayType { |
| 2365 | 2372 | IrInstruction *child_type; |
| 2366 | 2373 | }; |
| 2367 | 2374 | |
| 2375 | struct IrInstructionPromiseType { | |
| 2376 | IrInstruction base; | |
| 2377 | ||
| 2378 | IrInstruction *payload_type; | |
| 2379 | }; | |
| 2380 | ||
| 2368 | 2381 | struct IrInstructionSliceType { |
| 2369 | 2382 | IrInstruction base; |
| 2370 | 2383 |
src/analyze.cpp+1| ... | ... | @@ -3254,6 +3254,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { |
| 3254 | 3254 | case NodeTypeResume: |
| 3255 | 3255 | case NodeTypeAwaitExpr: |
| 3256 | 3256 | case NodeTypeSuspend: |
| 3257 | case NodeTypePromiseType: | |
| 3257 | 3258 | zig_unreachable(); |
| 3258 | 3259 | } |
| 3259 | 3260 | } |
src/ast_render.cpp+11| ... | ... | @@ -250,6 +250,8 @@ static const char *node_type_str(NodeType node_type) { |
| 250 | 250 | return "AwaitExpr"; |
| 251 | 251 | case NodeTypeSuspend: |
| 252 | 252 | return "Suspend"; |
| 253 | case NodeTypePromiseType: | |
| 254 | return "PromiseType"; | |
| 253 | 255 | } |
| 254 | 256 | zig_unreachable(); |
| 255 | 257 | } |
| ... | ... | @@ -781,6 +783,15 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 781 | 783 | render_node_ungrouped(ar, node->data.array_type.child_type); |
| 782 | 784 | break; |
| 783 | 785 | } |
| 786 | case NodeTypePromiseType: | |
| 787 | { | |
| 788 | fprintf(ar->f, "promise"); | |
| 789 | if (node->data.promise_type.payload_type != nullptr) { | |
| 790 | fprintf(ar->f, "->"); | |
| 791 | render_node_grouped(ar, node->data.promise_type.payload_type); | |
| 792 | } | |
| 793 | break; | |
| 794 | } | |
| 784 | 795 | case NodeTypeErrorType: |
| 785 | 796 | fprintf(ar->f, "error"); |
| 786 | 797 | break; |
src/codegen.cpp+1| ... | ... | @@ -4205,6 +4205,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 4205 | 4205 | case IrInstructionIdSetRuntimeSafety: |
| 4206 | 4206 | case IrInstructionIdSetFloatMode: |
| 4207 | 4207 | case IrInstructionIdArrayType: |
| 4208 | case IrInstructionIdPromiseType: | |
| 4208 | 4209 | case IrInstructionIdSliceType: |
| 4209 | 4210 | case IrInstructionIdSizeOf: |
| 4210 | 4211 | case IrInstructionIdSwitchTarget: |
src/ir.cpp+54| ... | ... | @@ -349,6 +349,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionArrayType *) { |
| 349 | 349 | return IrInstructionIdArrayType; |
| 350 | 350 | } |
| 351 | 351 | |
| 352 | static constexpr IrInstructionId ir_instruction_id(IrInstructionPromiseType *) { | |
| 353 | return IrInstructionIdPromiseType; | |
| 354 | } | |
| 355 | ||
| 352 | 356 | static constexpr IrInstructionId ir_instruction_id(IrInstructionSliceType *) { |
| 353 | 357 | return IrInstructionIdSliceType; |
| 354 | 358 | } |
| ... | ... | @@ -1469,6 +1473,17 @@ static IrInstruction *ir_build_array_type(IrBuilder *irb, Scope *scope, AstNode |
| 1469 | 1473 | return &instruction->base; |
| 1470 | 1474 | } |
| 1471 | 1475 | |
| 1476 | static IrInstruction *ir_build_promise_type(IrBuilder *irb, Scope *scope, AstNode *source_node, | |
| 1477 | IrInstruction *payload_type) | |
| 1478 | { | |
| 1479 | IrInstructionPromiseType *instruction = ir_build_instruction<IrInstructionPromiseType>(irb, scope, source_node); | |
| 1480 | instruction->payload_type = payload_type; | |
| 1481 | ||
| 1482 | if (payload_type != nullptr) ir_ref_instruction(payload_type, irb->current_basic_block); | |
| 1483 | ||
| 1484 | return &instruction->base; | |
| 1485 | } | |
| 1486 | ||
| 1472 | 1487 | static IrInstruction *ir_build_slice_type(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 1473 | 1488 | IrInstruction *child_type, bool is_const, bool is_volatile, IrInstruction *align_value) |
| 1474 | 1489 | { |
| ... | ... | @@ -5074,6 +5089,22 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n |
| 5074 | 5089 | } |
| 5075 | 5090 | } |
| 5076 | 5091 | |
| 5092 | static IrInstruction *ir_gen_promise_type(IrBuilder *irb, Scope *scope, AstNode *node) { | |
| 5093 | assert(node->type == NodeTypePromiseType); | |
| 5094 | ||
| 5095 | AstNode *payload_type_node = node->data.promise_type.payload_type; | |
| 5096 | IrInstruction *payload_type_value = nullptr; | |
| 5097 | ||
| 5098 | if (payload_type_node != nullptr) { | |
| 5099 | payload_type_value = ir_gen_node(irb, payload_type_node, scope); | |
| 5100 | if (payload_type_value == irb->codegen->invalid_instruction) | |
| 5101 | return payload_type_value; | |
| 5102 | ||
| 5103 | } | |
| 5104 | ||
| 5105 | return ir_build_promise_type(irb, scope, node, payload_type_value); | |
| 5106 | } | |
| 5107 | ||
| 5077 | 5108 | static IrInstruction *ir_gen_undefined_literal(IrBuilder *irb, Scope *scope, AstNode *node) { |
| 5078 | 5109 | assert(node->type == NodeTypeUndefinedLiteral); |
| 5079 | 5110 | return ir_build_const_undefined(irb, scope, node); |
| ... | ... | @@ -6282,6 +6313,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop |
| 6282 | 6313 | return ir_lval_wrap(irb, scope, ir_gen_bool_literal(irb, scope, node), lval); |
| 6283 | 6314 | case NodeTypeArrayType: |
| 6284 | 6315 | return ir_lval_wrap(irb, scope, ir_gen_array_type(irb, scope, node), lval); |
| 6316 | case NodeTypePromiseType: | |
| 6317 | return ir_lval_wrap(irb, scope, ir_gen_promise_type(irb, scope, node), lval); | |
| 6285 | 6318 | case NodeTypeStringLiteral: |
| 6286 | 6319 | return ir_lval_wrap(irb, scope, ir_gen_string_literal(irb, scope, node), lval); |
| 6287 | 6320 | case NodeTypeUndefinedLiteral: |
| ... | ... | @@ -14069,6 +14102,24 @@ static TypeTableEntry *ir_analyze_instruction_array_type(IrAnalyze *ira, |
| 14069 | 14102 | zig_unreachable(); |
| 14070 | 14103 | } |
| 14071 | 14104 | |
| 14105 | static TypeTableEntry *ir_analyze_instruction_promise_type(IrAnalyze *ira, IrInstructionPromiseType *instruction) { | |
| 14106 | TypeTableEntry *promise_type; | |
| 14107 | ||
| 14108 | if (instruction->payload_type == nullptr) { | |
| 14109 | promise_type = ira->codegen->builtin_types.entry_promise; | |
| 14110 | } else { | |
| 14111 | TypeTableEntry *payload_type = ir_resolve_type(ira, instruction->payload_type->other); | |
| 14112 | if (type_is_invalid(payload_type)) | |
| 14113 | return ira->codegen->builtin_types.entry_invalid; | |
| 14114 | ||
| 14115 | promise_type = get_promise_type(ira->codegen, payload_type); | |
| 14116 | } | |
| 14117 | ||
| 14118 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); | |
| 14119 | out_val->data.x_type = promise_type; | |
| 14120 | return ira->codegen->builtin_types.entry_type; | |
| 14121 | } | |
| 14122 | ||
| 14072 | 14123 | static TypeTableEntry *ir_analyze_instruction_size_of(IrAnalyze *ira, |
| 14073 | 14124 | IrInstructionSizeOf *size_of_instruction) |
| 14074 | 14125 | { |
| ... | ... | @@ -17907,6 +17958,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 17907 | 17958 | return ir_analyze_instruction_asm(ira, (IrInstructionAsm *)instruction); |
| 17908 | 17959 | case IrInstructionIdArrayType: |
| 17909 | 17960 | return ir_analyze_instruction_array_type(ira, (IrInstructionArrayType *)instruction); |
| 17961 | case IrInstructionIdPromiseType: | |
| 17962 | return ir_analyze_instruction_promise_type(ira, (IrInstructionPromiseType *)instruction); | |
| 17910 | 17963 | case IrInstructionIdSizeOf: |
| 17911 | 17964 | return ir_analyze_instruction_size_of(ira, (IrInstructionSizeOf *)instruction); |
| 17912 | 17965 | case IrInstructionIdTestNonNull: |
| ... | ... | @@ -18232,6 +18285,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 18232 | 18285 | case IrInstructionIdStructFieldPtr: |
| 18233 | 18286 | case IrInstructionIdUnionFieldPtr: |
| 18234 | 18287 | case IrInstructionIdArrayType: |
| 18288 | case IrInstructionIdPromiseType: | |
| 18235 | 18289 | case IrInstructionIdSliceType: |
| 18236 | 18290 | case IrInstructionIdSizeOf: |
| 18237 | 18291 | case IrInstructionIdTestNonNull: |
src/ir_print.cpp+11| ... | ... | @@ -404,6 +404,14 @@ static void ir_print_array_type(IrPrint *irp, IrInstructionArrayType *instructio |
| 404 | 404 | ir_print_other_instruction(irp, instruction->child_type); |
| 405 | 405 | } |
| 406 | 406 | |
| 407 | static void ir_print_promise_type(IrPrint *irp, IrInstructionPromiseType *instruction) { | |
| 408 | fprintf(irp->f, "promise"); | |
| 409 | if (instruction->payload_type != nullptr) { | |
| 410 | fprintf(irp->f, "->"); | |
| 411 | ir_print_other_instruction(irp, instruction->payload_type); | |
| 412 | } | |
| 413 | } | |
| 414 | ||
| 407 | 415 | static void ir_print_slice_type(IrPrint *irp, IrInstructionSliceType *instruction) { |
| 408 | 416 | const char *const_kw = instruction->is_const ? "const " : ""; |
| 409 | 417 | fprintf(irp->f, "[]%s", const_kw); |
| ... | ... | @@ -1263,6 +1271,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1263 | 1271 | case IrInstructionIdArrayType: |
| 1264 | 1272 | ir_print_array_type(irp, (IrInstructionArrayType *)instruction); |
| 1265 | 1273 | break; |
| 1274 | case IrInstructionIdPromiseType: | |
| 1275 | ir_print_promise_type(irp, (IrInstructionPromiseType *)instruction); | |
| 1276 | break; | |
| 1266 | 1277 | case IrInstructionIdSliceType: |
| 1267 | 1278 | ir_print_slice_type(irp, (IrInstructionSliceType *)instruction); |
| 1268 | 1279 | break; |
src/parser.cpp+13-1| ... | ... | @@ -705,7 +705,7 @@ static AstNode *ast_parse_comptime_expr(ParseContext *pc, size_t *token_index, b |
| 705 | 705 | } |
| 706 | 706 | |
| 707 | 707 | /* |
| 708 | PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ContainerDecl | ("continue" option(":" Symbol)) | ErrorSetDecl | |
| 708 | PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ContainerDecl | ("continue" option(":" Symbol)) | ErrorSetDecl | PromiseType | |
| 709 | 709 | KeywordLiteral = "true" | "false" | "null" | "undefined" | "error" | "this" | "unreachable" | "suspend" |
| 710 | 710 | ErrorSetDecl = "error" "{" list(Symbol, ",") "}" |
| 711 | 711 | */ |
| ... | ... | @@ -774,6 +774,15 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo |
| 774 | 774 | AstNode *node = ast_create_node(pc, NodeTypeSuspend, token); |
| 775 | 775 | *token_index += 1; |
| 776 | 776 | return node; |
| 777 | } else if (token->id == TokenIdKeywordPromise) { | |
| 778 | AstNode *node = ast_create_node(pc, NodeTypePromiseType, token); | |
| 779 | *token_index += 1; | |
| 780 | Token *arrow_tok = &pc->tokens->at(*token_index); | |
| 781 | if (arrow_tok->id == TokenIdArrow) { | |
| 782 | *token_index += 1; | |
| 783 | node->data.promise_type.payload_type = ast_parse_type_expr(pc, token_index, true); | |
| 784 | } | |
| 785 | return node; | |
| 777 | 786 | } else if (token->id == TokenIdKeywordError) { |
| 778 | 787 | Token *next_token = &pc->tokens->at(*token_index + 1); |
| 779 | 788 | if (next_token->id == TokenIdLBrace) { |
| ... | ... | @@ -3081,6 +3090,9 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont |
| 3081 | 3090 | visit_field(&node->data.array_type.child_type, visit, context); |
| 3082 | 3091 | visit_field(&node->data.array_type.align_expr, visit, context); |
| 3083 | 3092 | break; |
| 3093 | case NodeTypePromiseType: | |
| 3094 | visit_field(&node->data.promise_type.payload_type, visit, context); | |
| 3095 | break; | |
| 3084 | 3096 | case NodeTypeErrorType: |
| 3085 | 3097 | // none |
| 3086 | 3098 | break; |
src/tokenizer.cpp+2| ... | ... | @@ -135,6 +135,7 @@ static const struct ZigKeyword zig_keywords[] = { |
| 135 | 135 | {"null", TokenIdKeywordNull}, |
| 136 | 136 | {"or", TokenIdKeywordOr}, |
| 137 | 137 | {"packed", TokenIdKeywordPacked}, |
| 138 | {"promise", TokenIdKeywordPromise}, | |
| 138 | 139 | {"pub", TokenIdKeywordPub}, |
| 139 | 140 | {"resume", TokenIdKeywordResume}, |
| 140 | 141 | {"return", TokenIdKeywordReturn}, |
| ... | ... | @@ -1558,6 +1559,7 @@ const char * token_name(TokenId id) { |
| 1558 | 1559 | case TokenIdKeywordNull: return "null"; |
| 1559 | 1560 | case TokenIdKeywordOr: return "or"; |
| 1560 | 1561 | case TokenIdKeywordPacked: return "packed"; |
| 1562 | case TokenIdKeywordPromise: return "promise"; | |
| 1561 | 1563 | case TokenIdKeywordPub: return "pub"; |
| 1562 | 1564 | case TokenIdKeywordReturn: return "return"; |
| 1563 | 1565 | case TokenIdKeywordSection: return "section"; |
src/tokenizer.hpp+1| ... | ... | @@ -76,6 +76,7 @@ enum TokenId { |
| 76 | 76 | TokenIdKeywordNull, |
| 77 | 77 | TokenIdKeywordOr, |
| 78 | 78 | TokenIdKeywordPacked, |
| 79 | TokenIdKeywordPromise, | |
| 79 | 80 | TokenIdKeywordPub, |
| 80 | 81 | TokenIdKeywordResume, |
| 81 | 82 | TokenIdKeywordReturn, |
test/cases/coroutines.zig+1| ... | ... | @@ -5,6 +5,7 @@ var x: i32 = 1; |
| 5 | 5 | |
| 6 | 6 | test "create a coroutine and cancel it" { |
| 7 | 7 | const p = try async<std.debug.global_allocator> simpleAsyncFn(); |
| 8 | comptime assert(@typeOf(p) == promise->void); | |
| 8 | 9 | cancel p; |
| 9 | 10 | assert(x == 2); |
| 10 | 11 | } |