authorgravatar for timonkruiper@gmail.comTimon Kruiper <timonkruiper@gmail.com> 2021-04-07 14:55:11+02:00
committergravatar for timonkruiper@gmail.comTimon Kruiper <timonkruiper@gmail.com> 2021-04-08 14:23:18+02:00
loge85cd616ef6439fdb9e7ac118251bb7c2296e553
treeb3661a2f77897e6fcd2483838713193ed0784a5c
parenta97efbd1850cbf12dbf9332f7da2652385a38cd6

stage2: implement builtin function hasDecl


3 files changed, 50 insertions(+), 1 deletions(-)

src/AstGen.zig+11-1
...@@ -1245,6 +1245,7 @@ fn blockExprStmts(...@@ -1245,6 +1245,7 @@ fn blockExprStmts(
1245 .fn_type_var_args,1245 .fn_type_var_args,
1246 .fn_type_cc,1246 .fn_type_cc,
1247 .fn_type_cc_var_args,1247 .fn_type_cc_var_args,
1248 .has_decl,
1248 .int,1249 .int,
1249 .float,1250 .float,
1250 .float128,1251 .float128,
...@@ -4159,6 +4160,16 @@ fn builtinCall(...@@ -4159,6 +4160,16 @@ fn builtinCall(
4159 return rvalue(gz, scope, rl, .void_value, node);4160 return rvalue(gz, scope, rl, .void_value, node);
4160 },4161 },
41614162
4163 .has_decl => {
4164 const container_type = try typeExpr(gz, scope, params[0]);
4165 const name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[1]);
4166 const result = try gz.addPlNode(.has_decl, node, zir.Inst.Bin{
4167 .lhs = container_type,
4168 .rhs = name,
4169 });
4170 return rvalue(gz, scope, rl, result, node);
4171 },
4172
4162 .add_with_overflow,4173 .add_with_overflow,
4163 .align_cast,4174 .align_cast,
4164 .align_of,4175 .align_of,
...@@ -4191,7 +4202,6 @@ fn builtinCall(...@@ -4191,7 +4202,6 @@ fn builtinCall(
4191 .fence,4202 .fence,
4192 .field_parent_ptr,4203 .field_parent_ptr,
4193 .float_to_int,4204 .float_to_int,
4194 .has_decl,
4195 .has_field,4205 .has_field,
4196 .int_to_float,4206 .int_to_float,
4197 .int_to_ptr,4207 .int_to_ptr,
src/Sema.zig+34
...@@ -199,6 +199,7 @@ pub fn analyzeBody(...@@ -199,6 +199,7 @@ pub fn analyzeBody(
199 .fn_type_cc => try sema.zirFnTypeCc(block, inst, false),199 .fn_type_cc => try sema.zirFnTypeCc(block, inst, false),
200 .fn_type_cc_var_args => try sema.zirFnTypeCc(block, inst, true),200 .fn_type_cc_var_args => try sema.zirFnTypeCc(block, inst, true),
201 .fn_type_var_args => try sema.zirFnType(block, inst, true),201 .fn_type_var_args => try sema.zirFnType(block, inst, true),
202 .has_decl => try sema.zirHasDecl(block, inst),
202 .import => try sema.zirImport(block, inst),203 .import => try sema.zirImport(block, inst),
203 .indexable_ptr_len => try sema.zirIndexablePtrLen(block, inst),204 .indexable_ptr_len => try sema.zirIndexablePtrLen(block, inst),
204 .int => try sema.zirInt(block, inst),205 .int => try sema.zirInt(block, inst),
...@@ -3624,6 +3625,39 @@ fn validateSwitchNoRange(...@@ -3624,6 +3625,39 @@ fn validateSwitchNoRange(
3624 return sema.mod.failWithOwnedErrorMsg(&block.base, msg);3625 return sema.mod.failWithOwnedErrorMsg(&block.base, msg);
3625}3626}
36263627
3628fn zirHasDecl(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
3629 const tracy = trace(@src());
3630 defer tracy.end();
3631
3632 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
3633 const extra = sema.code.extraData(zir.Inst.Bin, inst_data.payload_index).data;
3634 const src = inst_data.src();
3635 const lhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
3636 const rhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
3637 const container_type = try sema.resolveType(block, lhs_src, extra.lhs);
3638 const decl_name = try sema.resolveConstString(block, rhs_src, extra.rhs);
3639
3640 const maybe_scope = container_type.getContainerScope();
3641 if (maybe_scope == null) {
3642 return sema.mod.fail(
3643 &block.base,
3644 src,
3645 "expected container (struct, enum, or union), found '{}'",
3646 .{container_type},
3647 );
3648 }
3649
3650 const found = blk: {
3651 for (maybe_scope.?.decls.items()) |kv| {
3652 if (mem.eql(u8, mem.spanZ(kv.key.name), decl_name))
3653 break :blk true;
3654 }
3655 break :blk false;
3656 };
3657
3658 return sema.mod.constBool(sema.arena, src, found);
3659}
3660
3627fn zirImport(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {3661fn zirImport(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
3628 const tracy = trace(@src());3662 const tracy = trace(@src());
3629 defer tracy.end();3663 defer tracy.end();
src/zir.zig+5
...@@ -364,6 +364,9 @@ pub const Inst = struct {...@@ -364,6 +364,9 @@ pub const Inst = struct {
364 fn_type_cc,364 fn_type_cc,
365 /// Same as `fn_type_cc` but the function is variadic.365 /// Same as `fn_type_cc` but the function is variadic.
366 fn_type_cc_var_args,366 fn_type_cc_var_args,
367 /// Determines whether a container has a declaration matching name.
368 /// Uses the `pl_node` union field. Payload is `Bin`.
369 has_decl,
367 /// `@import(operand)`.370 /// `@import(operand)`.
368 /// Uses the `un_node` field.371 /// Uses the `un_node` field.
369 import,372 import,
...@@ -751,6 +754,7 @@ pub const Inst = struct {...@@ -751,6 +754,7 @@ pub const Inst = struct {
751 .fn_type_var_args,754 .fn_type_var_args,
752 .fn_type_cc,755 .fn_type_cc,
753 .fn_type_cc_var_args,756 .fn_type_cc_var_args,
757 .has_decl,
754 .int,758 .int,
755 .float,759 .float,
756 .float128,760 .float128,
...@@ -1681,6 +1685,7 @@ const Writer = struct {...@@ -1681,6 +1685,7 @@ const Writer = struct {
1681 .cmp_gt,1685 .cmp_gt,
1682 .cmp_neq,1686 .cmp_neq,
1683 .div,1687 .div,
1688 .has_decl,
1684 .mod_rem,1689 .mod_rem,
1685 .shl,1690 .shl,
1686 .shr,1691 .shr,