Advertisement
Guest User

Untitled

a guest
Sep 19th, 2018
181
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.94 KB | None | 0 0
  1. const std = @import("std");
  2. const mem = @import("std").mem;
  3.  
  4. const typeinfo = @import("builtin").TypeInfo;
  5. const typeid = @import("builtin").TypeId;
  6. const Definition = typeinfo.Definition;
  7. const Data = Definition.Data;
  8.  
  9. fn definitions(comptime any: type) []Definition {
  10.     const type_kind = @typeInfo(any);
  11.  
  12.     switch (type_kind) {
  13.         typeid.Struct => |info| {
  14.             return info.defs;
  15.         },
  16.         typeid.Enum => |info| {
  17.             return info.defs;
  18.         },
  19.         typeid.Union => |info| {
  20.             return info.defs;
  21.         },
  22.         else => @compileError("Definitions are only available on Structs, Enums and Unions. Found type `" ++ @typeName(any) ++ "`."),
  23.     }
  24. }
  25.  
  26. fn definition_fn_names(comptime definition_list: []Definition) [][]const u8 {
  27.     var names: [definition_list.len][]const u8 = undefined;
  28.  
  29.     var missers = 0;
  30.  
  31.     for (definition_list) |definition, idx| {
  32.        
  33.         switch (definition.data) {
  34.             Data.Fn => {
  35.                 names[idx - missers] = definition.name;
  36.             },
  37.             else => missers += 1,
  38.         }
  39.     }
  40.  
  41.     return names[0..names.len - missers];
  42. }
  43.  
  44. fn definition_fn_signatures(comptime definition_list: []Definition) [][]const u8 {
  45.     var types: [definition_list.len][]const u8 = undefined;
  46.     var missers = 0;
  47.  
  48.     for(definition_list) |definition, idx| {
  49.         const data_type = switch(definition.data) {
  50.  
  51.             Data.Fn => |Fn| {
  52.                 types[idx - missers] = @typeName(Fn.fn_type);
  53.             },
  54.             else => missers += 1,
  55.         };
  56.  
  57.     }
  58.  
  59.     return types[0..types.len - missers];
  60. }
  61.  
  62.  
  63. /// Has `Type` a function with the name `name`, and the signature of `signature` (signature is in []const u8)
  64. fn has_fn(comptime Type: type, name: []const u8, signature: []const u8) bool {
  65.    
  66.     // type_definition_names is a list of all the names of the functions of the trait,
  67.     // type_definitions_fn_signatures a list of all the signatures (in []const u8).
  68.     // These are seperate lists, but they are in order, and indexing into the same index corresponds to the same function.
  69.    
  70.     comptime var type_definitions = comptime definitions(Type);
  71.     comptime var type_definitions_names = comptime definition_fn_names(type_definitions);
  72.     comptime var type_definitions_fn_signatures = comptime definition_fn_signatures(type_definitions);
  73.  
  74.     for(type_definitions_names) |type_def_name, idx| {
  75.         if (mem.eql(u8, type_def_name, name)) {
  76.             if (mem.eql(u8, type_definitions_fn_signatures[idx], signature)) {
  77.                 return true;
  78.             }
  79.         }
  80.     }
  81.  
  82.     return false;
  83.  
  84. }
  85.  
  86. fn require(comptime Type: type, comptime Trait: type) void {
  87.     // trait_definition_names is a list of all the names of the functions of the trait,
  88.     // trait_definitions_fn_signatures a list of all the signatures (in []const u8).
  89.     // These are seperate lists, but they are in order, and indexing into the same index corresponds to the same function.
  90.  
  91.     comptime var trait_definitions = comptime definitions(Trait);
  92.     comptime var trait_definitions_names = comptime definition_fn_names(trait_definitions);
  93.     comptime var trait_definitions_fn_signatures = comptime definition_fn_signatures(trait_definitions);
  94.  
  95.     for (trait_definitions_names) |trait_def_name, idx| {
  96.         if (!has_fn(Type, trait_def_name, trait_definitions_fn_signatures[idx])) {
  97.                                                                 // signature starts with `fn`, but we dont wont to print that
  98.             @compileError("Function `" ++ trait_def_name ++ "" ++ trait_definitions_fn_signatures[idx][2..] ++ "` from trait " ++ @typeName(Trait) ++ " not found in type `" ++ @typeName(Type) ++ "`." );
  99.         }
  100.     }
  101. }
  102.  
  103. //////////////////////////////////
  104. ///////////// TRAITS /////////////
  105. //////////////////////////////////
  106. fn AsRef(comptime T: type, comptime Target: type) type {
  107.     return struct {
  108.  
  109.         fn as_ref(self: *const T) *const Target {
  110.             return self.as_ref();
  111.         }
  112.     };
  113. }
  114.  
  115. fn AsMut(comptime T: type, comptime Target: type) type {
  116.     comptime require(T, AsRef(T, Target));
  117.  
  118.  
  119.     return struct {
  120.         fn as_mut(self: *T) *Target {
  121.             return self.as_mut();
  122.         }
  123.     };
  124. }
  125.  
  126. //////////////////////////////////
  127. //////////////////////////////////
  128.  
  129. //////////////////////////////////
  130. ///////// EXAMPLE STRUCT /////////
  131. //////////////////////////////////
  132.  
  133. const Foo = struct {
  134.     n: i64,
  135.  
  136.     fn as_ref(self: *const @This()) *const i64 {
  137.         return &self.n;
  138.     }
  139.  
  140.     fn as_mut(self: *@This()) *i64 {
  141.         return &self.n;
  142.     }
  143.  
  144. };
  145.  
  146. //////////////////////////////////
  147. //////////////////////////////////
  148.  
  149. fn example(comptime S: type, s: *S) void {
  150.     comptime require(S, AsMut(S, i64));
  151.  
  152.     s.as_mut().* += 1;
  153. }
  154.  
  155. pub fn main() void {
  156.     var foo = Foo {.n = 10,};
  157.  
  158.     example(Foo, &foo);
  159.  
  160.     std.debug.warn("{}\n", foo);
  161.  
  162. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement