stage2: implement builtin function hasDecl
This commit is contained in:
@@ -1245,6 +1245,7 @@ fn blockExprStmts(
|
||||
.fn_type_var_args,
|
||||
.fn_type_cc,
|
||||
.fn_type_cc_var_args,
|
||||
.has_decl,
|
||||
.int,
|
||||
.float,
|
||||
.float128,
|
||||
@@ -4159,6 +4160,16 @@ fn builtinCall(
|
||||
return rvalue(gz, scope, rl, .void_value, node);
|
||||
},
|
||||
|
||||
.has_decl => {
|
||||
const container_type = try typeExpr(gz, scope, params[0]);
|
||||
const name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[1]);
|
||||
const result = try gz.addPlNode(.has_decl, node, zir.Inst.Bin{
|
||||
.lhs = container_type,
|
||||
.rhs = name,
|
||||
});
|
||||
return rvalue(gz, scope, rl, result, node);
|
||||
},
|
||||
|
||||
.add_with_overflow,
|
||||
.align_cast,
|
||||
.align_of,
|
||||
@@ -4191,7 +4202,6 @@ fn builtinCall(
|
||||
.fence,
|
||||
.field_parent_ptr,
|
||||
.float_to_int,
|
||||
.has_decl,
|
||||
.has_field,
|
||||
.int_to_float,
|
||||
.int_to_ptr,
|
||||
|
||||
34
src/Sema.zig
34
src/Sema.zig
@@ -199,6 +199,7 @@ pub fn analyzeBody(
|
||||
.fn_type_cc => try sema.zirFnTypeCc(block, inst, false),
|
||||
.fn_type_cc_var_args => try sema.zirFnTypeCc(block, inst, true),
|
||||
.fn_type_var_args => try sema.zirFnType(block, inst, true),
|
||||
.has_decl => try sema.zirHasDecl(block, inst),
|
||||
.import => try sema.zirImport(block, inst),
|
||||
.indexable_ptr_len => try sema.zirIndexablePtrLen(block, inst),
|
||||
.int => try sema.zirInt(block, inst),
|
||||
@@ -3624,6 +3625,39 @@ fn validateSwitchNoRange(
|
||||
return sema.mod.failWithOwnedErrorMsg(&block.base, msg);
|
||||
}
|
||||
|
||||
fn zirHasDecl(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
|
||||
const extra = sema.code.extraData(zir.Inst.Bin, inst_data.payload_index).data;
|
||||
const src = inst_data.src();
|
||||
const lhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
|
||||
const rhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
|
||||
const container_type = try sema.resolveType(block, lhs_src, extra.lhs);
|
||||
const decl_name = try sema.resolveConstString(block, rhs_src, extra.rhs);
|
||||
|
||||
const maybe_scope = container_type.getContainerScope();
|
||||
if (maybe_scope == null) {
|
||||
return sema.mod.fail(
|
||||
&block.base,
|
||||
src,
|
||||
"expected container (struct, enum, or union), found '{}'",
|
||||
.{container_type},
|
||||
);
|
||||
}
|
||||
|
||||
const found = blk: {
|
||||
for (maybe_scope.?.decls.items()) |kv| {
|
||||
if (mem.eql(u8, mem.spanZ(kv.key.name), decl_name))
|
||||
break :blk true;
|
||||
}
|
||||
break :blk false;
|
||||
};
|
||||
|
||||
return sema.mod.constBool(sema.arena, src, found);
|
||||
}
|
||||
|
||||
fn zirImport(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
@@ -364,6 +364,9 @@ pub const Inst = struct {
|
||||
fn_type_cc,
|
||||
/// Same as `fn_type_cc` but the function is variadic.
|
||||
fn_type_cc_var_args,
|
||||
/// Determines whether a container has a declaration matching name.
|
||||
/// Uses the `pl_node` union field. Payload is `Bin`.
|
||||
has_decl,
|
||||
/// `@import(operand)`.
|
||||
/// Uses the `un_node` field.
|
||||
import,
|
||||
@@ -751,6 +754,7 @@ pub const Inst = struct {
|
||||
.fn_type_var_args,
|
||||
.fn_type_cc,
|
||||
.fn_type_cc_var_args,
|
||||
.has_decl,
|
||||
.int,
|
||||
.float,
|
||||
.float128,
|
||||
@@ -1681,6 +1685,7 @@ const Writer = struct {
|
||||
.cmp_gt,
|
||||
.cmp_neq,
|
||||
.div,
|
||||
.has_decl,
|
||||
.mod_rem,
|
||||
.shl,
|
||||
.shr,
|
||||
|
||||
Reference in New Issue
Block a user