Guest User

Untitled

a guest
Apr 23rd, 2018
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.36 KB | None | 0 0
  1. const std = @import("std");
  2. const warn = std.debug.warn;
  3. const TypeId = @import("builtin").TypeId;
  4.  
  5. fn Iterator(comptime T: type) type {
  6. return struct {
  7. const Self = this;
  8. const ResetError = error {
  9. NotResetable,
  10. };
  11.  
  12. const IterType = T;
  13.  
  14. next_fn: fn(self: &Self) ?T,
  15. reset_fn: ?fn(self: &Self) ResetError!void,
  16.  
  17. fn next(self: &Self) ?T {
  18. return self.next_fn(self);
  19. }
  20.  
  21. fn reset(self: &Self) !void {
  22. const rfn = self.reset_fn ?? return error.NotResetable;
  23. return rfn(self);
  24. }
  25. };
  26. }
  27.  
  28. fn UnwrapArg(comptime ArgType: type) type {
  29. if (@typeId(ArgType) == TypeId.Pointer) {
  30. return ArgType.Child;
  31. }
  32.  
  33. return ArgType;
  34. }
  35.  
  36. fn Filter(comptime filter_fn: var) type {
  37. const FnType = @typeOf(filter_fn);
  38.  
  39. if (@typeId(FnType) != TypeId.Fn) {
  40. @compileError("Filter expects a function parameter.");
  41. }
  42.  
  43. if (FnType.arg_count != 1) {
  44. @compileError("Filter expects a function with one argument.");
  45. }
  46.  
  47. if (FnType.ReturnType != bool) {
  48. @compileError("Filter expects a function that returns bool.");
  49. }
  50.  
  51. const T = UnwrapArg(@ArgType(FnType, 0));
  52. const It = Iterator(T);
  53.  
  54. return struct {
  55. const Self = this;
  56. it: It,
  57. input_it: &It,
  58.  
  59. fn init(input_it: &It) Self {
  60. return Self {
  61. .it = It {
  62. .next_fn = next,
  63. .reset_fn = reset,
  64. },
  65. .input_it = input_it,
  66. };
  67. }
  68.  
  69. fn next(it: &It) ?T {
  70. const self = @fieldParentPtr(Self, "it", it);
  71.  
  72. while (self.input_it.next()) |*val| {
  73. if (filter_fn(*val)) {
  74. return *val;
  75. }
  76. }
  77.  
  78. return null;
  79. }
  80.  
  81. fn reset(it: &It) !void {
  82. const self = @fieldParentPtr(Self, "it", it);
  83. return self.input_it.reset();
  84. }
  85. };
  86. }
  87.  
  88. fn Map(comptime map_fn: var) type {
  89. const FnType = @typeOf(map_fn);
  90.  
  91. if (@typeId(FnType) != TypeId.Fn) {
  92. @compileError("Map expects a function parameter.");
  93. }
  94.  
  95. if (FnType.arg_count != 1) {
  96. @compileError("Map expects a function with one argument.");
  97. }
  98.  
  99. const T = UnwrapArg(@ArgType(FnType, 0));
  100. const V = FnType.ReturnType;
  101.  
  102. const InputIt = Iterator(T);
  103. const OutputIt = Iterator(V);
  104.  
  105. return struct {
  106. const Self = this;
  107. it: OutputIt,
  108. input_it: &InputIt,
  109.  
  110. fn init(input_it: &InputIt) Self {
  111. return Self {
  112. .it = OutputIt {
  113. .next_fn = next,
  114. .reset_fn = reset,
  115. },
  116. .input_it = input_it,
  117. };
  118. }
  119.  
  120. fn next(it: &OutputIt) ?V {
  121. const self = @fieldParentPtr(Self, "it", it);
  122.  
  123. const val = self.input_it.next() ?? return null;
  124. return map_fn(val);
  125. }
  126.  
  127. fn reset(it: &OutputIt) !void {
  128. const self = @fieldParentPtr(Self, "it", it);
  129. return self.input_it.reset();
  130. }
  131. };
  132. }
  133.  
  134. fn Range(comptime start: usize, comptime end: usize) type {
  135. if (start > end) {
  136. @compileError("Invalid range.");
  137. }
  138.  
  139. const It = Iterator(usize);
  140.  
  141. return struct {
  142. const Self = this;
  143. it: It,
  144. current: usize,
  145.  
  146. fn init() Self {
  147. return Self {
  148. .it = It {
  149. .next_fn = next,
  150. .reset_fn = reset,
  151. },
  152. .current = start,
  153. };
  154. }
  155.  
  156. fn next(it: &It) ?usize {
  157. const self = @fieldParentPtr(Self, "it", it);
  158.  
  159. if (self.current >= end) {
  160. return null;
  161. }
  162.  
  163. var ret = self.current;
  164. self.current += 1;
  165. return ret;
  166. }
  167.  
  168. fn reset(it: &It) It.ResetError!void {
  169. const self = @fieldParentPtr(Self, "it", it);
  170.  
  171. self.current = start;
  172. }
  173. };
  174. }
  175.  
  176. fn Repeat(comptime val: var, comptime times: i64) type {
  177. const T = @typeOf(val);
  178. const It = Iterator(T);
  179.  
  180. return struct {
  181. const Self = this;
  182. it: It,
  183. current: if (times == -1) void else if (times > 0) i64 else unreachable,
  184.  
  185. fn init() Self {
  186. return Self {
  187. .it = It {
  188. .next_fn = next,
  189. .reset_fn = if (times == -1) null else reset,
  190. },
  191. .current = if (times == -1) {} else 0,
  192. };
  193. }
  194.  
  195. fn next(it: &It) ?T {
  196. if (times > 0) {
  197. const self = @fieldParentPtr(Self, "it", it);
  198.  
  199. if (self.current >= times) {
  200. return null;
  201. }
  202.  
  203. self.current += 1;
  204. }
  205.  
  206. return val;
  207. }
  208.  
  209. fn reset(it: &It) !void {
  210. if (times > 0) {
  211. const self = @fieldParentPtr(Self, "it", it);
  212. self.current = 0;
  213. }
  214.  
  215. return error.NotResetable;
  216. }
  217. };
  218. }
  219.  
  220. fn addOne(x: usize) usize {
  221. return x + 1;
  222. }
  223.  
  224. fn isEven(x: usize) bool {
  225. return x % 2 == 0;
  226. }
  227.  
  228. fn consume(it: var) void {
  229. while (it.next()) |*val| {
  230. warn("Next value: {}\n", *val);
  231. }
  232. }
  233.  
  234. const Foo = struct {
  235. data: usize,
  236. };
  237.  
  238. const FooIterator = struct {
  239. const Self = this;
  240. const It = Iterator(Foo);
  241.  
  242. it: It,
  243. current: usize,
  244.  
  245. fn init() Self {
  246. return Self {
  247. .it = It {
  248. .next_fn = next,
  249. .reset_fn = null,
  250. },
  251. .current = 0,
  252. };
  253. }
  254.  
  255. fn next(it: &It) ?Foo {
  256. const self = @fieldParentPtr(Self, "it", it);
  257. const current = self.current;
  258. self.current += 1;
  259.  
  260. if (self.current > 30) {
  261. return null;
  262. }
  263.  
  264. return Foo {
  265. .data = current,
  266. };
  267. }
  268. };
  269.  
  270. fn filter_foo(foo: &const Foo) bool {
  271. return isEven(foo.data);
  272. }
  273.  
  274. pub fn main() !void {
  275. var map_it = &Map(addOne).init(&Range(0, 10).init().it).it;
  276.  
  277. consume(map_it);
  278.  
  279. var filter_it = &Filter(isEven).init(map_it).it;
  280.  
  281. // Reset iterator
  282. try filter_it.reset();
  283.  
  284. consume(filter_it);
  285.  
  286. var filter_foos = &Filter(filter_foo).init(&FooIterator.init().it).it;
  287.  
  288. while (filter_foos.next()) |*val| {
  289. warn("Foo data: {}\n", val.data);
  290. }
  291. }
Add Comment
Please, Sign In to add comment