Commit e85cd616ef

Timon Kruiper <timonkruiper@gmail.com>
2021-04-07 14:55:11
stage2: implement builtin function hasDecl
1 parent a97efbd
Changed files (3)
src/AstGen.zig
@@ -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,
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();
src/zir.zig
@@ -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,