| author | |
| committer | |
| log | 3d58d7232ab6d1fd54523182beb99c31512bc4b9 |
| tree | 23303c1ac09a121c59fb075747e74fffcb838f83 |
| parent | af10b0fec213172b0403abfd8ff6e53c88f8c3c6 |
9 files changed, 171 insertions(+), 7 deletions(-)
doc/langref.html.in+4-2| ... | @@ -5663,7 +5663,7 @@ ErrorSetExpr = (PrefixOpExpression "!" PrefixOpExpression) | PrefixOpExpression | ... | @@ -5663,7 +5663,7 @@ ErrorSetExpr = (PrefixOpExpression "!" PrefixOpExpression) | PrefixOpExpression |
| 5663 | 5663 | ||
| 5664 | BlockOrExpression = Block | Expression | 5664 | BlockOrExpression = Block | Expression |
| 5665 | 5665 | ||
| 5666 | Expression = TryExpression | ReturnExpression | BreakExpression | AssignmentExpression | 5666 | Expression = TryExpression | ReturnExpression | BreakExpression | AssignmentExpression | CancelExpression |
| 5667 | 5667 | ||
| 5668 | AsmExpression = "asm" option("volatile") "(" String option(AsmOutput) ")" | 5668 | AsmExpression = "asm" option("volatile") "(" String option(AsmOutput) ")" |
| 5669 | 5669 | ||
| ... | @@ -5707,6 +5707,8 @@ TryExpression = "try" Expression | ... | @@ -5707,6 +5707,8 @@ TryExpression = "try" Expression |
| 5707 | 5707 | ||
| 5708 | BreakExpression = "break" option(":" Symbol) option(Expression) | 5708 | BreakExpression = "break" option(":" Symbol) option(Expression) |
| 5709 | 5709 | ||
| 5710 | CancelExpression = "cancel" Expression; | ||
| 5711 | |||
| 5710 | Defer(body) = ("defer" | "deferror") body | 5712 | Defer(body) = ("defer" | "deferror") body |
| 5711 | 5713 | ||
| 5712 | IfExpression(body) = "if" "(" Expression ")" body option("else" BlockExpression(body)) | 5714 | IfExpression(body) = "if" "(" Expression ")" body option("else" BlockExpression(body)) |
| ... | @@ -5745,7 +5747,7 @@ MultiplyOperator = "||" | "*" | "/" | "%" | "**" | "*%" | ... | @@ -5745,7 +5747,7 @@ MultiplyOperator = "||" | "*" | "/" | "%" | "**" | "*%" |
| 5745 | 5747 | ||
| 5746 | PrefixOpExpression = PrefixOp ErrorSetExpr | SuffixOpExpression | 5748 | PrefixOpExpression = PrefixOp ErrorSetExpr | SuffixOpExpression |
| 5747 | 5749 | ||
| 5748 | SuffixOpExpression = PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression) | 5750 | SuffixOpExpression = ("async" option("(" Expression ")") PrimaryExpression FnCallExpression) | PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression) |
| 5749 | 5751 | ||
| 5750 | FieldAccessExpression = "." Symbol | 5752 | FieldAccessExpression = "." Symbol |
| 5751 | 5753 |
src/all_types.hpp+16| ... | @@ -393,6 +393,7 @@ enum NodeType { | ... | @@ -393,6 +393,7 @@ enum NodeType { |
| 393 | NodeTypeIfErrorExpr, | 393 | NodeTypeIfErrorExpr, |
| 394 | NodeTypeTestExpr, | 394 | NodeTypeTestExpr, |
| 395 | NodeTypeErrorSetDecl, | 395 | NodeTypeErrorSetDecl, |
| 396 | NodeTypeCancel, | ||
| 396 | }; | 397 | }; |
| 397 | 398 | ||
| 398 | struct AstNodeRoot { | 399 | struct AstNodeRoot { |
| ... | @@ -567,6 +568,8 @@ struct AstNodeFnCallExpr { | ... | @@ -567,6 +568,8 @@ struct AstNodeFnCallExpr { |
| 567 | AstNode *fn_ref_expr; | 568 | AstNode *fn_ref_expr; |
| 568 | ZigList<AstNode *> params; | 569 | ZigList<AstNode *> params; |
| 569 | bool is_builtin; | 570 | bool is_builtin; |
| 571 | bool is_async; | ||
| 572 | AstNode *async_allocator; | ||
| 570 | }; | 573 | }; |
| 571 | 574 | ||
| 572 | struct AstNodeArrayAccessExpr { | 575 | struct AstNodeArrayAccessExpr { |
| ... | @@ -829,6 +832,10 @@ struct AstNodeBreakExpr { | ... | @@ -829,6 +832,10 @@ struct AstNodeBreakExpr { |
| 829 | AstNode *expr; // may be null | 832 | AstNode *expr; // may be null |
| 830 | }; | 833 | }; |
| 831 | 834 | ||
| 835 | struct AstNodeCancelExpr { | ||
| 836 | AstNode *expr; | ||
| 837 | }; | ||
| 838 | |||
| 832 | struct AstNodeContinueExpr { | 839 | struct AstNodeContinueExpr { |
| 833 | Buf *name; | 840 | Buf *name; |
| 834 | }; | 841 | }; |
| ... | @@ -900,6 +907,7 @@ struct AstNode { | ... | @@ -900,6 +907,7 @@ struct AstNode { |
| 900 | AstNodeErrorType error_type; | 907 | AstNodeErrorType error_type; |
| 901 | AstNodeVarLiteral var_literal; | 908 | AstNodeVarLiteral var_literal; |
| 902 | AstNodeErrorSetDecl err_set_decl; | 909 | AstNodeErrorSetDecl err_set_decl; |
| 910 | AstNodeCancelExpr cancel_expr; | ||
| 903 | } data; | 911 | } data; |
| 904 | }; | 912 | }; |
| 905 | 913 | ||
| ... | @@ -1495,6 +1503,7 @@ struct CodeGen { | ... | @@ -1495,6 +1503,7 @@ struct CodeGen { |
| 1495 | TypeTableEntry *entry_var; | 1503 | TypeTableEntry *entry_var; |
| 1496 | TypeTableEntry *entry_global_error_set; | 1504 | TypeTableEntry *entry_global_error_set; |
| 1497 | TypeTableEntry *entry_arg_tuple; | 1505 | TypeTableEntry *entry_arg_tuple; |
| 1506 | TypeTableEntry *entry_promise; | ||
| 1498 | } builtin_types; | 1507 | } builtin_types; |
| 1499 | 1508 | ||
| 1500 | EmitFileType emit_file_type; | 1509 | EmitFileType emit_file_type; |
| ... | @@ -1939,6 +1948,7 @@ enum IrInstructionId { | ... | @@ -1939,6 +1948,7 @@ enum IrInstructionId { |
| 1939 | IrInstructionIdExport, | 1948 | IrInstructionIdExport, |
| 1940 | IrInstructionIdErrorReturnTrace, | 1949 | IrInstructionIdErrorReturnTrace, |
| 1941 | IrInstructionIdErrorUnion, | 1950 | IrInstructionIdErrorUnion, |
| 1951 | IrInstructionIdCancel, | ||
| 1942 | }; | 1952 | }; |
| 1943 | 1953 | ||
| 1944 | struct IrInstruction { | 1954 | struct IrInstruction { |
| ... | @@ -2776,6 +2786,12 @@ struct IrInstructionErrorUnion { | ... | @@ -2776,6 +2786,12 @@ struct IrInstructionErrorUnion { |
| 2776 | IrInstruction *payload; | 2786 | IrInstruction *payload; |
| 2777 | }; | 2787 | }; |
| 2778 | 2788 | ||
| 2789 | struct IrInstructionCancel { | ||
| 2790 | IrInstruction base; | ||
| 2791 | |||
| 2792 | IrInstruction *target; | ||
| 2793 | }; | ||
| 2794 | |||
| 2779 | static const size_t slice_ptr_index = 0; | 2795 | static const size_t slice_ptr_index = 0; |
| 2780 | static const size_t slice_len_index = 1; | 2796 | static const size_t slice_len_index = 1; |
| 2781 | 2797 |
src/analyze.cpp+1| ... | @@ -3117,6 +3117,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { | ... | @@ -3117,6 +3117,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { |
| 3117 | case NodeTypeIfErrorExpr: | 3117 | case NodeTypeIfErrorExpr: |
| 3118 | case NodeTypeTestExpr: | 3118 | case NodeTypeTestExpr: |
| 3119 | case NodeTypeErrorSetDecl: | 3119 | case NodeTypeErrorSetDecl: |
| 3120 | case NodeTypeCancel: | ||
| 3120 | zig_unreachable(); | 3121 | zig_unreachable(); |
| 3121 | } | 3122 | } |
| 3122 | } | 3123 | } |
src/ast_render.cpp+8| ... | @@ -244,6 +244,8 @@ static const char *node_type_str(NodeType node_type) { | ... | @@ -244,6 +244,8 @@ static const char *node_type_str(NodeType node_type) { |
| 244 | return "TestExpr"; | 244 | return "TestExpr"; |
| 245 | case NodeTypeErrorSetDecl: | 245 | case NodeTypeErrorSetDecl: |
| 246 | return "ErrorSetDecl"; | 246 | return "ErrorSetDecl"; |
| 247 | case NodeTypeCancel: | ||
| 248 | return "Cancel"; | ||
| 247 | } | 249 | } |
| 248 | zig_unreachable(); | 250 | zig_unreachable(); |
| 249 | } | 251 | } |
| ... | @@ -1037,6 +1039,12 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { | ... | @@ -1037,6 +1039,12 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 1037 | fprintf(ar->f, "}"); | 1039 | fprintf(ar->f, "}"); |
| 1038 | break; | 1040 | break; |
| 1039 | } | 1041 | } |
| 1042 | case NodeTypeCancel: | ||
| 1043 | { | ||
| 1044 | fprintf(ar->f, "cancel "); | ||
| 1045 | render_node_grouped(ar, node->data.cancel_expr.expr); | ||
| 1046 | break; | ||
| 1047 | } | ||
| 1040 | case NodeTypeFnDecl: | 1048 | case NodeTypeFnDecl: |
| 1041 | case NodeTypeParamDecl: | 1049 | case NodeTypeParamDecl: |
| 1042 | case NodeTypeTestDecl: | 1050 | case NodeTypeTestDecl: |
src/codegen.cpp+16| ... | @@ -3088,6 +3088,10 @@ static LLVMValueRef ir_render_error_return_trace(CodeGen *g, IrExecutable *execu | ... | @@ -3088,6 +3088,10 @@ static LLVMValueRef ir_render_error_return_trace(CodeGen *g, IrExecutable *execu |
| 3088 | return g->cur_err_ret_trace_val; | 3088 | return g->cur_err_ret_trace_val; |
| 3089 | } | 3089 | } |
| 3090 | 3090 | ||
| 3091 | static LLVMValueRef ir_render_cancel(CodeGen *g, IrExecutable *executable, IrInstructionCancel *instruction) { | ||
| 3092 | zig_panic("TODO ir_render_cancel"); | ||
| 3093 | } | ||
| 3094 | |||
| 3091 | static LLVMAtomicOrdering to_LLVMAtomicOrdering(AtomicOrder atomic_order) { | 3095 | static LLVMAtomicOrdering to_LLVMAtomicOrdering(AtomicOrder atomic_order) { |
| 3092 | switch (atomic_order) { | 3096 | switch (atomic_order) { |
| 3093 | case AtomicOrderUnordered: return LLVMAtomicOrderingUnordered; | 3097 | case AtomicOrderUnordered: return LLVMAtomicOrderingUnordered; |
| ... | @@ -3862,6 +3866,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, | ... | @@ -3862,6 +3866,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 3862 | return ir_render_align_cast(g, executable, (IrInstructionAlignCast *)instruction); | 3866 | return ir_render_align_cast(g, executable, (IrInstructionAlignCast *)instruction); |
| 3863 | case IrInstructionIdErrorReturnTrace: | 3867 | case IrInstructionIdErrorReturnTrace: |
| 3864 | return ir_render_error_return_trace(g, executable, (IrInstructionErrorReturnTrace *)instruction); | 3868 | return ir_render_error_return_trace(g, executable, (IrInstructionErrorReturnTrace *)instruction); |
| 3869 | case IrInstructionIdCancel: | ||
| 3870 | return ir_render_cancel(g, executable, (IrInstructionCancel *)instruction); | ||
| 3865 | } | 3871 | } |
| 3866 | zig_unreachable(); | 3872 | zig_unreachable(); |
| 3867 | } | 3873 | } |
| ... | @@ -5271,6 +5277,16 @@ static void define_builtin_types(CodeGen *g) { | ... | @@ -5271,6 +5277,16 @@ static void define_builtin_types(CodeGen *g) { |
| 5271 | 5277 | ||
| 5272 | g->primitive_type_table.put(&entry->name, entry); | 5278 | g->primitive_type_table.put(&entry->name, entry); |
| 5273 | } | 5279 | } |
| 5280 | { | ||
| 5281 | TypeTableEntry *u8_ptr_type = get_pointer_to_type(g, g->builtin_types.entry_u8, false); | ||
| 5282 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdVoid); | ||
| 5283 | entry->type_ref = u8_ptr_type->type_ref; | ||
| 5284 | entry->zero_bits = false; | ||
| 5285 | buf_init_from_str(&entry->name, "promise"); | ||
| 5286 | entry->di_type = u8_ptr_type->di_type; | ||
| 5287 | g->builtin_types.entry_promise = entry; | ||
| 5288 | g->primitive_type_table.put(&entry->name, entry); | ||
| 5289 | } | ||
| 5274 | 5290 | ||
| 5275 | } | 5291 | } |
| 5276 | 5292 |
src/ir.cpp+46| ... | @@ -637,6 +637,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionErrorUnion *) { | ... | @@ -637,6 +637,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionErrorUnion *) { |
| 637 | return IrInstructionIdErrorUnion; | 637 | return IrInstructionIdErrorUnion; |
| 638 | } | 638 | } |
| 639 | 639 | ||
| 640 | static constexpr IrInstructionId ir_instruction_id(IrInstructionCancel *) { | ||
| 641 | return IrInstructionIdCancel; | ||
| 642 | } | ||
| 643 | |||
| 640 | template<typename T> | 644 | template<typename T> |
| 641 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { | 645 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| 642 | T *special_instruction = allocate<T>(1); | 646 | T *special_instruction = allocate<T>(1); |
| ... | @@ -2396,6 +2400,17 @@ static IrInstruction *ir_build_error_union(IrBuilder *irb, Scope *scope, AstNode | ... | @@ -2396,6 +2400,17 @@ static IrInstruction *ir_build_error_union(IrBuilder *irb, Scope *scope, AstNode |
| 2396 | return &instruction->base; | 2400 | return &instruction->base; |
| 2397 | } | 2401 | } |
| 2398 | 2402 | ||
| 2403 | static IrInstruction *ir_build_cancel(IrBuilder *irb, Scope *scope, AstNode *source_node, | ||
| 2404 | IrInstruction *target) | ||
| 2405 | { | ||
| 2406 | IrInstructionCancel *instruction = ir_build_instruction<IrInstructionCancel>(irb, scope, source_node); | ||
| 2407 | instruction->target = target; | ||
| 2408 | |||
| 2409 | ir_ref_instruction(target, irb->current_basic_block); | ||
| 2410 | |||
| 2411 | return &instruction->base; | ||
| 2412 | } | ||
| 2413 | |||
| 2399 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { | 2414 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { |
| 2400 | results[ReturnKindUnconditional] = 0; | 2415 | results[ReturnKindUnconditional] = 0; |
| 2401 | results[ReturnKindError] = 0; | 2416 | results[ReturnKindError] = 0; |
| ... | @@ -3873,6 +3888,10 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node | ... | @@ -3873,6 +3888,10 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node |
| 3873 | return args[i]; | 3888 | return args[i]; |
| 3874 | } | 3889 | } |
| 3875 | 3890 | ||
| 3891 | if (node->data.fn_call_expr.is_async) { | ||
| 3892 | zig_panic("TODO ir_gen_fn_call for async fn calls"); | ||
| 3893 | } | ||
| 3894 | |||
| 3876 | return ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto); | 3895 | return ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto); |
| 3877 | } | 3896 | } |
| 3878 | 3897 | ||
| ... | @@ -5598,6 +5617,16 @@ static IrInstruction *ir_gen_fn_proto(IrBuilder *irb, Scope *parent_scope, AstNo | ... | @@ -5598,6 +5617,16 @@ static IrInstruction *ir_gen_fn_proto(IrBuilder *irb, Scope *parent_scope, AstNo |
| 5598 | return ir_build_fn_proto(irb, parent_scope, node, param_types, align_value, return_type, is_var_args); | 5617 | return ir_build_fn_proto(irb, parent_scope, node, param_types, align_value, return_type, is_var_args); |
| 5599 | } | 5618 | } |
| 5600 | 5619 | ||
| 5620 | static IrInstruction *ir_gen_cancel(IrBuilder *irb, Scope *parent_scope, AstNode *node) { | ||
| 5621 | assert(node->type == NodeTypeCancel); | ||
| 5622 | |||
| 5623 | IrInstruction *target_inst = ir_gen_node(irb, node->data.cancel_expr.expr, parent_scope); | ||
| 5624 | if (target_inst == irb->codegen->invalid_instruction) | ||
| 5625 | return irb->codegen->invalid_instruction; | ||
| 5626 | |||
| 5627 | return ir_build_cancel(irb, parent_scope, node, target_inst); | ||
| 5628 | } | ||
| 5629 | |||
| 5601 | static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scope, | 5630 | static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scope, |
| 5602 | LVal lval) | 5631 | LVal lval) |
| 5603 | { | 5632 | { |
| ... | @@ -5694,6 +5723,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop | ... | @@ -5694,6 +5723,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop |
| 5694 | return ir_lval_wrap(irb, scope, ir_gen_fn_proto(irb, scope, node), lval); | 5723 | return ir_lval_wrap(irb, scope, ir_gen_fn_proto(irb, scope, node), lval); |
| 5695 | case NodeTypeErrorSetDecl: | 5724 | case NodeTypeErrorSetDecl: |
| 5696 | return ir_lval_wrap(irb, scope, ir_gen_err_set_decl(irb, scope, node), lval); | 5725 | return ir_lval_wrap(irb, scope, ir_gen_err_set_decl(irb, scope, node), lval); |
| 5726 | case NodeTypeCancel: | ||
| 5727 | return ir_lval_wrap(irb, scope, ir_gen_cancel(irb, scope, node), lval); | ||
| 5697 | } | 5728 | } |
| 5698 | zig_unreachable(); | 5729 | zig_unreachable(); |
| 5699 | } | 5730 | } |
| ... | @@ -16459,6 +16490,17 @@ static TypeTableEntry *ir_analyze_instruction_tag_type(IrAnalyze *ira, IrInstruc | ... | @@ -16459,6 +16490,17 @@ static TypeTableEntry *ir_analyze_instruction_tag_type(IrAnalyze *ira, IrInstruc |
| 16459 | } | 16490 | } |
| 16460 | } | 16491 | } |
| 16461 | 16492 | ||
| 16493 | static TypeTableEntry *ir_analyze_instruction_cancel(IrAnalyze *ira, IrInstructionCancel *instruction) { | ||
| 16494 | IrInstruction *casted_target = ir_implicit_cast(ira, instruction->target->other, ira->codegen->builtin_types.entry_promise); | ||
| 16495 | if (type_is_invalid(casted_target->value.type)) | ||
| 16496 | return ira->codegen->builtin_types.entry_invalid; | ||
| 16497 | |||
| 16498 | IrInstruction *result = ir_build_cancel(&ira->new_irb, instruction->base.scope, instruction->base.source_node, casted_target); | ||
| 16499 | result->value.type = casted_target->value.type; | ||
| 16500 | ir_link_new_instruction(result, &instruction->base); | ||
| 16501 | return result->value.type; | ||
| 16502 | } | ||
| 16503 | |||
| 16462 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { | 16504 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { |
| 16463 | switch (instruction->id) { | 16505 | switch (instruction->id) { |
| 16464 | case IrInstructionIdInvalid: | 16506 | case IrInstructionIdInvalid: |
| ... | @@ -16661,6 +16703,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi | ... | @@ -16661,6 +16703,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 16661 | return ir_analyze_instruction_error_return_trace(ira, (IrInstructionErrorReturnTrace *)instruction); | 16703 | return ir_analyze_instruction_error_return_trace(ira, (IrInstructionErrorReturnTrace *)instruction); |
| 16662 | case IrInstructionIdErrorUnion: | 16704 | case IrInstructionIdErrorUnion: |
| 16663 | return ir_analyze_instruction_error_union(ira, (IrInstructionErrorUnion *)instruction); | 16705 | return ir_analyze_instruction_error_union(ira, (IrInstructionErrorUnion *)instruction); |
| 16706 | case IrInstructionIdCancel: | ||
| 16707 | return ir_analyze_instruction_cancel(ira, (IrInstructionCancel *)instruction); | ||
| 16664 | } | 16708 | } |
| 16665 | zig_unreachable(); | 16709 | zig_unreachable(); |
| 16666 | } | 16710 | } |
| ... | @@ -16774,7 +16818,9 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -16774,7 +16818,9 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 16774 | case IrInstructionIdPtrTypeOf: | 16818 | case IrInstructionIdPtrTypeOf: |
| 16775 | case IrInstructionIdSetAlignStack: | 16819 | case IrInstructionIdSetAlignStack: |
| 16776 | case IrInstructionIdExport: | 16820 | case IrInstructionIdExport: |
| 16821 | case IrInstructionIdCancel: | ||
| 16777 | return true; | 16822 | return true; |
| 16823 | |||
| 16778 | case IrInstructionIdPhi: | 16824 | case IrInstructionIdPhi: |
| 16779 | case IrInstructionIdUnOp: | 16825 | case IrInstructionIdUnOp: |
| 16780 | case IrInstructionIdBinOp: | 16826 | case IrInstructionIdBinOp: |
src/ir_print.cpp+8| ... | @@ -1010,6 +1010,11 @@ static void ir_print_error_union(IrPrint *irp, IrInstructionErrorUnion *instruct | ... | @@ -1010,6 +1010,11 @@ static void ir_print_error_union(IrPrint *irp, IrInstructionErrorUnion *instruct |
| 1010 | ir_print_other_instruction(irp, instruction->payload); | 1010 | ir_print_other_instruction(irp, instruction->payload); |
| 1011 | } | 1011 | } |
| 1012 | 1012 | ||
| 1013 | static void ir_print_cancel(IrPrint *irp, IrInstructionCancel *instruction) { | ||
| 1014 | fprintf(irp->f, "cancel "); | ||
| 1015 | ir_print_other_instruction(irp, instruction->target); | ||
| 1016 | } | ||
| 1017 | |||
| 1013 | static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | 1018 | static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1014 | ir_print_prefix(irp, instruction); | 1019 | ir_print_prefix(irp, instruction); |
| 1015 | switch (instruction->id) { | 1020 | switch (instruction->id) { |
| ... | @@ -1330,6 +1335,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | ... | @@ -1330,6 +1335,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1330 | case IrInstructionIdErrorUnion: | 1335 | case IrInstructionIdErrorUnion: |
| 1331 | ir_print_error_union(irp, (IrInstructionErrorUnion *)instruction); | 1336 | ir_print_error_union(irp, (IrInstructionErrorUnion *)instruction); |
| 1332 | break; | 1337 | break; |
| 1338 | case IrInstructionIdCancel: | ||
| 1339 | ir_print_cancel(irp, (IrInstructionCancel *)instruction); | ||
| 1340 | break; | ||
| 1333 | } | 1341 | } |
| 1334 | fprintf(irp->f, "\n"); | 1342 | fprintf(irp->f, "\n"); |
| 1335 | } | 1343 | } |
src/parser.cpp+56-5| ... | @@ -920,7 +920,7 @@ static AstNode *ast_parse_curly_suffix_expr(ParseContext *pc, size_t *token_inde | ... | @@ -920,7 +920,7 @@ static AstNode *ast_parse_curly_suffix_expr(ParseContext *pc, size_t *token_inde |
| 920 | } | 920 | } |
| 921 | 921 | ||
| 922 | /* | 922 | /* |
| 923 | SuffixOpExpression = PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression) | 923 | SuffixOpExpression = ("async" option("(" Expression ")") PrimaryExpression FnCallExpression) | PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression) |
| 924 | FnCallExpression : token(LParen) list(Expression, token(Comma)) token(RParen) | 924 | FnCallExpression : token(LParen) list(Expression, token(Comma)) token(RParen) |
| 925 | ArrayAccessExpression : token(LBracket) Expression token(RBracket) | 925 | ArrayAccessExpression : token(LBracket) Expression token(RBracket) |
| 926 | SliceExpression = "[" Expression ".." option(Expression) "]" | 926 | SliceExpression = "[" Expression ".." option(Expression) "]" |
| ... | @@ -928,9 +928,34 @@ FieldAccessExpression : token(Dot) token(Symbol) | ... | @@ -928,9 +928,34 @@ FieldAccessExpression : token(Dot) token(Symbol) |
| 928 | StructLiteralField : token(Dot) token(Symbol) token(Eq) Expression | 928 | StructLiteralField : token(Dot) token(Symbol) token(Eq) Expression |
| 929 | */ | 929 | */ |
| 930 | static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, size_t *token_index, bool mandatory) { | 930 | static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, size_t *token_index, bool mandatory) { |
| 931 | AstNode *primary_expr = ast_parse_primary_expr(pc, token_index, mandatory); | 931 | AstNode *primary_expr; |
| 932 | if (!primary_expr) | 932 | |
| 933 | return nullptr; | 933 | Token *async_token = &pc->tokens->at(*token_index); |
| 934 | if (async_token->id == TokenIdKeywordAsync) { | ||
| 935 | *token_index += 1; | ||
| 936 | |||
| 937 | AstNode *allocator_expr_node = nullptr; | ||
| 938 | Token *async_lparen_tok = &pc->tokens->at(*token_index); | ||
| 939 | if (async_lparen_tok->id == TokenIdLParen) { | ||
| 940 | *token_index += 1; | ||
| 941 | allocator_expr_node = ast_parse_expression(pc, token_index, true); | ||
| 942 | ast_eat_token(pc, token_index, TokenIdRParen); | ||
| 943 | } | ||
| 944 | |||
| 945 | AstNode *fn_ref_expr_node = ast_parse_primary_expr(pc, token_index, true); | ||
| 946 | Token *lparen_tok = ast_eat_token(pc, token_index, TokenIdLParen); | ||
| 947 | AstNode *node = ast_create_node(pc, NodeTypeFnCallExpr, lparen_tok); | ||
| 948 | node->data.fn_call_expr.is_async = true; | ||
| 949 | node->data.fn_call_expr.async_allocator = allocator_expr_node; | ||
| 950 | node->data.fn_call_expr.fn_ref_expr = fn_ref_expr_node; | ||
| 951 | ast_parse_fn_call_param_list(pc, token_index, &node->data.fn_call_expr.params); | ||
| 952 | |||
| 953 | primary_expr = node; | ||
| 954 | } else { | ||
| 955 | primary_expr = ast_parse_primary_expr(pc, token_index, mandatory); | ||
| 956 | if (!primary_expr) | ||
| 957 | return nullptr; | ||
| 958 | } | ||
| 934 | 959 | ||
| 935 | while (true) { | 960 | while (true) { |
| 936 | Token *first_token = &pc->tokens->at(*token_index); | 961 | Token *first_token = &pc->tokens->at(*token_index); |
| ... | @@ -1535,6 +1560,24 @@ static AstNode *ast_parse_break_expr(ParseContext *pc, size_t *token_index) { | ... | @@ -1535,6 +1560,24 @@ static AstNode *ast_parse_break_expr(ParseContext *pc, size_t *token_index) { |
| 1535 | return node; | 1560 | return node; |
| 1536 | } | 1561 | } |
| 1537 | 1562 | ||
| 1563 | /* | ||
| 1564 | CancelExpression = "cancel" Expression; | ||
| 1565 | */ | ||
| 1566 | static AstNode *ast_parse_cancel_expr(ParseContext *pc, size_t *token_index) { | ||
| 1567 | Token *token = &pc->tokens->at(*token_index); | ||
| 1568 | |||
| 1569 | if (token->id != TokenIdKeywordCancel) { | ||
| 1570 | return nullptr; | ||
| 1571 | } | ||
| 1572 | *token_index += 1; | ||
| 1573 | |||
| 1574 | AstNode *node = ast_create_node(pc, NodeTypeCancel, token); | ||
| 1575 | |||
| 1576 | node->data.cancel_expr.expr = ast_parse_expression(pc, token_index, false); | ||
| 1577 | |||
| 1578 | return node; | ||
| 1579 | } | ||
| 1580 | |||
| 1538 | /* | 1581 | /* |
| 1539 | Defer(body) = ("defer" | "errdefer") body | 1582 | Defer(body) = ("defer" | "errdefer") body |
| 1540 | */ | 1583 | */ |
| ... | @@ -2159,7 +2202,7 @@ static AstNode *ast_parse_block_or_expression(ParseContext *pc, size_t *token_in | ... | @@ -2159,7 +2202,7 @@ static AstNode *ast_parse_block_or_expression(ParseContext *pc, size_t *token_in |
| 2159 | } | 2202 | } |
| 2160 | 2203 | ||
| 2161 | /* | 2204 | /* |
| 2162 | Expression = TryExpression | ReturnExpression | BreakExpression | AssignmentExpression | 2205 | Expression = TryExpression | ReturnExpression | BreakExpression | AssignmentExpression | CancelExpression |
| 2163 | */ | 2206 | */ |
| 2164 | static AstNode *ast_parse_expression(ParseContext *pc, size_t *token_index, bool mandatory) { | 2207 | static AstNode *ast_parse_expression(ParseContext *pc, size_t *token_index, bool mandatory) { |
| 2165 | Token *token = &pc->tokens->at(*token_index); | 2208 | Token *token = &pc->tokens->at(*token_index); |
| ... | @@ -2176,6 +2219,10 @@ static AstNode *ast_parse_expression(ParseContext *pc, size_t *token_index, bool | ... | @@ -2176,6 +2219,10 @@ static AstNode *ast_parse_expression(ParseContext *pc, size_t *token_index, bool |
| 2176 | if (break_expr) | 2219 | if (break_expr) |
| 2177 | return break_expr; | 2220 | return break_expr; |
| 2178 | 2221 | ||
| 2222 | AstNode *cancel_expr = ast_parse_cancel_expr(pc, token_index); | ||
| 2223 | if (cancel_expr) | ||
| 2224 | return cancel_expr; | ||
| 2225 | |||
| 2179 | AstNode *ass_expr = ast_parse_ass_expr(pc, token_index, false); | 2226 | AstNode *ass_expr = ast_parse_ass_expr(pc, token_index, false); |
| 2180 | if (ass_expr) | 2227 | if (ass_expr) |
| 2181 | return ass_expr; | 2228 | return ass_expr; |
| ... | @@ -2809,6 +2856,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont | ... | @@ -2809,6 +2856,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont |
| 2809 | case NodeTypeFnCallExpr: | 2856 | case NodeTypeFnCallExpr: |
| 2810 | visit_field(&node->data.fn_call_expr.fn_ref_expr, visit, context); | 2857 | visit_field(&node->data.fn_call_expr.fn_ref_expr, visit, context); |
| 2811 | visit_node_list(&node->data.fn_call_expr.params, visit, context); | 2858 | visit_node_list(&node->data.fn_call_expr.params, visit, context); |
| 2859 | visit_field(&node->data.fn_call_expr.async_allocator, visit, context); | ||
| 2812 | break; | 2860 | break; |
| 2813 | case NodeTypeArrayAccessExpr: | 2861 | case NodeTypeArrayAccessExpr: |
| 2814 | visit_field(&node->data.array_access_expr.array_ref_expr, visit, context); | 2862 | visit_field(&node->data.array_access_expr.array_ref_expr, visit, context); |
| ... | @@ -2931,5 +2979,8 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont | ... | @@ -2931,5 +2979,8 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont |
| 2931 | case NodeTypeErrorSetDecl: | 2979 | case NodeTypeErrorSetDecl: |
| 2932 | visit_node_list(&node->data.err_set_decl.decls, visit, context); | 2980 | visit_node_list(&node->data.err_set_decl.decls, visit, context); |
| 2933 | break; | 2981 | break; |
| 2982 | case NodeTypeCancel: | ||
| 2983 | visit_field(&node->data.cancel_expr.expr, visit, context); | ||
| 2984 | break; | ||
| 2934 | } | 2985 | } |
| 2935 | } | 2986 | } |
std/mem.zig+16| ... | @@ -116,6 +116,22 @@ pub const Allocator = struct { | ... | @@ -116,6 +116,22 @@ pub const Allocator = struct { |
| 116 | const non_const_ptr = @intToPtr(&u8, @ptrToInt(bytes.ptr)); | 116 | const non_const_ptr = @intToPtr(&u8, @ptrToInt(bytes.ptr)); |
| 117 | self.freeFn(self, non_const_ptr[0..bytes.len]); | 117 | self.freeFn(self, non_const_ptr[0..bytes.len]); |
| 118 | } | 118 | } |
| 119 | |||
| 120 | pub const AsyncAllocator = struct { | ||
| 121 | allocator: &Allocator, | ||
| 122 | |||
| 123 | fn alloc(self: &const AsyncAllocator, byte_count: usize, alignment: u29) Error![]u8 { | ||
| 124 | return self.allocator.allocFn(self.allocator, byte_count, alignment); | ||
| 125 | } | ||
| 126 | |||
| 127 | fn free(self: &const AsyncAllocator, old_mem: []u8) { | ||
| 128 | return self.allocator.freeFn(self.allocator, old_mem); | ||
| 129 | } | ||
| 130 | }; | ||
| 131 | |||
| 132 | fn toAsync(self: &Allocator) AsyncAllocator { | ||
| 133 | return AsyncAllocator { .allocator = self }; | ||
| 134 | } | ||
| 119 | }; | 135 | }; |
| 120 | 136 | ||
| 121 | /// Copy all of source into dest at position 0. | 137 | /// Copy all of source into dest at position 0. |