authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-11-03 00:00:57-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-11-03 00:00:57-04:00
loga31b23c46ba2a8c28df01adc1aa0b4d878b9a5cf
treeb9f978f1c930a4c251e876ea850b380de13bfa4b
parentdc8b011d616991da166ad83795bf0b7e90471bd3

more compile-time type reflection

See #383

4 files changed, 81 insertions(+), 6 deletions(-)

src-self-hosted/main.zig+9-6
......@@ -3,24 +3,28 @@ const io = @import("std").io;
33const os = @import("std").os;
44const heap = @import("std").mem;
55
6// TODO: OutSteam and InStream interface
7// TODO: move allocator to heap namespace
86// TODO: sync up CLI with c++ code
7// TODO: concurrency
8// TODO: ability to iterate over enums at compile time (for listing targets)
99
1010error InvalidArgument;
1111error MissingArg0;
1212
1313var arg0: []u8 = undefined;
1414
15var stderr_file: io.File = undefined;
16const stderr = &stderr_file.out_stream;
17
1518pub fn main() -> %void {
19 stderr_file = %return io.getStdErr();
1620 if (internal_main()) |_| {
1721 return;
1822 } else |err| {
1923 if (err == error.InvalidArgument) {
20 io.stderr.printf("\n") %% return err;
21 printUsage(&io.stderr) %% return err;
24 stderr.print("\n") %% return err;
25 printUsage(stderr) %% return err;
2226 } else {
23 io.stderr.printf("{}\n", err) %% return err;
27 stderr.print("{}\n", err) %% return err;
2428 }
2529 return err;
2630 }
......@@ -266,7 +270,6 @@ fn printUsage(outstream: &io.OutStream) -> %void {
266270 \\ --test-cmd-bin appends test binary path to test cmd args
267271 \\
268272 );
269 %return outstream.flush();
270273}
271274
272275const ZIG_ZEN =
src/ir.cpp+49
......@@ -11643,6 +11643,55 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru
1164311643 buf_ptr(&child_type->name), buf_ptr(field_name)));
1164411644 return ira->codegen->builtin_types.entry_invalid;
1164511645 }
11646 } else if (child_type->id == TypeTableEntryIdErrorUnion) {
11647 if (buf_eql_str(field_name, "Child")) {
11648 bool ptr_is_const = true;
11649 bool ptr_is_volatile = false;
11650 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
11651 create_const_type(ira->codegen, child_type->data.error.child_type),
11652 ira->codegen->builtin_types.entry_type,
11653 ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
11654 } else {
11655 ir_add_error(ira, &field_ptr_instruction->base,
11656 buf_sprintf("type '%s' has no member called '%s'",
11657 buf_ptr(&child_type->name), buf_ptr(field_name)));
11658 return ira->codegen->builtin_types.entry_invalid;
11659 }
11660 } else if (child_type->id == TypeTableEntryIdMaybe) {
11661 if (buf_eql_str(field_name, "Child")) {
11662 bool ptr_is_const = true;
11663 bool ptr_is_volatile = false;
11664 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
11665 create_const_type(ira->codegen, child_type->data.maybe.child_type),
11666 ira->codegen->builtin_types.entry_type,
11667 ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
11668 } else {
11669 ir_add_error(ira, &field_ptr_instruction->base,
11670 buf_sprintf("type '%s' has no member called '%s'",
11671 buf_ptr(&child_type->name), buf_ptr(field_name)));
11672 return ira->codegen->builtin_types.entry_invalid;
11673 }
11674 } else if (child_type->id == TypeTableEntryIdFn) {
11675 if (buf_eql_str(field_name, "ReturnType")) {
11676 bool ptr_is_const = true;
11677 bool ptr_is_volatile = false;
11678 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
11679 create_const_type(ira->codegen, child_type->data.fn.fn_type_id.return_type),
11680 ira->codegen->builtin_types.entry_type,
11681 ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
11682 } else if (buf_eql_str(field_name, "is_var_args")) {
11683 bool ptr_is_const = true;
11684 bool ptr_is_volatile = false;
11685 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base,
11686 create_const_bool(ira->codegen, child_type->data.fn.fn_type_id.is_var_args),
11687 ira->codegen->builtin_types.entry_bool,
11688 ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile);
11689 } else {
11690 ir_add_error(ira, &field_ptr_instruction->base,
11691 buf_sprintf("type '%s' has no member called '%s'",
11692 buf_ptr(&child_type->name), buf_ptr(field_name)));
11693 return ira->codegen->builtin_types.entry_invalid;
11694 }
1164611695 } else {
1164711696 ir_add_error(ira, &field_ptr_instruction->base,
1164811697 buf_sprintf("type '%s' does not support field access", buf_ptr(&child_type->name)));
test/behavior.zig+1
......@@ -29,6 +29,7 @@ comptime {
2929 _ = @import("cases/null.zig");
3030 _ = @import("cases/pub_enum/index.zig");
3131 _ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig");
32 _ = @import("cases/reflection.zig");
3233 _ = @import("cases/sizeof_and_typeof.zig");
3334 _ = @import("cases/slice.zig");
3435 _ = @import("cases/struct.zig");
test/cases/reflection.zig created+22
......@@ -0,0 +1,22 @@
1const assert = @import("std").debug.assert;
2const mem = @import("std").mem;
3
4test "reflection: array, pointer, nullable, error union type child" {
5 comptime {
6 assert(([10]u8).Child == u8);
7 assert((&u8).Child == u8);
8 assert((%u8).Child == u8);
9 assert((?u8).Child == u8);
10 }
11}
12
13test "reflection: function return type and var args" {
14 comptime {
15 assert(@typeOf(dummy).ReturnType == i32);
16 assert(!@typeOf(dummy).is_var_args);
17 assert(@typeOf(dummy_varargs).is_var_args);
18 }
19}
20
21fn dummy() -> i32 { 1234 }
22fn dummy_varargs(args: ...) {}