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...@@ -5863,7 +5863,9 @@ StructLiteralField = "." Symbol "=" Expression
58635863
5864PrefixOp = "!" | "-" | "~" | "*" | ("&amp;" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "??" | "-%" | "try" | "await"5864PrefixOp = "!" | "-" | "~" | "*" | ("&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)) | ErrorSetDecl5866PrimaryExpression = 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
5868ArrayType : "[" option(Expression) "]" option("align" "(" Expression option(":" Integer ":" Integer) ")")) option("const") option("volatile") TypeExpr5870ArrayType : "[" 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 {...@@ -409,6 +409,7 @@ enum NodeType {
409 NodeTypeResume,409 NodeTypeResume,
410 NodeTypeAwaitExpr,410 NodeTypeAwaitExpr,
411 NodeTypeSuspend,411 NodeTypeSuspend,
412 NodeTypePromiseType,
412};413};
413414
414struct AstNodeRoot {415struct AstNodeRoot {
...@@ -879,6 +880,10 @@ struct AstNodeSuspend {...@@ -879,6 +880,10 @@ struct AstNodeSuspend {
879 AstNode *promise_symbol;880 AstNode *promise_symbol;
880};881};
881882
883struct AstNodePromiseType {
884 AstNode *payload_type; // can be NULL
885};
886
882struct AstNode {887struct AstNode {
883 enum NodeType type;888 enum NodeType type;
884 size_t line;889 size_t line;
...@@ -939,6 +944,7 @@ struct AstNode {...@@ -939,6 +944,7 @@ struct AstNode {
939 AstNodeResumeExpr resume_expr;944 AstNodeResumeExpr resume_expr;
940 AstNodeAwaitExpr await_expr;945 AstNodeAwaitExpr await_expr;
941 AstNodeSuspend suspend;946 AstNodeSuspend suspend;
947 AstNodePromiseType promise_type;
942 } data;948 } data;
943};949};
944950
...@@ -1947,6 +1953,7 @@ enum IrInstructionId {...@@ -1947,6 +1953,7 @@ enum IrInstructionId {
1947 IrInstructionIdSetRuntimeSafety,1953 IrInstructionIdSetRuntimeSafety,
1948 IrInstructionIdSetFloatMode,1954 IrInstructionIdSetFloatMode,
1949 IrInstructionIdArrayType,1955 IrInstructionIdArrayType,
1956 IrInstructionIdPromiseType,
1950 IrInstructionIdSliceType,1957 IrInstructionIdSliceType,
1951 IrInstructionIdAsm,1958 IrInstructionIdAsm,
1952 IrInstructionIdSizeOf,1959 IrInstructionIdSizeOf,
...@@ -2365,6 +2372,12 @@ struct IrInstructionArrayType {...@@ -2365,6 +2372,12 @@ struct IrInstructionArrayType {
2365 IrInstruction *child_type;2372 IrInstruction *child_type;
2366};2373};
23672374
2375struct IrInstructionPromiseType {
2376 IrInstruction base;
2377
2378 IrInstruction *payload_type;
2379};
2380
2368struct IrInstructionSliceType {2381struct IrInstructionSliceType {
2369 IrInstruction base;2382 IrInstruction base;
23702383
src/analyze.cpp+1
...@@ -3254,6 +3254,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {...@@ -3254,6 +3254,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
3254 case NodeTypeResume:3254 case NodeTypeResume:
3255 case NodeTypeAwaitExpr:3255 case NodeTypeAwaitExpr:
3256 case NodeTypeSuspend:3256 case NodeTypeSuspend:
3257 case NodeTypePromiseType:
3257 zig_unreachable();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,6 +250,8 @@ static const char *node_type_str(NodeType node_type) {
250 return "AwaitExpr";250 return "AwaitExpr";
251 case NodeTypeSuspend:251 case NodeTypeSuspend:
252 return "Suspend";252 return "Suspend";
253 case NodeTypePromiseType:
254 return "PromiseType";
253 }255 }
254 zig_unreachable();256 zig_unreachable();
255}257}
...@@ -781,6 +783,15 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {...@@ -781,6 +783,15 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
781 render_node_ungrouped(ar, node->data.array_type.child_type);783 render_node_ungrouped(ar, node->data.array_type.child_type);
782 break;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 case NodeTypeErrorType:795 case NodeTypeErrorType:
785 fprintf(ar->f, "error");796 fprintf(ar->f, "error");
786 break;797 break;
src/codegen.cpp+1
...@@ -4205,6 +4205,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -4205,6 +4205,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
4205 case IrInstructionIdSetRuntimeSafety:4205 case IrInstructionIdSetRuntimeSafety:
4206 case IrInstructionIdSetFloatMode:4206 case IrInstructionIdSetFloatMode:
4207 case IrInstructionIdArrayType:4207 case IrInstructionIdArrayType:
4208 case IrInstructionIdPromiseType:
4208 case IrInstructionIdSliceType:4209 case IrInstructionIdSliceType:
4209 case IrInstructionIdSizeOf:4210 case IrInstructionIdSizeOf:
4210 case IrInstructionIdSwitchTarget:4211 case IrInstructionIdSwitchTarget:
src/ir.cpp+54
...@@ -349,6 +349,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionArrayType *) {...@@ -349,6 +349,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionArrayType *) {
349 return IrInstructionIdArrayType;349 return IrInstructionIdArrayType;
350}350}
351351
352static constexpr IrInstructionId ir_instruction_id(IrInstructionPromiseType *) {
353 return IrInstructionIdPromiseType;
354}
355
352static constexpr IrInstructionId ir_instruction_id(IrInstructionSliceType *) {356static constexpr IrInstructionId ir_instruction_id(IrInstructionSliceType *) {
353 return IrInstructionIdSliceType;357 return IrInstructionIdSliceType;
354}358}
...@@ -1469,6 +1473,17 @@ static IrInstruction *ir_build_array_type(IrBuilder *irb, Scope *scope, AstNode...@@ -1469,6 +1473,17 @@ static IrInstruction *ir_build_array_type(IrBuilder *irb, Scope *scope, AstNode
1469 return &instruction->base;1473 return &instruction->base;
1470}1474}
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
1472static IrInstruction *ir_build_slice_type(IrBuilder *irb, Scope *scope, AstNode *source_node,1487static IrInstruction *ir_build_slice_type(IrBuilder *irb, Scope *scope, AstNode *source_node,
1473 IrInstruction *child_type, bool is_const, bool is_volatile, IrInstruction *align_value)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,6 +5089,22 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n
5074 }5089 }
5075}5090}
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
5077static IrInstruction *ir_gen_undefined_literal(IrBuilder *irb, Scope *scope, AstNode *node) {5108static IrInstruction *ir_gen_undefined_literal(IrBuilder *irb, Scope *scope, AstNode *node) {
5078 assert(node->type == NodeTypeUndefinedLiteral);5109 assert(node->type == NodeTypeUndefinedLiteral);
5079 return ir_build_const_undefined(irb, scope, node);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,6 +6313,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
6282 return ir_lval_wrap(irb, scope, ir_gen_bool_literal(irb, scope, node), lval);6313 return ir_lval_wrap(irb, scope, ir_gen_bool_literal(irb, scope, node), lval);
6283 case NodeTypeArrayType:6314 case NodeTypeArrayType:
6284 return ir_lval_wrap(irb, scope, ir_gen_array_type(irb, scope, node), lval);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 case NodeTypeStringLiteral:6318 case NodeTypeStringLiteral:
6286 return ir_lval_wrap(irb, scope, ir_gen_string_literal(irb, scope, node), lval);6319 return ir_lval_wrap(irb, scope, ir_gen_string_literal(irb, scope, node), lval);
6287 case NodeTypeUndefinedLiteral:6320 case NodeTypeUndefinedLiteral:
...@@ -14069,6 +14102,24 @@ static TypeTableEntry *ir_analyze_instruction_array_type(IrAnalyze *ira,...@@ -14069,6 +14102,24 @@ static TypeTableEntry *ir_analyze_instruction_array_type(IrAnalyze *ira,
14069 zig_unreachable();14102 zig_unreachable();
14070}14103}
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
14072static TypeTableEntry *ir_analyze_instruction_size_of(IrAnalyze *ira,14123static TypeTableEntry *ir_analyze_instruction_size_of(IrAnalyze *ira,
14073 IrInstructionSizeOf *size_of_instruction)14124 IrInstructionSizeOf *size_of_instruction)
14074{14125{
...@@ -17907,6 +17958,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi...@@ -17907,6 +17958,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
17907 return ir_analyze_instruction_asm(ira, (IrInstructionAsm *)instruction);17958 return ir_analyze_instruction_asm(ira, (IrInstructionAsm *)instruction);
17908 case IrInstructionIdArrayType:17959 case IrInstructionIdArrayType:
17909 return ir_analyze_instruction_array_type(ira, (IrInstructionArrayType *)instruction);17960 return ir_analyze_instruction_array_type(ira, (IrInstructionArrayType *)instruction);
17961 case IrInstructionIdPromiseType:
17962 return ir_analyze_instruction_promise_type(ira, (IrInstructionPromiseType *)instruction);
17910 case IrInstructionIdSizeOf:17963 case IrInstructionIdSizeOf:
17911 return ir_analyze_instruction_size_of(ira, (IrInstructionSizeOf *)instruction);17964 return ir_analyze_instruction_size_of(ira, (IrInstructionSizeOf *)instruction);
17912 case IrInstructionIdTestNonNull:17965 case IrInstructionIdTestNonNull:
...@@ -18232,6 +18285,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -18232,6 +18285,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
18232 case IrInstructionIdStructFieldPtr:18285 case IrInstructionIdStructFieldPtr:
18233 case IrInstructionIdUnionFieldPtr:18286 case IrInstructionIdUnionFieldPtr:
18234 case IrInstructionIdArrayType:18287 case IrInstructionIdArrayType:
18288 case IrInstructionIdPromiseType:
18235 case IrInstructionIdSliceType:18289 case IrInstructionIdSliceType:
18236 case IrInstructionIdSizeOf:18290 case IrInstructionIdSizeOf:
18237 case IrInstructionIdTestNonNull:18291 case IrInstructionIdTestNonNull:
src/ir_print.cpp+11
...@@ -404,6 +404,14 @@ static void ir_print_array_type(IrPrint *irp, IrInstructionArrayType *instructio...@@ -404,6 +404,14 @@ static void ir_print_array_type(IrPrint *irp, IrInstructionArrayType *instructio
404 ir_print_other_instruction(irp, instruction->child_type);404 ir_print_other_instruction(irp, instruction->child_type);
405}405}
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
407static void ir_print_slice_type(IrPrint *irp, IrInstructionSliceType *instruction) {415static void ir_print_slice_type(IrPrint *irp, IrInstructionSliceType *instruction) {
408 const char *const_kw = instruction->is_const ? "const " : "";416 const char *const_kw = instruction->is_const ? "const " : "";
409 fprintf(irp->f, "[]%s", const_kw);417 fprintf(irp->f, "[]%s", const_kw);
...@@ -1263,6 +1271,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1263,6 +1271,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1263 case IrInstructionIdArrayType:1271 case IrInstructionIdArrayType:
1264 ir_print_array_type(irp, (IrInstructionArrayType *)instruction);1272 ir_print_array_type(irp, (IrInstructionArrayType *)instruction);
1265 break;1273 break;
1274 case IrInstructionIdPromiseType:
1275 ir_print_promise_type(irp, (IrInstructionPromiseType *)instruction);
1276 break;
1266 case IrInstructionIdSliceType:1277 case IrInstructionIdSliceType:
1267 ir_print_slice_type(irp, (IrInstructionSliceType *)instruction);1278 ir_print_slice_type(irp, (IrInstructionSliceType *)instruction);
1268 break;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,7 +705,7 @@ static AstNode *ast_parse_comptime_expr(ParseContext *pc, size_t *token_index, b
705}705}
706706
707/*707/*
708PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ContainerDecl | ("continue" option(":" Symbol)) | ErrorSetDecl708PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ContainerDecl | ("continue" option(":" Symbol)) | ErrorSetDecl | PromiseType
709KeywordLiteral = "true" | "false" | "null" | "undefined" | "error" | "this" | "unreachable" | "suspend"709KeywordLiteral = "true" | "false" | "null" | "undefined" | "error" | "this" | "unreachable" | "suspend"
710ErrorSetDecl = "error" "{" list(Symbol, ",") "}"710ErrorSetDecl = "error" "{" list(Symbol, ",") "}"
711*/711*/
...@@ -774,6 +774,15 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo...@@ -774,6 +774,15 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo
774 AstNode *node = ast_create_node(pc, NodeTypeSuspend, token);774 AstNode *node = ast_create_node(pc, NodeTypeSuspend, token);
775 *token_index += 1;775 *token_index += 1;
776 return node;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 } else if (token->id == TokenIdKeywordError) {786 } else if (token->id == TokenIdKeywordError) {
778 Token *next_token = &pc->tokens->at(*token_index + 1);787 Token *next_token = &pc->tokens->at(*token_index + 1);
779 if (next_token->id == TokenIdLBrace) {788 if (next_token->id == TokenIdLBrace) {
...@@ -3081,6 +3090,9 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont...@@ -3081,6 +3090,9 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
3081 visit_field(&node->data.array_type.child_type, visit, context);3090 visit_field(&node->data.array_type.child_type, visit, context);
3082 visit_field(&node->data.array_type.align_expr, visit, context);3091 visit_field(&node->data.array_type.align_expr, visit, context);
3083 break;3092 break;
3093 case NodeTypePromiseType:
3094 visit_field(&node->data.promise_type.payload_type, visit, context);
3095 break;
3084 case NodeTypeErrorType:3096 case NodeTypeErrorType:
3085 // none3097 // none
3086 break;3098 break;
src/tokenizer.cpp+2
...@@ -135,6 +135,7 @@ static const struct ZigKeyword zig_keywords[] = {...@@ -135,6 +135,7 @@ static const struct ZigKeyword zig_keywords[] = {
135 {"null", TokenIdKeywordNull},135 {"null", TokenIdKeywordNull},
136 {"or", TokenIdKeywordOr},136 {"or", TokenIdKeywordOr},
137 {"packed", TokenIdKeywordPacked},137 {"packed", TokenIdKeywordPacked},
138 {"promise", TokenIdKeywordPromise},
138 {"pub", TokenIdKeywordPub},139 {"pub", TokenIdKeywordPub},
139 {"resume", TokenIdKeywordResume},140 {"resume", TokenIdKeywordResume},
140 {"return", TokenIdKeywordReturn},141 {"return", TokenIdKeywordReturn},
...@@ -1558,6 +1559,7 @@ const char * token_name(TokenId id) {...@@ -1558,6 +1559,7 @@ const char * token_name(TokenId id) {
1558 case TokenIdKeywordNull: return "null";1559 case TokenIdKeywordNull: return "null";
1559 case TokenIdKeywordOr: return "or";1560 case TokenIdKeywordOr: return "or";
1560 case TokenIdKeywordPacked: return "packed";1561 case TokenIdKeywordPacked: return "packed";
1562 case TokenIdKeywordPromise: return "promise";
1561 case TokenIdKeywordPub: return "pub";1563 case TokenIdKeywordPub: return "pub";
1562 case TokenIdKeywordReturn: return "return";1564 case TokenIdKeywordReturn: return "return";
1563 case TokenIdKeywordSection: return "section";1565 case TokenIdKeywordSection: return "section";
src/tokenizer.hpp+1
...@@ -76,6 +76,7 @@ enum TokenId {...@@ -76,6 +76,7 @@ enum TokenId {
76 TokenIdKeywordNull,76 TokenIdKeywordNull,
77 TokenIdKeywordOr,77 TokenIdKeywordOr,
78 TokenIdKeywordPacked,78 TokenIdKeywordPacked,
79 TokenIdKeywordPromise,
79 TokenIdKeywordPub,80 TokenIdKeywordPub,
80 TokenIdKeywordResume,81 TokenIdKeywordResume,
81 TokenIdKeywordReturn,82 TokenIdKeywordReturn,
test/cases/coroutines.zig+1
...@@ -5,6 +5,7 @@ var x: i32 = 1;...@@ -5,6 +5,7 @@ var x: i32 = 1;
55
6test "create a coroutine and cancel it" {6test "create a coroutine and cancel it" {
7 const p = try async<std.debug.global_allocator> simpleAsyncFn();7 const p = try async<std.debug.global_allocator> simpleAsyncFn();
8 comptime assert(@typeOf(p) == promise->void);
8 cancel p;9 cancel p;
9 assert(x == 2);10 assert(x == 2);
10}11}