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