- Timestamp:
- Nov 15, 2024, 5:48:11 PM (5 weeks ago)
- Branches:
- master
- Children:
- e255902b
- Parents:
- 2325b57
- Location:
- doc/theses/mike_brooks_MMath
- Files:
-
- 3 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
doc/theses/mike_brooks_MMath/Makefile
r2325b57 r489d3ba 10 10 TeXSRC = ${wildcard *.tex} 11 11 PicSRC = ${notdir ${wildcard ${Pictures}/*.png}} 12 Demo SRC = ${notdir ${wildcard ${Programs}/*-demo.cfa}}12 DemoPgmSRC = ${notdir ${wildcard ${Programs}/*-demo.cfa}} 13 13 PgmSRC = ${notdir ${wildcard ${Programs}/*}} 14 14 RunPgmSRC = ${notdir ${wildcard ${Programs}/*.run.*}} … … 24 24 BASE = ${basename ${DOCUMENT}} # remove suffix 25 25 26 DemoTex = ${DemoSRC:%.cfa=${Build}/%.tex}27 26 RunPgmExe = ${addprefix ${Build}/,${basename ${basename ${RunPgmSRC}}}} 28 27 RunPgmOut = ${RunPgmExe:%=%.out} 28 DemoPgmExe = ${addprefix ${Build}/,${basename ${basename ${DemoPgmSRC}}}} 29 DemoPgmOut = ${DemoPgmExe:%=%.out} 29 30 30 31 # Commands … … 38 39 # Rules and Recipes 39 40 40 .PHONY : all fragments_ran clean # not file names 41 .PRECIOUS : ${Build}/% ${Build}/%-demo # don't delete intermediates 41 .PHONY : all clean # not file names 42 .SECONDARY: 43 #.PRECIOUS : ${Build}/% # don't delete intermediates 42 44 .ONESHELL : 43 45 44 all : fragments_ran ${DOCUMENT} 45 46 fragments_ran : $(RunPgmOut) 46 all : ${DOCUMENT} 47 47 48 48 clean : … … 51 51 # File Dependencies 52 52 53 %.pdf : ${TeXSRC} $ {DemoTex} ${PicSRC} ${PgmSRC} ${BibSRC} ${BibRep}/pl.bib ${LaTMac}/common.tex Makefile | ${Build}53 %.pdf : ${TeXSRC} $(RunPgmOut) ${DemoPgmOut} ${PicSRC} ${BibSRC} ${BibRep}/pl.bib ${LaTMac}/common.tex Makefile | ${Build} 54 54 ${LaTeX} ${BASE} 55 55 ${BibTeX} ${Build}/${BASE} … … 64 64 mkdir -p $@ 65 65 66 %-demo.tex: %-demo| ${Build}67 $ < >$@66 ${Build}/%-demo: ${Programs}/%-demo.cfa | ${Build} 67 ${CFA} $< -o $@ 68 68 69 ${Build}/% -demo: ${Programs}/%-demo.cfa | ${Build}69 ${Build}/%: ${Programs}/%-demo.cfa | ${Build} 70 70 ${CFA} $< -o $@ 71 71 -
doc/theses/mike_brooks_MMath/programs/sharing-demo.cfa
r2325b57 r489d3ba 5 5 #define str(s) #s 6 6 7 ofstream outfile; 8 7 9 void demo1() { 8 10 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\\\\"; 11 // sout | "Consider two strings @s1@ and @s1a@ that are in an aliasing relationship, and a third, @s2@, made by a simple copy from @s1@."; 13 12 14 13 #define S1 string s1 = "abc" … … 21 20 assert( s1a == "abc" ); 22 21 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\\\\"; 22 23 open( outfile, "build/sharing1.tex" ); 24 outfile | "\\begin{cquote}"; 25 outfile | "\\begin{tabular}{@{}llll@{}}"; 26 outfile | "\t\t\t& @s1@\t& @s1a@\t& @s2@\t\\\\"; 27 outfile | xstr(S1) | "\t\\\\"; 28 outfile | xstr(S1A) | "\t\\\\"; 29 outfile | xstr(S2) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2; 30 outfile | "\\end{tabular}"; 31 outfile | "\\end{cquote}"; 32 close( outfile ); 33 34 // sout | "Aliasing (@`shareEdits@) means that changes flow in both directions; with a simple copy, they do not."; 35 open( outfile, "build/sharing2.tex" ); 36 outfile | "\\begin{cquote}"; 37 outfile | "\\begin{tabular}{@{}llll@{}}"; 38 outfile | "\t\t& @s1@\t& @s1a@\t& @s2@\t\\\\"; 39 outfile | "\\multicolumn{1}{r}{initial} & " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\"; 34 40 35 41 #define S1s1 s1 [1] = '+' 36 42 S1s1; 37 43 assert( s1 == "a+c" ); 38 sout| xstr(S1s1) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\";44 outfile | xstr(S1s1) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\"; 39 45 40 46 #define S1As1 s1a[1] = '-' 41 47 S1As1; 42 48 assert( s1a == "a-c" ); 43 sout| xstr(S1As1) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\";49 outfile | xstr(S1As1) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\"; 44 50 45 51 #define S2s1 s2 [1] = '|' 46 52 S2s1; 47 53 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\\\\"; 54 outfile | xstr(S2s1) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2; 55 outfile | "\\end{tabular}"; 56 outfile | "\\end{cquote}"; 57 close( outfile ); 58 59 // sout | "Assignment of a value is just a modificiation." 60 // "\nThe aliasing relationship is established at construction and is unaffected by assignment of a value."; 61 open( outfile, "build/sharing3.tex" ); 62 outfile | "\\begin{cquote}"; 63 outfile | "\\begin{tabular}{llll}"; 64 outfile | "\t\t& @s1@\t& @s1a@\t& @s2@\t\\\\"; 65 outfile | "\\multicolumn{1}{r}{initial} & " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\"; 58 66 59 67 #define S1qrs s1 = "qrs" 60 68 S1qrs; 61 69 assert( s1 == "qrs" ); 62 sout| xstr(S1qrs) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\";70 outfile | xstr(S1qrs) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\"; 63 71 64 72 #define S1Atuv s1a = "tuv" 65 73 S1Atuv; 66 74 assert( s1a == "tuv" ); 67 sout| xstr(S1Atuv) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\";75 outfile | xstr(S1Atuv) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\"; 68 76 69 77 #define S2wxy s2 = "wxy" 70 78 S2wxy; 71 79 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\\\\"; 80 outfile | xstr(S2wxy) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2; 81 outfile | "\\end{tabular}"; 82 outfile | "\\end{cquote}"; 83 close( outfile ); 84 85 // sout | "Assignment from a string is just assignment of a value." 86 // "\nWhether of not the RHS participates in aliasing is irrelevant. Any aliasing of the LHS is unaffected."; 87 open( outfile, "build/sharing4.tex" ); 88 outfile | "\\begin{cquote}"; 89 outfile | "\\begin{tabular}{llll}"; 90 outfile | "\t\t& @s1@\t& @s1a@\t& @s2@\t\\\\"; 91 outfile | "\\multicolumn{1}{r}{initial} & " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\"; 82 92 83 93 #define S1S2 s1 = s2 … … 86 96 assert( s1a == "wxy" ); 87 97 assert( s2 == "wxy" ); 88 sout| xstr(S1S2) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\";98 outfile | xstr(S1S2) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\"; 89 99 90 100 #define S1aaa s1 = "aaa" … … 93 103 assert( s1a == "aaa" ); 94 104 assert( s2 == "wxy" ); 95 sout| xstr(S1aaa) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\";105 outfile | xstr(S1aaa) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\"; 96 106 97 107 #define S2S1 s2 = s1 … … 100 110 assert( s1a == "aaa" ); 101 111 assert( s2 == "aaa" ); 102 sout| xstr(S2S1) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\";112 outfile | xstr(S2S1) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\"; 103 113 104 114 #define S2bbb s2 = "bbb" … … 107 117 assert( s1a == "aaa" ); 108 118 assert( s2 == "bbb" ); 109 sout| xstr(S2bbb) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\";119 outfile | xstr(S2bbb) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\"; 110 120 111 121 #define S2S1a s2 = s1a … … 114 124 assert( s1a == "aaa" ); 115 125 assert( s2 == "aaa" ); 116 sout| xstr(S2S1a) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\";126 outfile | xstr(S2S1a) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\"; 117 127 118 128 #define S2ccc s2 = "ccc" … … 121 131 assert( s1a == "aaa" ); 122 132 assert( s2 == "ccc" ); 123 sout| xstr(S2ccc) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\";133 outfile | xstr(S2ccc) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\"; 124 134 125 135 #define S1xxx s1 = "xxx" … … 128 138 assert( s1a == "xxx" ); 129 139 assert( s2 == "ccc" ); 130 sout | xstr(S1xxx) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\"; 131 sout | "\\end{tabular}"; 132 sout | "\\par"; 140 outfile | xstr(S1xxx) | "\t& " | s1 | "\t& " | s1a | "\t& " | s2 | "\t\\\\"; 141 outfile | "\\end{tabular}"; 142 outfile | "\\end{cquote}"; 143 close( outfile ); 133 144 } 134 145 135 146 136 147 void 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\\\\"; 148 // 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@."; 149 open( outfile, "build/sharing5.tex" ); 150 outfile | "\\begin{cquote}"; 151 outfile | "\\begin{tabular}{llll}"; 152 outfile | "\t\t\t\t& @s1@\t& @s1_mid@\t& @s2@\t\\\\"; 141 153 142 154 #define D2_s1_abcd string s1 = "abcd" 143 155 D2_s1_abcd; 144 sout| xstr(D2_s1_abcd) | "\t\\\\";156 outfile | xstr(D2_s1_abcd) | "\t\\\\"; 145 157 146 158 #define D2_s1mid_s1 string s1_mid = s1(1,2)`shareEdits 147 159 D2_s1mid_s1; 148 sout| xstr(D2_s1mid_s1) | "\t\\\\";160 outfile | xstr(D2_s1mid_s1) | "\t\\\\"; 149 161 150 162 #define D2_s2_s1 string s2 = s1(1,2) … … 153 165 assert( s1_mid == "bc" ); 154 166 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\\\\"; 167 outfile | xstr(D2_s2_s1) | "\t& " | s1 | "\t& " | s1_mid | "\t& " | s2 | "\t\\\\"; 168 outfile | "\\end{tabular}"; 169 outfile | "\\end{cquote}"; 170 close( outfile ); 171 172 // 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."; 173 open( outfile, "build/sharing6.tex" ); 174 outfile | "\\begin{cquote}"; 175 outfile | "\\begin{tabular}{llll}"; 176 outfile | "\t\t\t\t& @s1@\t& @s1_mid@\t& @s2@\t\\\\"; 177 outfile | "\\multicolumn{1}{r}{initial} & " | s1 | "\t& " | s1_mid | "\t& " | s2 | "\t\\\\"; 164 178 165 179 #define D2_s1_plus s1 [1] = '+' … … 168 182 assert( s1_mid == "+c" ); 169 183 assert( s2 == "bc" ); 170 sout| xstr(D2_s1_plus) | "\t& " | s1 | "\t& " | s1_mid | "\t& " | s2 | "\t\\\\";184 outfile | xstr(D2_s1_plus) | "\t& " | s1 | "\t& " | s1_mid | "\t& " | s2 | "\t\\\\"; 171 185 172 186 #define D2_s1mid_minus s1_mid[0] = '-' … … 175 189 assert( s1_mid == "-c" ); 176 190 assert( s2 == "bc" ); 177 sout| xstr(D2_s1mid_minus) | "\t& " | s1 | "\t& " | s1_mid | "\t& " | s2 | "\t\\\\";191 outfile | xstr(D2_s1mid_minus) | "\t& " | s1 | "\t& " | s1_mid | "\t& " | s2 | "\t\\\\"; 178 192 179 193 #define D2_s2_pipe s2 [0] = '|' … … 182 196 assert( s1_mid == "-c" ); 183 197 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\\\\"; 198 outfile | xstr(D2_s2_pipe) | "\t& " | s1 | "\t& " | s1_mid | "\t& " | s2 | "\t\\\\"; 199 outfile | "\\end{tabular}"; 200 outfile | "\\end{cquote}"; 201 close( outfile ); 202 203 // sout | "Once again, assignment of a value is a modificiation that flows through the aliasing relationship, without affecting its structure."; 204 open( outfile, "build/sharing7.tex" ); 205 outfile | "\\begin{cquote}"; 206 outfile | "\\begin{tabular}{llll}"; 207 outfile | "\t\t\t\t& @s1@\t& @s1_mid@\t& @s2@\t\\\\"; 208 outfile | "\\multicolumn{1}{r}{initial} & " | s1 | "\t& " | s1_mid | "\t& " | s2 | "\t\\\\"; 193 209 194 210 #define D2_s1mid_ff s1_mid = "ff" … … 197 213 assert( s1_mid == "ff" ); 198 214 assert( s2 == "|c" ); 199 sout| xstr(D2_s1mid_ff) | "\t& " | s1 | "\t& " | s1_mid | "\t& " | s2 | "\t\\\\";215 outfile | xstr(D2_s1mid_ff) | "\t& " | s1 | "\t& " | s1_mid | "\t& " | s2 | "\t\\\\"; 200 216 201 217 #define D2_s2_gg s2 = "gg" … … 204 220 assert( s1_mid == "ff" ); 205 221 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\\\\"; 222 outfile | xstr(D2_s2_gg) | "\t& " | s1 | "\t& " | s1_mid | "\t& " | s2 | "\t\\\\"; 223 outfile | "\\end{tabular}"; 224 outfile | "\\end{cquote}"; 225 close( outfile ); 226 227 // 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."; 228 // sout | "\\par"; 229 230 231 // 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."; 232 open( outfile, "build/sharing8.tex" ); 233 outfile | "\\begin{cquote}"; 234 outfile | "\\begin{tabular}{lll}"; 235 outfile | "\t\t\t\t& @s1@\t& @s1_mid@\t\\\\"; 236 outfile | "\\multicolumn{1}{r}{initial} & " | s1 | "\t& " | s1_mid | "\t\\\\"; 219 237 220 238 assert( s1 == "affd" ); 221 239 // assert( s1_mid == "fc" ); // ????????? bug? 222 sout| xstr(D2_s2_gg) | "\t& " | s1 | "\t& " | s1_mid | "\t\\\\";240 outfile | xstr(D2_s2_gg) | "\t& " | s1 | "\t& " | s1_mid | "\t\\\\"; 223 241 224 242 #define D2_s1mid_hhhh s1_mid = "hhhh" … … 226 244 assert( s1 == "ahhhhd" ); 227 245 assert( s1_mid == "hhhh" ); 228 sout| xstr(D2_s1mid_hhhh) | "\t& " | s1 | "\t& " | s1_mid | "\t\\\\";246 outfile | xstr(D2_s1mid_hhhh) | "\t& " | s1 | "\t& " | s1_mid | "\t\\\\"; 229 247 230 248 #define D2_s1mid_i s1_mid = "i" … … 232 250 assert( s1 == "aid" ); 233 251 assert( s1_mid == "i" ); 234 sout| xstr(D2_s1mid_i) | "\t& " | s1 | "\t& " | s1_mid | "\t\\\\";252 outfile | xstr(D2_s1mid_i) | "\t& " | s1 | "\t& " | s1_mid | "\t\\\\"; 235 253 236 254 #define D2_s1mid_empty s1_mid = "" … … 238 256 assert( s1 == "ad" ); 239 257 // assert( s1_mid == "" ); ------ Should be so, but fails 240 sout| xstr(D2_s1mid_empty) | "\t& " | s1 | "\t& " | s1_mid | "\t\\\\";258 outfile | xstr(D2_s1mid_empty) | "\t& " | s1 | "\t& " | s1_mid | "\t\\\\"; 241 259 242 260 #define D2_s1mid_jj s1_mid = "jj" … … 244 262 assert( s1 == "ajjd" ); 245 263 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\\\\"; 264 outfile | xstr(D2_s1mid_jj) | "\t& " | s1 | "\t& " | s1_mid | "\t\\\\"; 265 outfile | "\\end{tabular}"; 266 outfile | "\\end{cquote}"; 267 close( outfile ); 268 269 // 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."; 270 open( outfile, "build/sharing9.tex" ); 271 outfile | "\\begin{cquote}"; 272 outfile | "\\begin{tabular}{lllll}"; 273 outfile | "\t\t\t\t& @s1@\t& @s1_bgn@\t& @s1_mid@\t& @s1_end@\t\\\\"; 254 274 255 275 #define D2_s1bgn_s1 string s1_bgn = s1(0, 1)`shareEdits 256 276 D2_s1bgn_s1; 257 sout| xstr(D2_s1bgn_s1) | "\t\\\\";277 outfile | xstr(D2_s1bgn_s1) | "\t\\\\"; 258 278 259 279 #define D2_s1end_s1 string s1_end = s1(3, 1)`shareEdits … … 263 283 assert( s1_mid == "jj" ); 264 284 assert( s1_end == "d" ); 265 sout| xstr(D2_s1end_s1) | "\t& " | s1 | "\t& " | s1_bgn | "\t& " | s1_mid | "\t& " | s1_end | "\t\\\\";285 outfile | xstr(D2_s1end_s1) | "\t& " | s1 | "\t& " | s1_bgn | "\t& " | s1_mid | "\t& " | s1_end | "\t\\\\"; 266 286 267 287 #define D1_s1bgn_zzz s1_bgn = "zzzz" … … 271 291 assert( s1_mid == "jj" ); 272 292 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\\\\"; 293 outfile | xstr(D1_s1bgn_zzz) | "\t& " | s1 | "\t& " | s1_bgn | "\t& " | s1_mid | "\t& " | s1_end | "\t\\\\"; 294 outfile | "\\end{tabular}"; 295 outfile | "\\end{cquote}"; 296 close( outfile ); 297 298 // 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."; 299 open( outfile, "build/sharing10.tex" ); 300 outfile | "\\begin{cquote}"; 301 outfile | "\\begin{tabular}{llllll}"; 302 outfile | "\t\t\t\t& @s1@\t& @s1_bgn@\t& @s1_crs@\t& @s1_mid@\t& @s1_end@\t\\\\"; 281 303 282 304 #define D2_s1crs_s1 string s1_crs = s1(3, 2)`shareEdits … … 287 309 assert( s1_mid == "jj" ); 288 310 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\\\\";311 outfile | xstr(D2_s1crs_s1) | "\t& " | s1 | "\t& " | s1_bgn | "\t& " | s1_crs | "\t& " | s1_mid | "\t& " | s1_end | "\t\\\\"; 290 312 291 313 #define D2_s1crs_ppp s1_crs = "+++" … … 296 318 assert( s1_mid == "j" ); 297 319 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";320 outfile | xstr(D2_s1crs_ppp) | "\t& " | s1 | "\t& " | s1_bgn | "\t& " | s1_crs | "\t& " | s1_mid | "\t& " | s1_end | "\t\\\\"; 321 outfile | "\\end{tabular}"; 322 outfile | "\\end{cquote}"; 323 close( outfile ); 302 324 303 325 // "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." … … 379 401 demo1(); 380 402 demo2(); 381 printf("%% %s done running\n", argv[0]);403 // printf("%% %s done running\n", argv[0]); 382 404 } -
doc/theses/mike_brooks_MMath/string.tex
r2325b57 r489d3ba 67 67 \CFA provides a dynamic mechanism to indicate mutable or immutable as an assignment attribute: @`shareEdits@. 68 68 69 \input{sharing-demo.tex}70 71 69 Consider two strings @s1@ and @s1a@ that are in an aliasing relationship, and a third, @s2@, made by a simple copy from @s1@. 72 \par\noindent 73 \begin{tabular}{llll} 74 & @s1@ & @s1a@ & @s2@ \\ 75 %\input{sharing-demo1.tex} 76 \end{tabular} 77 \par\noindent 70 Aliasing (@`shareEdits@) means that changes flow in both directions; with a simple copy, they do not. 71 \input{sharing1.tex} 72 73 Aliasing (@`shareEdits@) means that changes flow in both directions; with a simple copy, they do not. 74 \input{sharing2.tex} 75 76 Assignment of a value is just a modification. 77 The aliasing relationship is established at construction and is unaffected by assignment of a value. 78 \input{sharing3.tex} 79 80 Assignment from a string is just assignment of a value. 81 Whether of not the RHS participates in aliasing is irrelevant. Any aliasing of the LHS is unaffected. 82 \input{sharing4.tex} 83 84 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@. 85 \input{sharing5.tex} 86 87 Again, @`shareEdits@ passes changes in both directions; copy does not. 88 Note the difference in index values, with the \emph{b} position being 1 in the longer string and 0 in the shorter strings. 89 In the case of s1 aliasing with @s1_mid@, the very same character is being accessed by different positions. 90 \input{sharing6.tex} 91 92 Once again, assignment of a value is a modification that flows through the aliasing relationship, without affecting its structure. 93 \input{sharing7.tex} 94 95 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). 96 The following rules for edits through aliasing substrings will guide how to flow in the opposite direction. 97 98 Growth and shrinkage are natural extensions. 99 An empty substring is a real thing, at a well-defined location, whose meaning is extrapolated from the examples so far. 100 The intended metaphor is to operating a GUI text editor. 101 Having an aliasing substring is like using the mouse to select a few words. 102 Assigning onto an aliasing substring is like typing from having a few words selected: depending how much you type, the file being edited can get shorter or longer. 103 \input{sharing8.tex} 104 105 Multiple portions can be aliased. 106 When there are several aliasing substrings at once, the text editor analogy becomes an online multi-user editor. 107 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. 108 \input{sharing9.tex} 109 110 When an edit happens on an aliasing substring that overlaps another, an effect is unavoidable. 111 Here, the passive party sees its selection shortened, to exclude the characters that were not part of the original selection. 112 \input{sharing10.tex} 113 114 TODO: finish typesetting the demo 115 116 %\input{sharing-demo.tex} 78 117 79 118 80 119 \subsection{RAII limitations} 81 120 82 Earlier work on \CFA [to cite Schluntz] implemented the feature of constructors and destructors. A constructor is a user-defined function that runs implicitly, when control passes an object's declaration, while a destructor runs at the exit of the declaration's lexical scope. The feature allows programmers to assume that, whenever a runtime object of a certain type is accessible, the system called one of the programmer's constructor functions on that object, and a matching destructor call will happen in the future. The feature helps programmers know that their programs' invariants obtain. 83 84 The purposes of such invariants go beyond ensuring authentic values for the bits inside the object. These invariants can track occurrences of the managed objects in other data structures. Reference counting is a typical application of the latter invariant type. With a reference-counting smart pointer, the constructor and destructor \emph{of the pointer type} track the life cycles of occurrences of these pointers, by incrementing and decrementing a counter (usually) on the referent object, that is, they maintain a that is state separate from the objects to whose life cycles they are attached. Both the \CC and \CFA RAII systems ares powerful enough to achieve such reference counting. 85 86 The \CC RAII system supports a more advanced application. A life cycle function has access to the object under management, by location; constructors and destructors receive a @this@ parameter providing its memory address. A lifecycle-function implementation can then add its objects to a collection upon creation, and remove them at destruction. A module that provides such objects, by using and encapsulating such a collection, can traverse the collection at relevant times, to keep the objects ``good.'' Then, if you are the user of such an module, declaring an object of its type means not only receiving an authentically ``good'' value at initialization, but receiving a subscription to a service that will keep the value ``good'' until you are done with it. 87 88 In many cases, the relationship between memory location and lifecycle is simple. But with stack-allocated objects being used as parameters and returns, there is a sender version in one stack frame and a receiver version in another. \CC is able to treat those versions as distinct objects and guarantee a copy-constructor call for communicating the value from one to the other. This ability has implications on the language's calling convention. Consider an ordinary function @void f( Vehicle x )@, which receives an aggregate by value. If the type @Vehicle@ has custom lifecycle functions, then a call to a user-provided copy constructor occurs, after the caller evaluates its argument expression, after the callee's stack frame exists, with room for its variable @x@ (which is the location that the copy-constructor must target), but before the user-provided body of @f@ begins executing. \CC achieves this ordering by changing the function signature, in the compiled form, to pass-by-reference and having the callee invoke the copy constructor in its preamble. On the other hand, if @Vehicle@ is a simple structure then the C calling convention is applied as the code originally appeared, that is, the call-site implementation code performs a bitwise copy from the caller's expression result, into the callee's x. 121 Earlier work on \CFA~\cite[ch.~2]{Schluntz17} implemented object constructors and destructors for all types (basic and user defined). 122 A constructor is a user-defined function run implicitly \emph{after} an object's declaration-storage is created, and a destructor is a user-defined function run \emph{before} an object's declaration-storage is deleted. 123 This feature guarantees pre invariants for users before accessing an object and post invariants for the programming environment after an object terminates. 124 125 The purposes of these invariants goes beyond ensuring authentic values inside an object. 126 Invariants can also track occurrences of the managed objects in other data structures. 127 For example, reference counting is a typical application of an invariant outside of the data values. 128 With a reference-counting smart-pointer, the constructor and destructor \emph{of a pointer type} tracks the life cycle of the object it points to. 129 Both \CC and \CFA RAII systems are powerful enough to achieve reference counting. 130 131 In general, a lifecycle function has access to an object by location, \ie constructors and destructors receive a @this@ parameter providing an object's memory address. 132 The lifecycle implementation can then add this object to a collection upon creation and remove it at destruction. 133 A module that provides such objects, by using and encapsulating such a collection, can traverse the collection at relevant times, to keep the objects ``good.''. 134 Hence, declaring such an object not only ensures ``good'' authentic at initialization, but also an implicit subscription to a service that keeps the value ``good'' across its lifetime. 135 136 In many cases, the relationship between memory location and lifecycle is simple. 137 But with stack-allocated objects being used as parameters and returns, there is a sender version in one stack frame and a receiver version in another. 138 \CC is able to treat those versions as distinct objects and guarantee a copy-constructor call for communicating the value from one to the other. 139 This ability has implications on the language's calling convention. 140 Consider an ordinary function @void f( Vehicle x )@, which receives an aggregate by value. 141 If the type @Vehicle@ has custom lifecycle functions, then a call to a user-provided copy constructor occurs, after the caller evaluates its argument expression, after the callee's stack frame exists, with room for its variable @x@ (which is the location that the copy-constructor must target), but before the user-provided body of @f@ begins executing. 142 \CC achieves this ordering by changing the function signature, in the compiled form, to pass-by-reference and having the callee invoke the copy constructor in its preamble. 143 On the other hand, if @Vehicle@ is a simple structure then the C calling convention is applied as the code originally appeared, that is, the call-site implementation code performs a bitwise copy from the caller's expression result, into the callee's x. 89 144 90 145 TODO: learn correction to fix inconsistency: this discussion says the callee invokes the copy constructor, but only the caller knows which copy constructor to use! … … 149 204 150 205 The \CFA sting library provides the @string_sharectx@ type to control an ambient sharing context for the current thread. It allows two adjustments: to opt out of sharing entirely, or to begin sharing within a private context. Either way, the chosen mode applies to the current thread, for the duration of the lifetime of the created @string_sharectx@ object, up to being suspended by child lifetimes of different contexts. The indented use is with stack-managed lifetimes, in which the established context lasts until the current function returns, and affects all functions called that don't create their own contexts. 151 \lstinputlisting[language=CFA, firstline=20, lastline=34]{sharectx -demo.cfa}206 \lstinputlisting[language=CFA, firstline=20, lastline=34]{sharectx.run.cfa} 152 207 In this example, the single-letter functions are called in alphabetic order. The functions @a@ and @d@ share string character ranges within themselves, but not with each other. The functions @b@, @c@ and @e@ never share anything. 153 208 … … 169 224 \subsection{Performance assessment} 170 225 171 I assessed the CFA string library's speed and memory usage. I present these results in even equivalent cases, due to either micro-optimizations foregone, or fundamental costs of the added functionality. They also show the benefits and tradeoffs, as >100\% effects, of switching to CFA, with the tradeoff points quantified. The final test shows the overall win of the CFA text-sharing mechanism. It exercises several operations together, showingCFA enabling clean user code to achieve performance that STL requires less-clean user code to achieve.172 173 To discuss: general goal of ... while STL makes you think about memory management, all the time, and if you do your performance can be great ... CFA sacrifices this advantage modestly in exchange for big wins when you're not thinking about memory management. [Does this position cover all of it?]226 I assessed the \CFA string library's speed and memory usage. I present these results in even equivalent cases, due to either micro-optimizations foregone, or fundamental costs of the added functionality. They also show the benefits and tradeoffs, as >100\% effects, of switching to \CFA, with the tradeoff points quantified. The final test shows the overall win of the \CFA text-sharing mechanism. It exercises several operations together, showing \CFA enabling clean user code to achieve performance that STL requires less-clean user code to achieve. 227 228 To discuss: general goal of ... while STL makes you think about memory management, all the time, and if you do your performance can be great ... \CFA sacrifices this advantage modestly in exchange for big wins when you're not thinking about memory management. [Does this position cover all of it?] 174 229 175 230 To discuss: revisit HL v LL APIs … … 196 251 \subsubsection{Test: Append} 197 252 198 This test measures the speed of appending fragments of text onto a growing string. Its subcases include both CFA being similar to STL, and their designs offering a tradeoff.253 This test measures the speed of appending fragments of text onto a growing string. Its subcases include both \CFA being similar to STL, and their designs offering a tradeoff. 199 254 200 255 One experimental variable is the user's operation being @a = a + b@ vs. @a += b@. While experienced programmers expect the latter to be ``what you obviously should do,'' controlling the penalty of the former both helps the API be accessible to beginners and also helps offer confidence that when a user tries to compose operations, the forms that are most natural to the user's composition are viable. … … 210 265 @ } @ & @ } @ 211 266 \end{tabular}\\ 212 These benchmark drivers have an outer loop for ``until a sample-worthy amount of execution has happened'' and an inner loop for ``build up the desired-length string.'' It is sensible to doubt that a user should have to care about this difference, yet the STL performs differently in these cases. Concretely, both cases incur the cost of copying characters into the target string, but only the allocation-fresh case incurs a further reallocation cost, which is generally paid at points of doubling the length. For the STL, this cost includes obtaining a fresh buffer from the memory allocator and copying older characters into the new buffer, while CFA-sharing hides such a cost entirely. The reuse-vs-fresh distinction is only relevant in the current \emph{append} tests.267 These benchmark drivers have an outer loop for ``until a sample-worthy amount of execution has happened'' and an inner loop for ``build up the desired-length string.'' It is sensible to doubt that a user should have to care about this difference, yet the STL performs differently in these cases. Concretely, both cases incur the cost of copying characters into the target string, but only the allocation-fresh case incurs a further reallocation cost, which is generally paid at points of doubling the length. For the STL, this cost includes obtaining a fresh buffer from the memory allocator and copying older characters into the new buffer, while \CFA-sharing hides such a cost entirely. The reuse-vs-fresh distinction is only relevant in the current \emph{append} tests. 213 268 214 269 The \emph{append} tests use the varying-from-1 corpus construction; that is they do not assume away the STL's advantage from small-string optimization. … … 230 285 \end{figure} 231 286 232 In sharing mode, \CFA makes the fresh/reuse difference disappear, as shown in Figure \ref{fig:string-graph-peq-sharing}. At append lengths 5 and above, CFA not only splits the two baseline STL cases, but its slowdown of 16\% over (STL with user-managed reuse) is close to the \CFA-v-STL implementation difference seen with \CFA in STL-emulation mode.287 In sharing mode, \CFA makes the fresh/reuse difference disappear, as shown in Figure \ref{fig:string-graph-peq-sharing}. At append lengths 5 and above, \CFA not only splits the two baseline STL cases, but its slowdown of 16\% over (STL with user-managed reuse) is close to the \CFA-v-STL implementation difference seen with \CFA in STL-emulation mode. 233 288 234 289 \begin{figure} … … 238 293 \end{figure} 239 294 240 When the user takes a further step beyond the STL's optimal zone, by running @x = x + y@, as in Figure \ref{fig:string-graph-pta-sharing}, the STL's penalty is above $15 \times$ while CFA's (with sharing) is under $2 \times$, averaged across the cases shown here. Moreover, the STL's gap increases with string size, while \CFA's converges.295 When the user takes a further step beyond the STL's optimal zone, by running @x = x + y@, as in Figure \ref{fig:string-graph-pta-sharing}, the STL's penalty is above $15 \times$ while \CFA's (with sharing) is under $2 \times$, averaged across the cases shown here. Moreover, the STL's gap increases with string size, while \CFA's converges. 241 296 242 297 \subsubsection{Test: Pass argument} … … 275 330 \begin{figure} 276 331 \includegraphics[width=\textwidth]{string-graph-allocn.png} 277 \caption{Space and time performance, under varying fraction-live targets, for the five string lengths shown, at (\emph{Fixed-size} corpus construction. [MISSING] The identified clusters are for the default fraction-live target, which is 30\%. MISSING: STL results, typically just below the 0.5--0.9 CFA segment. All runs keep an average of 836 strings live, and the median string lifetime is ?? allocations.}332 \caption{Space and time performance, under varying fraction-live targets, for the five string lengths shown, at (\emph{Fixed-size} corpus construction. [MISSING] The identified clusters are for the default fraction-live target, which is 30\%. MISSING: STL results, typically just below the 0.5--0.9 \CFA segment. All runs keep an average of 836 strings live, and the median string lifetime is ?? allocations.} 278 333 \label{fig:string-graph-allocn} 279 334 \end{figure} … … 285 340 \subsubsection{Test: Normalize} 286 341 287 This test is more applied than the earlier ones. It combines the effects of several operations. It also demonstrates a case of the CFA API allowing user code to perform well, while being written without overt memory management, while achieving similar performance in STL requires adding memory-management complexity.342 This test is more applied than the earlier ones. It combines the effects of several operations. It also demonstrates a case of the \CFA API allowing user code to perform well, while being written without overt memory management, while achieving similar performance in STL requires adding memory-management complexity. 288 343 289 344 To motivate: edits being rare
Note: See TracChangeset
for help on using the changeset viewer.