zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit a31b23c46ba2a8c28df01adc1aa0b4d878b9a5cf (tree)
parent dc8b011d616991da166ad83795bf0b7e90471bd3
Author: Andrew Kelley <superjoe30@gmail.com>
Date:   Fri,  3 Nov 2017 00:00:57 -0400

more compile-time type reflection

See #383

Diffstat:
Msrc-self-hosted/main.zig | 15+++++++++------
Msrc/ir.cpp | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Mtest/behavior.zig | 1+
Atest/cases/reflection.zig | 22++++++++++++++++++++++
4 files changed, 81 insertions(+), 6 deletions(-)

diff --git a/src-self-hosted/main.zig b/src-self-hosted/main.zig @@ -3,24 +3,28 @@ const io = @import("std").io; const os = @import("std").os; const heap = @import("std").mem; -// TODO: OutSteam and InStream interface -// TODO: move allocator to heap namespace // TODO: sync up CLI with c++ code +// TODO: concurrency +// TODO: ability to iterate over enums at compile time (for listing targets) error InvalidArgument; error MissingArg0; var arg0: []u8 = undefined; +var stderr_file: io.File = undefined; +const stderr = &stderr_file.out_stream; + pub fn main() -> %void { + stderr_file = %return io.getStdErr(); if (internal_main()) |_| { return; } else |err| { if (err == error.InvalidArgument) { - io.stderr.printf("\n") %% return err; - printUsage(&io.stderr) %% return err; + stderr.print("\n") %% return err; + printUsage(stderr) %% return err; } else { - io.stderr.printf("{}\n", err) %% return err; + stderr.print("{}\n", err) %% return err; } return err; } @@ -266,7 +270,6 @@ fn printUsage(outstream: &io.OutStream) -> %void { \\ --test-cmd-bin appends test binary path to test cmd args \\ ); - %return outstream.flush(); } const ZIG_ZEN = diff --git a/src/ir.cpp b/src/ir.cpp @@ -11643,6 +11643,55 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru buf_ptr(&child_type->name), buf_ptr(field_name))); return ira->codegen->builtin_types.entry_invalid; } + } else if (child_type->id == TypeTableEntryIdErrorUnion) { + if (buf_eql_str(field_name, "Child")) { + bool ptr_is_const = true; + bool ptr_is_volatile = false; + return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, + create_const_type(ira->codegen, child_type->data.error.child_type), + ira->codegen->builtin_types.entry_type, + ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile); + } else { + ir_add_error(ira, &field_ptr_instruction->base, + buf_sprintf("type '%s' has no member called '%s'", + buf_ptr(&child_type->name), buf_ptr(field_name))); + return ira->codegen->builtin_types.entry_invalid; + } + } else if (child_type->id == TypeTableEntryIdMaybe) { + if (buf_eql_str(field_name, "Child")) { + bool ptr_is_const = true; + bool ptr_is_volatile = false; + return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, + create_const_type(ira->codegen, child_type->data.maybe.child_type), + ira->codegen->builtin_types.entry_type, + ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile); + } else { + ir_add_error(ira, &field_ptr_instruction->base, + buf_sprintf("type '%s' has no member called '%s'", + buf_ptr(&child_type->name), buf_ptr(field_name))); + return ira->codegen->builtin_types.entry_invalid; + } + } else if (child_type->id == TypeTableEntryIdFn) { + if (buf_eql_str(field_name, "ReturnType")) { + bool ptr_is_const = true; + bool ptr_is_volatile = false; + return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, + create_const_type(ira->codegen, child_type->data.fn.fn_type_id.return_type), + ira->codegen->builtin_types.entry_type, + ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile); + } else if (buf_eql_str(field_name, "is_var_args")) { + bool ptr_is_const = true; + bool ptr_is_volatile = false; + return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, + create_const_bool(ira->codegen, child_type->data.fn.fn_type_id.is_var_args), + ira->codegen->builtin_types.entry_bool, + ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile); + } else { + ir_add_error(ira, &field_ptr_instruction->base, + buf_sprintf("type '%s' has no member called '%s'", + buf_ptr(&child_type->name), buf_ptr(field_name))); + return ira->codegen->builtin_types.entry_invalid; + } } else { ir_add_error(ira, &field_ptr_instruction->base, buf_sprintf("type '%s' does not support field access", buf_ptr(&child_type->name))); diff --git a/test/behavior.zig b/test/behavior.zig @@ -29,6 +29,7 @@ comptime { _ = @import("cases/null.zig"); _ = @import("cases/pub_enum/index.zig"); _ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig"); + _ = @import("cases/reflection.zig"); _ = @import("cases/sizeof_and_typeof.zig"); _ = @import("cases/slice.zig"); _ = @import("cases/struct.zig"); diff --git a/test/cases/reflection.zig b/test/cases/reflection.zig @@ -0,0 +1,22 @@ +const assert = @import("std").debug.assert; +const mem = @import("std").mem; + +test "reflection: array, pointer, nullable, error union type child" { + comptime { + assert(([10]u8).Child == u8); + assert((&u8).Child == u8); + assert((%u8).Child == u8); + assert((?u8).Child == u8); + } +} + +test "reflection: function return type and var args" { + comptime { + assert(@typeOf(dummy).ReturnType == i32); + assert(!@typeOf(dummy).is_var_args); + assert(@typeOf(dummy_varargs).is_var_args); + } +} + +fn dummy() -> i32 { 1234 } +fn dummy_varargs(args: ...) {}