authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-03-24 19:25:53-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-03-24 19:25:53-04:00
log897e783763d60449ad1b9514cb5ba86a38f7ae4a
tree1f1603884432590aba99c7d2edd0d035548c5286
parent18af2f9a2764cc340571578d58cb2575faeccdc6

add promise->T syntax parsing

closes #857

11 files changed, 111 insertions(+), 2 deletions(-)

doc/langref.html.in+3-1
......@@ -5863,7 +5863,9 @@ StructLiteralField = "." Symbol "=" Expression
58635863
58645864PrefixOp = "!" | "-" | "~" | "*" | ("&amp;" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "??" | "-%" | "try" | "await"
58655865
5866PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ContainerDecl | ("continue" option(":" Symbol)) | ErrorSetDecl
5866PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ContainerDecl | ("continue" option(":" Symbol)) | ErrorSetDecl | PromiseType
5867
5868PromiseType = "promise" option("-&gt;" TypeExpr)
58675869
58685870ArrayType : "[" option(Expression) "]" option("align" "(" Expression option(":" Integer ":" Integer) ")")) option("const") option("volatile") TypeExpr
58695871
src/all_types.hpp+13
......@@ -409,6 +409,7 @@ enum NodeType {
409409 NodeTypeResume,
410410 NodeTypeAwaitExpr,
411411 NodeTypeSuspend,
412 NodeTypePromiseType,
412413};
413414
414415struct AstNodeRoot {
......@@ -879,6 +880,10 @@ struct AstNodeSuspend {
879880 AstNode *promise_symbol;
880881};
881882
883struct AstNodePromiseType {
884 AstNode *payload_type; // can be NULL
885};
886
882887struct AstNode {
883888 enum NodeType type;
884889 size_t line;
......@@ -939,6 +944,7 @@ struct AstNode {
939944 AstNodeResumeExpr resume_expr;
940945 AstNodeAwaitExpr await_expr;
941946 AstNodeSuspend suspend;
947 AstNodePromiseType promise_type;
942948 } data;
943949};
944950
......@@ -1947,6 +1953,7 @@ enum IrInstructionId {
19471953 IrInstructionIdSetRuntimeSafety,
19481954 IrInstructionIdSetFloatMode,
19491955 IrInstructionIdArrayType,
1956 IrInstructionIdPromiseType,
19501957 IrInstructionIdSliceType,
19511958 IrInstructionIdAsm,
19521959 IrInstructionIdSizeOf,
......@@ -2365,6 +2372,12 @@ struct IrInstructionArrayType {
23652372 IrInstruction *child_type;
23662373};
23672374
2375struct IrInstructionPromiseType {
2376 IrInstruction base;
2377
2378 IrInstruction *payload_type;
2379};
2380
23682381struct IrInstructionSliceType {
23692382 IrInstruction base;
23702383
src/analyze.cpp+1
......@@ -3254,6 +3254,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
32543254 case NodeTypeResume:
32553255 case NodeTypeAwaitExpr:
32563256 case NodeTypeSuspend:
3257 case NodeTypePromiseType:
32573258 zig_unreachable();
32583259 }
32593260}
src/ast_render.cpp+11
......@@ -250,6 +250,8 @@ static const char *node_type_str(NodeType node_type) {
250250 return "AwaitExpr";
251251 case NodeTypeSuspend:
252252 return "Suspend";
253 case NodeTypePromiseType:
254 return "PromiseType";
253255 }
254256 zig_unreachable();
255257}
......@@ -781,6 +783,15 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
781783 render_node_ungrouped(ar, node->data.array_type.child_type);
782784 break;
783785 }
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 }
784795 case NodeTypeErrorType:
785796 fprintf(ar->f, "error");
786797 break;
src/codegen.cpp+1
......@@ -4205,6 +4205,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
42054205 case IrInstructionIdSetRuntimeSafety:
42064206 case IrInstructionIdSetFloatMode:
42074207 case IrInstructionIdArrayType:
4208 case IrInstructionIdPromiseType:
42084209 case IrInstructionIdSliceType:
42094210 case IrInstructionIdSizeOf:
42104211 case IrInstructionIdSwitchTarget:
src/ir.cpp+54
......@@ -349,6 +349,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionArrayType *) {
349349 return IrInstructionIdArrayType;
350350}
351351
352static constexpr IrInstructionId ir_instruction_id(IrInstructionPromiseType *) {
353 return IrInstructionIdPromiseType;
354}
355
352356static constexpr IrInstructionId ir_instruction_id(IrInstructionSliceType *) {
353357 return IrInstructionIdSliceType;
354358}
......@@ -1469,6 +1473,17 @@ static IrInstruction *ir_build_array_type(IrBuilder *irb, Scope *scope, AstNode
14691473 return &instruction->base;
14701474}
14711475
1476static 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
14721487static IrInstruction *ir_build_slice_type(IrBuilder *irb, Scope *scope, AstNode *source_node,
14731488 IrInstruction *child_type, bool is_const, bool is_volatile, IrInstruction *align_value)
14741489{
......@@ -5074,6 +5089,22 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n
50745089 }
50755090}
50765091
5092static 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
50775108static IrInstruction *ir_gen_undefined_literal(IrBuilder *irb, Scope *scope, AstNode *node) {
50785109 assert(node->type == NodeTypeUndefinedLiteral);
50795110 return ir_build_const_undefined(irb, scope, node);
......@@ -6282,6 +6313,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
62826313 return ir_lval_wrap(irb, scope, ir_gen_bool_literal(irb, scope, node), lval);
62836314 case NodeTypeArrayType:
62846315 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);
62856318 case NodeTypeStringLiteral:
62866319 return ir_lval_wrap(irb, scope, ir_gen_string_literal(irb, scope, node), lval);
62876320 case NodeTypeUndefinedLiteral:
......@@ -14069,6 +14102,24 @@ static TypeTableEntry *ir_analyze_instruction_array_type(IrAnalyze *ira,
1406914102 zig_unreachable();
1407014103}
1407114104
14105static 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
1407214123static TypeTableEntry *ir_analyze_instruction_size_of(IrAnalyze *ira,
1407314124 IrInstructionSizeOf *size_of_instruction)
1407414125{
......@@ -17907,6 +17958,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
1790717958 return ir_analyze_instruction_asm(ira, (IrInstructionAsm *)instruction);
1790817959 case IrInstructionIdArrayType:
1790917960 return ir_analyze_instruction_array_type(ira, (IrInstructionArrayType *)instruction);
17961 case IrInstructionIdPromiseType:
17962 return ir_analyze_instruction_promise_type(ira, (IrInstructionPromiseType *)instruction);
1791017963 case IrInstructionIdSizeOf:
1791117964 return ir_analyze_instruction_size_of(ira, (IrInstructionSizeOf *)instruction);
1791217965 case IrInstructionIdTestNonNull:
......@@ -18232,6 +18285,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
1823218285 case IrInstructionIdStructFieldPtr:
1823318286 case IrInstructionIdUnionFieldPtr:
1823418287 case IrInstructionIdArrayType:
18288 case IrInstructionIdPromiseType:
1823518289 case IrInstructionIdSliceType:
1823618290 case IrInstructionIdSizeOf:
1823718291 case IrInstructionIdTestNonNull:
src/ir_print.cpp+11
......@@ -404,6 +404,14 @@ static void ir_print_array_type(IrPrint *irp, IrInstructionArrayType *instructio
404404 ir_print_other_instruction(irp, instruction->child_type);
405405}
406406
407static 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
407415static void ir_print_slice_type(IrPrint *irp, IrInstructionSliceType *instruction) {
408416 const char *const_kw = instruction->is_const ? "const " : "";
409417 fprintf(irp->f, "[]%s", const_kw);
......@@ -1263,6 +1271,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
12631271 case IrInstructionIdArrayType:
12641272 ir_print_array_type(irp, (IrInstructionArrayType *)instruction);
12651273 break;
1274 case IrInstructionIdPromiseType:
1275 ir_print_promise_type(irp, (IrInstructionPromiseType *)instruction);
1276 break;
12661277 case IrInstructionIdSliceType:
12671278 ir_print_slice_type(irp, (IrInstructionSliceType *)instruction);
12681279 break;
src/parser.cpp+13-1
......@@ -705,7 +705,7 @@ static AstNode *ast_parse_comptime_expr(ParseContext *pc, size_t *token_index, b
705705}
706706
707707/*
708PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ContainerDecl | ("continue" option(":" Symbol)) | ErrorSetDecl
708PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ContainerDecl | ("continue" option(":" Symbol)) | ErrorSetDecl | PromiseType
709709KeywordLiteral = "true" | "false" | "null" | "undefined" | "error" | "this" | "unreachable" | "suspend"
710710ErrorSetDecl = "error" "{" list(Symbol, ",") "}"
711711*/
......@@ -774,6 +774,15 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo
774774 AstNode *node = ast_create_node(pc, NodeTypeSuspend, token);
775775 *token_index += 1;
776776 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;
777786 } else if (token->id == TokenIdKeywordError) {
778787 Token *next_token = &pc->tokens->at(*token_index + 1);
779788 if (next_token->id == TokenIdLBrace) {
......@@ -3081,6 +3090,9 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
30813090 visit_field(&node->data.array_type.child_type, visit, context);
30823091 visit_field(&node->data.array_type.align_expr, visit, context);
30833092 break;
3093 case NodeTypePromiseType:
3094 visit_field(&node->data.promise_type.payload_type, visit, context);
3095 break;
30843096 case NodeTypeErrorType:
30853097 // none
30863098 break;
src/tokenizer.cpp+2
......@@ -135,6 +135,7 @@ static const struct ZigKeyword zig_keywords[] = {
135135 {"null", TokenIdKeywordNull},
136136 {"or", TokenIdKeywordOr},
137137 {"packed", TokenIdKeywordPacked},
138 {"promise", TokenIdKeywordPromise},
138139 {"pub", TokenIdKeywordPub},
139140 {"resume", TokenIdKeywordResume},
140141 {"return", TokenIdKeywordReturn},
......@@ -1558,6 +1559,7 @@ const char * token_name(TokenId id) {
15581559 case TokenIdKeywordNull: return "null";
15591560 case TokenIdKeywordOr: return "or";
15601561 case TokenIdKeywordPacked: return "packed";
1562 case TokenIdKeywordPromise: return "promise";
15611563 case TokenIdKeywordPub: return "pub";
15621564 case TokenIdKeywordReturn: return "return";
15631565 case TokenIdKeywordSection: return "section";
src/tokenizer.hpp+1
......@@ -76,6 +76,7 @@ enum TokenId {
7676 TokenIdKeywordNull,
7777 TokenIdKeywordOr,
7878 TokenIdKeywordPacked,
79 TokenIdKeywordPromise,
7980 TokenIdKeywordPub,
8081 TokenIdKeywordResume,
8182 TokenIdKeywordReturn,
test/cases/coroutines.zig+1
......@@ -5,6 +5,7 @@ var x: i32 = 1;
55
66test "create a coroutine and cancel it" {
77 const p = try async<std.debug.global_allocator> simpleAsyncFn();
8 comptime assert(@typeOf(p) == promise->void);
89 cancel p;
910 assert(x == 2);
1011}