065_builtins2.zig 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. //
  2. // Zig has builtins for mathematical operations such as...
  3. //
  4. // @sqrt @sin @cos
  5. // @exp @log @floor
  6. //
  7. // ...and lots of type casting operations such as...
  8. //
  9. // @as @intToError @intToFloat
  10. // @intToPtr @ptrToInt @enumToInt
  11. //
  12. // Spending part of a rainy day skimming through the complete
  13. // list of builtins in the official Zig documentation wouldn't be
  14. // a bad use of your time. There are some seriously cool features
  15. // in there. Check out @call, @compileLog, @embedFile, and @src!
  16. //
  17. // ...
  18. //
  19. // For now, we're going to complete our examination of builtins
  20. // by exploring just THREE of Zig's MANY introspection abilities:
  21. //
  22. // 1. @This() type
  23. //
  24. // Returns the innermost struct, enum, or union that a function
  25. // call is inside.
  26. //
  27. // 2. @typeInfo(comptime T: type) @import("std").builtin.TypeInfo
  28. //
  29. // Returns information about any type in a TypeInfo union which
  30. // will contain different information depending on which type
  31. // you're examining.
  32. //
  33. // 3. @TypeOf(...) type
  34. //
  35. // Returns the type common to all input parameters (each of which
  36. // may be any expression). The type is resolved using the same
  37. // "peer type resolution" process the compiler itself uses when
  38. // inferring types.
  39. //
  40. // (Notice how the two functions which return types start with
  41. // uppercase letters? This is a standard naming practice in Zig.)
  42. //
  43. const print = import(std).debug.print; // Oops!
  44. const Narcissus = struct {
  45. me: *Narcissus = undefined,
  46. myself: *Narcissus = undefined,
  47. echo: void = undefined,
  48. fn fetchTheMostBeautifulType() type {
  49. return @This();
  50. }
  51. };
  52. pub fn main() void {
  53. var narcissus: Narcissus = Narcissus{};
  54. // Oops! We cannot leave the 'me' and 'myself' fields
  55. // undefined. Please set them here:
  56. ??? = &narcissus;
  57. ??? = &narcissus;
  58. // This determines a "peer type" from three separate
  59. // references (they just happen to all be the same object).
  60. const T1 = @TypeOf(narcissus, narcissus.me.*, narcissus.myself.*);
  61. // Oh dear, we seem to have done something wrong when calling
  62. // this function. It is namespaced to the struct, but doesn't
  63. // use the method syntax (there's no self parameter). Please
  64. // fix this call:
  65. const T2 = narcissus.fetchTheMostBeautifulType();
  66. print("A {} loves all {}es. ", .{ T1, T2 });
  67. // His final words as he was looking in
  68. // those waters he habitually watched
  69. // were these:
  70. // "Alas, my beloved boy, in vain!"
  71. // The place gave every word back in reply.
  72. // He cried:
  73. // "Farewell."
  74. // And Echo called:
  75. // "Farewell!"
  76. //
  77. // --Ovid, The Metamorphoses
  78. // translated by Ian Johnston
  79. print("He has room in his heart for:", .{});
  80. // A StructFields array
  81. const fields = @typeInfo(Narcissus).Struct.fields;
  82. // 'fields' is a slice of StructFields. Here's the declaration:
  83. //
  84. // pub const StructField = struct {
  85. // name: []const u8,
  86. // field_type: type,
  87. // default_value: anytype,
  88. // is_comptime: bool,
  89. // alignment: comptime_int,
  90. // };
  91. //
  92. // Please complete these 'if' statements so that the field
  93. // name will not be printed if the field is of type 'void'
  94. // (which is a zero-bit type that takes up no space at all!):
  95. if (fields[0].??? != void) {
  96. print(" {s}", .{@typeInfo(Narcissus).Struct.fields[0].name});
  97. }
  98. if (fields[1].??? != void) {
  99. print(" {s}", .{@typeInfo(Narcissus).Struct.fields[1].name});
  100. }
  101. if (fields[2].??? != void) {
  102. print(" {s}", .{@typeInfo(Narcissus).Struct.fields[2].name});
  103. }
  104. // Yuck, look at all that repeated code above! I don't know
  105. // about you, but it makes me itchy.
  106. //
  107. // Alas, we can't use a regular 'for' loop here because
  108. // 'fields' can only be evaluated at compile time. It seems
  109. // like we're overdue to learn about this "comptime" stuff,
  110. // isn't it? :-)
  111. print(".\n", .{});
  112. }