add the anyframe and anyframe->T types

This commit is contained in:
Andrew Kelley 2019-07-26 19:52:35 -04:00
parent 018a89c7a1
commit ee64a22045
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
19 changed files with 337 additions and 50 deletions

View File

@ -1,6 +1,4 @@
* reimplement @frameSize with Prefix Data * make the anyframe type and anyframe->T type work with resume
* reimplement with function splitting rather than switch
* add the `anyframe` type and `anyframe->T`
* await * await
* await of a non async function * await of a non async function
* await in single-threaded mode * await in single-threaded mode
@ -12,3 +10,5 @@
* implicit cast of normal function to async function should be allowed when it is inferred to be async * implicit cast of normal function to async function should be allowed when it is inferred to be async
* go over the commented out tests * go over the commented out tests
* revive std.event.Loop * revive std.event.Loop
* reimplement with function splitting rather than switch
* @typeInfo for @Frame(func)

View File

@ -479,6 +479,7 @@ enum NodeType {
NodeTypeResume, NodeTypeResume,
NodeTypeAwaitExpr, NodeTypeAwaitExpr,
NodeTypeSuspend, NodeTypeSuspend,
NodeTypeAnyFrameType,
NodeTypeEnumLiteral, NodeTypeEnumLiteral,
}; };
@ -936,6 +937,10 @@ struct AstNodeSuspend {
AstNode *block; AstNode *block;
}; };
struct AstNodeAnyFrameType {
AstNode *payload_type; // can be NULL
};
struct AstNodeEnumLiteral { struct AstNodeEnumLiteral {
Token *period; Token *period;
Token *identifier; Token *identifier;
@ -1001,6 +1006,7 @@ struct AstNode {
AstNodeResumeExpr resume_expr; AstNodeResumeExpr resume_expr;
AstNodeAwaitExpr await_expr; AstNodeAwaitExpr await_expr;
AstNodeSuspend suspend; AstNodeSuspend suspend;
AstNodeAnyFrameType anyframe_type;
AstNodeEnumLiteral enum_literal; AstNodeEnumLiteral enum_literal;
} data; } data;
}; };
@ -1253,6 +1259,7 @@ enum ZigTypeId {
ZigTypeIdArgTuple, ZigTypeIdArgTuple,
ZigTypeIdOpaque, ZigTypeIdOpaque,
ZigTypeIdCoroFrame, ZigTypeIdCoroFrame,
ZigTypeIdAnyFrame,
ZigTypeIdVector, ZigTypeIdVector,
ZigTypeIdEnumLiteral, ZigTypeIdEnumLiteral,
}; };
@ -1272,6 +1279,10 @@ struct ZigTypeCoroFrame {
ZigType *locals_struct; ZigType *locals_struct;
}; };
struct ZigTypeAnyFrame {
ZigType *result_type; // null if `anyframe` instead of `anyframe->T`
};
struct ZigType { struct ZigType {
ZigTypeId id; ZigTypeId id;
Buf name; Buf name;
@ -1298,11 +1309,13 @@ struct ZigType {
ZigTypeVector vector; ZigTypeVector vector;
ZigTypeOpaque opaque; ZigTypeOpaque opaque;
ZigTypeCoroFrame frame; ZigTypeCoroFrame frame;
ZigTypeAnyFrame any_frame;
} data; } data;
// use these fields to make sure we don't duplicate type table entries for the same type // use these fields to make sure we don't duplicate type table entries for the same type
ZigType *pointer_parent[2]; // [0 - mut, 1 - const] ZigType *pointer_parent[2]; // [0 - mut, 1 - const]
ZigType *optional_parent; ZigType *optional_parent;
ZigType *any_frame_parent;
// If we generate a constant name value for this type, we memoize it here. // If we generate a constant name value for this type, we memoize it here.
// The type of this is array // The type of this is array
ConstExprValue *cached_const_name_val; ConstExprValue *cached_const_name_val;
@ -1781,6 +1794,7 @@ struct CodeGen {
ZigType *entry_arg_tuple; ZigType *entry_arg_tuple;
ZigType *entry_enum_literal; ZigType *entry_enum_literal;
ZigType *entry_frame_header; ZigType *entry_frame_header;
ZigType *entry_any_frame;
} builtin_types; } builtin_types;
ZigType *align_amt_type; ZigType *align_amt_type;
ZigType *stack_trace_type; ZigType *stack_trace_type;
@ -2208,6 +2222,7 @@ enum IrInstructionId {
IrInstructionIdSetRuntimeSafety, IrInstructionIdSetRuntimeSafety,
IrInstructionIdSetFloatMode, IrInstructionIdSetFloatMode,
IrInstructionIdArrayType, IrInstructionIdArrayType,
IrInstructionIdAnyFrameType,
IrInstructionIdSliceType, IrInstructionIdSliceType,
IrInstructionIdGlobalAsm, IrInstructionIdGlobalAsm,
IrInstructionIdAsm, IrInstructionIdAsm,
@ -2709,6 +2724,12 @@ struct IrInstructionPtrType {
bool is_allow_zero; bool is_allow_zero;
}; };
struct IrInstructionAnyFrameType {
IrInstruction base;
IrInstruction *payload_type;
};
struct IrInstructionSliceType { struct IrInstructionSliceType {
IrInstruction base; IrInstruction base;

View File

@ -256,6 +256,7 @@ AstNode *type_decl_node(ZigType *type_entry) {
case ZigTypeIdBoundFn: case ZigTypeIdBoundFn:
case ZigTypeIdArgTuple: case ZigTypeIdArgTuple:
case ZigTypeIdVector: case ZigTypeIdVector:
case ZigTypeIdAnyFrame:
return nullptr; return nullptr;
} }
zig_unreachable(); zig_unreachable();
@ -322,6 +323,7 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) {
case ZigTypeIdBoundFn: case ZigTypeIdBoundFn:
case ZigTypeIdArgTuple: case ZigTypeIdArgTuple:
case ZigTypeIdVector: case ZigTypeIdVector:
case ZigTypeIdAnyFrame:
return true; return true;
} }
zig_unreachable(); zig_unreachable();
@ -354,6 +356,31 @@ ZigType *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x) {
return get_int_type(g, false, bits_needed_for_unsigned(x)); return get_int_type(g, false, bits_needed_for_unsigned(x));
} }
ZigType *get_any_frame_type(CodeGen *g, ZigType *result_type) {
if (result_type != nullptr && result_type->any_frame_parent != nullptr) {
return result_type->any_frame_parent;
} else if (result_type == nullptr && g->builtin_types.entry_any_frame != nullptr) {
return g->builtin_types.entry_any_frame;
}
ZigType *entry = new_type_table_entry(ZigTypeIdAnyFrame);
entry->abi_size = g->builtin_types.entry_usize->abi_size;
entry->size_in_bits = g->builtin_types.entry_usize->size_in_bits;
entry->abi_align = g->builtin_types.entry_usize->abi_align;
entry->data.any_frame.result_type = result_type;
buf_init_from_str(&entry->name, "anyframe");
if (result_type != nullptr) {
buf_appendf(&entry->name, "->%s", buf_ptr(&result_type->name));
}
if (result_type != nullptr) {
result_type->any_frame_parent = entry;
} else if (result_type == nullptr) {
g->builtin_types.entry_any_frame = entry;
}
return entry;
}
static const char *ptr_len_to_star_str(PtrLen ptr_len) { static const char *ptr_len_to_star_str(PtrLen ptr_len) {
switch (ptr_len) { switch (ptr_len) {
case PtrLenSingle: case PtrLenSingle:
@ -1080,6 +1107,7 @@ static Error emit_error_unless_type_allowed_in_packed_struct(CodeGen *g, ZigType
case ZigTypeIdArgTuple: case ZigTypeIdArgTuple:
case ZigTypeIdOpaque: case ZigTypeIdOpaque:
case ZigTypeIdCoroFrame: case ZigTypeIdCoroFrame:
case ZigTypeIdAnyFrame:
add_node_error(g, source_node, add_node_error(g, source_node,
buf_sprintf("type '%s' not allowed in packed struct; no guaranteed in-memory representation", buf_sprintf("type '%s' not allowed in packed struct; no guaranteed in-memory representation",
buf_ptr(&type_entry->name))); buf_ptr(&type_entry->name)));
@ -1169,6 +1197,7 @@ bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {
case ZigTypeIdArgTuple: case ZigTypeIdArgTuple:
case ZigTypeIdVoid: case ZigTypeIdVoid:
case ZigTypeIdCoroFrame: case ZigTypeIdCoroFrame:
case ZigTypeIdAnyFrame:
return false; return false;
case ZigTypeIdOpaque: case ZigTypeIdOpaque:
case ZigTypeIdUnreachable: case ZigTypeIdUnreachable:
@ -1340,6 +1369,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
case ZigTypeIdFn: case ZigTypeIdFn:
case ZigTypeIdVector: case ZigTypeIdVector:
case ZigTypeIdCoroFrame: case ZigTypeIdCoroFrame:
case ZigTypeIdAnyFrame:
switch (type_requires_comptime(g, type_entry)) { switch (type_requires_comptime(g, type_entry)) {
case ReqCompTimeNo: case ReqCompTimeNo:
break; break;
@ -1436,6 +1466,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
case ZigTypeIdFn: case ZigTypeIdFn:
case ZigTypeIdVector: case ZigTypeIdVector:
case ZigTypeIdCoroFrame: case ZigTypeIdCoroFrame:
case ZigTypeIdAnyFrame:
switch (type_requires_comptime(g, fn_type_id.return_type)) { switch (type_requires_comptime(g, fn_type_id.return_type)) {
case ReqCompTimeInvalid: case ReqCompTimeInvalid:
return g->builtin_types.entry_invalid; return g->builtin_types.entry_invalid;
@ -2997,6 +3028,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
case NodeTypeAwaitExpr: case NodeTypeAwaitExpr:
case NodeTypeSuspend: case NodeTypeSuspend:
case NodeTypeEnumLiteral: case NodeTypeEnumLiteral:
case NodeTypeAnyFrameType:
zig_unreachable(); zig_unreachable();
} }
} }
@ -3049,6 +3081,7 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry
case ZigTypeIdBoundFn: case ZigTypeIdBoundFn:
case ZigTypeIdVector: case ZigTypeIdVector:
case ZigTypeIdCoroFrame: case ZigTypeIdCoroFrame:
case ZigTypeIdAnyFrame:
return type_entry; return type_entry;
} }
zig_unreachable(); zig_unreachable();
@ -3550,6 +3583,7 @@ bool is_container(ZigType *type_entry) {
case ZigTypeIdOpaque: case ZigTypeIdOpaque:
case ZigTypeIdVector: case ZigTypeIdVector:
case ZigTypeIdCoroFrame: case ZigTypeIdCoroFrame:
case ZigTypeIdAnyFrame:
return false; return false;
} }
zig_unreachable(); zig_unreachable();
@ -3607,6 +3641,7 @@ Error resolve_container_type(CodeGen *g, ZigType *type_entry) {
case ZigTypeIdOpaque: case ZigTypeIdOpaque:
case ZigTypeIdVector: case ZigTypeIdVector:
case ZigTypeIdCoroFrame: case ZigTypeIdCoroFrame:
case ZigTypeIdAnyFrame:
zig_unreachable(); zig_unreachable();
} }
zig_unreachable(); zig_unreachable();
@ -3615,11 +3650,13 @@ Error resolve_container_type(CodeGen *g, ZigType *type_entry) {
ZigType *get_src_ptr_type(ZigType *type) { ZigType *get_src_ptr_type(ZigType *type) {
if (type->id == ZigTypeIdPointer) return type; if (type->id == ZigTypeIdPointer) return type;
if (type->id == ZigTypeIdFn) return type; if (type->id == ZigTypeIdFn) return type;
if (type->id == ZigTypeIdAnyFrame) return type;
if (type->id == ZigTypeIdOptional) { if (type->id == ZigTypeIdOptional) {
if (type->data.maybe.child_type->id == ZigTypeIdPointer) { if (type->data.maybe.child_type->id == ZigTypeIdPointer) {
return type->data.maybe.child_type->data.pointer.allow_zero ? nullptr : type->data.maybe.child_type; return type->data.maybe.child_type->data.pointer.allow_zero ? nullptr : type->data.maybe.child_type;
} }
if (type->data.maybe.child_type->id == ZigTypeIdFn) return type->data.maybe.child_type; if (type->data.maybe.child_type->id == ZigTypeIdFn) return type->data.maybe.child_type;
if (type->data.maybe.child_type->id == ZigTypeIdAnyFrame) return type->data.maybe.child_type;
} }
return nullptr; return nullptr;
} }
@ -3635,6 +3672,13 @@ bool type_is_nonnull_ptr(ZigType *type) {
return get_codegen_ptr_type(type) == type && !ptr_allows_addr_zero(type); return get_codegen_ptr_type(type) == type && !ptr_allows_addr_zero(type);
} }
static uint32_t get_coro_frame_align_bytes(CodeGen *g) {
uint32_t a = g->pointer_size_bytes * 2;
// promises have at least alignment 8 so that we can have 3 extra bits when doing atomicrmw
if (a < 8) a = 8;
return a;
}
uint32_t get_ptr_align(CodeGen *g, ZigType *type) { uint32_t get_ptr_align(CodeGen *g, ZigType *type) {
ZigType *ptr_type = get_src_ptr_type(type); ZigType *ptr_type = get_src_ptr_type(type);
if (ptr_type->id == ZigTypeIdPointer) { if (ptr_type->id == ZigTypeIdPointer) {
@ -3646,6 +3690,8 @@ uint32_t get_ptr_align(CodeGen *g, ZigType *type) {
// when getting the alignment of `?extern fn() void`. // when getting the alignment of `?extern fn() void`.
// See http://lists.llvm.org/pipermail/llvm-dev/2018-September/126142.html // See http://lists.llvm.org/pipermail/llvm-dev/2018-September/126142.html
return (ptr_type->data.fn.fn_type_id.alignment == 0) ? 1 : ptr_type->data.fn.fn_type_id.alignment; return (ptr_type->data.fn.fn_type_id.alignment == 0) ? 1 : ptr_type->data.fn.fn_type_id.alignment;
} else if (ptr_type->id == ZigTypeIdAnyFrame) {
return get_coro_frame_align_bytes(g);
} else { } else {
zig_unreachable(); zig_unreachable();
} }
@ -3657,6 +3703,8 @@ bool get_ptr_const(ZigType *type) {
return ptr_type->data.pointer.is_const; return ptr_type->data.pointer.is_const;
} else if (ptr_type->id == ZigTypeIdFn) { } else if (ptr_type->id == ZigTypeIdFn) {
return true; return true;
} else if (ptr_type->id == ZigTypeIdAnyFrame) {
return true;
} else { } else {
zig_unreachable(); zig_unreachable();
} }
@ -4153,6 +4201,7 @@ bool handle_is_ptr(ZigType *type_entry) {
case ZigTypeIdFn: case ZigTypeIdFn:
case ZigTypeIdEnum: case ZigTypeIdEnum:
case ZigTypeIdVector: case ZigTypeIdVector:
case ZigTypeIdAnyFrame:
return false; return false;
case ZigTypeIdArray: case ZigTypeIdArray:
case ZigTypeIdStruct: case ZigTypeIdStruct:
@ -4404,6 +4453,9 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
case ZigTypeIdCoroFrame: case ZigTypeIdCoroFrame:
// TODO better hashing algorithm // TODO better hashing algorithm
return 675741936; return 675741936;
case ZigTypeIdAnyFrame:
// TODO better hashing algorithm
return 3747294894;
case ZigTypeIdBoundFn: case ZigTypeIdBoundFn:
case ZigTypeIdInvalid: case ZigTypeIdInvalid:
case ZigTypeIdUnreachable: case ZigTypeIdUnreachable:
@ -4469,6 +4521,7 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) {
case ZigTypeIdErrorSet: case ZigTypeIdErrorSet:
case ZigTypeIdEnum: case ZigTypeIdEnum:
case ZigTypeIdCoroFrame: case ZigTypeIdCoroFrame:
case ZigTypeIdAnyFrame:
return false; return false;
case ZigTypeIdPointer: case ZigTypeIdPointer:
@ -4541,6 +4594,7 @@ static bool return_type_is_cacheable(ZigType *return_type) {
case ZigTypeIdPointer: case ZigTypeIdPointer:
case ZigTypeIdVector: case ZigTypeIdVector:
case ZigTypeIdCoroFrame: case ZigTypeIdCoroFrame:
case ZigTypeIdAnyFrame:
return true; return true;
case ZigTypeIdArray: case ZigTypeIdArray:
@ -4673,6 +4727,7 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
case ZigTypeIdFloat: case ZigTypeIdFloat:
case ZigTypeIdErrorUnion: case ZigTypeIdErrorUnion:
case ZigTypeIdCoroFrame: case ZigTypeIdCoroFrame:
case ZigTypeIdAnyFrame:
return OnePossibleValueNo; return OnePossibleValueNo;
case ZigTypeIdUndefined: case ZigTypeIdUndefined:
case ZigTypeIdNull: case ZigTypeIdNull:
@ -4761,6 +4816,7 @@ ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) {
case ZigTypeIdVoid: case ZigTypeIdVoid:
case ZigTypeIdUnreachable: case ZigTypeIdUnreachable:
case ZigTypeIdCoroFrame: case ZigTypeIdCoroFrame:
case ZigTypeIdAnyFrame:
return ReqCompTimeNo; return ReqCompTimeNo;
} }
zig_unreachable(); zig_unreachable();
@ -5433,6 +5489,8 @@ bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) {
return true; return true;
case ZigTypeIdCoroFrame: case ZigTypeIdCoroFrame:
zig_panic("TODO"); zig_panic("TODO");
case ZigTypeIdAnyFrame:
zig_panic("TODO");
case ZigTypeIdUndefined: case ZigTypeIdUndefined:
zig_panic("TODO"); zig_panic("TODO");
case ZigTypeIdNull: case ZigTypeIdNull:
@ -5786,7 +5844,11 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
return; return;
} }
case ZigTypeIdCoroFrame: case ZigTypeIdCoroFrame:
buf_appendf(buf, "(TODO: coroutine frame value)"); buf_appendf(buf, "(TODO: async function frame value)");
return;
case ZigTypeIdAnyFrame:
buf_appendf(buf, "(TODO: anyframe value)");
return; return;
} }
@ -5836,6 +5898,7 @@ uint32_t type_id_hash(TypeId x) {
case ZigTypeIdBoundFn: case ZigTypeIdBoundFn:
case ZigTypeIdArgTuple: case ZigTypeIdArgTuple:
case ZigTypeIdCoroFrame: case ZigTypeIdCoroFrame:
case ZigTypeIdAnyFrame:
zig_unreachable(); zig_unreachable();
case ZigTypeIdErrorUnion: case ZigTypeIdErrorUnion:
return hash_ptr(x.data.error_union.err_set_type) ^ hash_ptr(x.data.error_union.payload_type); return hash_ptr(x.data.error_union.err_set_type) ^ hash_ptr(x.data.error_union.payload_type);
@ -5885,6 +5948,7 @@ bool type_id_eql(TypeId a, TypeId b) {
case ZigTypeIdArgTuple: case ZigTypeIdArgTuple:
case ZigTypeIdOpaque: case ZigTypeIdOpaque:
case ZigTypeIdCoroFrame: case ZigTypeIdCoroFrame:
case ZigTypeIdAnyFrame:
zig_unreachable(); zig_unreachable();
case ZigTypeIdErrorUnion: case ZigTypeIdErrorUnion:
return a.data.error_union.err_set_type == b.data.error_union.err_set_type && return a.data.error_union.err_set_type == b.data.error_union.err_set_type &&
@ -6051,6 +6115,7 @@ static const ZigTypeId all_type_ids[] = {
ZigTypeIdArgTuple, ZigTypeIdArgTuple,
ZigTypeIdOpaque, ZigTypeIdOpaque,
ZigTypeIdCoroFrame, ZigTypeIdCoroFrame,
ZigTypeIdAnyFrame,
ZigTypeIdVector, ZigTypeIdVector,
ZigTypeIdEnumLiteral, ZigTypeIdEnumLiteral,
}; };
@ -6116,10 +6181,12 @@ size_t type_id_index(ZigType *entry) {
return 21; return 21;
case ZigTypeIdCoroFrame: case ZigTypeIdCoroFrame:
return 22; return 22;
case ZigTypeIdVector: case ZigTypeIdAnyFrame:
return 23; return 23;
case ZigTypeIdEnumLiteral: case ZigTypeIdVector:
return 24; return 24;
case ZigTypeIdEnumLiteral:
return 25;
} }
zig_unreachable(); zig_unreachable();
} }
@ -6178,6 +6245,8 @@ const char *type_id_name(ZigTypeId id) {
return "Vector"; return "Vector";
case ZigTypeIdCoroFrame: case ZigTypeIdCoroFrame:
return "Frame"; return "Frame";
case ZigTypeIdAnyFrame:
return "AnyFrame";
} }
zig_unreachable(); zig_unreachable();
} }
@ -7398,6 +7467,40 @@ static void resolve_llvm_types_coro_frame(CodeGen *g, ZigType *frame_type, Resol
frame_type->llvm_di_type = frame_type->data.frame.locals_struct->llvm_di_type; frame_type->llvm_di_type = frame_type->data.frame.locals_struct->llvm_di_type;
} }
static void resolve_llvm_types_any_frame(CodeGen *g, ZigType *any_frame_type, ResolveStatus wanted_resolve_status) {
if (any_frame_type->llvm_di_type != nullptr) return;
ZigType *result_type = any_frame_type->data.any_frame.result_type;
Buf *name = buf_sprintf("(%s header)", buf_ptr(&any_frame_type->name));
ZigType *frame_header_type;
if (result_type == nullptr || !type_has_bits(result_type)) {
const char *field_names[] = {"resume_index", "fn_ptr", "awaiter"};
ZigType *field_types[] = {
g->builtin_types.entry_usize,
g->builtin_types.entry_usize,
g->builtin_types.entry_usize,
};
frame_header_type = get_struct_type(g, buf_ptr(name), field_names, field_types, 3);
} else {
ZigType *ptr_result_type = get_pointer_to_type(g, result_type, false);
const char *field_names[] = {"resume_index", "fn_ptr", "awaiter", "result_ptr", "result"};
ZigType *field_types[] = {
g->builtin_types.entry_usize,
g->builtin_types.entry_usize,
g->builtin_types.entry_usize,
ptr_result_type,
result_type,
};
frame_header_type = get_struct_type(g, buf_ptr(name), field_names, field_types, 5);
}
ZigType *ptr_type = get_pointer_to_type(g, frame_header_type, false);
any_frame_type->llvm_type = get_llvm_type(g, ptr_type);
any_frame_type->llvm_di_type = get_llvm_di_type(g, ptr_type);
}
static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status) { static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status) {
assert(type->id == ZigTypeIdOpaque || type_is_resolved(type, ResolveStatusSizeKnown)); assert(type->id == ZigTypeIdOpaque || type_is_resolved(type, ResolveStatusSizeKnown));
assert(wanted_resolve_status > ResolveStatusSizeKnown); assert(wanted_resolve_status > ResolveStatusSizeKnown);
@ -7460,6 +7563,8 @@ static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_r
} }
case ZigTypeIdCoroFrame: case ZigTypeIdCoroFrame:
return resolve_llvm_types_coro_frame(g, type, wanted_resolve_status); return resolve_llvm_types_coro_frame(g, type, wanted_resolve_status);
case ZigTypeIdAnyFrame:
return resolve_llvm_types_any_frame(g, type, wanted_resolve_status);
} }
zig_unreachable(); zig_unreachable();
} }

