| author | |
| committer | |
| log | 6b4f6ebd89c4788fde09dd5cde17f3cb54c6c656 |
| tree | 890e2c1ad40f4baee0d5728afe3eecf5685f2ccf |
| parent | 06909ceaab8ecb33d1f41049870797a3ae721610 |
5 files changed, 63 insertions(+), 7 deletions(-)
src/all_types.hpp+2-1| ... | ... | @@ -1292,6 +1292,7 @@ enum BuiltinFnId { |
| 1292 | 1292 | BuiltinFnIdMemberCount, |
| 1293 | 1293 | BuiltinFnIdMemberType, |
| 1294 | 1294 | BuiltinFnIdMemberName, |
| 1295 | BuiltinFnIdField, | |
| 1295 | 1296 | BuiltinFnIdTypeof, |
| 1296 | 1297 | BuiltinFnIdAddWithOverflow, |
| 1297 | 1298 | BuiltinFnIdSubWithOverflow, |
| ... | ... | @@ -2225,7 +2226,7 @@ struct IrInstructionFieldPtr { |
| 2225 | 2226 | IrInstruction base; |
| 2226 | 2227 | |
| 2227 | 2228 | IrInstruction *container_ptr; |
| 2228 | Buf *field_name; | |
| 2229 | IrInstruction *field_name_expr; | |
| 2229 | 2230 | bool is_const; |
| 2230 | 2231 | }; |
| 2231 | 2232 |
src/codegen.cpp+1-1| ... | ... | @@ -6114,6 +6114,7 @@ static void define_builtin_fns(CodeGen *g) { |
| 6114 | 6114 | create_builtin_fn(g, BuiltinFnIdMemberCount, "memberCount", 1); |
| 6115 | 6115 | create_builtin_fn(g, BuiltinFnIdMemberType, "memberType", 2); |
| 6116 | 6116 | create_builtin_fn(g, BuiltinFnIdMemberName, "memberName", 2); |
| 6117 | create_builtin_fn(g, BuiltinFnIdField, "field", 2); | |
| 6117 | 6118 | create_builtin_fn(g, BuiltinFnIdTypeof, "typeOf", 1); // TODO rename to TypeOf |
| 6118 | 6119 | create_builtin_fn(g, BuiltinFnIdAddWithOverflow, "addWithOverflow", 4); |
| 6119 | 6120 | create_builtin_fn(g, BuiltinFnIdSubWithOverflow, "subWithOverflow", 4); |
| ... | ... | @@ -7185,4 +7186,3 @@ PackageTableEntry *codegen_create_package(CodeGen *g, const char *root_src_dir, |
| 7185 | 7186 | } |
| 7186 | 7187 | return pkg; |
| 7187 | 7188 | } |
| 7188 |
src/ir.cpp+34-4| ... | ... | @@ -1033,18 +1033,26 @@ static IrInstruction *ir_build_elem_ptr_from(IrBuilder *irb, IrInstruction *old_ |
| 1033 | 1033 | return new_instruction; |
| 1034 | 1034 | } |
| 1035 | 1035 | |
| 1036 | static IrInstruction *ir_build_field_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, | |
| 1037 | IrInstruction *container_ptr, Buf *field_name) | |
| 1036 | static IrInstruction *ir_build_field_ptr_inner(IrBuilder *irb, Scope *scope, AstNode *source_node, | |
| 1037 | IrInstruction *container_ptr, IrInstruction *field_name_expr) | |
| 1038 | 1038 | { |
| 1039 | 1039 | IrInstructionFieldPtr *instruction = ir_build_instruction<IrInstructionFieldPtr>(irb, scope, source_node); |
| 1040 | 1040 | instruction->container_ptr = container_ptr; |
| 1041 | instruction->field_name = field_name; | |
| 1041 | instruction->field_name_expr = field_name_expr; | |
| 1042 | 1042 | |
| 1043 | 1043 | ir_ref_instruction(container_ptr, irb->current_basic_block); |
| 1044 | ir_ref_instruction(field_name_expr, irb->current_basic_block); | |
| 1044 | 1045 | |
| 1045 | 1046 | return &instruction->base; |
| 1046 | 1047 | } |
| 1047 | 1048 | |
| 1049 | static IrInstruction *ir_build_field_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, | |
| 1050 | IrInstruction *container_ptr, Buf *field_name) | |
| 1051 | { | |
| 1052 | IrInstruction *field_name_expr = ir_build_const_str_lit(irb, scope, source_node, field_name); | |
| 1053 | return ir_build_field_ptr_inner(irb, scope, source_node, container_ptr, field_name_expr); | |
| 1054 | } | |
| 1055 | ||
| 1048 | 1056 | static IrInstruction *ir_build_struct_field_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 1049 | 1057 | IrInstruction *struct_ptr, TypeStructField *field) |
| 1050 | 1058 | { |
| ... | ... | @@ -4015,6 +4023,24 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 4015 | 4023 | |
| 4016 | 4024 | return ir_build_member_name(irb, scope, node, arg0_value, arg1_value); |
| 4017 | 4025 | } |
| 4026 | case BuiltinFnIdField: | |
| 4027 | { | |
| 4028 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | |
| 4029 | IrInstruction *arg0_value = ir_gen_node_extra(irb, arg0_node, scope, LVAL_PTR); | |
| 4030 | if (arg0_value == irb->codegen->invalid_instruction) | |
| 4031 | return arg0_value; | |
| 4032 | ||
| 4033 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | |
| 4034 | IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); | |
| 4035 | if (arg1_value == irb->codegen->invalid_instruction) | |
| 4036 | return arg1_value; | |
| 4037 | ||
| 4038 | IrInstruction *ptr_instruction = ir_build_field_ptr_inner(irb, scope, node, arg0_value, arg1_value); | |
| 4039 | //if (lval.is_ptr) | |
| 4040 | // return ptr_instruction; | |
| 4041 | ||
| 4042 | return ir_build_load_ptr(irb, scope, node, ptr_instruction); | |
| 4043 | } | |
| 4018 | 4044 | case BuiltinFnIdBreakpoint: |
| 4019 | 4045 | return ir_build_breakpoint(irb, scope, node); |
| 4020 | 4046 | case BuiltinFnIdReturnAddress: |
| ... | ... | @@ -13458,7 +13484,11 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 13458 | 13484 | zig_unreachable(); |
| 13459 | 13485 | } |
| 13460 | 13486 | |
| 13461 | Buf *field_name = field_ptr_instruction->field_name; | |
| 13487 | IrInstruction *field_name_expr = field_ptr_instruction->field_name_expr->other; | |
| 13488 | Buf *field_name = ir_resolve_str(ira, field_name_expr); | |
| 13489 | if (!field_name) | |
| 13490 | return ira->codegen->builtin_types.entry_invalid; | |
| 13491 | ||
| 13462 | 13492 | AstNode *source_node = field_ptr_instruction->base.source_node; |
| 13463 | 13493 | |
| 13464 | 13494 | if (type_is_invalid(container_type)) { |
src/ir_print.cpp+2-1| ... | ... | @@ -360,7 +360,8 @@ static void ir_print_ptr_type_child(IrPrint *irp, IrInstructionPtrTypeChild *ins |
| 360 | 360 | static void ir_print_field_ptr(IrPrint *irp, IrInstructionFieldPtr *instruction) { |
| 361 | 361 | fprintf(irp->f, "fieldptr "); |
| 362 | 362 | ir_print_other_instruction(irp, instruction->container_ptr); |
| 363 | fprintf(irp->f, ".%s", buf_ptr(instruction->field_name)); | |
| 363 | fprintf(irp->f, "."); | |
| 364 | ir_print_other_instruction(irp, instruction->field_name_expr); | |
| 364 | 365 | } |
| 365 | 366 | |
| 366 | 367 | static void ir_print_struct_field_ptr(IrPrint *irp, IrInstructionStructFieldPtr *instruction) { |
test/cases/reflection.zig+24| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | 1 | const assert = @import("std").debug.assert; |
| 2 | 2 | const mem = @import("std").mem; |
| 3 | const reflection = this; | |
| 3 | 4 | |
| 4 | 5 | test "reflection: array, pointer, nullable, error union type child" { |
| 5 | 6 | comptime { |
| ... | ... | @@ -56,7 +57,30 @@ test "reflection: enum member types and names" { |
| 56 | 57 | |
| 57 | 58 | } |
| 58 | 59 | |
| 60 | test "reflection: @field" { | |
| 61 | const f = Foo { | |
| 62 | .one = 42, | |
| 63 | .two = true, | |
| 64 | .three = void{}, | |
| 65 | }; | |
| 66 | ||
| 67 | assert(f.one == f.one); | |
| 68 | assert(@field(f, "o" ++ "ne") == f.one); | |
| 69 | assert(@field(f, "t" ++ "wo") == f.two); | |
| 70 | assert(@field(f, "th" ++ "ree") == f.three); | |
| 71 | assert(@field(Foo, "const" ++ "ant") == Foo.constant); | |
| 72 | assert(@field(Bar, "O" ++ "ne") == Bar.One); | |
| 73 | assert(@field(Bar, "O" ++ "ne") == Bar.One); | |
| 74 | assert(@field(Bar, "O" ++ "ne") == Bar.One); | |
| 75 | assert(@field(Bar, "T" ++ "wo") == Bar.Two); | |
| 76 | assert(@field(Bar, "Th" ++ "ree") == Bar.Three); | |
| 77 | assert(@field(Bar, "F" ++ "our") == Bar.Four); | |
| 78 | assert(@field(reflection, "dum" ++ "my")(true, 1, 2) == dummy(true, 1, 2)); | |
| 79 | } | |
| 80 | ||
| 59 | 81 | const Foo = struct { |
| 82 | const constant = 52; | |
| 83 | ||
| 60 | 84 | one: i32, |
| 61 | 85 | two: bool, |
| 62 | 86 | three: void, |