add promise->T syntax parsing

closes #857
This commit is contained in:
Andrew Kelley 2018-03-24 19:25:53 -04:00
parent 18af2f9a27
commit 897e783763
11 changed files with 111 additions and 2 deletions

View File

@ -5863,7 +5863,9 @@ StructLiteralField = "." Symbol "=" Expression
PrefixOp = "!" | "-" | "~" | "*" | ("&" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "??" | "-%" | "try" | "await"
PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ContainerDecl | ("continue" option(":" Symbol)) | ErrorSetDecl
PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ContainerDecl | ("continue" option(":" Symbol)) | ErrorSetDecl | PromiseType
PromiseType = "promise" option("->" TypeExpr)
ArrayType : "[" option(Expression) "]" option("align" "(" Expression option(":" Integer ":" Integer) ")")) option("const") option("volatile") TypeExpr

View File

@ -409,6 +409,7 @@ enum NodeType {
NodeTypeResume,
NodeTypeAwaitExpr,
NodeTypeSuspend,
NodeTypePromiseType,
};
struct AstNodeRoot {
@ -879,6 +880,10 @@ struct AstNodeSuspend {
AstNode *promise_symbol;
};
struct AstNodePromiseType {
AstNode *payload_type; // can be NULL
};
struct AstNode {
enum NodeType type;
size_t line;
@ -939,6 +944,7 @@ struct AstNode {
AstNodeResumeExpr resume_expr;
AstNodeAwaitExpr await_expr;
AstNodeSuspend suspend;
AstNodePromiseType promise_type;
} data;
};
@ -1947,6 +1953,7 @@ enum IrInstructionId {
IrInstructionIdSetRuntimeSafety,
IrInstructionIdSetFloatMode,
IrInstructionIdArrayType,
IrInstructionIdPromiseType,
IrInstructionIdSliceType,
IrInstructionIdAsm,
IrInstructionIdSizeOf,
@ -2365,6 +2372,12 @@ struct IrInstructionArrayType {
IrInstruction *child_type;
};
struct IrInstructionPromiseType {
IrInstruction base;
IrInstruction *payload_type;
};
struct IrInstructionSliceType {
IrInstruction base;

View File

@ -3254,6 +3254,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
case NodeTypeResume:
case NodeTypeAwaitExpr:
case NodeTypeSuspend:
case NodeTypePromiseType:
zig_unreachable();
}
}

View File

@ -250,6 +250,8 @@ static const char *node_type_str(NodeType node_type) {
return "AwaitExpr";
case NodeTypeSuspend:
return "Suspend";
case NodeTypePromiseType:
return "PromiseType";
}
zig_unreachable();
}
@ -781,6 +783,15 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
render_node_ungrouped(ar, node->data.array_type.child_type);
break;
}
case NodeTypePromiseType:
{
fprintf(ar->f, "promise");
if (node->data.promise_type.payload_type != nullptr) {
fprintf(ar->f, "->");
render_node_grouped(ar, node->data.promise_type.payload_type);
}
break;
}
case NodeTypeErrorType:
fprintf(ar->f, "error");
break;

View File

@ -4205,6 +4205,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdSetRuntimeSafety:
case IrInstructionIdSetFloatMode:
case IrInstructionIdArrayType:
case IrInstructionIdPromiseType:
case IrInstructionIdSliceType:
case IrInstructionIdSizeOf:
case IrInstructionIdSwitchTarget:

View File

@ -349,6 +349,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionArrayType *) {
return IrInstructionIdArrayType;
}
static constexpr IrInstructionId ir_instruction_id(IrInstructionPromiseType *) {
return IrInstructionIdPromiseType;
}
static constexpr IrInstructionId ir_instruction_id(IrInstructionSliceType *) {
return IrInstructionIdSliceType;
}
@ -1469,6 +1473,17 @@ static IrInstruction *ir_build_array_type(IrBuilder *irb, Scope *scope, AstNode
return &instruction->base;
}
static IrInstruction *ir_build_promise_type(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrInstruction *payload_type)
{
IrInstructionPromiseType *instruction = ir_build_instruction<IrInstructionPromiseType>(irb, scope, source_node);
instruction->payload_type = payload_type;
if (payload_type != nullptr) ir_ref_instruction(payload_type, irb->current_basic_block);
return &instruction->base;
}
static IrInstruction *ir_build_slice_type(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrInstruction *child_type, bool is_const, bool is_volatile, IrInstruction *align_value)
{
@ -5074,6 +5089,22 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n
}
}
static IrInstruction *ir_gen_promise_type(IrBuilder *irb, Scope *scope, AstNode *node) {
assert(node->type == NodeTypePromiseType);
AstNode *payload_type_node = node->data.promise_type.payload_type;
IrInstruction *payload_type_value = nullptr;
if (payload_type_node != nullptr) {
payload_type_value = ir_gen_node(irb, payload_type_node, scope);
if (payload_type_value == irb->codegen->invalid_instruction)
return payload_type_value;
}
return ir_build_promise_type(irb, scope, node, payload_type_value);
}
static IrInstruction *ir_gen_undefined_literal(IrBuilder *irb, Scope *scope, AstNode *node) {
assert(node->type == NodeTypeUndefinedLiteral);
return ir_build_const_undefined(irb, scope, node);
@ -6282,6 +6313,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
return ir_lval_wrap(irb, scope, ir_gen_bool_literal(irb, scope, node), lval);
case NodeTypeArrayType:
return ir_lval_wrap(irb, scope, ir_gen_array_type(irb, scope, node), lval);
case NodeTypePromiseType:
return ir_lval_wrap(irb, scope, ir_gen_promise_type(irb, scope, node), lval);
case NodeTypeStringLiteral:
return ir_lval_wrap(irb, scope, ir_gen_string_literal(irb, scope, node), lval);
case NodeTypeUndefinedLiteral:
@ -14069,6 +14102,24 @@ static TypeTableEntry *ir_analyze_instruction_array_type(IrAnalyze *ira,
zig_unreachable();
}
static TypeTableEntry *ir_analyze_instruction_promise_type(IrAnalyze *ira, IrInstructionPromiseType *instruction) {
TypeTableEntry *promise_type;
if (instruction->payload_type == nullptr) {
promise_type = ira->codegen->builtin_types.entry_promise;
} else {
TypeTableEntry *payload_type = ir_resolve_type(ira, instruction->payload_type->other);
if (type_is_invalid(payload_type))
return ira->codegen->builtin_types.entry_invalid;
promise_type = get_promise_type(ira->codegen, payload_type);
}
ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
out_val->data.x_type = promise_type;
return ira->codegen->builtin_types.entry_type;
}
static TypeTableEntry *ir_analyze_instruction_size_of(IrAnalyze *ira,
IrInstructionSizeOf *size_of_instruction)
{
@ -17907,6 +17958,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
return ir_analyze_instruction_asm(ira, (IrInstructionAsm *)instruction);
case IrInstructionIdArrayType:
return ir_analyze_instruction_array_type(ira, (IrInstructionArrayType *)instruction);
case IrInstructionIdPromiseType:
return ir_analyze_instruction_promise_type(ira, (IrInstructionPromiseType *)instruction);
case IrInstructionIdSizeOf:
return ir_analyze_instruction_size_of(ira, (IrInstructionSizeOf *)instruction);
case IrInstructionIdTestNonNull:
@ -18232,6 +18285,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdStructFieldPtr:
case IrInstructionIdUnionFieldPtr:
case IrInstructionIdArrayType:
case IrInstructionIdPromiseType:
case IrInstructionIdSliceType:
case IrInstructionIdSizeOf:
case IrInstructionIdTestNonNull:

View File

@ -404,6 +404,14 @@ static void ir_print_array_type(IrPrint *irp, IrInstructionArrayType *instructio
ir_print_other_instruction(irp, instruction->child_type);
}
static void ir_print_promise_type(IrPrint *irp, IrInstructionPromiseType *instruction) {
fprintf(irp->f, "promise");
if (instruction->payload_type != nullptr) {
fprintf(irp->f, "->");
ir_print_other_instruction(irp, instruction->payload_type);
}
}
static void ir_print_slice_type(IrPrint *irp, IrInstructionSliceType *instruction) {
const char *const_kw = instruction->is_const ? "const " : "";
fprintf(irp->f, "[]%s", const_kw);
@ -1263,6 +1271,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdArrayType:
ir_print_array_type(irp, (IrInstructionArrayType *)instruction);
break;
case IrInstructionIdPromiseType:
ir_print_promise_type(irp, (IrInstructionPromiseType *)instruction);
break;
case IrInstructionIdSliceType:
ir_print_slice_type(irp, (IrInstructionSliceType *)instruction);
break;

View File

@ -705,7 +705,7 @@ static AstNode *ast_parse_comptime_expr(ParseContext *pc, size_t *token_index, b
}
/*
PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ContainerDecl | ("continue" option(":" Symbol)) | ErrorSetDecl
PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ContainerDecl | ("continue" option(":" Symbol)) | ErrorSetDecl | PromiseType
KeywordLiteral = "true" | "false" | "null" | "undefined" | "error" | "this" | "unreachable" | "suspend"
ErrorSetDecl = "error" "{" list(Symbol, ",") "}"
*/
@ -774,6 +774,15 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo
AstNode *node = ast_create_node(pc, NodeTypeSuspend, token);
*token_index += 1;
return node;
} else if (token->id == TokenIdKeywordPromise) {
AstNode *node = ast_create_node(pc, NodeTypePromiseType, token);
*token_index += 1;
Token *arrow_tok = &pc->tokens->at(*token_index);
if (arrow_tok->id == TokenIdArrow) {
*token_index += 1;
node->data.promise_type.payload_type = ast_parse_type_expr(pc, token_index, true);
}
return node;
} else if (token->id == TokenIdKeywordError) {
Token *next_token = &pc->tokens->at(*token_index + 1);
if (next_token->id == TokenIdLBrace) {
@ -3081,6 +3090,9 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
visit_field(&node->data.array_type.child_type, visit, context);
visit_field(&node->data.array_type.align_expr, visit, context);
break;
case NodeTypePromiseType:
visit_field(&node->data.promise_type.payload_type, visit, context);
break;
case NodeTypeErrorType:
// none
break;

View File

@ -135,6 +135,7 @@ static const struct ZigKeyword zig_keywords[] = {
{"null", TokenIdKeywordNull},
{"or", TokenIdKeywordOr},
{"packed", TokenIdKeywordPacked},
{"promise", TokenIdKeywordPromise},
{"pub", TokenIdKeywordPub},
{"resume", TokenIdKeywordResume},
{"return", TokenIdKeywordReturn},
@ -1558,6 +1559,7 @@ const char * token_name(TokenId id) {
case TokenIdKeywordNull: return "null";
case TokenIdKeywordOr: return "or";
case TokenIdKeywordPacked: return "packed";
case TokenIdKeywordPromise: return "promise";
case TokenIdKeywordPub: return "pub";
case TokenIdKeywordReturn: return "return";
case TokenIdKeywordSection: return "section";

View File

@ -76,6 +76,7 @@ enum TokenId {
TokenIdKeywordNull,
TokenIdKeywordOr,
TokenIdKeywordPacked,
TokenIdKeywordPromise,
TokenIdKeywordPub,
TokenIdKeywordResume,
TokenIdKeywordReturn,

View File

@ -5,6 +5,7 @@ var x: i32 = 1;
test "create a coroutine and cancel it" {
const p = try async<std.debug.global_allocator> simpleAsyncFn();
comptime assert(@typeOf(p) == promise->void);
cancel p;
assert(x == 2);
}