View File

@ -41,6 +41,7 @@ ZigType *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const c
ZigType *get_struct_type(CodeGen *g, const char *type_name, const char *field_names[], ZigType *get_struct_type(CodeGen *g, const char *type_name, const char *field_names[],
ZigType *field_types[], size_t field_count); ZigType *field_types[], size_t field_count);
ZigType *get_test_fn_type(CodeGen *g); ZigType *get_test_fn_type(CodeGen *g);
ZigType *get_any_frame_type(CodeGen *g, ZigType *result_type);
bool handle_is_ptr(ZigType *type_entry); bool handle_is_ptr(ZigType *type_entry);
bool type_has_bits(ZigType *type_entry); bool type_has_bits(ZigType *type_entry);

View File

@ -259,6 +259,8 @@ static const char *node_type_str(NodeType node_type) {
return "Suspend"; return "Suspend";
case NodeTypePointerType: case NodeTypePointerType:
return "PointerType"; return "PointerType";
case NodeTypeAnyFrameType:
return "AnyFrameType";
case NodeTypeEnumLiteral: case NodeTypeEnumLiteral:
return "EnumLiteral"; return "EnumLiteral";
} }
@ -847,6 +849,14 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
render_node_ungrouped(ar, node->data.inferred_array_type.child_type); render_node_ungrouped(ar, node->data.inferred_array_type.child_type);
break; break;
} }
case NodeTypeAnyFrameType: {
fprintf(ar->f, "anyframe");
if (node->data.anyframe_type.payload_type != nullptr) {
fprintf(ar->f, "->");
render_node_grouped(ar, node->data.anyframe_type.payload_type);
}
break;
}
case NodeTypeErrorType: case NodeTypeErrorType:
fprintf(ar->f, "anyerror"); fprintf(ar->f, "anyerror");
break; break;

