mirror of
https://github.com/ziglang/zig.git
synced 2025-01-25 11:21:02 +00:00
parent
18af2f9a27
commit
897e783763
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -3254,6 +3254,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
|
||||
case NodeTypeResume:
|
||||
case NodeTypeAwaitExpr:
|
||||
case NodeTypeSuspend:
|
||||
case NodeTypePromiseType:
|
||||
zig_unreachable();
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
54
src/ir.cpp
54
src/ir.cpp
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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";
|
||||
|
@ -76,6 +76,7 @@ enum TokenId {
|
||||
TokenIdKeywordNull,
|
||||
TokenIdKeywordOr,
|
||||
TokenIdKeywordPacked,
|
||||
TokenIdKeywordPromise,
|
||||
TokenIdKeywordPub,
|
||||
TokenIdKeywordResume,
|
||||
TokenIdKeywordReturn,
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user