# source:doc/theses/mike_brooks_MMath/content/string/sharing-demo.cfa@12048a1

Last change on this file since 12048a1 was 12048a1, checked in by Michael Brooks <mlbrooks@…>, 2 years ago

Simplifying the substring-aliasing demo's code-gen

• Property mode set to 100644
File size: 13.4 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 | sepDisable;;
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 = s1shareEdits
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,3)shareEdits
147        D2_s1mid_s1;
148        sout | xstr(D2_s1mid_s1) | "\t\\\\";
149
150        #define D2_s2_s1 string s2     = s1(1,3)
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, 4)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, 5)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,3)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,15)shareEdits;
321        string greet_bgn = all(10,11)shareEdits;
322        string greet_end = all(14,15)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.