Guest User

Untitled

a guest
Apr 19th, 2018
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.88 KB | None | 0 0
  1. const std = @import("std");
  2. const TypeId = @import("builtin").TypeId;
  3. const allocPrint = std.fmt.allocPrint;
  4.  
  5. // This should be equivalent to Tuple(f32, f32)
  6. fn TestTuple() type {
  7. return struct {
  8. const Self = this;
  9. const Types = []type { f32, f32 };
  10.  
  11. field0: f32,
  12. field1: f32,
  13.  
  14. fn init(arg0: f32, arg1: f32) Self {
  15. return Self {
  16. .field0 = arg0,
  17. .field1 = arg1
  18. };
  19. }
  20.  
  21. fn get(self: &Self, comptime i: usize) &(@memberType(Self, i)) {
  22. return if (i == 0) &self.field0 else &self.field1;
  23. }
  24.  
  25. // Takes a series of pointers or nullable pointers and unpacks the tuple fields into them.
  26. // null pointers are ignored.
  27. fn unpack(self: &const Self, args: ...) void {
  28. if (args.len == 0) {
  29. @compileError("You have to unpack at least one field.");
  30. }
  31.  
  32. if (args.len > Self.Types.len) {
  33. @compileError("Cannot unpack more fields than the tuple has.");
  34. }
  35.  
  36. comptime var i = 0;
  37. inline while (i < args.len) : (i += 1) {
  38. comptime var nullable = false;
  39.  
  40. if (@typeId(@typeOf(args[i])) == TypeId.Nullable) {
  41. nullable = true;
  42. }
  43.  
  44. comptime const arg_type = if (nullable) @typeOf(args[i]).Child else @typeOf(args[i]);
  45. comptime const type_id = @typeId(arg_type);
  46.  
  47. if (type_id != TypeId.Pointer) {
  48. @compileError("Must pass pointers to unpack.");
  49. }
  50.  
  51. if (arg_type.Child != Self.Types[i]) {
  52. @compileError("Invalid pointer type.");
  53. }
  54.  
  55. if (nullable) {
  56. if (args[i] != null) {
  57. *??args[i] = if (i == 0) self.field0 else self.field1;
  58. }
  59. } else {
  60. *args[i] = if (i == 0) self.field0 else self.field1;
  61. }
  62. }
  63. }
  64. };
  65. }
  66.  
  67. fn ChildRefType(comptime ref_type: type, comptime i: usize) type {
  68. // TODO: Check for constness of ref_type, propagate it to the result type
  69. return &(@memberType(ref_type.Child, i));
  70. }
  71.  
  72. // get the i'th field of a struct
  73. pub fn get(self: var, comptime i: usize) ChildRefType(@typeOf(self), i) {
  74. return if (i == 0) &self.field0 else &self.field1;
  75. }
  76.  
  77. pub fn Tuple(comptime types: []type) type {
  78. if (types.len == 0) {
  79. @compileError("No types passed to Tuple.");
  80. }
  81.  
  82. var allocator_data: [1024 * 8]u8 = undefined;
  83. const alloc = &std.heap.FixedBufferAllocator.init(allocator_data).allocator;
  84.  
  85. var member_names: [types.len][]const u8 = undefined;
  86. var member_types: [types.len][]const &TypeInfo = undefined;
  87.  
  88. for (types) |t, i| {
  89. member_names[i] = allocPrint(alloc, "field{}", i) catch unreachable;
  90. member_types[i] = @reflect(t);
  91. }
  92.  
  93. // Free the member names upon exiting the function.
  94. defer for (member_names) |m| {
  95. alloc.free(m);
  96. };
  97.  
  98. // Build our tuple type.
  99. // These types should be builtin so no need for import, right?
  100. const struct_detail = StructTypeInfoDetail.init(false, member_names, member_types);
  101.  
  102. const detail = TypeInfoDetail {
  103. .Struct = struct_detail
  104. };
  105.  
  106. // Perhaps:
  107. // const detail = TypeInfoDetail.init(TypeId.Struct, false, member_names, member_types);
  108.  
  109. // TODO: Add methods
  110. // init(args: ...), get(comptime i: usize) &types[i], ...
  111. const type_info = TypeInfo.init(false, false, detail);
  112.  
  113. return @reify(type_info);
  114.  
  115. // TODO: Better TypeBuilder interface, look at the TypeId's currently available.
  116. // var builder = TypeBuilder.init();
  117. // builder.buildTypeAndStuff();
  118. // @reify(builder)
  119. }
  120.  
  121. fn vararg_types(args: ...) []type {
  122. var ts: [args.len]type = undefined;
  123.  
  124. var i = 0;
  125. while (i < args.len) : (i += 1) {
  126. ts[i] = @typeOf(args[i]);
  127. }
  128.  
  129. return ts;
  130. }
  131.  
  132. pub fn make_tuple(args: ...) Tuple(vararg_types(args)) {
  133. const TupleType = @typeOf(this).ReturnType;
  134.  
  135. var tup: TupleType = undefined;
  136. inline for (args) |arg, i| {
  137. *tup.get(i) = arg;
  138. }
  139.  
  140. return tup;
  141. }
  142.  
  143. pub fn main() !void {
  144. var stdout_file = try std.io.getStdOut();
  145. var adapter = std.io.FileOutStream.init(&stdout_file);
  146. var stream = &adapter.stream;
  147.  
  148. const Point = TestTuple();
  149. //const Point = Tuple(f32, f32);
  150.  
  151. var p = Point.init(0.0, 0.0);
  152. try stream.print("({}, {})\n", *p.get(0), *p.get(1));
  153.  
  154. *p.get(0) = 1.0;
  155.  
  156. try stream.print("({}, {})\n", *p.get(0), *p.get(1));
  157.  
  158. *get(p, 1) = 1.0;
  159.  
  160. try stream.print("({}, {})\n", *p.get(0), *p.get(1));
  161.  
  162. *p.get(1) = 2.0;
  163.  
  164. var to_unpack: f32 = undefined;
  165. var nullable: ?&f32 = null;
  166. p.unpack(nullable, &to_unpack);
  167.  
  168. try stream.print("UNPACKED {}\n", to_unpack);
  169.  
  170. // const pp = Point.init(1.0, 1.0);
  171. // *get(pp, 0) = 2.0;
  172. }
Add Comment
Please, Sign In to add comment