source: doc/theses/mike_brooks_MMath/programs/sharing-demo.cfa@ 4558df2

Last change on this file since 4558df2 was 5546f50b, checked in by Peter A. Buhr <pabuhr@…>, 18 months ago

more switch to tabs

  • Property mode set to 100644
File size: 13.3 KB
Line 
1#include <string.hfa>
2#include <assert.h>
3
4#define xstr(s) str(@s;@)
5#define str(s) #s
6
7void demo1() {
8 sout | sepOff;
9 sout | "Consider two strings @s1@ and @s1a@ that are in an aliasing relationship, and a third, @s2@, made by a simple copy from @s1@.";
10 sout | "\\par\\noindent";
11 sout | "\\begin{tabular}{llll}";
12 sout | "\t\t\t\t& @s1@\t& @s1a@\t& @s2@\t\\\\";
13
14 #define S1 string s1 = "abc"
15 #define S1A string s1a = s1`shareEdits
16 #define S2 string s2 = s1
17 S1;
18 S1A;
19 S2;
20 assert( s1 == "abc" );
21 assert( s1a == "abc" );
22 assert( s2 == "abc" );
23 sout | xstr(S1) | "\t\\\\";
24 sout | xstr(S1A) | "\t\\\\";
25 sout | xstr(S2) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2;
26 sout | "\\end{tabular}";
27 sout | "\\par\\noindent";
28
29 sout | "Aliasing (@`shareEdits@) means that changes flow in both directions; with a simple copy, they do not.";
30 sout | "\\par\\noindent";
31 sout | "\\begin{tabular}{llll}";
32 sout | "\t\t& @s1@\t& @s1a@\t& @s2@\t\\\\";
33 sout | "\t\t& " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\";
34
35 #define S1s1 s1 [1] = '+'
36 S1s1;
37 assert( s1 == "a+c" );
38 sout | xstr(S1s1) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\";
39
40 #define S1As1 s1a[1] = '-'
41 S1As1;
42 assert( s1a == "a-c" );
43 sout | xstr(S1As1) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\";
44
45 #define S2s1 s2 [1] = '|'
46 S2s1;
47 assert( s2 == "a|c" );
48 sout | xstr(S2s1) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2;
49 sout | "\\end{tabular}";
50 sout | "\\par\\noindent";
51
52 sout | "Assignment of a value is just a modificiation."
53 "\nThe aliasing relationship is established at construction and is unaffected by assignment of a value.";
54 sout | "\\par\\noindent";
55 sout | "\\begin{tabular}{llll}";
56 sout | "\t\t& @s1@\t& @s1a@\t& @s2@\t\\\\";
57 sout | "\t\t& " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\";
58
59 #define S1qrs s1 = "qrs"
60 S1qrs;
61 assert( s1 == "qrs" );
62 sout | xstr(S1qrs) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\";
63
64 #define S1Atuv s1a = "tuv"
65 S1Atuv;
66 assert( s1a == "tuv" );
67 sout | xstr(S1Atuv) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\";
68
69 #define S2wxy s2 = "wxy"
70 S2wxy;
71 assert( s2 == "wxy" );
72 sout | xstr(S2wxy) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2;
73 sout | "\\end{tabular}";
74 sout | "\\par\\noindent";
75
76 sout | "Assignment from a string is just assignment of a value."
77 "\nWhether of not the RHS participates in aliasing is irrelevant. Any aliasing of the LHS is unaffected.";
78 sout | "\\par\\noindent";
79 sout | "\\begin{tabular}{llll}";
80 sout | "\t\t& @s1@\t& @s1a@\t& @s2@\t\\\\";
81 sout | "\t\t& " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\";
82
83 #define S1S2 s1 = s2
84 S1S2;
85 assert( s1 == "wxy" );
86 assert( s1a == "wxy" );
87 assert( s2 == "wxy" );
88 sout | xstr(S1S2) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\";
89
90 #define S1aaa s1 = "aaa"
91 S1aaa;
92 assert( s1 == "aaa" );
93 assert( s1a == "aaa" );
94 assert( s2 == "wxy" );
95 sout | xstr(S1aaa) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\";
96
97 #define S2S1 s2 = s1
98 S2S1;
99 assert( s1 == "aaa" );
100 assert( s1a == "aaa" );
101 assert( s2 == "aaa" );
102 sout | xstr(S2S1) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\";
103
104 #define S2bbb s2 = "bbb"
105 S2bbb;
106 assert( s1 == "aaa" );
107 assert( s1a == "aaa" );
108 assert( s2 == "bbb" );
109 sout | xstr(S2bbb) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\";
110
111 #define S2S1a s2 = s1a
112 S2S1a;
113 assert( s1 == "aaa" );
114 assert( s1a == "aaa" );
115 assert( s2 == "aaa" );
116 sout | xstr(S2S1a) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\";
117
118 #define S2ccc s2 = "ccc"
119 S2ccc;
120 assert( s1 == "aaa" );
121 assert( s1a == "aaa" );
122 assert( s2 == "ccc" );
123 sout | xstr(S2ccc) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\";
124
125 #define S1xxx s1 = "xxx"
126 S1xxx;
127 assert( s1 == "xxx" );
128 assert( s1a == "xxx" );
129 assert( s2 == "ccc" );
130 sout | xstr(S1xxx) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\";
131 sout | "\\end{tabular}";
132 sout | "\\par";
133}
134
135
136void demo2() {
137 sout | "Consider new strings @s1_mid@ being an alias for a run in the middle of @s1@, along with @s2@, made by a simple copy from the middle of @s1@.";
138 sout | "\\par\\noindent";
139 sout | "\\begin{tabular}{llll}";
140 sout | "\t\t\t\t& @s1@\t& @s1_mid@\t& @s2@\t\\\\";
141
142 #define D2_s1_abcd string s1 = "abcd"
143 D2_s1_abcd;
144 sout | xstr(D2_s1_abcd) | "\t\\\\";
145
146 #define D2_s1mid_s1 string s1_mid = s1(1,2)`shareEdits
147 D2_s1mid_s1;
148 sout | xstr(D2_s1mid_s1) | "\t\\\\";
149
150 #define D2_s2_s1 string s2 = s1(1,2)
151 D2_s2_s1;
152 assert( s1 == "abcd" );
153 assert( s1_mid == "bc" );
154 assert( s2 == "bc" );
155 sout | xstr(D2_s2_s1) | "\t& " | s1 | "\t& " | s1_mid | "\t& " | s2 | "\t\\\\";
156 sout | "\\end{tabular}";
157 sout | "\\par\\noindent";
158
159 sout | "Again, @`shareEdits@ passes changes in both directions; copy does not. Note the difference in index values, with the \\emph{b} position being 1 in the longer string and 0 in the shorter strings. In the case of s1 aliasing with @s1_mid@, the very same character is being accessed by different postitions.";
160 sout | "\\par\\noindent";
161 sout | "\\begin{tabular}{llll}";
162 sout | "\t\t\t\t& @s1@\t& @s1_mid@\t& @s2@\t\\\\";
163 sout | "\t& " | s1 | "\t& " | s1_mid | "\t& " | s2 | "\t\\\\";
164
165 #define D2_s1_plus s1 [1] = '+'
166 D2_s1_plus;
167 assert( s1 == "a+cd" );
168 assert( s1_mid == "+c" );
169 assert( s2 == "bc" );
170 sout | xstr(D2_s1_plus) | "\t& " | s1 | "\t& " | s1_mid | "\t& " | s2 | "\t\\\\";
171
172 #define D2_s1mid_minus s1_mid[0] = '-'
173 D2_s1mid_minus;
174 assert( s1 == "a-cd" );
175 assert( s1_mid == "-c" );
176 assert( s2 == "bc" );
177 sout | xstr(D2_s1mid_minus) | "\t& " | s1 | "\t& " | s1_mid | "\t& " | s2 | "\t\\\\";
178
179 #define D2_s2_pipe s2 [0] = '|'
180 D2_s2_pipe;
181 assert( s1 == "a-cd" );
182 assert( s1_mid == "-c" );
183 assert( s2 == "|c" );
184 sout | xstr(D2_s2_pipe) | "\t& " | s1 | "\t& " | s1_mid | "\t& " | s2 | "\t\\\\";
185 sout | "\\end{tabular}";
186 sout | "\\par\\noindent";
187
188 sout | "Once again, assignment of a value is a modificiation that flows through the aliasing relationship, without affecting its structure.";
189 sout | "\\par\\noindent";
190 sout | "\\begin{tabular}{llll}";
191 sout | "\t\t\t\t& @s1@\t& @s1_mid@\t& @s2@\t\\\\";
192 sout | "\t& " | s1 | "\t& " | s1_mid | "\t& " | s2 | "\t\\\\";
193
194 #define D2_s1mid_ff s1_mid = "ff"
195 D2_s1mid_ff;
196 assert( s1 == "affd" );
197 assert( s1_mid == "ff" );
198 assert( s2 == "|c" );
199 sout | xstr(D2_s1mid_ff) | "\t& " | s1 | "\t& " | s1_mid | "\t& " | s2 | "\t\\\\";
200
201 #define D2_s2_gg s2 = "gg"
202 D2_s2_gg;
203 assert( s1 == "affd" );
204 assert( s1_mid == "ff" );
205 assert( s2 == "gg" );
206 sout | xstr(D2_s2_gg) | "\t& " | s1 | "\t& " | s1_mid | "\t& " | s2 | "\t\\\\";
207 sout | "\\end{tabular}";
208 sout | "\\par\\noindent";
209
210 sout | "In the \\emph{ff} step, which is a positive example of flow across an aliasing relationship, the result is straightforward to accept because the flow direction is from contained (small) to containing (large). The following rules for edits through aliasing substrings will guide how to flow in the opposite direction.";
211 sout | "\\par";
212
213
214 sout | "Growth and shrinkage are natural extensions. An empty substring is a real thing, at a well-defined location, whose meaning is extrapolated from the examples so far. The intended metaphor is to operating a GUI text editor. Having an aliasing substring is like using the mouse to select a few words. Assigning onto an aliasign substring is like typing from having a few words selected: depending how much you type, the file being edited can get shorter or longer.";
215 sout | "\\par\\noindent";
216 sout | "\\begin{tabular}{lll}";
217 sout | "\t\t\t\t& @s1@\t& @s1_mid@\t\\\\";
218 sout | "\t& " | s1 | "\t& " | s1_mid | "\t\\\\";
219
220 assert( s1 == "affd" );
221// assert( s1_mid == "fc" ); // ????????? bug?
222 sout | xstr(D2_s2_gg) | "\t& " | s1 | "\t& " | s1_mid | "\t\\\\";
223
224 #define D2_s1mid_hhhh s1_mid = "hhhh"
225 D2_s1mid_hhhh;
226 assert( s1 == "ahhhhd" );
227 assert( s1_mid == "hhhh" );
228 sout | xstr(D2_s1mid_hhhh) | "\t& " | s1 | "\t& " | s1_mid | "\t\\\\";
229
230 #define D2_s1mid_i s1_mid = "i"
231 D2_s1mid_i;
232 assert( s1 == "aid" );
233 assert( s1_mid == "i" );
234 sout | xstr(D2_s1mid_i) | "\t& " | s1 | "\t& " | s1_mid | "\t\\\\";
235
236 #define D2_s1mid_empty s1_mid = ""
237 D2_s1mid_empty;
238 assert( s1 == "ad" );
239 // assert( s1_mid == "" ); ------ Should be so, but fails
240 sout | xstr(D2_s1mid_empty) | "\t& " | s1 | "\t& " | s1_mid | "\t\\\\";
241
242 #define D2_s1mid_jj s1_mid = "jj"
243 D2_s1mid_jj;
244 assert( s1 == "ajjd" );
245 assert( s1_mid == "jj" );
246 sout | xstr(D2_s1mid_jj) | "\t& " | s1 | "\t& " | s1_mid | "\t\\\\";
247 sout | "\\end{tabular}";
248 sout | "\\par\\noindent";
249
250 sout | "Multiple portions can be aliased. When there are several aliasing substrings at once, the text editor analogy becomes an online multi-user editor. I should be able to edit a paragraph in one place (changing the document's length), without my edits affecting which letters are within a mouse-selection that you had made previously, somewhere else.";
251 sout | "\\par\\noindent";
252 sout | "\\begin{tabular}{lllll}";
253 sout | "\t\t\t\t& @s1@\t& @s1_bgn@\t& @s1_mid@\t& @s1_end@\t\\\\";
254
255 #define D2_s1bgn_s1 string s1_bgn = s1(0, 1)`shareEdits
256 D2_s1bgn_s1;
257 sout | xstr(D2_s1bgn_s1) | "\t\\\\";
258
259 #define D2_s1end_s1 string s1_end = s1(3, 1)`shareEdits
260 D2_s1end_s1;
261 assert( s1 == "ajjd" );
262 assert( s1_bgn == "a" );
263 assert( s1_mid == "jj" );
264 assert( s1_end == "d" );
265 sout | xstr(D2_s1end_s1) | "\t& " | s1 | "\t& " | s1_bgn | "\t& " | s1_mid | "\t& " | s1_end | "\t\\\\";
266
267 #define D1_s1bgn_zzz s1_bgn = "zzzz"
268 D1_s1bgn_zzz;
269 assert( s1 == "zzzzjjd" );
270 assert( s1_bgn == "zzzz" );
271 assert( s1_mid == "jj" );
272 assert( s1_end == "d" );
273 sout | xstr(D1_s1bgn_zzz) | "\t& " | s1 | "\t& " | s1_bgn | "\t& " | s1_mid | "\t& " | s1_end | "\t\\\\";
274 sout | "\\end{tabular}";
275 sout | "\\par\\noindent";
276
277 sout | "When an edit happens on an aliasing substring that overlaps another, an effect is unavoidable. Here, the passive party sees its selection shortened, to exclude the characters that were not part of the original selection.";
278 sout | "\\par\\noindent";
279 sout | "\\begin{tabular}{llllll}";
280 sout | "\t\t\t\t& @s1@\t& @s1_bgn@\t& @s1_crs@\t& @s1_mid@\t& @s1_end@\t\\\\";
281
282 #define D2_s1crs_s1 string s1_crs = s1(3, 2)`shareEdits
283 D2_s1crs_s1;
284 assert( s1 == "zzzzjjd" );
285 assert( s1_bgn == "zzzz" );
286 assert( s1_crs == "zj" );
287 assert( s1_mid == "jj" );
288 assert( s1_end == "d" );
289 sout | xstr(D2_s1crs_s1) | "\t& " | s1 | "\t& " | s1_bgn | "\t& " | s1_crs | "\t& " | s1_mid | "\t& " | s1_end | "\t\\\\";
290
291 #define D2_s1crs_ppp s1_crs = "+++"
292 D2_s1crs_ppp;
293 assert( s1 == "zzz+++jd" );
294 assert( s1_bgn == "zzz" );
295 assert( s1_crs == "+++" );
296 assert( s1_mid == "j" );
297 assert( s1_end == "d" );
298 sout | xstr(D2_s1crs_ppp) | "\t& " | s1 | "\t& " | s1_bgn | "\t& " | s1_crs | "\t& " | s1_mid | "\t& " | s1_end | "\t\\\\";
299 sout | "\\end{tabular}";
300 sout | "\\par\\noindent";
301 sout | "TODO: finish typesetting the demo";
302
303 // "This shortening behaviour means that a modification has to occur entirely inside a substring, to show up in that substring. Sharing changes through the intersection of partially overlapping aliases is still possible, so long as the receiver's boundary is not inside the edit."
304
305 string word = "Phi";
306 string consonants = word(0,2)`shareEdits;
307 string miniscules = word(1,2)`shareEdits;
308 assert( word == "Phi" );
309 assert( consonants == "Ph" );
310 assert( miniscules == "hi" );
311
312 consonants[1] = 's';
313 assert( word == "Psi" );
314 assert( consonants == "Ps" );
315 assert( miniscules == "si" );
316
317 // "The extreme form of this shortening happens when a bystander alias is a proper substring of an edit. The bystander becomes an empty substring."
318
319 string all = "They said hello again";
320 string greet = all(10,5)`shareEdits;
321 string greet_bgn = all(10,1)`shareEdits;
322 string greet_end = all(14,1)`shareEdits;
323
324 assert( all == "They said hello again" );
325 assert( greet == "hello" );
326 assert( greet_bgn == "h" );
327 assert( greet_end == "o" );
328
329
330 greet = "sup";
331 assert( all == "They said sup again" );
332 assert( greet == "sup" );
333 // assert( greet_bgn == "" ); ------ Should be so, but fails
334 // assert( greet_end == "" );
335
336
337
338
339
340 /* As in the earlier step where \emph{aj} becomes \emph{ajjd}, such empty substrings maintain their places in the total string, and can be used for filling it. Because @greet_bgn@ was orginally at the start of the edit, in the outcome, the empty @greet_bgn@ sits just before the written value. Similarly @greed_end@ goes after. Though not shown, an overwritten substring at neither side goes arbitrarily to the before side. */
341
342
343
344
345 greet_bgn = "what";
346
347
348 assert( all == "They said whatsup again" );
349
350 assert( greet == "sup" );
351
352 assert( greet_bgn == "what" );
353 // assert( greet_end == "" ); ------ Should be so, but fails
354
355
356 greet_end = "...";
357
358
359 assert( all == "They said whatsup... again" );
360
361 assert( greet == "sup" );
362
363 assert( greet_bgn == "what" );
364
365 assert( greet_end == "..." );
366
367
368
369
370
371 /* Though these empty substrings hold their places in the total string, an empty string only belongs to bigger strings when it occurs completely inside them. There is no such state as including an empty substring at an edge. For this reason, @word@ gains the characters added by assigning to @greet_bgn@ and @greet_end@, but the string @greet@ does not. */
372
373
374}
375
376
377int main(int argc, char ** argv) {
378
379 demo1();
380 demo2();
381 printf("%% %s done running\n", argv[0]);
382}
Note: See TracBrowser for help on using the repository browser.