1 | // |
---|
2 | // Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo |
---|
3 | // |
---|
4 | // The contents of this file are covered under the licence agreement in the |
---|
5 | // file "LICENCE" distributed with Cforall. |
---|
6 | // |
---|
7 | // function-operator.c -- |
---|
8 | // |
---|
9 | // Author : Rob Schluntz |
---|
10 | // Created On : Fri Aug 25 15:21:11 2017 |
---|
11 | // Last Modified By : Rob Schluntz |
---|
12 | // Last Modified On : Fri Aug 25 15:31:29 2017 |
---|
13 | // Update Count : 2 |
---|
14 | // |
---|
15 | |
---|
16 | #include <fstream> |
---|
17 | #include <stdlib> |
---|
18 | |
---|
19 | #define length(array) (sizeof((array))/sizeof((array)[0])) |
---|
20 | #define begin(array) (&array[0]) // there's currently a bug in passing an array to a polymorphic function, so ensure a pointer is passed instead |
---|
21 | #define end(array) (&array[length(array)]) |
---|
22 | |
---|
23 | // STL-like Algorithms |
---|
24 | trait Assignable(dtype T, dtype U) { T ?=?(T &, U); }; |
---|
25 | trait Copyable(dtype T) { void ?{}(T &, T); }; |
---|
26 | trait Destructable(dtype T) { void ^?{}(T &); }; |
---|
27 | |
---|
28 | trait Iterator(dtype iter | sized(iter) | Copyable(iter) | Destructable(iter), otype T) { |
---|
29 | T & *?(iter); |
---|
30 | iter ++?(iter &); |
---|
31 | int ?!=?(iter, iter); |
---|
32 | }; |
---|
33 | |
---|
34 | forall(otype Tin, dtype Input | Iterator(Input, Tin), otype Tout, dtype Output | Iterator(Output, Tout) | Assignable(Tout, Tin)) |
---|
35 | Output copy(Input first, Input last, Output result) { |
---|
36 | while (first != last) { |
---|
37 | *result = *first; |
---|
38 | ++result; ++first; |
---|
39 | } |
---|
40 | return result; |
---|
41 | } |
---|
42 | |
---|
43 | // test ?()(T *, ...) -- ?() with function call-by-pointer |
---|
44 | forall(otype Tin, dtype Input | Iterator(Input, Tin), otype Tout, dtype Output | Iterator(Output, Tout), otype FuncRet, dtype Func | { FuncRet ?()(Func *, Tin); } | Assignable(Tout, FuncRet)) |
---|
45 | Output transform (Input first, Input last, Output result, Func * op) { |
---|
46 | while (first != last) { |
---|
47 | *result = op(*first); |
---|
48 | ++result; ++first; |
---|
49 | } |
---|
50 | return result; |
---|
51 | } |
---|
52 | |
---|
53 | // test ?()(T, ...) -- ?() with function call-by-value |
---|
54 | forall(dtype Iter, otype T | Iterator(Iter, T), otype Pred | { int ?()(Pred, T); }) |
---|
55 | Iter find_if (Iter first, Iter last, Pred pred) { |
---|
56 | while (first != last) { |
---|
57 | if (pred(*first)) return first; |
---|
58 | ++first; |
---|
59 | } |
---|
60 | return last; |
---|
61 | } |
---|
62 | |
---|
63 | // test ?()(T, ...) -- ?() with function call-by-reference |
---|
64 | forall(otype Generator, otype GenRet | { GenRet ?()(Generator &); }, dtype Iter, otype T| Iterator(Iter, T) | Assignable(T, GenRet)) |
---|
65 | void generate(Iter first, Iter last, Generator & gen) { |
---|
66 | int i = 0; |
---|
67 | while (first != last) { |
---|
68 | *first = gen(); |
---|
69 | ++first; |
---|
70 | } |
---|
71 | } |
---|
72 | |
---|
73 | // encapsulate a counter that increments by one every time it is called |
---|
74 | struct Counter { int c; }; |
---|
75 | void ?{}(Counter & cnt) { cnt.c = 0; } |
---|
76 | int ?()(Counter & cnt) { return cnt.c++; } |
---|
77 | |
---|
78 | // TODO: abstract over os type with ostream trait; resolver is currently too slow for this to be reasonable, but it does work. |
---|
79 | struct os_wrapper { |
---|
80 | ofstream * out; |
---|
81 | }; |
---|
82 | |
---|
83 | // TODO: abstract over (os, T) |
---|
84 | os_wrapper ?=?(os_wrapper & wrapper, int x) { |
---|
85 | wrapper.out | x | endl; |
---|
86 | return wrapper; |
---|
87 | } |
---|
88 | |
---|
89 | struct ostream_iterator { |
---|
90 | os_wrapper * out; |
---|
91 | }; |
---|
92 | void ?{}(ostream_iterator & iter, ofstream * out) { |
---|
93 | iter.out = new(out); |
---|
94 | } |
---|
95 | // no destructor, memory leak. This is necessary for this to work at the moment, since |
---|
96 | // *? requires its parameter by value and returns a reference. |
---|
97 | |
---|
98 | // implement Iterator |
---|
99 | os_wrapper & *?(ostream_iterator iter) { |
---|
100 | return *iter.out; |
---|
101 | } |
---|
102 | ostream_iterator ++?(ostream_iterator & iter) { |
---|
103 | // nothing to do |
---|
104 | return iter; |
---|
105 | } |
---|
106 | int ?!=?(ostream_iterator i1, ostream_iterator i2) { |
---|
107 | return i1.out->out != i2.out->out; |
---|
108 | } |
---|
109 | |
---|
110 | forall(otype T | { int ?==?(T, T); }) |
---|
111 | struct Equals { |
---|
112 | T val; |
---|
113 | }; |
---|
114 | |
---|
115 | forall(otype T | { int ?==?(T, T); }) |
---|
116 | int ?()(Equals(T) eq, T x) { |
---|
117 | return eq.val == x; |
---|
118 | } |
---|
119 | |
---|
120 | forall(otype T | { T ?*?(T, T); }) |
---|
121 | struct Multiply { |
---|
122 | T val; |
---|
123 | }; |
---|
124 | |
---|
125 | forall(otype T | { T ?*?(T, T); }) |
---|
126 | T ?()(Multiply(T) * mult, T x) { |
---|
127 | return mult->val * x; |
---|
128 | } |
---|
129 | |
---|
130 | // TODO: generalize to ttype return; doesn't work yet |
---|
131 | // like std::function |
---|
132 | forall(otype Return, ttype Args) |
---|
133 | struct function { |
---|
134 | Return (*f)(Args); |
---|
135 | }; |
---|
136 | // TODO: missing adapter in these functions |
---|
137 | // // value, reference, pointer operators |
---|
138 | // forall(otype Return, ttype Args) Return ?()(function(Return, Args) func, Args args) { return func.f(args); } |
---|
139 | // forall(otype Return, ttype Args) Return ?()(function(Return, Args) & func, Args args) { return func.f(args); } |
---|
140 | // forall(otype Return, ttype Args) Return ?()(function(Return, Args) * func, Args args) { return func->f(args); } |
---|
141 | |
---|
142 | int main() { |
---|
143 | // generate for array fill |
---|
144 | Counter c; |
---|
145 | int x[10], y[10]; |
---|
146 | generate(begin(x), end(x), c); |
---|
147 | generate(begin(y), end(y), c); |
---|
148 | |
---|
149 | // copy for output |
---|
150 | ostream_iterator out_iter = { sout }; |
---|
151 | copy(begin(x), end(x), out_iter); |
---|
152 | copy(begin(y), end(y), out_iter); |
---|
153 | |
---|
154 | // find_if for searching |
---|
155 | Equals(int) is5 = { 5 }; |
---|
156 | if (find_if(begin(x), end(x), is5) != end(y)) { |
---|
157 | printf("Found 5 in x.\n"); |
---|
158 | } else { |
---|
159 | printf("Did not find 5 in x.\n"); |
---|
160 | } |
---|
161 | if (find_if(begin(y), end(y), is5) != end(y)) { |
---|
162 | printf("Found 5 in y.\n"); |
---|
163 | } else { |
---|
164 | printf("Did not find 5 in y.\n"); |
---|
165 | } |
---|
166 | |
---|
167 | Multiply(int) times2 = { 2 }; |
---|
168 | transform(begin(x), end(x), begin(x), ×2); |
---|
169 | copy(begin(x), end(x), out_iter); |
---|
170 | } |
---|
171 | |
---|
172 | // Local Variables: // |
---|
173 | // tab-width: 4 // |
---|
174 | // End: // |
---|