View File

@ -4947,6 +4947,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdSetRuntimeSafety: case IrInstructionIdSetRuntimeSafety:
case IrInstructionIdSetFloatMode: case IrInstructionIdSetFloatMode:
case IrInstructionIdArrayType: case IrInstructionIdArrayType:
case IrInstructionIdAnyFrameType:
case IrInstructionIdSliceType: case IrInstructionIdSliceType:
case IrInstructionIdSizeOf: case IrInstructionIdSizeOf:
case IrInstructionIdSwitchTarget: case IrInstructionIdSwitchTarget:
@ -5438,7 +5439,9 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
return val; return val;
} }
case ZigTypeIdCoroFrame: case ZigTypeIdCoroFrame:
zig_panic("TODO bit pack a coroutine frame"); zig_panic("TODO bit pack an async function frame");
case ZigTypeIdAnyFrame:
zig_panic("TODO bit pack an anyframe");
} }
zig_unreachable(); zig_unreachable();
} }
@ -5961,6 +5964,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
zig_unreachable(); zig_unreachable();
case ZigTypeIdCoroFrame: case ZigTypeIdCoroFrame:
zig_panic("TODO"); zig_panic("TODO");
case ZigTypeIdAnyFrame:
zig_panic("TODO");
} }
zig_unreachable(); zig_unreachable();
} }
@ -7176,6 +7181,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
" ArgTuple: void,\n" " ArgTuple: void,\n"
" Opaque: void,\n" " Opaque: void,\n"
" Frame: void,\n" " Frame: void,\n"
" AnyFrame: AnyFrame,\n"
" Vector: Vector,\n" " Vector: Vector,\n"
" EnumLiteral: void,\n" " EnumLiteral: void,\n"
"\n\n" "\n\n"
@ -7291,6 +7297,10 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
" args: []FnArg,\n" " args: []FnArg,\n"
" };\n" " };\n"
"\n" "\n"
" pub const AnyFrame = struct {\n"
" child: ?type,\n"
" };\n"
"\n"
" pub const Vector = struct {\n" " pub const Vector = struct {\n"
" len: comptime_int,\n" " len: comptime_int,\n"
" child: type,\n" " child: type,\n"
@ -8448,6 +8458,7 @@ static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, ZigType *type_e
case ZigTypeIdErrorUnion: case ZigTypeIdErrorUnion:
case ZigTypeIdErrorSet: case ZigTypeIdErrorSet:
case ZigTypeIdCoroFrame: case ZigTypeIdCoroFrame:
case ZigTypeIdAnyFrame:
zig_unreachable(); zig_unreachable();
case ZigTypeIdVoid: case ZigTypeIdVoid:
case ZigTypeIdUnreachable: case ZigTypeIdUnreachable:
@ -8632,6 +8643,7 @@ static void get_c_type(CodeGen *g, GenH *gen_h, ZigType *type_entry, Buf *out_bu
case ZigTypeIdNull: case ZigTypeIdNull:
case ZigTypeIdArgTuple: case ZigTypeIdArgTuple:
case ZigTypeIdCoroFrame: case ZigTypeIdCoroFrame:
case ZigTypeIdAnyFrame:
zig_unreachable(); zig_unreachable();
} }
} }
@ -8800,7 +8812,9 @@ static void gen_h_file(CodeGen *g) {
case ZigTypeIdFn: case ZigTypeIdFn:
case ZigTypeIdVector: case ZigTypeIdVector:
case ZigTypeIdCoroFrame: case ZigTypeIdCoroFrame:
case ZigTypeIdAnyFrame:
zig_unreachable(); zig_unreachable();
case ZigTypeIdEnum: case ZigTypeIdEnum:
if (type_entry->data.enumeration.layout == ContainerLayoutExtern) { if (type_entry->data.enumeration.layout == ContainerLayoutExtern) {
fprintf(out_h, "enum %s {\n", buf_ptr(type_h_name(type_entry))); fprintf(out_h, "enum %s {\n", buf_ptr(type_h_name(type_entry)));

View File

@ -303,6 +303,7 @@ static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {
case ZigTypeIdBoundFn: case ZigTypeIdBoundFn:
case ZigTypeIdErrorSet: case ZigTypeIdErrorSet:
case ZigTypeIdOpaque: case ZigTypeIdOpaque:
case ZigTypeIdAnyFrame:
return true; return true;
case ZigTypeIdFloat: case ZigTypeIdFloat:
return a->data.floating.bit_count == b->data.floating.bit_count; return a->data.floating.bit_count == b->data.floating.bit_count;
@ -563,6 +564,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionArrayType *) {
return IrInstructionIdArrayType; return IrInstructionIdArrayType;
} }
static constexpr IrInstructionId ir_instruction_id(IrInstructionAnyFrameType *) {
return IrInstructionIdAnyFrameType;
}
static constexpr IrInstructionId ir_instruction_id(IrInstructionSliceType *) { static constexpr IrInstructionId ir_instruction_id(IrInstructionSliceType *) {
return IrInstructionIdSliceType; return IrInstructionIdSliceType;
} }
@ -1696,6 +1701,16 @@ static IrInstruction *ir_build_array_type(IrBuilder *irb, Scope *scope, AstNode
return &instruction->base; return &instruction->base;
} }
static IrInstruction *ir_build_anyframe_type(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrInstruction *payload_type)
{
IrInstructionAnyFrameType *instruction = ir_build_instruction<IrInstructionAnyFrameType>(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, 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, bool is_allow_zero) IrInstruction *child_type, bool is_const, bool is_volatile, IrInstruction *align_value, bool is_allow_zero)
{ {
@ -6515,6 +6530,22 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n
} }
} }
static IrInstruction *ir_gen_anyframe_type(IrBuilder *irb, Scope *scope, AstNode *node) {
assert(node->type == NodeTypeAnyFrameType);
AstNode *payload_type_node = node->data.anyframe_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_anyframe_type(irb, scope, node, payload_type_value);
}
static IrInstruction *ir_gen_undefined_literal(IrBuilder *irb, Scope *scope, AstNode *node) { static IrInstruction *ir_gen_undefined_literal(IrBuilder *irb, Scope *scope, AstNode *node) {
assert(node->type == NodeTypeUndefinedLiteral); assert(node->type == NodeTypeUndefinedLiteral);
return ir_build_const_undefined(irb, scope, node); return ir_build_const_undefined(irb, scope, node);
@ -7884,6 +7915,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
return ir_lval_wrap(irb, scope, ir_gen_array_type(irb, scope, node), lval, result_loc); return ir_lval_wrap(irb, scope, ir_gen_array_type(irb, scope, node), lval, result_loc);
case NodeTypePointerType: case NodeTypePointerType:
return ir_lval_wrap(irb, scope, ir_gen_pointer_type(irb, scope, node), lval, result_loc); return ir_lval_wrap(irb, scope, ir_gen_pointer_type(irb, scope, node), lval, result_loc);
case NodeTypeAnyFrameType:
return ir_lval_wrap(irb, scope, ir_gen_anyframe_type(irb, scope, node), lval, result_loc);
case NodeTypeStringLiteral: case NodeTypeStringLiteral:
return ir_lval_wrap(irb, scope, ir_gen_string_literal(irb, scope, node), lval, result_loc); return ir_lval_wrap(irb, scope, ir_gen_string_literal(irb, scope, node), lval, result_loc);
case NodeTypeUndefinedLiteral: case NodeTypeUndefinedLiteral:
@ -12775,6 +12808,7 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
case ZigTypeIdArgTuple: case ZigTypeIdArgTuple:
case ZigTypeIdEnum: case ZigTypeIdEnum:
case ZigTypeIdEnumLiteral: case ZigTypeIdEnumLiteral:
case ZigTypeIdAnyFrame:
operator_allowed = is_equality_cmp; operator_allowed = is_equality_cmp;
break; break;
@ -14155,6 +14189,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
case ZigTypeIdArgTuple: case ZigTypeIdArgTuple:
case ZigTypeIdOpaque: case ZigTypeIdOpaque:
case ZigTypeIdCoroFrame: case ZigTypeIdCoroFrame:
case ZigTypeIdAnyFrame:
ir_add_error(ira, target, ir_add_error(ira, target,
buf_sprintf("invalid export target '%s'", buf_ptr(&type_value->name))); buf_sprintf("invalid export target '%s'", buf_ptr(&type_value->name)));
break; break;
@ -14180,6 +14215,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
case ZigTypeIdOpaque: case ZigTypeIdOpaque:
case ZigTypeIdEnumLiteral: case ZigTypeIdEnumLiteral:
case ZigTypeIdCoroFrame: case ZigTypeIdCoroFrame:
case ZigTypeIdAnyFrame:
ir_add_error(ira, target, ir_add_error(ira, target,
buf_sprintf("invalid export target type '%s'", buf_ptr(&target->value.type->name))); buf_sprintf("invalid export target type '%s'", buf_ptr(&target->value.type->name)));
break; break;
@ -15720,7 +15756,9 @@ static IrInstruction *ir_analyze_optional_type(IrAnalyze *ira, IrInstructionUnOp
case ZigTypeIdBoundFn: case ZigTypeIdBoundFn:
case ZigTypeIdArgTuple: case ZigTypeIdArgTuple:
case ZigTypeIdCoroFrame: case ZigTypeIdCoroFrame:
case ZigTypeIdAnyFrame:
return ir_const_type(ira, &un_op_instruction->base, get_optional_type(ira->codegen, type_entry)); return ir_const_type(ira, &un_op_instruction->base, get_optional_type(ira->codegen, type_entry));
case ZigTypeIdUnreachable: case ZigTypeIdUnreachable:
case ZigTypeIdOpaque: case ZigTypeIdOpaque:
ir_add_error_node(ira, un_op_instruction->base.source_node, ir_add_error_node(ira, un_op_instruction->base.source_node,
@ -17443,6 +17481,20 @@ static IrInstruction *ir_analyze_instruction_set_float_mode(IrAnalyze *ira,
return ir_const_void(ira, &instruction->base); return ir_const_void(ira, &instruction->base);
} }
static IrInstruction *ir_analyze_instruction_any_frame_type(IrAnalyze *ira,
IrInstructionAnyFrameType *instruction)
{
ZigType *payload_type = nullptr;
if (instruction->payload_type != nullptr) {
payload_type = ir_resolve_type(ira, instruction->payload_type->child);
if (type_is_invalid(payload_type))
return ira->codegen->invalid_instruction;
}
ZigType *any_frame_type = get_any_frame_type(ira->codegen, payload_type);
return ir_const_type(ira, &instruction->base, any_frame_type);
}
static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira, static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira,
IrInstructionSliceType *slice_type_instruction) IrInstructionSliceType *slice_type_instruction)
{ {
@ -17492,6 +17544,7 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira,
case ZigTypeIdBoundFn: case ZigTypeIdBoundFn:
case ZigTypeIdVector: case ZigTypeIdVector:
case ZigTypeIdCoroFrame: case ZigTypeIdCoroFrame:
case ZigTypeIdAnyFrame:
{ {
ResolveStatus needed_status = (align_bytes == 0) ? ResolveStatus needed_status = (align_bytes == 0) ?
ResolveStatusZeroBitsKnown : ResolveStatusAlignmentKnown; ResolveStatusZeroBitsKnown : ResolveStatusAlignmentKnown;
@ -17607,6 +17660,7 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira,
case ZigTypeIdBoundFn: case ZigTypeIdBoundFn:
case ZigTypeIdVector: case ZigTypeIdVector:
case ZigTypeIdCoroFrame: case ZigTypeIdCoroFrame:
case ZigTypeIdAnyFrame:
{ {
if ((err = ensure_complete_type(ira->codegen, child_type))) if ((err = ensure_complete_type(ira->codegen, child_type)))
return ira->codegen->invalid_instruction; return ira->codegen->invalid_instruction;
@ -17658,6 +17712,7 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira,
case ZigTypeIdFn: case ZigTypeIdFn:
case ZigTypeIdVector: case ZigTypeIdVector:
case ZigTypeIdCoroFrame: case ZigTypeIdCoroFrame:
case ZigTypeIdAnyFrame:
{ {
uint64_t size_in_bytes = type_size(ira->codegen, type_entry); uint64_t size_in_bytes = type_size(ira->codegen, type_entry);
return ir_const_unsigned(ira, &size_of_instruction->base, size_in_bytes); return ir_const_unsigned(ira, &size_of_instruction->base, size_in_bytes);
@ -18222,6 +18277,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
case ZigTypeIdOpaque: case ZigTypeIdOpaque:
case ZigTypeIdVector: case ZigTypeIdVector:
case ZigTypeIdCoroFrame: case ZigTypeIdCoroFrame:
case ZigTypeIdAnyFrame:
ir_add_error(ira, &switch_target_instruction->base, ir_add_error(ira, &switch_target_instruction->base,
buf_sprintf("invalid switch target type '%s'", buf_ptr(&target_type->name))); buf_sprintf("invalid switch target type '%s'", buf_ptr(&target_type->name)));
return ira->codegen->invalid_instruction; return ira->codegen->invalid_instruction;
@ -19656,6 +19712,22 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
break; break;
} }
case ZigTypeIdAnyFrame: {
result = create_const_vals(1);
result->special = ConstValSpecialStatic;
result->type = ir_type_info_get_type(ira, "AnyFrame", nullptr);
ConstExprValue *fields = create_const_vals(1);
result->data.x_struct.fields = fields;
// child: ?type
ensure_field_index(result->type, "child", 0);
fields[0].special = ConstValSpecialStatic;
fields[0].type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_type);
fields[0].data.x_optional = (type_entry->data.any_frame.result_type == nullptr) ? nullptr :
create_const_type(ira->codegen, type_entry->data.any_frame.result_type);
break;
}
case ZigTypeIdEnum: case ZigTypeIdEnum:
{ {
result = create_const_vals(1); result = create_const_vals(1);
@ -20062,7 +20134,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
break; break;
} }
case ZigTypeIdCoroFrame: case ZigTypeIdCoroFrame:
zig_panic("TODO @typeInfo for coro frames"); zig_panic("TODO @typeInfo for async function frames");
} }
assert(result != nullptr); assert(result != nullptr);
@ -21852,6 +21924,7 @@ static IrInstruction *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruct
case ZigTypeIdFn: case ZigTypeIdFn:
case ZigTypeIdVector: case ZigTypeIdVector:
case ZigTypeIdCoroFrame: case ZigTypeIdCoroFrame:
case ZigTypeIdAnyFrame:
{ {
uint64_t align_in_bytes = get_abi_alignment(ira->codegen, type_entry); uint64_t align_in_bytes = get_abi_alignment(ira->codegen, type_entry);
return ir_const_unsigned(ira, &instruction->base, align_in_bytes); return ir_const_unsigned(ira, &instruction->base, align_in_bytes);
@ -23004,7 +23077,9 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
case ZigTypeIdUnion: case ZigTypeIdUnion:
zig_panic("TODO buf_write_value_bytes union type"); zig_panic("TODO buf_write_value_bytes union type");
case ZigTypeIdCoroFrame: case ZigTypeIdCoroFrame:
zig_panic("TODO buf_write_value_bytes coro frame type"); zig_panic("TODO buf_write_value_bytes async fn frame type");
case ZigTypeIdAnyFrame:
zig_panic("TODO buf_write_value_bytes anyframe type");
} }
zig_unreachable(); zig_unreachable();
} }
@ -23185,7 +23260,9 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou
case ZigTypeIdUnion: case ZigTypeIdUnion:
zig_panic("TODO buf_read_value_bytes union type"); zig_panic("TODO buf_read_value_bytes union type");
case ZigTypeIdCoroFrame: case ZigTypeIdCoroFrame:
zig_panic("TODO buf_read_value_bytes coro frame type"); zig_panic("TODO buf_read_value_bytes async fn frame type");
case ZigTypeIdAnyFrame:
zig_panic("TODO buf_read_value_bytes anyframe type");
} }
zig_unreachable(); zig_unreachable();
} }
@ -24327,6 +24404,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
return ir_analyze_instruction_set_runtime_safety(ira, (IrInstructionSetRuntimeSafety *)instruction); return ir_analyze_instruction_set_runtime_safety(ira, (IrInstructionSetRuntimeSafety *)instruction);
case IrInstructionIdSetFloatMode: case IrInstructionIdSetFloatMode:
return ir_analyze_instruction_set_float_mode(ira, (IrInstructionSetFloatMode *)instruction); return ir_analyze_instruction_set_float_mode(ira, (IrInstructionSetFloatMode *)instruction);
case IrInstructionIdAnyFrameType:
return ir_analyze_instruction_any_frame_type(ira, (IrInstructionAnyFrameType *)instruction);
case IrInstructionIdSliceType: case IrInstructionIdSliceType:
return ir_analyze_instruction_slice_type(ira, (IrInstructionSliceType *)instruction); return ir_analyze_instruction_slice_type(ira, (IrInstructionSliceType *)instruction);
case IrInstructionIdGlobalAsm: case IrInstructionIdGlobalAsm:
@ -24707,6 +24786,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdStructFieldPtr: case IrInstructionIdStructFieldPtr:
case IrInstructionIdArrayType: case IrInstructionIdArrayType:
case IrInstructionIdSliceType: case IrInstructionIdSliceType:
case IrInstructionIdAnyFrameType:
case IrInstructionIdSizeOf: case IrInstructionIdSizeOf:
case IrInstructionIdTestNonNull: case IrInstructionIdTestNonNull:
case IrInstructionIdOptionalUnwrapPtr: case IrInstructionIdOptionalUnwrapPtr:

View File

@ -471,6 +471,15 @@ static void ir_print_slice_type(IrPrint *irp, IrInstructionSliceType *instructio
ir_print_other_instruction(irp, instruction->child_type); ir_print_other_instruction(irp, instruction->child_type);
} }
static void ir_print_any_frame_type(IrPrint *irp, IrInstructionAnyFrameType *instruction) {
if (instruction->payload_type == nullptr) {
fprintf(irp->f, "anyframe");
} else {
fprintf(irp->f, "anyframe->");
ir_print_other_instruction(irp, instruction->payload_type);
}
}
static void ir_print_global_asm(IrPrint *irp, IrInstructionGlobalAsm *instruction) { static void ir_print_global_asm(IrPrint *irp, IrInstructionGlobalAsm *instruction) {
fprintf(irp->f, "asm(\"%s\")", buf_ptr(instruction->asm_code)); fprintf(irp->f, "asm(\"%s\")", buf_ptr(instruction->asm_code));
} }
@ -1629,6 +1638,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdSliceType: case IrInstructionIdSliceType:
ir_print_slice_type(irp, (IrInstructionSliceType *)instruction); ir_print_slice_type(irp, (IrInstructionSliceType *)instruction);
break; break;
case IrInstructionIdAnyFrameType:
ir_print_any_frame_type(irp, (IrInstructionAnyFrameType *)instruction);
break;
case IrInstructionIdGlobalAsm: case IrInstructionIdGlobalAsm:
ir_print_global_asm(irp, (IrInstructionGlobalAsm *)instruction); ir_print_global_asm(irp, (IrInstructionGlobalAsm *)instruction);
break; break;

