| 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,6 +1292,7 @@ enum BuiltinFnId { |
| 1292 | BuiltinFnIdMemberCount, | 1292 | BuiltinFnIdMemberCount, |
| 1293 | BuiltinFnIdMemberType, | 1293 | BuiltinFnIdMemberType, |
| 1294 | BuiltinFnIdMemberName, | 1294 | BuiltinFnIdMemberName, |
| 1295 | BuiltinFnIdField, | ||
| 1295 | BuiltinFnIdTypeof, | 1296 | BuiltinFnIdTypeof, |
| 1296 | BuiltinFnIdAddWithOverflow, | 1297 | BuiltinFnIdAddWithOverflow, |
| 1297 | BuiltinFnIdSubWithOverflow, | 1298 | BuiltinFnIdSubWithOverflow, |
| ... | @@ -2225,7 +2226,7 @@ struct IrInstructionFieldPtr { | ... | @@ -2225,7 +2226,7 @@ struct IrInstructionFieldPtr { |
| 2225 | IrInstruction base; | 2226 | IrInstruction base; |
| 2226 | 2227 | ||
| 2227 | IrInstruction *container_ptr; | 2228 | IrInstruction *container_ptr; |
| 2228 | Buf *field_name; | 2229 | IrInstruction *field_name_expr; |
| 2229 | bool is_const; | 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,6 +6114,7 @@ static void define_builtin_fns(CodeGen *g) { |
| 6114 | create_builtin_fn(g, BuiltinFnIdMemberCount, "memberCount", 1); | 6114 | create_builtin_fn(g, BuiltinFnIdMemberCount, "memberCount", 1); |
| 6115 | create_builtin_fn(g, BuiltinFnIdMemberType, "memberType", 2); | 6115 | create_builtin_fn(g, BuiltinFnIdMemberType, "memberType", 2); |
| 6116 | create_builtin_fn(g, BuiltinFnIdMemberName, "memberName", 2); | 6116 | create_builtin_fn(g, BuiltinFnIdMemberName, "memberName", 2); |
| 6117 | create_builtin_fn(g, BuiltinFnIdField, "field", 2); | ||
| 6117 | create_builtin_fn(g, BuiltinFnIdTypeof, "typeOf", 1); // TODO rename to TypeOf | 6118 | create_builtin_fn(g, BuiltinFnIdTypeof, "typeOf", 1); // TODO rename to TypeOf |
| 6118 | create_builtin_fn(g, BuiltinFnIdAddWithOverflow, "addWithOverflow", 4); | 6119 | create_builtin_fn(g, BuiltinFnIdAddWithOverflow, "addWithOverflow", 4); |
| 6119 | create_builtin_fn(g, BuiltinFnIdSubWithOverflow, "subWithOverflow", 4); | 6120 | create_builtin_fn(g, BuiltinFnIdSubWithOverflow, "subWithOverflow", 4); |
| ... | @@ -7185,4 +7186,3 @@ PackageTableEntry *codegen_create_package(CodeGen *g, const char *root_src_dir, | ... | @@ -7185,4 +7186,3 @@ PackageTableEntry *codegen_create_package(CodeGen *g, const char *root_src_dir, |
| 7185 | } | 7186 | } |
| 7186 | return pkg; | 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,18 +1033,26 @@ static IrInstruction *ir_build_elem_ptr_from(IrBuilder *irb, IrInstruction *old_ |
| 1033 | return new_instruction; | 1033 | return new_instruction; |
| 1034 | } | 1034 | } |
| 1035 | 1035 | ||
| 1036 | static IrInstruction *ir_build_field_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, | 1036 | static IrInstruction *ir_build_field_ptr_inner(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 1037 | IrInstruction *container_ptr, Buf *field_name) | 1037 | IrInstruction *container_ptr, IrInstruction *field_name_expr) |
| 1038 | { | 1038 | { |
| 1039 | IrInstructionFieldPtr *instruction = ir_build_instruction<IrInstructionFieldPtr>(irb, scope, source_node); | 1039 | IrInstructionFieldPtr *instruction = ir_build_instruction<IrInstructionFieldPtr>(irb, scope, source_node); |
| 1040 | instruction->container_ptr = container_ptr; | 1040 | instruction->container_ptr = container_ptr; |
| 1041 | instruction->field_name = field_name; | 1041 | instruction->field_name_expr = field_name_expr; |
| 1042 | 1042 | ||
| 1043 | ir_ref_instruction(container_ptr, irb->current_basic_block); | 1043 | ir_ref_instruction(container_ptr, irb->current_basic_block); |
| 1044 | ir_ref_instruction(field_name_expr, irb->current_basic_block); | ||
| 1044 | 1045 | ||
| 1045 | return &instruction->base; | 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 | static IrInstruction *ir_build_struct_field_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, | 1056 | static IrInstruction *ir_build_struct_field_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 1049 | IrInstruction *struct_ptr, TypeStructField *field) | 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,6 +4023,24 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 4015 | 4023 | ||
| 4016 | return ir_build_member_name(irb, scope, node, arg0_value, arg1_value); | 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 | case BuiltinFnIdBreakpoint: | 4044 | case BuiltinFnIdBreakpoint: |
| 4019 | return ir_build_breakpoint(irb, scope, node); | 4045 | return ir_build_breakpoint(irb, scope, node); |
| 4020 | case BuiltinFnIdReturnAddress: | 4046 | case BuiltinFnIdReturnAddress: |
| ... | @@ -13458,7 +13484,11 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru | ... | @@ -13458,7 +13484,11 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 13458 | zig_unreachable(); | 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 | AstNode *source_node = field_ptr_instruction->base.source_node; | 13492 | AstNode *source_node = field_ptr_instruction->base.source_node; |
| 13463 | 13493 | ||
| 13464 | if (type_is_invalid(container_type)) { | 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,7 +360,8 @@ static void ir_print_ptr_type_child(IrPrint *irp, IrInstructionPtrTypeChild *ins |
| 360 | static void ir_print_field_ptr(IrPrint *irp, IrInstructionFieldPtr *instruction) { | 360 | static void ir_print_field_ptr(IrPrint *irp, IrInstructionFieldPtr *instruction) { |
| 361 | fprintf(irp->f, "fieldptr "); | 361 | fprintf(irp->f, "fieldptr "); |
| 362 | ir_print_other_instruction(irp, instruction->container_ptr); | 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 | static void ir_print_struct_field_ptr(IrPrint *irp, IrInstructionStructFieldPtr *instruction) { | 367 | static void ir_print_struct_field_ptr(IrPrint *irp, IrInstructionStructFieldPtr *instruction) { |
test/cases/reflection.zig+24| ... | @@ -1,5 +1,6 @@ | ... | @@ -1,5 +1,6 @@ |
| 1 | const assert = @import("std").debug.assert; | 1 | const assert = @import("std").debug.assert; |
| 2 | const mem = @import("std").mem; | 2 | const mem = @import("std").mem; |
| 3 | const reflection = this; | ||
| 3 | 4 | ||
| 4 | test "reflection: array, pointer, nullable, error union type child" { | 5 | test "reflection: array, pointer, nullable, error union type child" { |
| 5 | comptime { | 6 | comptime { |
| ... | @@ -56,7 +57,30 @@ test "reflection: enum member types and names" { | ... | @@ -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 | const Foo = struct { | 81 | const Foo = struct { |
| 82 | const constant = 52; | ||
| 83 | |||
| 60 | one: i32, | 84 | one: i32, |
| 61 | two: bool, | 85 | two: bool, |
| 62 | three: void, | 86 | three: void, |