View File

@ -282,6 +282,9 @@ static AstNode *ast_parse_prefix_op_expr(
case NodeTypeAwaitExpr: case NodeTypeAwaitExpr:
right = &prefix->data.await_expr.expr; right = &prefix->data.await_expr.expr;
break; break;
case NodeTypeAnyFrameType:
right = &prefix->data.anyframe_type.payload_type;
break;
case NodeTypeArrayType: case NodeTypeArrayType:
right = &prefix->data.array_type.child_type; right = &prefix->data.array_type.child_type;
break; break;
@ -1640,6 +1643,10 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) {
if (null != nullptr) if (null != nullptr)
return ast_create_node(pc, NodeTypeNullLiteral, null); return ast_create_node(pc, NodeTypeNullLiteral, null);
Token *anyframe = eat_token_if(pc, TokenIdKeywordAnyFrame);
if (anyframe != nullptr)
return ast_create_node(pc, NodeTypeAnyFrameType, anyframe);
Token *true_token = eat_token_if(pc, TokenIdKeywordTrue); Token *true_token = eat_token_if(pc, TokenIdKeywordTrue);
if (true_token != nullptr) { if (true_token != nullptr) {
AstNode *res = ast_create_node(pc, NodeTypeBoolLiteral, true_token); AstNode *res = ast_create_node(pc, NodeTypeBoolLiteral, true_token);
@ -2510,7 +2517,7 @@ static AstNode *ast_parse_prefix_op(ParseContext *pc) {
// PrefixTypeOp // PrefixTypeOp
// <- QUESTIONMARK // <- QUESTIONMARK
// / KEYWORD_promise MINUSRARROW // / KEYWORD_anyframe MINUSRARROW
// / ArrayTypeStart (ByteAlign / KEYWORD_const / KEYWORD_volatile)* // / ArrayTypeStart (ByteAlign / KEYWORD_const / KEYWORD_volatile)*
// / PtrTypeStart (KEYWORD_align LPAREN Expr (COLON INTEGER COLON INTEGER)? RPAREN / KEYWORD_const / KEYWORD_volatile)* // / PtrTypeStart (KEYWORD_align LPAREN Expr (COLON INTEGER COLON INTEGER)? RPAREN / KEYWORD_const / KEYWORD_volatile)*
static AstNode *ast_parse_prefix_type_op(ParseContext *pc) { static AstNode *ast_parse_prefix_type_op(ParseContext *pc) {
@ -2521,6 +2528,16 @@ static AstNode *ast_parse_prefix_type_op(ParseContext *pc) {
return res; return res;
} }
Token *anyframe = eat_token_if(pc, TokenIdKeywordAnyFrame);
if (anyframe != nullptr) {
if (eat_token_if(pc, TokenIdArrow) != nullptr) {
AstNode *res = ast_create_node(pc, NodeTypeAnyFrameType, anyframe);
return res;
}
put_back_token(pc);
}
AstNode *array = ast_parse_array_type_start(pc); AstNode *array = ast_parse_array_type_start(pc);
if (array != nullptr) { if (array != nullptr) {
assert(array->type == NodeTypeArrayType); assert(array->type == NodeTypeArrayType);
@ -3005,6 +3022,9 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
case NodeTypeInferredArrayType: case NodeTypeInferredArrayType:
visit_field(&node->data.array_type.child_type, visit, context); visit_field(&node->data.array_type.child_type, visit, context);
break; break;
case NodeTypeAnyFrameType:
visit_field(&node->data.anyframe_type.payload_type, visit, context);
break;
case NodeTypeErrorType: case NodeTypeErrorType:
// none // none
break; break;

View File

@ -109,6 +109,7 @@ static const struct ZigKeyword zig_keywords[] = {
{"align", TokenIdKeywordAlign}, {"align", TokenIdKeywordAlign},
{"allowzero", TokenIdKeywordAllowZero}, {"allowzero", TokenIdKeywordAllowZero},
{"and", TokenIdKeywordAnd}, {"and", TokenIdKeywordAnd},
{"anyframe", TokenIdKeywordAnyFrame},
{"asm", TokenIdKeywordAsm}, {"asm", TokenIdKeywordAsm},
{"async", TokenIdKeywordAsync}, {"async", TokenIdKeywordAsync},
{"await", TokenIdKeywordAwait}, {"await", TokenIdKeywordAwait},
@ -1533,6 +1534,7 @@ const char * token_name(TokenId id) {
case TokenIdKeywordCancel: return "cancel"; case TokenIdKeywordCancel: return "cancel";
case TokenIdKeywordAlign: return "align"; case TokenIdKeywordAlign: return "align";
case TokenIdKeywordAnd: return "and"; case TokenIdKeywordAnd: return "and";
case TokenIdKeywordAnyFrame: return "anyframe";
case TokenIdKeywordAsm: return "asm"; case TokenIdKeywordAsm: return "asm";
case TokenIdKeywordBreak: return "break"; case TokenIdKeywordBreak: return "break";
case TokenIdKeywordCatch: return "catch"; case TokenIdKeywordCatch: return "catch";

View File

@ -53,6 +53,7 @@ enum TokenId {
TokenIdKeywordAlign, TokenIdKeywordAlign,
TokenIdKeywordAllowZero, TokenIdKeywordAllowZero,
TokenIdKeywordAnd, TokenIdKeywordAnd,
TokenIdKeywordAnyFrame,
TokenIdKeywordAsm, TokenIdKeywordAsm,
TokenIdKeywordAsync, TokenIdKeywordAsync,
TokenIdKeywordAwait, TokenIdKeywordAwait,

View File

@ -540,6 +540,7 @@ pub fn autoHash(key: var, comptime rng: *std.rand.Random, comptime HashInt: type
.Undefined, .Undefined,
.ArgTuple, .ArgTuple,
.Frame, .Frame,
.AnyFrame,
=> @compileError("cannot hash this type"), => @compileError("cannot hash this type"),
.Void, .Void,

View File

@ -30,6 +30,7 @@ pub fn expectEqual(expected: var, actual: @typeOf(expected)) void {
.ArgTuple, .ArgTuple,
.Opaque, .Opaque,
.Frame, .Frame,
.AnyFrame,
=> @compileError("value of type " ++ @typeName(@typeOf(actual)) ++ " encountered"), => @compileError("value of type " ++ @typeName(@typeOf(actual)) ++ " encountered"),
.Undefined, .Undefined,

View File

@ -400,7 +400,7 @@ pub const Node = struct {
VarType, VarType,
ErrorType, ErrorType,
FnProto, FnProto,
PromiseType, AnyFrameType,
// Primary expressions // Primary expressions
IntegerLiteral, IntegerLiteral,
@ -952,9 +952,9 @@ pub const Node = struct {
} }
}; };
pub const PromiseType = struct { pub const AnyFrameType = struct {
base: Node, base: Node,
promise_token: TokenIndex, anyframe_token: TokenIndex,
result: ?Result, result: ?Result,
pub const Result = struct { pub const Result = struct {
@ -962,7 +962,7 @@ pub const Node = struct {
return_type: *Node, return_type: *Node,
}; };
pub fn iterate(self: *PromiseType, index: usize) ?*Node { pub fn iterate(self: *AnyFrameType, index: usize) ?*Node {
var i = index; var i = index;
if (self.result) |result| { if (self.result) |result| {
@ -973,13 +973,13 @@ pub const Node = struct {
return null; return null;
} }
pub fn firstToken(self: *const PromiseType) TokenIndex { pub fn firstToken(self: *const AnyFrameType) TokenIndex {
return self.promise_token; return self.anyframe_token;
} }
pub fn lastToken(self: *const PromiseType) TokenIndex { pub fn lastToken(self: *const AnyFrameType) TokenIndex {
if (self.result) |result| return result.return_type.lastToken(); if (self.result) |result| return result.return_type.lastToken();
return self.promise_token; return self.anyframe_token;
} }
}; };

View File

@ -1201,7 +1201,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
/// / KEYWORD_error DOT IDENTIFIER /// / KEYWORD_error DOT IDENTIFIER
/// / KEYWORD_false /// / KEYWORD_false
/// / KEYWORD_null /// / KEYWORD_null
/// / KEYWORD_promise /// / KEYWORD_anyframe
/// / KEYWORD_true /// / KEYWORD_true
/// / KEYWORD_undefined /// / KEYWORD_undefined
/// / KEYWORD_unreachable /// / KEYWORD_unreachable
@ -1256,11 +1256,11 @@ fn parsePrimaryTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*N
} }
if (eatToken(it, .Keyword_false)) |token| return createLiteral(arena, Node.BoolLiteral, token); if (eatToken(it, .Keyword_false)) |token| return createLiteral(arena, Node.BoolLiteral, token);
if (eatToken(it, .Keyword_null)) |token| return createLiteral(arena, Node.NullLiteral, token); if (eatToken(it, .Keyword_null)) |token| return createLiteral(arena, Node.NullLiteral, token);
if (eatToken(it, .Keyword_promise)) |token| { if (eatToken(it, .Keyword_anyframe)) |token| {
const node = try arena.create(Node.PromiseType); const node = try arena.create(Node.AnyFrameType);
node.* = Node.PromiseType{ node.* = Node.AnyFrameType{
.base = Node{ .id = .PromiseType }, .base = Node{ .id = .AnyFrameType },
.promise_token = token, .anyframe_token = token,
.result = null, .result = null,
}; };
return &node.base; return &node.base;
@ -2194,7 +2194,7 @@ fn parsePrefixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
/// PrefixTypeOp /// PrefixTypeOp
/// <- QUESTIONMARK /// <- QUESTIONMARK
/// / KEYWORD_promise MINUSRARROW /// / KEYWORD_anyframe MINUSRARROW
/// / ArrayTypeStart (ByteAlign / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)* /// / ArrayTypeStart (ByteAlign / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)*
/// / PtrTypeStart (KEYWORD_align LPAREN Expr (COLON INTEGER COLON INTEGER)? RPAREN / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)* /// / PtrTypeStart (KEYWORD_align LPAREN Expr (COLON INTEGER COLON INTEGER)? RPAREN / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)*
fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
@ -2209,20 +2209,20 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
return &node.base; return &node.base;
} }
// TODO: Returning a PromiseType instead of PrefixOp makes casting and setting .rhs or // TODO: Returning a AnyFrameType instead of PrefixOp makes casting and setting .rhs or
// .return_type more difficult for the caller (see parsePrefixOpExpr helper). // .return_type more difficult for the caller (see parsePrefixOpExpr helper).
// Consider making the PromiseType a member of PrefixOp and add a // Consider making the AnyFrameType a member of PrefixOp and add a
// PrefixOp.PromiseType variant? // PrefixOp.AnyFrameType variant?
if (eatToken(it, .Keyword_promise)) |token| { if (eatToken(it, .Keyword_anyframe)) |token| {
const arrow = eatToken(it, .Arrow) orelse { const arrow = eatToken(it, .Arrow) orelse {
putBackToken(it, token); putBackToken(it, token);
return null; return null;
}; };
const node = try arena.create(Node.PromiseType); const node = try arena.create(Node.AnyFrameType);
node.* = Node.PromiseType{ node.* = Node.AnyFrameType{
.base = Node{ .id = .PromiseType }, .base = Node{ .id = .AnyFrameType },
.promise_token = token, .anyframe_token = token,
.result = Node.PromiseType.Result{ .result = Node.AnyFrameType.Result{
.arrow_token = arrow, .arrow_token = arrow,
.return_type = undefined, // set by caller .return_type = undefined, // set by caller
}, },
@ -2903,8 +2903,8 @@ fn parsePrefixOpExpr(
rightmost_op = rhs; rightmost_op = rhs;
} else break; } else break;
}, },
.PromiseType => { .AnyFrameType => {
const prom = rightmost_op.cast(Node.PromiseType).?; const prom = rightmost_op.cast(Node.AnyFrameType).?;
if (try opParseFn(arena, it, tree)) |rhs| { if (try opParseFn(arena, it, tree)) |rhs| {
prom.result.?.return_type = rhs; prom.result.?.return_type = rhs;
rightmost_op = rhs; rightmost_op = rhs;
@ -2922,8 +2922,8 @@ fn parsePrefixOpExpr(
.InvalidToken = AstError.InvalidToken{ .token = it.index }, .InvalidToken = AstError.InvalidToken{ .token = it.index },
}); });
}, },
.PromiseType => { .AnyFrameType => {
const prom = rightmost_op.cast(Node.PromiseType).?; const prom = rightmost_op.cast(Node.AnyFrameType).?;
prom.result.?.return_type = try expectNode(arena, it, tree, childParseFn, AstError{ prom.result.?.return_type = try expectNode(arena, it, tree, childParseFn, AstError{
.InvalidToken = AstError.InvalidToken{ .token = it.index }, .InvalidToken = AstError.InvalidToken{ .token = it.index },
}); });

View File

@ -2111,12 +2111,12 @@ test "zig fmt: coroutines" {
\\ suspend; \\ suspend;
\\ x += 1; \\ x += 1;
\\ suspend; \\ suspend;
\\ const p: promise->void = async simpleAsyncFn() catch unreachable; \\ const p: anyframe->void = async simpleAsyncFn() catch unreachable;
\\ await p; \\ await p;
\\} \\}
\\ \\
\\test "coroutine suspend, resume, cancel" { \\test "coroutine suspend, resume, cancel" {
\\ const p: promise = try async<std.debug.global_allocator> testAsyncSeq(); \\ const p: anyframe = try async<std.debug.global_allocator> testAsyncSeq();
\\ resume p; \\ resume p;
\\ cancel p; \\ cancel p;
\\} \\}

View File

@ -1205,15 +1205,15 @@ fn renderExpression(
} }
}, },
ast.Node.Id.PromiseType => { ast.Node.Id.AnyFrameType => {
const promise_type = @fieldParentPtr(ast.Node.PromiseType, "base", base); const anyframe_type = @fieldParentPtr(ast.Node.AnyFrameType, "base", base);
if (promise_type.result) |result| { if (anyframe_type.result) |result| {
try renderToken(tree, stream, promise_type.promise_token, indent, start_col, Space.None); // promise try renderToken(tree, stream, anyframe_type.anyframe_token, indent, start_col, Space.None); // anyframe
try renderToken(tree, stream, result.arrow_token, indent, start_col, Space.None); // -> try renderToken(tree, stream, result.arrow_token, indent, start_col, Space.None); // ->
return renderExpression(allocator, stream, tree, indent, start_col, result.return_type, space); return renderExpression(allocator, stream, tree, indent, start_col, result.return_type, space);
} else { } else {
return renderToken(tree, stream, promise_type.promise_token, indent, start_col, space); // promise return renderToken(tree, stream, anyframe_type.anyframe_token, indent, start_col, space); // anyframe
} }
}, },

View File

@ -15,6 +15,7 @@ pub const Token = struct {
Keyword{ .bytes = "align", .id = Id.Keyword_align }, Keyword{ .bytes = "align", .id = Id.Keyword_align },
Keyword{ .bytes = "allowzero", .id = Id.Keyword_allowzero }, Keyword{ .bytes = "allowzero", .id = Id.Keyword_allowzero },
Keyword{ .bytes = "and", .id = Id.Keyword_and }, Keyword{ .bytes = "and", .id = Id.Keyword_and },
Keyword{ .bytes = "anyframe", .id = Id.Keyword_anyframe },
Keyword{ .bytes = "asm", .id = Id.Keyword_asm }, Keyword{ .bytes = "asm", .id = Id.Keyword_asm },
Keyword{ .bytes = "async", .id = Id.Keyword_async }, Keyword{ .bytes = "async", .id = Id.Keyword_async },
Keyword{ .bytes = "await", .id = Id.Keyword_await }, Keyword{ .bytes = "await", .id = Id.Keyword_await },
@ -42,7 +43,6 @@ pub const Token = struct {
Keyword{ .bytes = "or", .id = Id.Keyword_or }, Keyword{ .bytes = "or", .id = Id.Keyword_or },
Keyword{ .bytes = "orelse", .id = Id.Keyword_orelse }, Keyword{ .bytes = "orelse", .id = Id.Keyword_orelse },
Keyword{ .bytes = "packed", .id = Id.Keyword_packed }, Keyword{ .bytes = "packed", .id = Id.Keyword_packed },
Keyword{ .bytes = "promise", .id = Id.Keyword_promise },
Keyword{ .bytes = "pub", .id = Id.Keyword_pub }, Keyword{ .bytes = "pub", .id = Id.Keyword_pub },
Keyword{ .bytes = "resume", .id = Id.Keyword_resume }, Keyword{ .bytes = "resume", .id = Id.Keyword_resume },
Keyword{ .bytes = "return", .id = Id.Keyword_return }, Keyword{ .bytes = "return", .id = Id.Keyword_return },
@ -174,7 +174,7 @@ pub const Token = struct {
Keyword_or, Keyword_or,
Keyword_orelse, Keyword_orelse,
Keyword_packed, Keyword_packed,
Keyword_promise, Keyword_anyframe,
Keyword_pub, Keyword_pub,
Keyword_resume, Keyword_resume,
Keyword_return, Keyword_return,

View File

@ -177,11 +177,11 @@ fn testUnion() void {
expect(TypeId(typeinfo_info) == TypeId.Union); expect(TypeId(typeinfo_info) == TypeId.Union);
expect(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto); expect(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto);
expect(typeinfo_info.Union.tag_type.? == TypeId); expect(typeinfo_info.Union.tag_type.? == TypeId);
expect(typeinfo_info.Union.fields.len == 25); expect(typeinfo_info.Union.fields.len == 26);
expect(typeinfo_info.Union.fields[4].enum_field != null); expect(typeinfo_info.Union.fields[4].enum_field != null);
expect(typeinfo_info.Union.fields[4].enum_field.?.value == 4); expect(typeinfo_info.Union.fields[4].enum_field.?.value == 4);
expect(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int)); expect(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int));
expect(typeinfo_info.Union.decls.len == 20); expect(typeinfo_info.Union.decls.len == 21);
const TestNoTagUnion = union { const TestNoTagUnion = union {
Foo: void, Foo: void,
@ -280,6 +280,25 @@ fn testVector() void {
expect(vec_info.Vector.child == i32); expect(vec_info.Vector.child == i32);
} }
test "type info: anyframe and anyframe->T" {
testAnyFrame();
comptime testAnyFrame();
}
fn testAnyFrame() void {
{
const anyframe_info = @typeInfo(anyframe->i32);
expect(TypeId(anyframe_info) == .AnyFrame);
expect(anyframe_info.AnyFrame.child.? == i32);
}
{
const anyframe_info = @typeInfo(anyframe);
expect(TypeId(anyframe_info) == .AnyFrame);
expect(anyframe_info.AnyFrame.child == null);
}
}
test "type info: optional field unwrapping" { test "type info: optional field unwrapping" {
const Struct = struct { const Struct = struct {
cdOffset: u32, cdOffset: u32,