diff options
32 files changed, 767 insertions, 217 deletions
diff --git a/html/002test.cc.html b/html/002test.cc.html index 84903a24..3afbc33d 100644 --- a/html/002test.cc.html +++ b/html/002test.cc.html @@ -91,8 +91,8 @@ Passed = <span class="Constant">true</span><span class="Delimiter">;</span> <span class="CommentedCode">//? cerr << i << '\n';</span> run_test<span class="Delimiter">(</span>i<span class="Delimiter">);</span> <span class="Delimiter">}</span> - <span class="Comment">// End Tests</span> cerr << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + <span class="Comment">// End Tests</span> <span class="Normal">if</span> <span class="Delimiter">(</span>Num_failures > <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> cerr << Num_failures << <span class="Constant">" failure"</span> << <span class="Delimiter">(</span>Num_failures > <span class="Constant">1</span> ? <span class="Constant">"s"</span> : <span class="Constant">""</span><span class="Delimiter">)</span> diff --git a/html/003trace.cc.html b/html/003trace.cc.html index 13cba511..33c54ba1 100644 --- a/html/003trace.cc.html +++ b/html/003trace.cc.html @@ -309,6 +309,18 @@ START_TRACING_UNTIL_END_OF_SCOPE <span class="Identifier">return</span> result<span class="Delimiter">;</span> <span class="Delimiter">}</span> +<span class="Normal">int</span> trace_count_prefix<span class="Delimiter">(</span>string label<span class="Delimiter">,</span> string prefix<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!Trace_stream<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">0</span><span class="Delimiter">;</span> + <span class="Normal">long</span> result = <span class="Constant">0</span><span class="Delimiter">;</span> + <span class="Normal">for</span> <span class="Delimiter">(</span>vector<trace_line>::iterator p = Trace_stream<span class="Delimiter">-></span>past_lines<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != Trace_stream<span class="Delimiter">-></span>past_lines<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>label == p<span class="Delimiter">-></span>label<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>starts_with<span class="Delimiter">(</span>trim<span class="Delimiter">(</span>p<span class="Delimiter">-></span>contents<span class="Delimiter">),</span> trim<span class="Delimiter">(</span>prefix<span class="Delimiter">)))</span> + ++result<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + <span class="Identifier">return</span> result<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + <span class="PreProc">#define CHECK_TRACE_CONTAINS_ERROR() CHECK(trace_count(</span><span class="Constant">"error"</span><span class="PreProc">) > </span><span class="Constant">0</span><span class="PreProc">)</span> <span class="PreProc">#define CHECK_TRACE_DOESNT_CONTAIN_ERROR() \</span> <span class="PreProc"> </span><span class="Normal">if</span><span class="PreProc"> (trace_count(</span><span class="Constant">"error"</span><span class="PreProc">) > </span><span class="Constant">0</span><span class="PreProc">) </span><span class="Delimiter">{</span><span class="PreProc"> \</span> diff --git a/html/014literal_string.cc.html b/html/014literal_string.cc.html index 80844f8d..c917373b 100644 --- a/html/014literal_string.cc.html +++ b/html/014literal_string.cc.html @@ -74,8 +74,8 @@ string slurp_quoted<span class="Delimiter">(</span>istream& in<span class="D <span class="Identifier">return</span> out<span class="Delimiter">.</span>str<span class="Delimiter">();</span> <span class="Delimiter">}</span> -<span class="Comment">// A string is a code string if it contains a newline before any non-whitespace</span> -<span class="Comment">// todo: support comments before the newline. But that gets messy.</span> +<span class="Comment">// A string is a code string (ignores comments when scanning for matching</span> +<span class="Comment">// brackets) if it contains a newline at the start before any non-whitespace.</span> <span class="Normal">bool</span> is_code_string<span class="Delimiter">(</span>istream& in<span class="Delimiter">,</span> ostream& out<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">while</span> <span class="Delimiter">(</span>has_data<span class="Delimiter">(</span>in<span class="Delimiter">))</span> <span class="Delimiter">{</span> <span class="Normal">char</span> c = in<span class="Delimiter">.</span>get<span class="Delimiter">();</span> diff --git a/html/020run.cc.html b/html/020run.cc.html index f3a54f18..acfcb8a4 100644 --- a/html/020run.cc.html +++ b/html/020run.cc.html @@ -95,7 +95,7 @@ map<string<span class="Delimiter">,</span> <span class="Normal">int</span>> <span class="Delimiter">}</span> <span class="Normal">void</span> run_current_routine<span class="Delimiter">()</span> -<span class="Delimiter">{</span> <span class="Comment">// curly on a separate line, because later layers will modify header</span> +<span class="Delimiter">{</span> <span class="Comment">// curly on a separate line, because later layers will modify function header</span> <span class="Normal">while</span> <span class="Delimiter">(</span>!Current_routine<span class="Delimiter">-></span>completed<span class="Delimiter">())</span> <span class="Comment">// later layers will modify condition</span> <span class="Delimiter">{</span> <span class="Comment">// Running One Instruction</span> @@ -124,14 +124,16 @@ map<string<span class="Delimiter">,</span> <span class="Normal">int</span>> cout << <span class="Constant">"not a primitive op: "</span> << current_instruction<span class="Delimiter">().</span>operation << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> + <span class="Comment">// Write Products of Instruction</span> <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>products<span class="Delimiter">)</span> < SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">))</span> <span class="Delimiter">{</span> raise << SIZE<span class="Delimiter">(</span>products<span class="Delimiter">)</span> << <span class="Constant">" vs "</span> << SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">)</span> << <span class="Constant">": failed to write to all products! "</span> << to_original_string<span class="Delimiter">(</span>current_instruction<span class="Delimiter">())</span> << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> <span class="Delimiter">}</span> <span class="Normal">else</span> <span class="Delimiter">{</span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> - write_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> i<span class="Delimiter">);</span> + write_memory<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> <span class="Delimiter">}</span> - <span class="Comment">// End of Instruction</span> + <span class="Comment">// End Write Products of Instruction</span> + <span class="Comment">// End Running One Instruction</span> <span class="Normal">finish_instruction</span>:<span class="Delimiter">;</span> ++current_step_index<span class="Delimiter">();</span> <span class="Delimiter">}</span> @@ -315,7 +317,8 @@ vector<<span class="Normal">double</span>> read_memory<span class="Delimit <span class="Identifier">return</span> result<span class="Delimiter">;</span> <span class="Delimiter">}</span> -<span class="Normal">void</span> write_memory<span class="Delimiter">(</span>reagent<span class="Comment">/*</span><span class="Comment">copy</span><span class="Comment">*/</span> x<span class="Delimiter">,</span> <span class="Normal">const</span> vector<<span class="Normal">double</span>>& data<span class="Delimiter">,</span> <span class="Normal">const</span> <span class="Normal">int</span> <span class="Comment">/*</span><span class="Comment">only when called in the run loop above to save results; -1 otherwise</span><span class="Comment">*/</span> product_index<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="Normal">void</span> write_memory<span class="Delimiter">(</span>reagent<span class="Comment">/*</span><span class="Comment">copy</span><span class="Comment">*/</span> x<span class="Delimiter">,</span> <span class="Normal">const</span> vector<<span class="Normal">double</span>>& data<span class="Delimiter">)</span> <span class="Delimiter">{</span> + assert<span class="Delimiter">(</span>Current_routine<span class="Delimiter">);</span> <span class="Comment">// run-time only</span> <span class="Comment">// Begin Preprocess write_memory(x, data)</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!x<span class="Delimiter">.</span>type<span class="Delimiter">)</span> <span class="Delimiter">{</span> raise << <span class="Constant">"can't write to '"</span> << to_string<span class="Delimiter">(</span>x<span class="Delimiter">)</span> << <span class="Constant">"'; no type</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> @@ -371,7 +374,7 @@ vector<<span class="Normal">double</span>> read_memory<span class="Delimit <span class="Delimiter">}</span> <span class="Comment">// helper for tests</span> -<span class="Normal">void</span> run<span class="Delimiter">(</span>string form<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="Normal">void</span> run<span class="Delimiter">(</span><span class="Normal">const</span> string& form<span class="Delimiter">)</span> <span class="Delimiter">{</span> vector<recipe_ordinal> tmp = load<span class="Delimiter">(</span>form<span class="Delimiter">);</span> transform_all<span class="Delimiter">();</span> <span class="Normal">if</span> <span class="Delimiter">(</span>tmp<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">return</span><span class="Delimiter">;</span> diff --git a/html/021check_instruction.cc.html b/html/021check_instruction.cc.html index fc6ef270..c96bd6ab 100644 --- a/html/021check_instruction.cc.html +++ b/html/021check_instruction.cc.html @@ -237,6 +237,13 @@ $error: <span class="Constant">0</span> <span class="Identifier">return</span> r<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value == get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"number"</span><span class="Delimiter">);</span> <span class="Delimiter">}</span> +<span class="Normal">bool</span> is_mu_character<span class="Delimiter">(</span>reagent<span class="Comment">/*</span><span class="Comment">copy</span><span class="Comment">*/</span> r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Comment">// End Preprocess is_mu_character(reagent r)</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!r<span class="Delimiter">.</span>type<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>is_literal<span class="Delimiter">(</span>r<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + <span class="Identifier">return</span> r<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value == get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"character"</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + <span class="Normal">bool</span> is_mu_scalar<span class="Delimiter">(</span>reagent<span class="Comment">/*</span><span class="Comment">copy</span><span class="Comment">*/</span> r<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!r<span class="Delimiter">.</span>type<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_literal<span class="Delimiter">(</span>r<span class="Delimiter">))</span> diff --git a/html/022arithmetic.cc.html b/html/022arithmetic.cc.html index 510b5a4c..728eef67 100644 --- a/html/022arithmetic.cc.html +++ b/html/022arithmetic.cc.html @@ -21,6 +21,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color .cSpecial { color: #008000; } .Identifier { color: #fcb165; } .Normal { color: #eeeeee; background-color: #080808; padding-bottom: 1px; } +.PreProc { color: #800080; } --> </style> @@ -718,6 +719,73 @@ def main [ <span class="Constant">1</span>:number<span class="Special"> <- </span>flip-bits <span class="Constant">12</span> ] <span class="traceContains">+mem: storing -13 in location 1</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +ROUND<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"round"</span><span class="Delimiter">,</span> ROUND<span class="Delimiter">);</span> +<span class="Delimiter">:(before "End Primitive Recipe Checks")</span> +<span class="Normal">case</span> ROUND: <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'round' requires exactly one ingredient, but got '"</span> << inst<span class="Delimiter">.</span>original_string << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"first ingredient of 'round' should be a number, but got '"</span> << inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +<span class="Normal">case</span> ROUND: <span class="Delimiter">{</span> + products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> + products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>rint<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)));</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario round_to_nearest_integer)</span> +def main [ + <span class="Constant">1</span>:number<span class="Special"> <- </span>round <span class="Constant">12.2</span> +] +<span class="traceContains">+mem: storing 12 in location 1</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +CHARACTER_TO_CODE<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"character-to-code"</span><span class="Delimiter">,</span> CHARACTER_TO_CODE<span class="Delimiter">);</span> +<span class="Delimiter">:(before "End Primitive Recipe Checks")</span> +<span class="Normal">case</span> CHARACTER_TO_CODE: <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'character-to-code' requires exactly one ingredient, but got '"</span> << inst<span class="Delimiter">.</span>original_string << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_character<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"first ingredient of 'character-to-code' should be a character, but got '"</span> << inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'character-to-code' requires exactly one product, but got '"</span> << inst<span class="Delimiter">.</span>original_string << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"first product of 'character-to-code' should be a number, but got '"</span> << inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +<span class="Normal">case</span> CHARACTER_TO_CODE: <span class="Delimiter">{</span> + <span class="Normal">double</span> result = <span class="Constant">0</span><span class="Delimiter">;</span> + <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + result += ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> + <span class="Delimiter">}</span> + products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> + products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>result<span class="Delimiter">);</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(before "End Includes")</span> +<span class="PreProc">#include </span><span class="Constant"><math.h></span> </pre> </body> </html> diff --git a/html/027call_ingredient.cc.html b/html/027call_ingredient.cc.html index 3f159981..0fc668d6 100644 --- a/html/027call_ingredient.cc.html +++ b/html/027call_ingredient.cc.html @@ -67,6 +67,7 @@ next_ingredient_to_process = <span class="Constant">0</span><span class="Delimit reagent<span class="Comment">/*</span><span class="Comment">copy</span><span class="Comment">*/</span> ingredient = call_instruction<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> <span class="Comment">// End Compute Call Ingredient</span> current_call<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>ingredient<span class="Delimiter">);</span> + <span class="Comment">// End Populate Call Ingredient</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> diff --git a/html/032array.cc.html b/html/032array.cc.html index 7b551645..cd0955f2 100644 --- a/html/032array.cc.html +++ b/html/032array.cc.html @@ -447,7 +447,7 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span reagent element<span class="Delimiter">;</span> element<span class="Delimiter">.</span>type = copy_array_element<span class="Delimiter">(</span>base<span class="Delimiter">.</span>type<span class="Delimiter">);</span> <span class="Normal">int</span> address = base_address + <span class="Constant">1</span> + index_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span>*size_of<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">);</span> - element<span class="Delimiter">.</span>value = address<span class="Delimiter">;</span> + element<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>address<span class="Delimiter">);</span> trace<span class="Delimiter">(</span><span class="Constant">9998</span><span class="Delimiter">,</span> <span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"address to copy to is "</span> << address << end<span class="Delimiter">();</span> <span class="Comment">// optimization: directly write the element rather than updating 'product'</span> <span class="Comment">// and writing the entire array</span> diff --git a/html/035lookup.cc.html b/html/035lookup.cc.html index 49ab32c8..c6fa72cf 100644 --- a/html/035lookup.cc.html +++ b/html/035lookup.cc.html @@ -172,6 +172,8 @@ def main [ <span class="Normal">if</span> <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>r<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Delimiter">:(before "End Preprocess is_mu_boolean(reagent r)")</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>r<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Preprocess is_mu_character(reagent r)")</span> +<span class="Normal">if</span> <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>r<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Delimiter">:(after "Update product While Type-checking Merge")</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>product<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> diff --git a/html/036refcount.cc.html b/html/036refcount.cc.html index 05896aad..c1f923ae 100644 --- a/html/036refcount.cc.html +++ b/html/036refcount.cc.html @@ -22,6 +22,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color .Special { color: #c00000; } .Identifier { color: #fcb165; } .Normal { color: #eeeeee; background-color: #080808; padding-bottom: 1px; } +.Todo { color: #000000; background-color: #ffff00; padding-bottom: 1px; } --> </style> @@ -52,54 +53,65 @@ def main [ <span class="traceContains">+run: {2: ("address" "number")} <- copy {0: "literal"}</span> <span class="traceContains">+mem: decrementing refcount of 1000: 1 -> 0</span> +<span class="Delimiter">:(before "End Globals")</span> +<span class="Comment">//: escape hatch for a later layer</span> +<span class="Normal">bool</span> Update_refcounts_in_write_memory = <span class="Constant">true</span><span class="Delimiter">;</span> + <span class="Delimiter">:(before "End write_memory(x) Special-cases")</span> -<span class="Normal">if</span> <span class="Delimiter">(</span>should_update_refcounts_in_write_memory<span class="Delimiter">(</span>product_index<span class="Delimiter">))</span> <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_address<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Delimiter">{</span> +<span class="Normal">if</span> <span class="Delimiter">(</span>Update_refcounts_in_write_memory<span class="Delimiter">)</span> + update_any_refcounts<span class="Delimiter">(</span>x<span class="Delimiter">,</span> data<span class="Delimiter">);</span> + +<span class="Delimiter">:(code)</span> +<span class="Normal">void</span> update_any_refcounts<span class="Delimiter">(</span><span class="Normal">const</span> reagent& canonized_x<span class="Delimiter">,</span> <span class="Normal">const</span> vector<<span class="Normal">double</span>>& data<span class="Delimiter">)</span> <span class="Delimiter">{</span> + increment_any_refcounts<span class="Delimiter">(</span>canonized_x<span class="Delimiter">,</span> data<span class="Delimiter">);</span> <span class="Comment">// increment first so we don't reclaim on x <- copy x</span> + decrement_any_refcounts<span class="Delimiter">(</span>canonized_x<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +<span class="Normal">void</span> increment_any_refcounts<span class="Delimiter">(</span><span class="Normal">const</span> reagent& canonized_x<span class="Delimiter">,</span> <span class="Normal">const</span> vector<<span class="Normal">double</span>>& data<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_address<span class="Delimiter">(</span>canonized_x<span class="Delimiter">))</span> <span class="Delimiter">{</span> assert<span class="Delimiter">(</span>scalar<span class="Delimiter">(</span>data<span class="Delimiter">));</span> - assert<span class="Delimiter">(</span>x<span class="Delimiter">.</span>value<span class="Delimiter">);</span> - assert<span class="Delimiter">(</span>!x<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span>size<span class="Delimiter">);</span> - update_refcounts<span class="Delimiter">(</span>x<span class="Delimiter">,</span> data<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> + assert<span class="Delimiter">(</span>!canonized_x<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span>size<span class="Delimiter">);</span> + increment_refcount<span class="Delimiter">(</span>data<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> <span class="Delimiter">}</span> - <span class="Comment">// End Update Refcounts in write_memory(x)</span> + <span class="Comment">// End Increment Refcounts(canonized_x)</span> <span class="Delimiter">}</span> -<span class="Delimiter">:(code)</span> -<span class="Comment">//: hook for a later layer</span> -<span class="Normal">bool</span> should_update_refcounts_in_write_memory<span class="Delimiter">(</span><span class="Normal">int</span> product_index<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> +<span class="Normal">void</span> increment_refcount<span class="Delimiter">(</span><span class="Normal">int</span> new_address<span class="Delimiter">)</span> <span class="Delimiter">{</span> + assert<span class="Delimiter">(</span>new_address >= <span class="Constant">0</span><span class="Delimiter">);</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>new_address == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Normal">int</span> new_refcount = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> new_address<span class="Delimiter">);</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"incrementing refcount of "</span> << new_address << <span class="Constant">": "</span> << new_refcount << <span class="Constant">" -> "</span> << new_refcount+<span class="Constant">1</span> << end<span class="Delimiter">();</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> new_address<span class="Delimiter">,</span> new_refcount+<span class="Constant">1</span><span class="Delimiter">);</span> <span class="Delimiter">}</span> -<span class="Normal">void</span> update_refcounts<span class="Delimiter">(</span><span class="Normal">const</span> reagent& old<span class="Delimiter">,</span> <span class="Normal">int</span> new_address<span class="Delimiter">)</span> <span class="Delimiter">{</span> - assert<span class="Delimiter">(</span>is_mu_address<span class="Delimiter">(</span>old<span class="Delimiter">));</span> - update_refcounts<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> old<span class="Delimiter">.</span>value<span class="Delimiter">),</span> new_address<span class="Delimiter">,</span> old<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">,</span> payload_size<span class="Delimiter">(</span>old<span class="Delimiter">));</span> +<span class="Normal">void</span> decrement_any_refcounts<span class="Delimiter">(</span><span class="Normal">const</span> reagent& canonized_x<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_address<span class="Delimiter">(</span>canonized_x<span class="Delimiter">))</span> <span class="Delimiter">{</span> + assert<span class="Delimiter">(</span>canonized_x<span class="Delimiter">.</span>value<span class="Delimiter">);</span> + assert<span class="Delimiter">(</span>!canonized_x<span class="Delimiter">.</span>metadata<span class="Delimiter">.</span>size<span class="Delimiter">);</span> + decrement_refcount<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> canonized_x<span class="Delimiter">.</span>value<span class="Delimiter">),</span> canonized_x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">,</span> payload_size<span class="Delimiter">(</span>canonized_x<span class="Delimiter">));</span> + <span class="Delimiter">}</span> + <span class="Comment">// End Decrement Refcounts(canonized_x)</span> <span class="Delimiter">}</span> -<span class="Normal">void</span> update_refcounts<span class="Delimiter">(</span><span class="Normal">int</span> old_address<span class="Delimiter">,</span> <span class="Normal">int</span> new_address<span class="Delimiter">,</span> <span class="Normal">const</span> type_tree* payload_type<span class="Delimiter">,</span> <span class="Normal">int</span> <span class="Comment">/*</span><span class="Comment">just in case it's an array</span><span class="Comment">*/</span>payload_size<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>old_address == new_address<span class="Delimiter">)</span> <span class="Delimiter">{</span> - trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"copying address to itself; refcount unchanged"</span> << end<span class="Delimiter">();</span> - <span class="Identifier">return</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> - <span class="Comment">// decrement refcount of old address</span> +<span class="Normal">void</span> decrement_refcount<span class="Delimiter">(</span><span class="Normal">int</span> old_address<span class="Delimiter">,</span> <span class="Normal">const</span> type_tree* payload_type<span class="Delimiter">,</span> <span class="Normal">int</span> payload_size<span class="Delimiter">)</span> <span class="Delimiter">{</span> assert<span class="Delimiter">(</span>old_address >= <span class="Constant">0</span><span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>old_address<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">int</span> old_refcount = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> old_address<span class="Delimiter">);</span> - trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"decrementing refcount of "</span> << old_address << <span class="Constant">": "</span> << old_refcount << <span class="Constant">" -> "</span> << <span class="Delimiter">(</span>old_refcount-<span class="Constant">1</span><span class="Delimiter">)</span> << end<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"decrementing refcount of "</span> << old_address << <span class="Constant">": "</span> << old_refcount << <span class="Constant">" -> "</span> << old_refcount-<span class="Constant">1</span> << end<span class="Delimiter">();</span> --old_refcount<span class="Delimiter">;</span> put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> old_address<span class="Delimiter">,</span> old_refcount<span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>old_refcount < <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> tb_shutdown<span class="Delimiter">();</span> - DUMP<span class="Delimiter">(</span><span class="Constant">""</span><span class="Delimiter">);</span> - cerr << <span class="Constant">"Negative refcount: "</span> << old_address << <span class="Constant">' '</span> << old_refcount << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + cerr << <span class="Constant">"Negative refcount!!! "</span> << old_address << <span class="Constant">' '</span> << old_refcount << <span class="cSpecial">'\n'</span><span class="Delimiter">;</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>Trace_stream<span class="Delimiter">)</span> <span class="Delimiter">{</span> + cerr << <span class="Constant">"Saving trace to last_trace.</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">;</span> + ofstream fout<span class="Delimiter">(</span><span class="Constant">"last_trace"</span><span class="Delimiter">);</span> + fout << Trace_stream<span class="Delimiter">-></span>readable_contents<span class="Delimiter">(</span><span class="Constant">""</span><span class="Delimiter">);</span> + fout<span class="Delimiter">.</span>close<span class="Delimiter">();</span> + <span class="Delimiter">}</span> exit<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> <span class="Delimiter">}</span> - <span class="Comment">// End Decrement Reference Count(old_address, payload_type, payload_size)</span> - <span class="Delimiter">}</span> - <span class="Comment">// increment refcount of new address</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>new_address<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">int</span> new_refcount = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> new_address<span class="Delimiter">);</span> - assert<span class="Delimiter">(</span>new_refcount >= <span class="Constant">0</span><span class="Delimiter">);</span> <span class="Comment">// == 0 only when new_address == old_address</span> - trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"incrementing refcount of "</span> << new_address << <span class="Constant">": "</span> << new_refcount << <span class="Constant">" -> "</span> << <span class="Delimiter">(</span>new_refcount+<span class="Constant">1</span><span class="Delimiter">)</span> << end<span class="Delimiter">();</span> - put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> new_address<span class="Delimiter">,</span> new_refcount+<span class="Constant">1</span><span class="Delimiter">);</span> + <span class="Comment">// End Decrement Refcount(old_address, payload_type, payload_size)</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> @@ -118,7 +130,8 @@ def main [ <span class="traceContains">+run: {1: ("address" "number")} <- new {number: "type"}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 0 -> 1</span> <span class="traceContains">+run: {1: ("address" "number")} <- copy {1: ("address" "number")}</span> -<span class="traceContains">+mem: copying address to itself; refcount unchanged</span> +<span class="traceContains">+mem: incrementing refcount of 1000: 1 -> 2</span> +<span class="traceContains">+mem: decrementing refcount of 1000: 2 -> 1</span> <span class="Delimiter">:(scenario refcounts_call)</span> def main [ @@ -133,7 +146,9 @@ def foo [ ] <span class="traceContains">+run: {1: ("address" "number")} <- new {number: "type"}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 0 -> 1</span> -<span class="traceContains">+run: {2: ("address" "number")} <- next-ingredient</span> +<span class="traceContains">+run: foo {1: ("address" "number")}</span> +<span class="Comment"># leave ambiguous precisely when the next increment happens; a later layer</span> +<span class="Comment"># will mess with that</span> <span class="traceContains">+mem: incrementing refcount of 1000: 1 -> 2</span> <span class="traceContains">+run: {1: ("address" "number")} <- new {number: "type"}</span> <span class="traceContains">+mem: decrementing refcount of 1000: 2 -> 1</span> @@ -161,10 +176,8 @@ def main [ <span class="Delimiter">:(after "Write Memory in PUT in Run")</span> reagent<span class="Comment">/*</span><span class="Comment">copy</span><span class="Comment">*/</span> element = element_type<span class="Delimiter">(</span>base<span class="Delimiter">.</span>type<span class="Delimiter">,</span> offset<span class="Delimiter">);</span> assert<span class="Delimiter">(</span>!has_property<span class="Delimiter">(</span>element<span class="Delimiter">,</span> <span class="Constant">"lookup"</span><span class="Delimiter">));</span> -element<span class="Delimiter">.</span>value = address<span class="Delimiter">;</span> -<span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_address<span class="Delimiter">(</span>element<span class="Delimiter">))</span> - update_refcounts<span class="Delimiter">(</span>element<span class="Delimiter">,</span> ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> -<span class="Comment">// End Update Refcounts in PUT</span> +element<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>address<span class="Delimiter">);</span> +update_any_refcounts<span class="Delimiter">(</span>element<span class="Delimiter">,</span> ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">));</span> <span class="Delimiter">:(scenario refcounts_put_index)</span> def main [ @@ -181,9 +194,7 @@ def main [ <span class="traceContains">+mem: incrementing refcount of 1000: 1 -> 2</span> <span class="Delimiter">:(after "Write Memory in PUT_INDEX in Run")</span> -<span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_address<span class="Delimiter">(</span>element<span class="Delimiter">))</span> - update_refcounts<span class="Delimiter">(</span>element<span class="Delimiter">,</span> value<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> -<span class="Comment">// End Update Refcounts in PUT_INDEX</span> +update_any_refcounts<span class="Delimiter">(</span>element<span class="Delimiter">,</span> value<span class="Delimiter">);</span> <span class="Delimiter">:(scenario refcounts_maybe_convert)</span> exclusive-container foo [ @@ -205,9 +216,11 @@ def main [ <span class="traceContains">+mem: incrementing refcount of 1000: 2 -> 3</span> <span class="Delimiter">:(after "Write Memory in Successful MAYBE_CONVERT")</span> -<span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_address<span class="Delimiter">(</span>product<span class="Delimiter">))</span> - update_refcounts<span class="Delimiter">(</span>product<span class="Delimiter">,</span> get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> base_address+<span class="Comment">/*</span><span class="Comment">skip tag</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">));</span> -<span class="Comment">// End Update Refcounts in Successful MAYBE_CONVERT</span> +<span class="Comment">// </span><span class="Todo">TODO</span><span class="Comment">: double-check data here as well</span> +vector<<span class="Normal">double</span>> data<span class="Delimiter">;</span> +<span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < size_of<span class="Delimiter">(</span>product<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> + data<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> base_address+<span class="Comment">/*</span><span class="Comment">skip tag</span><span class="Comment">*/</span><span class="Constant">1</span>+i<span class="Delimiter">));</span> +update_any_refcounts<span class="Delimiter">(</span>product<span class="Delimiter">,</span> data<span class="Delimiter">);</span> <span class="SalientComment">//:: manage refcounts in instructions that copy multiple locations at a time</span> @@ -403,34 +416,33 @@ Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</spa <span class="Comment">//: use metadata.address to update refcounts within containers, arrays and</span> <span class="Comment">//: exclusive containers</span> -<span class="Delimiter">:(before "End Update Refcounts in write_memory(x)")</span> -<span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_container<span class="Delimiter">(</span>x<span class="Delimiter">)</span> || is_mu_exclusive_container<span class="Delimiter">(</span>x<span class="Delimiter">))</span> - update_container_refcounts<span class="Delimiter">(</span>x<span class="Delimiter">,</span> data<span class="Delimiter">);</span> -<span class="Delimiter">:(before "End Update Refcounts in PUT")</span> -<span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_container<span class="Delimiter">(</span>element<span class="Delimiter">)</span> || is_mu_exclusive_container<span class="Delimiter">(</span>element<span class="Delimiter">))</span> - update_container_refcounts<span class="Delimiter">(</span>element<span class="Delimiter">,</span> ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">));</span> -<span class="Delimiter">:(before "End Update Refcounts in PUT_INDEX")</span> -<span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_container<span class="Delimiter">(</span>element<span class="Delimiter">)</span> || is_mu_exclusive_container<span class="Delimiter">(</span>element<span class="Delimiter">))</span> - update_container_refcounts<span class="Delimiter">(</span>element<span class="Delimiter">,</span> value<span class="Delimiter">);</span> -<span class="Delimiter">:(before "End Update Refcounts in Successful MAYBE_CONVERT")</span> -<span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_container<span class="Delimiter">(</span>product<span class="Delimiter">)</span> || is_mu_exclusive_container<span class="Delimiter">(</span>product<span class="Delimiter">))</span> <span class="Delimiter">{</span> - vector<<span class="Normal">double</span>> data<span class="Delimiter">;</span> - <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < size_of<span class="Delimiter">(</span>product<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> - data<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> base_address+<span class="Comment">/*</span><span class="Comment">skip tag</span><span class="Comment">*/</span><span class="Constant">1</span>+i<span class="Delimiter">));</span> - update_container_refcounts<span class="Delimiter">(</span>product<span class="Delimiter">,</span> data<span class="Delimiter">);</span> +<span class="Delimiter">:(before "End Increment Refcounts(canonized_x)")</span> +<span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_container<span class="Delimiter">(</span>canonized_x<span class="Delimiter">)</span> || is_mu_exclusive_container<span class="Delimiter">(</span>canonized_x<span class="Delimiter">))</span> <span class="Delimiter">{</span> + <span class="Normal">const</span> container_metadata& metadata = get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> canonized_x<span class="Delimiter">.</span>type<span class="Delimiter">);</span> + <span class="Normal">for</span> <span class="Delimiter">(</span>map<set<tag_condition_info><span class="Delimiter">,</span> set<address_element_info> >::const_iterator p = metadata<span class="Delimiter">.</span>address<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != metadata<span class="Delimiter">.</span>address<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!all_match<span class="Delimiter">(</span>data<span class="Delimiter">,</span> p<span class="Delimiter">-></span>first<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + <span class="Normal">for</span> <span class="Delimiter">(</span>set<address_element_info>::const_iterator info = p<span class="Delimiter">-></span>second<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> info != p<span class="Delimiter">-></span>second<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++info<span class="Delimiter">)</span> + increment_refcount<span class="Delimiter">(</span>data<span class="Delimiter">.</span>at<span class="Delimiter">(</span>info<span class="Delimiter">-></span>offset<span class="Delimiter">));</span> + <span class="Delimiter">}</span> <span class="Delimiter">}</span> -<span class="Delimiter">:(code)</span> -<span class="Normal">void</span> update_container_refcounts<span class="Delimiter">(</span><span class="Normal">const</span> reagent& x<span class="Delimiter">,</span> <span class="Normal">const</span> vector<<span class="Normal">double</span>>& data<span class="Delimiter">)</span> <span class="Delimiter">{</span> - assert<span class="Delimiter">(</span>is_mu_container<span class="Delimiter">(</span>x<span class="Delimiter">)</span> || is_mu_exclusive_container<span class="Delimiter">(</span>x<span class="Delimiter">));</span> - <span class="Normal">const</span> container_metadata& metadata = get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> x<span class="Delimiter">.</span>type<span class="Delimiter">);</span> +<span class="Delimiter">:(before "End Decrement Refcounts(canonized_x)")</span> +<span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_container<span class="Delimiter">(</span>canonized_x<span class="Delimiter">)</span> || is_mu_exclusive_container<span class="Delimiter">(</span>canonized_x<span class="Delimiter">))</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"need to read old value to figure out what refcounts to decrement"</span> << end<span class="Delimiter">();</span> + <span class="Comment">// read from canonized_x but without canonizing again</span> + <span class="Comment">// todo: inline without running canonize all over again</span> + reagent<span class="Comment">/*</span><span class="Comment">copy</span><span class="Comment">*/</span> tmp = canonized_x<span class="Delimiter">;</span> + tmp<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair<string<span class="Delimiter">,</span> string_tree*><span class="Delimiter">(</span><span class="Constant">"raw"</span><span class="Delimiter">,</span> <span class="Constant">NULL</span><span class="Delimiter">));</span> + vector<<span class="Normal">double</span>> data = read_memory<span class="Delimiter">(</span>tmp<span class="Delimiter">);</span> + <span class="Normal">const</span> container_metadata& metadata = get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> canonized_x<span class="Delimiter">.</span>type<span class="Delimiter">);</span> <span class="Normal">for</span> <span class="Delimiter">(</span>map<set<tag_condition_info><span class="Delimiter">,</span> set<address_element_info> >::const_iterator p = metadata<span class="Delimiter">.</span>address<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != metadata<span class="Delimiter">.</span>address<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!all_match<span class="Delimiter">(</span>data<span class="Delimiter">,</span> p<span class="Delimiter">-></span>first<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Normal">for</span> <span class="Delimiter">(</span>set<address_element_info>::const_iterator info = p<span class="Delimiter">-></span>second<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> info != p<span class="Delimiter">-></span>second<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++info<span class="Delimiter">)</span> - update_refcounts<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> x<span class="Delimiter">.</span>value + info<span class="Delimiter">-></span>offset<span class="Delimiter">),</span> data<span class="Delimiter">.</span>at<span class="Delimiter">(</span>info<span class="Delimiter">-></span>offset<span class="Delimiter">),</span> info<span class="Delimiter">-></span>payload_type<span class="Delimiter">,</span> size_of<span class="Delimiter">(</span>info<span class="Delimiter">-></span>payload_type<span class="Delimiter">)</span>+<span class="Comment">/*</span><span class="Comment">refcount</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">);</span> + decrement_refcount<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> canonized_x<span class="Delimiter">.</span>value + info<span class="Delimiter">-></span>offset<span class="Delimiter">),</span> info<span class="Delimiter">-></span>payload_type<span class="Delimiter">,</span> size_of<span class="Delimiter">(</span>info<span class="Delimiter">-></span>payload_type<span class="Delimiter">)</span>+<span class="Comment">/*</span><span class="Comment">refcount</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> +<span class="Delimiter">:(code)</span> <span class="Normal">bool</span> all_match<span class="Delimiter">(</span><span class="Normal">const</span> vector<<span class="Normal">double</span>>& data<span class="Delimiter">,</span> <span class="Normal">const</span> set<tag_condition_info>& conditions<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">for</span> <span class="Delimiter">(</span>set<tag_condition_info>::const_iterator p = conditions<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != conditions<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>data<span class="Delimiter">.</span>at<span class="Delimiter">(</span>p<span class="Delimiter">-></span>offset<span class="Delimiter">)</span> != p<span class="Delimiter">-></span>tag<span class="Delimiter">)</span> @@ -460,7 +472,7 @@ def main [ <span class="Comment"># put increments refcount inside container</span> <span class="traceContains">+mem: incrementing refcount of 1000: 2 -> 3</span> -<span class="Delimiter">:(scenario refcounts_put_index_container)</span> +<span class="Delimiter">:(scenario refcounts_put_index_array)</span> container bar [ <span class="Normal">x</span>:address:number ] @@ -617,6 +629,53 @@ def main [ <span class="traceContains">+run: {20: "foo"} <- copy {10: "foo"}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 2 -> 3</span> +<span class="Delimiter">:(scenario refcounts_copy_array_within_container)</span> +container foo [ + <span class="Normal">x</span>:address:array:number +] +def main [ + <span class="Constant">1</span>:address:array:number<span class="Special"> <- </span><span class="Normal">new</span> number:type<span class="Delimiter">,</span> <span class="Constant">3</span> + <span class="Constant">2</span>:foo<span class="Special"> <- </span>merge <span class="Constant">1</span>:address:array:number + <span class="Constant">3</span>:address:array:number<span class="Special"> <- </span><span class="Normal">new</span> number:type<span class="Delimiter">,</span> <span class="Constant">5</span> + <span class="Constant">2</span>:foo<span class="Special"> <- </span>merge <span class="Constant">3</span>:address:array:number +] +<span class="traceContains">+run: {1: ("address" "array" "number")} <- new {number: "type"}, {3: "literal"}</span> +<span class="traceContains">+mem: incrementing refcount of 1000: 0 -> 1</span> +<span class="traceContains">+run: {2: "foo"} <- merge {1: ("address" "array" "number")}</span> +<span class="traceContains">+mem: incrementing refcount of 1000: 1 -> 2</span> +<span class="traceContains">+run: {2: "foo"} <- merge {3: ("address" "array" "number")}</span> +<span class="traceContains">+mem: decrementing refcount of 1000: 2 -> 1</span> + +<span class="Delimiter">:(scenario refcounts_handle_exclusive_containers_with_different_tags)</span> +container foo1 [ + <span class="Normal">x</span>:address:number + <span class="Normal">y</span>:number +] +container foo2 [ + <span class="Normal">x</span>:number + <span class="Normal">y</span>:address:number +] +exclusive-container bar [ + <span class="Normal">a</span>:foo1 + <span class="Normal">b</span>:foo2 +] +def main [ + <span class="Constant">1</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">12000</span>/unsafe <span class="Comment"># pretend allocation</span> + *<span class="Constant">1</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">34</span> + <span class="Constant">2</span>:bar<span class="Special"> <- </span>merge <span class="Constant">0</span>/foo1<span class="Delimiter">,</span> <span class="Constant">1</span>:address:number<span class="Delimiter">,</span> <span class="Constant">97</span> + <span class="Constant">5</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">13000</span>/unsafe <span class="Comment"># pretend allocation</span> + *<span class="Constant">5</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">35</span> + <span class="Constant">6</span>:bar<span class="Special"> <- </span>merge <span class="Constant">1</span>/foo2<span class="Delimiter">,</span> <span class="Constant">98</span><span class="Delimiter">,</span> <span class="Constant">5</span>:address:number + <span class="Constant">2</span>:bar<span class="Special"> <- </span>copy <span class="Constant">6</span>:bar +] +<span class="traceContains">+run: {2: "bar"} <- merge {0: "literal", "foo1": ()}, {1: ("address" "number")}, {97: "literal"}</span> +<span class="traceContains">+mem: incrementing refcount of 12000: 1 -> 2</span> +<span class="traceContains">+run: {6: "bar"} <- merge {1: "literal", "foo2": ()}, {98: "literal"}, {5: ("address" "number")}</span> +<span class="traceContains">+mem: incrementing refcount of 13000: 1 -> 2</span> +<span class="traceContains">+run: {2: "bar"} <- copy {6: "bar"}</span> +<span class="traceContains">+mem: incrementing refcount of 13000: 2 -> 3</span> +<span class="traceContains">+mem: decrementing refcount of 12000: 2 -> 1</span> + <span class="Delimiter">:(code)</span> <span class="Normal">bool</span> is_mu_container<span class="Delimiter">(</span><span class="Normal">const</span> reagent& r<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Identifier">return</span> is_mu_container<span class="Delimiter">(</span>r<span class="Delimiter">.</span>type<span class="Delimiter">);</span> diff --git a/html/037abandon.cc.html b/html/037abandon.cc.html index 661b2bb8..1339c4f0 100644 --- a/html/037abandon.cc.html +++ b/html/037abandon.cc.html @@ -48,7 +48,7 @@ def main [ <span class="Comment"># both allocations should have returned the same address</span> <span class="traceContains">+mem: storing 1 in location 5</span> -<span class="Delimiter">:(before "End Decrement Reference Count(old_address, payload_type, payload_size)")</span> +<span class="Delimiter">:(before "End Decrement Refcount(old_address, payload_type, payload_size)")</span> <span class="Normal">if</span> <span class="Delimiter">(</span>old_refcount == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"automatically abandoning "</span> << old_address << end<span class="Delimiter">();</span> abandon<span class="Delimiter">(</span>old_address<span class="Delimiter">,</span> payload_type<span class="Delimiter">,</span> payload_size<span class="Delimiter">);</span> @@ -71,27 +71,17 @@ map<<span class="Normal">int</span><span class="Delimiter">,</span> <span cla element<span class="Delimiter">.</span>type = copy_array_element<span class="Delimiter">(</span>payload_type<span class="Delimiter">);</span> <span class="Normal">int</span> array_length = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> address+<span class="Comment">/*</span><span class="Comment">skip refcount</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">);</span> assert<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>name != <span class="Constant">"array"</span><span class="Delimiter">);</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_address<span class="Delimiter">(</span>element<span class="Delimiter">))</span> <span class="Delimiter">{</span> - <span class="Normal">for</span> <span class="Delimiter">(</span>element<span class="Delimiter">.</span>value = address+<span class="Comment">/*</span><span class="Comment">skip refcount</span><span class="Comment">*/</span><span class="Constant">1</span>+<span class="Comment">/*</span><span class="Comment">skip length</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">;</span> element<span class="Delimiter">.</span>value < address+<span class="Comment">/*</span><span class="Comment">skip refcount</span><span class="Comment">*/</span><span class="Constant">1</span>+<span class="Comment">/*</span><span class="Comment">skip length</span><span class="Comment">*/</span><span class="Constant">1</span>+array_length<span class="Delimiter">;</span> ++element<span class="Delimiter">.</span>value<span class="Delimiter">)</span> - update_refcounts<span class="Delimiter">(</span>element<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> - <span class="Delimiter">}</span> - <span class="Normal">else</span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_container<span class="Delimiter">(</span>element<span class="Delimiter">)</span> || is_mu_exclusive_container<span class="Delimiter">(</span>element<span class="Delimiter">))</span> <span class="Delimiter">{</span> - <span class="Normal">int</span> element_size = size_of<span class="Delimiter">(</span>element<span class="Delimiter">);</span> - vector<<span class="Normal">double</span>> zeros<span class="Delimiter">;</span> - zeros<span class="Delimiter">.</span>resize<span class="Delimiter">(</span>element_size<span class="Delimiter">);</span> - <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < array_length<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - element<span class="Delimiter">.</span>value = address + <span class="Comment">/*</span><span class="Comment">skip refcount</span><span class="Comment">*/</span><span class="Constant">1</span> + <span class="Comment">/*</span><span class="Comment">skip array length</span><span class="Comment">*/</span><span class="Constant">1</span> + i*element_size<span class="Delimiter">;</span> - update_container_refcounts<span class="Delimiter">(</span>element<span class="Delimiter">,</span> zeros<span class="Delimiter">);</span> - <span class="Delimiter">}</span> + <span class="Normal">int</span> element_size = size_of<span class="Delimiter">(</span>element<span class="Delimiter">);</span> + <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < array_length<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + element<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>address + <span class="Comment">/*</span><span class="Comment">skip refcount</span><span class="Comment">*/</span><span class="Constant">1</span> + <span class="Comment">/*</span><span class="Comment">skip array length</span><span class="Comment">*/</span><span class="Constant">1</span> + i*element_size<span class="Delimiter">);</span> + decrement_any_refcounts<span class="Delimiter">(</span>element<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Normal">else</span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_container<span class="Delimiter">(</span>payload_type<span class="Delimiter">)</span> || is_mu_exclusive_container<span class="Delimiter">(</span>payload_type<span class="Delimiter">))</span> <span class="Delimiter">{</span> reagent tmp<span class="Delimiter">;</span> - tmp<span class="Delimiter">.</span>value = address + <span class="Comment">/*</span><span class="Comment">skip refcount</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">;</span> tmp<span class="Delimiter">.</span>type = <span class="Normal">new</span> type_tree<span class="Delimiter">(</span>*payload_type<span class="Delimiter">);</span> - vector<<span class="Normal">double</span>> zeros<span class="Delimiter">;</span> - zeros<span class="Delimiter">.</span>resize<span class="Delimiter">(</span>size_of<span class="Delimiter">(</span>payload_type<span class="Delimiter">));</span> - update_container_refcounts<span class="Delimiter">(</span>tmp<span class="Delimiter">,</span> zeros<span class="Delimiter">);</span> + tmp<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>address + <span class="Comment">/*</span><span class="Comment">skip refcount</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">);</span> + decrement_any_refcounts<span class="Delimiter">(</span>tmp<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Comment">// clear memory</span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> curr = address<span class="Delimiter">;</span> curr < address+payload_size<span class="Delimiter">;</span> ++curr<span class="Delimiter">)</span> @@ -168,7 +158,9 @@ def foo [ ] <span class="traceContains">+run: {1: ("address" "number")} <- new {number: "type"}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 0 -> 1</span> -<span class="traceContains">+run: {2: ("address" "number")} <- next-ingredient</span> +<span class="traceContains">+run: foo {1: ("address" "number")}</span> +<span class="Comment"># leave ambiguous precisely when the next increment happens; a later layer</span> +<span class="Comment"># will mess with that</span> <span class="traceContains">+mem: incrementing refcount of 1000: 1 -> 2</span> <span class="traceContains">+run: {2: ("address" "number")} <- copy {0: "literal"}</span> <span class="traceContains">+mem: decrementing refcount of 1000: 2 -> 1</span> diff --git a/html/043space.cc.html b/html/043space.cc.html index 22f7f869..e04b8cfc 100644 --- a/html/043space.cc.html +++ b/html/043space.cc.html @@ -91,9 +91,8 @@ absolutize<span class="Delimiter">(</span>x<span class="Delimiter">);</span> <span class="Normal">void</span> absolutize<span class="Delimiter">(</span>reagent& x<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_raw<span class="Delimiter">(</span>x<span class="Delimiter">)</span> || is_dummy<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Normal">if</span> <span class="Delimiter">(</span>x<span class="Delimiter">.</span>name == <span class="Constant">"default-space"</span><span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!x<span class="Delimiter">.</span>initialized<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!x<span class="Delimiter">.</span>initialized<span class="Delimiter">)</span> raise << to_original_string<span class="Delimiter">(</span>current_instruction<span class="Delimiter">())</span> << <span class="Constant">": reagent not initialized: '"</span> << x<span class="Delimiter">.</span>original_string << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> - <span class="Delimiter">}</span> x<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>address<span class="Delimiter">(</span>x<span class="Delimiter">.</span>value<span class="Delimiter">,</span> space_base<span class="Delimiter">(</span>x<span class="Delimiter">)));</span> x<span class="Delimiter">.</span>properties<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>pair<string<span class="Delimiter">,</span> string_tree*><span class="Delimiter">(</span><span class="Constant">"raw"</span><span class="Delimiter">,</span> <span class="Constant">NULL</span><span class="Delimiter">));</span> assert<span class="Delimiter">(</span>is_raw<span class="Delimiter">(</span>x<span class="Delimiter">));</span> @@ -277,13 +276,13 @@ try_reclaim_locals<span class="Delimiter">();</span> <span class="Normal">const</span> instruction& inst = exiting_recipe<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Comment">// local variables only</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>has_property<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> <span class="Constant">"space"</span><span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Normal">if</span> <span class="Delimiter">(</span>has_property<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> <span class="Constant">"lookup"</span><span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Normal">if</span> <span class="Delimiter">(</span>has_property<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> <span class="Constant">"raw"</span><span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Comment">// tests often want to check such locations after they run</span> <span class="Normal">if</span> <span class="Delimiter">(</span>escaping<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + <span class="Comment">// End Checks For Reclaiming Locals</span> trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"clearing "</span> << inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>original_string << end<span class="Delimiter">();</span> zeros<span class="Delimiter">.</span>resize<span class="Delimiter">(</span>size_of<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)));</span> - write_memory<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> zeros<span class="Delimiter">,</span> <span class="Comment">/*</span><span class="Comment">always update refcounts</span><span class="Comment">*/</span>-<span class="Constant">1</span><span class="Delimiter">);</span> + write_memory<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> zeros<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"automatically abandoning "</span> << current_call<span class="Delimiter">().</span>default_space << end<span class="Delimiter">();</span> @@ -292,23 +291,6 @@ try_reclaim_locals<span class="Delimiter">();</span> <span class="Comment">/*</span><span class="Comment">refcount</span><span class="Comment">*/</span><span class="Constant">1</span> + <span class="Comment">/*</span><span class="Comment">array length</span><span class="Comment">*/</span><span class="Constant">1</span> + <span class="Comment">/*</span><span class="Comment">number-of-locals</span><span class="Comment">*/</span>Name[r][<span class="Constant">""</span>]<span class="Delimiter">);</span> <span class="Delimiter">}</span> -<span class="Comment">//: since we don't decrement refcounts for escaping values above, make sure we</span> -<span class="Comment">//: don't increment them when the caller saves them either</span> - -<span class="Delimiter">:(replace{} "bool should_update_refcounts_in_write_memory(int product_index)")</span> -<span class="Normal">bool</span> should_update_refcounts_in_write_memory<span class="Delimiter">(</span><span class="Normal">int</span> product_index<span class="Delimiter">)</span> <span class="Delimiter">{</span> - assert<span class="Delimiter">(</span>Current_routine<span class="Delimiter">);</span> <span class="Comment">// run-time only</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>product_index == -<span class="Constant">1</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> - assert<span class="Delimiter">(</span>product_index >= <span class="Constant">0</span><span class="Delimiter">);</span> - <span class="Normal">const</span> instruction& inst = current_instruction<span class="Delimiter">();</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>operation < MAX_PRIMITIVE_RECIPES<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>operation<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> - <span class="Normal">const</span> recipe& caller = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>operation<span class="Delimiter">);</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>caller<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> - <span class="Comment">// if the recipe deosn't begin with 'local-scope', always update refcounts</span> - <span class="Identifier">return</span> caller<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>old_name != <span class="Constant">"local-scope"</span><span class="Delimiter">;</span> -<span class="Delimiter">}</span> - <span class="Delimiter">:(code)</span> <span class="Comment">// is this reagent one of the values returned by the current (reply) instruction?</span> <span class="Comment">// is the corresponding ingredient saved in the caller?</span> @@ -325,6 +307,24 @@ try_reclaim_locals<span class="Delimiter">();</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> +<span class="Comment">//: since we don't decrement refcounts for escaping values above, make sure we</span> +<span class="Comment">//: don't increment them when the caller saves them either</span> + +<span class="Delimiter">:(after "Write Products of Instruction")</span> +Update_refcounts_in_write_memory = should_update_refcounts_in_write_memory<span class="Delimiter">();</span> +<span class="Delimiter">:(before "End Write Products of Instruction")</span> +Update_refcounts_in_write_memory = <span class="Constant">true</span><span class="Delimiter">;</span> +<span class="Delimiter">:(code)</span> +<span class="Normal">bool</span> should_update_refcounts_in_write_memory<span class="Delimiter">()</span> <span class="Delimiter">{</span> + <span class="Normal">const</span> instruction& inst = current_instruction<span class="Delimiter">();</span> + <span class="Comment">// End should_update_refcounts_in_write_memory Special-cases For Primitives</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>operation < MAX_PRIMITIVE_RECIPES<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>operation<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> + <span class="Normal">const</span> recipe& callee = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>operation<span class="Delimiter">);</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>callee<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> + <span class="Identifier">return</span> callee<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>old_name != <span class="Constant">"local-scope"</span><span class="Delimiter">;</span> <span class="Comment">// callees that call local-scope are already dealt with before return</span> +<span class="Delimiter">}</span> + <span class="Normal">bool</span> caller_uses_product<span class="Delimiter">(</span><span class="Normal">int</span> product_index<span class="Delimiter">)</span> <span class="Delimiter">{</span> assert<span class="Delimiter">(</span>Current_routine<span class="Delimiter">);</span> <span class="Comment">// run-time only</span> assert<span class="Delimiter">(</span>!Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>empty<span class="Delimiter">());</span> diff --git a/html/044space_surround.cc.html b/html/044space_surround.cc.html index 745e8ffd..3c564c0b 100644 --- a/html/044space_surround.cc.html +++ b/html/044space_surround.cc.html @@ -62,6 +62,9 @@ def dummy [ <span class="Comment"># just for the /names: property above</span> <span class="Comment"># store to chained space: /*contents of location 12*/20 + /*skip refcount*/1 + /*skip length*/1 + /*index*/1</span> <span class="traceContains">+mem: storing 33 in location 23</span> +<span class="Delimiter">:(before "End Checks For Reclaiming Locals")</span> +<span class="Normal">if</span> <span class="Delimiter">(</span>space_index<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">))</span> > <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + <span class="Comment">//: If you think of a space as a collection of variables with a common</span> <span class="Comment">//: lifetime, surrounding allows managing shorter lifetimes inside a longer</span> <span class="Comment">//: one.</span> diff --git a/html/050scenario.cc.html b/html/050scenario.cc.html index 0727ae0e..a660cefb 100644 --- a/html/050scenario.cc.html +++ b/html/050scenario.cc.html @@ -150,23 +150,26 @@ scenario foo [ Num_core_mu_scenarios = SIZE<span class="Delimiter">(</span>Scenarios<span class="Delimiter">);</span> <span class="Delimiter">:(before "End Tests")</span> Hide_missing_default_space_errors = <span class="Constant">false</span><span class="Delimiter">;</span> -time<span class="Delimiter">(</span>&t<span class="Delimiter">);</span> -cerr << <span class="Constant">"</span><span class="cSpecial">\n</span><span class="Constant">Mu tests: "</span> << ctime<span class="Delimiter">(</span>&t<span class="Delimiter">);</span> -<span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < Num_core_mu_scenarios<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cerr << i << ": " << Scenarios.at(i).name << '\n';</span> - run_mu_scenario<span class="Delimiter">(</span>Scenarios<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>Passed<span class="Delimiter">)</span> cerr << <span class="Constant">"."</span><span class="Delimiter">;</span> +<span class="Normal">if</span> <span class="Delimiter">(</span>Num_core_mu_scenarios<span class="Delimiter">)</span> <span class="Delimiter">{</span> + time<span class="Delimiter">(</span>&t<span class="Delimiter">);</span> + cerr << <span class="Constant">"Mu tests: "</span> << ctime<span class="Delimiter">(</span>&t<span class="Delimiter">);</span> + <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < Num_core_mu_scenarios<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="CommentedCode">//? cerr << '\n' << i << ": " << Scenarios.at(i).name;</span> + run_mu_scenario<span class="Delimiter">(</span>Scenarios<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>Passed<span class="Delimiter">)</span> cerr << <span class="Constant">"."</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + cerr << <span class="Constant">"</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> -cerr << <span class="Constant">"</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">;</span> <span class="Normal">run_app_scenarios</span>: <span class="Normal">if</span> <span class="Delimiter">(</span>Num_core_mu_scenarios != SIZE<span class="Delimiter">(</span>Scenarios<span class="Delimiter">))</span> <span class="Delimiter">{</span> time<span class="Delimiter">(</span>&t<span class="Delimiter">);</span> cerr << <span class="Constant">"App tests: "</span> << ctime<span class="Delimiter">(</span>&t<span class="Delimiter">);</span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = Num_core_mu_scenarios<span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>Scenarios<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> -<span class="CommentedCode">//? cerr << i << ": " << Scenarios.at(i).name << '\n';</span> +<span class="CommentedCode">//? cerr << '\n' << i << ": " << Scenarios.at(i).name;</span> run_mu_scenario<span class="Delimiter">(</span>Scenarios<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> <span class="Normal">if</span> <span class="Delimiter">(</span>Passed<span class="Delimiter">)</span> cerr << <span class="Constant">"."</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> + cerr << <span class="Constant">"</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Comment">//: For faster debugging, support running tests for just the Mu app(s) we are</span> @@ -530,7 +533,6 @@ def main [ <span class="traceAbsent">-error: location 1 can't contain non-number 34 # comment</span> <span class="Comment"># but there'll be an error signalled by memory-should-contain</span> -<span class="Delimiter">:(code)</span> <span class="Comment">//: 'trace-should-contain' is like the '+' lines in our scenarios so far</span> <span class="Comment">// Like runs of contiguous '+' lines, order is important. The trace checks</span> <span class="Comment">// that the lines are present *and* in the specified sequence. (There can be</span> diff --git a/html/055shape_shifting_container.cc.html b/html/055shape_shifting_container.cc.html index fd9e9029..a50c090b 100644 --- a/html/055shape_shifting_container.cc.html +++ b/html/055shape_shifting_container.cc.html @@ -224,14 +224,19 @@ def main [ <span class="Constant">3</span>:foo:point<span class="Special"> <- </span>merge <span class="Constant">0</span>/x<span class="Delimiter">,</span> <span class="Constant">15</span><span class="Delimiter">,</span> <span class="Constant">16</span> <span class="Constant">6</span>:foo:point<span class="Special"> <- </span>merge <span class="Constant">1</span>/y<span class="Delimiter">,</span> <span class="Constant">23</span> ] +<span class="traceContains">+run: {1: ("foo" "number")} <- merge {0: "literal", "x": ()}, {34: "literal"}</span> <span class="traceContains">+mem: storing 0 in location 1</span> <span class="traceContains">+mem: storing 34 in location 2</span> +<span class="traceContains">+run: {3: ("foo" "point")} <- merge {0: "literal", "x": ()}, {15: "literal"}, {16: "literal"}</span> <span class="traceContains">+mem: storing 0 in location 3</span> <span class="traceContains">+mem: storing 15 in location 4</span> <span class="traceContains">+mem: storing 16 in location 5</span> +<span class="traceContains">+run: {6: ("foo" "point")} <- merge {1: "literal", "y": ()}, {23: "literal"}</span> <span class="traceContains">+mem: storing 1 in location 6</span> <span class="traceContains">+mem: storing 23 in location 7</span> -$mem: <span class="Constant">7</span> +<span class="traceContains">+run: reply</span> +<span class="Comment"># no other stores</span> +<span class="Special">% CHECK(trace_count_prefix("mem", "storing") == 7);</span> <span class="Delimiter">:(scenario get_on_shape_shifting_container)</span> container foo:_t [ diff --git a/html/060rewrite_literal_string.cc.html b/html/060rewrite_literal_string.cc.html index 275a8fc3..27c825fe 100644 --- a/html/060rewrite_literal_string.cc.html +++ b/html/060rewrite_literal_string.cc.html @@ -60,13 +60,11 @@ set<string> recipes_taking_literal_strings<span class="Delimiter">;</span> recipes_taking_literal_strings<span class="Delimiter">.</span>insert<span class="Delimiter">(</span><span class="Constant">"assert"</span><span class="Delimiter">);</span> recipes_taking_literal_strings<span class="Delimiter">.</span>insert<span class="Delimiter">(</span><span class="Constant">"new"</span><span class="Delimiter">);</span> recipes_taking_literal_strings<span class="Delimiter">.</span>insert<span class="Delimiter">(</span><span class="Constant">"run"</span><span class="Delimiter">);</span> - recipes_taking_literal_strings<span class="Delimiter">.</span>insert<span class="Delimiter">(</span><span class="Constant">"assume-console"</span><span class="Delimiter">);</span> recipes_taking_literal_strings<span class="Delimiter">.</span>insert<span class="Delimiter">(</span><span class="Constant">"memory-should-contain"</span><span class="Delimiter">);</span> recipes_taking_literal_strings<span class="Delimiter">.</span>insert<span class="Delimiter">(</span><span class="Constant">"trace-should-contain"</span><span class="Delimiter">);</span> recipes_taking_literal_strings<span class="Delimiter">.</span>insert<span class="Delimiter">(</span><span class="Constant">"trace-should-not-contain"</span><span class="Delimiter">);</span> recipes_taking_literal_strings<span class="Delimiter">.</span>insert<span class="Delimiter">(</span><span class="Constant">"check-trace-count-for-label"</span><span class="Delimiter">);</span> - recipes_taking_literal_strings<span class="Delimiter">.</span>insert<span class="Delimiter">(</span><span class="Constant">"screen-should-contain"</span><span class="Delimiter">);</span> - recipes_taking_literal_strings<span class="Delimiter">.</span>insert<span class="Delimiter">(</span><span class="Constant">"screen-should-contain-in-color"</span><span class="Delimiter">);</span> + <span class="Comment">// End initialize_transform_rewrite_literal_string_to_text()</span> <span class="Delimiter">}</span> <span class="Normal">void</span> rewrite_literal_string_to_text<span class="Delimiter">(</span>recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span> diff --git a/html/061text.mu.html b/html/061text.mu.html index 589ca78e..268d4275 100644 --- a/html/061text.mu.html +++ b/html/061text.mu.html @@ -156,6 +156,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Constant">load-ingredients</span> result<span class="Special"> <- </span>new <span class="Constant">buffer:type</span> *result<span class="Special"> <- </span>put *result, <span class="Constant">length:offset</span>, <span class="Constant">0</span> + <span class="Delimiter">{</span> + <span class="muControl">break-if</span> capacity + <span class="Comment"># capacity not provided</span> + capacity<span class="Special"> <- </span>copy <span class="Constant">10</span> + <span class="Delimiter">}</span> data:address:array:character<span class="Special"> <- </span>new <span class="Constant">character:type</span>, capacity *result<span class="Special"> <- </span>put *result, <span class="Constant">data:offset</span>, data <span class="muControl">return</span> result @@ -276,6 +281,15 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] ] +<span class="muScenario">scenario</span> buffer-append-to-empty [ + run [ + <span class="Constant">local-scope</span> + x:address:buffer<span class="Special"> <- </span>new-buffer + c:character<span class="Special"> <- </span>copy <span class="Constant">97/a</span> + x<span class="Special"> <- </span>append x, c + ] +] + <span class="muScenario">scenario</span> buffer-append-handles-backspace [ run [ <span class="Constant">local-scope</span> diff --git a/html/067random.cc.html b/html/067random.cc.html index 28cd2bf5..6eaca039 100644 --- a/html/067random.cc.html +++ b/html/067random.cc.html @@ -14,14 +14,10 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background- body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 12pt; font-size: 1em; } .Constant { color: #00a0a0; } -.Special { color: #c00000; } -.traceContains { color: #008000; } .Comment { color: #9090ff; } .Delimiter { color: #800080; } -.cSpecial { color: #008000; } .Identifier { color: #fcb165; } .Normal { color: #eeeeee; background-color: #080808; padding-bottom: 1px; } -.PreProc { color: #800080; } --> </style> @@ -63,38 +59,6 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span srand<span class="Delimiter">(</span>time<span class="Delimiter">(</span><span class="Constant">NULL</span><span class="Delimiter">));</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - -<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> -ROUND<span class="Delimiter">,</span> -<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> -put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"round"</span><span class="Delimiter">,</span> ROUND<span class="Delimiter">);</span> -<span class="Delimiter">:(before "End Primitive Recipe Checks")</span> -<span class="Normal">case</span> ROUND: <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'round' requires exactly one ingredient, but got '"</span> << inst<span class="Delimiter">.</span>original_string << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"first ingredient of 'round' should be a number, but got '"</span> << inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> -<span class="Delimiter">}</span> -<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> -<span class="Normal">case</span> ROUND: <span class="Delimiter">{</span> - products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> - products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>rint<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)));</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> -<span class="Delimiter">}</span> - -<span class="Delimiter">:(scenario round_to_nearest_integer)</span> -def main [ - <span class="Constant">1</span>:number<span class="Special"> <- </span>round <span class="Constant">12.2</span> -] -<span class="traceContains">+mem: storing 12 in location 1</span> - -<span class="Delimiter">:(before "End Includes")</span> -<span class="PreProc">#include </span><span class="Constant"><math.h></span> </pre> </body> </html> diff --git a/html/069hash.cc.html b/html/069hash.cc.html index ee1776d1..07fd97ee 100644 --- a/html/069hash.cc.html +++ b/html/069hash.cc.html @@ -91,7 +91,7 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span <span class="Normal">size_t</span> hash_mu_address<span class="Delimiter">(</span><span class="Normal">size_t</span> h<span class="Delimiter">,</span> reagent& r<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>r<span class="Delimiter">.</span>value == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">0</span><span class="Delimiter">;</span> trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"location "</span> << r<span class="Delimiter">.</span>value << <span class="Constant">" is "</span> << no_scientific<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> r<span class="Delimiter">.</span>value<span class="Delimiter">))</span> << end<span class="Delimiter">();</span> - r<span class="Delimiter">.</span>value = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> r<span class="Delimiter">.</span>value<span class="Delimiter">);</span> + r<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> r<span class="Delimiter">.</span>value<span class="Delimiter">));</span> <span class="Normal">if</span> <span class="Delimiter">(</span>r<span class="Delimiter">.</span>value != <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> trace<span class="Delimiter">(</span><span class="Constant">9999</span><span class="Delimiter">,</span> <span class="Constant">"mem"</span><span class="Delimiter">)</span> << <span class="Constant">"skipping refcount at "</span> << r<span class="Delimiter">.</span>value << end<span class="Delimiter">();</span> r<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>r<span class="Delimiter">.</span>value+<span class="Constant">1</span><span class="Delimiter">);</span> <span class="Comment">// skip refcount</span> @@ -116,7 +116,7 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span elem<span class="Delimiter">.</span>type = copy_array_element<span class="Delimiter">(</span>r<span class="Delimiter">.</span>type<span class="Delimiter">);</span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i=<span class="Constant">0</span><span class="Delimiter">,</span> address = r<span class="Delimiter">.</span>value+<span class="Constant">1</span><span class="Delimiter">;</span> i < size<span class="Delimiter">;</span> ++i<span class="Delimiter">,</span> address += size_of<span class="Delimiter">(</span>elem<span class="Delimiter">))</span> <span class="Delimiter">{</span> reagent<span class="Comment">/*</span><span class="Comment">copy</span><span class="Comment">*/</span> tmp = elem<span class="Delimiter">;</span> - tmp<span class="Delimiter">.</span>value = address<span class="Delimiter">;</span> + tmp<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>address<span class="Delimiter">);</span> h = hash<span class="Delimiter">(</span>h<span class="Delimiter">,</span> tmp<span class="Delimiter">);</span> <span class="CommentedCode">//? cerr << i << " (" << address << "): " << h << '\n';</span> <span class="Delimiter">}</span> diff --git a/html/072scheduler.cc.html b/html/072scheduler.cc.html index cf588699..55f7ba88 100644 --- a/html/072scheduler.cc.html +++ b/html/072scheduler.cc.html @@ -207,6 +207,7 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span reagent<span class="Comment">/*</span><span class="Comment">copy</span><span class="Comment">*/</span> ingredient = current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> canonize_type<span class="Delimiter">(</span>ingredient<span class="Delimiter">);</span> new_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>front<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>ingredient<span class="Delimiter">);</span> + <span class="Comment">// End Populate start-running Ingredient</span> <span class="Delimiter">}</span> Routines<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>new_routine<span class="Delimiter">);</span> products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> @@ -261,6 +262,73 @@ def f2 [ ] <span class="traceContains">+mem: storing 4 in location 2</span> +<span class="Comment">//: more complex: refcounting management when starting up new routines</span> + +<span class="Delimiter">:(scenario start_running_immediately_updates_refcounts_of_ingredients)</span> +<span class="Special">% Scheduling_interval = 1;</span> +def main [ + local-scope + create-<span class="Normal">new</span>-routine + <span class="Comment"># padding to make sure we run new-routine before returning</span> + <span class="Normal">dummy</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> + <span class="Normal">dummy</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> +] +def create-<span class="Normal">new</span>-routine [ + local-scope + <span class="Normal">n</span>:address:number<span class="Special"> <- </span><span class="Normal">new</span> number:type + *n<span class="Special"> <- </span>copy <span class="Constant">34</span> + start-running <span class="Normal">new</span>-routine<span class="Delimiter">,</span> n + <span class="Comment"># refcount of n decremented</span> +] +def <span class="Normal">new</span>-routine n:address:number [ + local-scope + load-ingredients + <span class="Constant">1</span>:number/<span class="Special">raw <- </span>copy *n +] +<span class="Comment"># check that n wasn't reclaimed when create-new-routine returned</span> +<span class="traceContains">+mem: storing 34 in location 1</span> + +<span class="Comment">//: to support the previous scenario we'll increment refcounts for all call</span> +<span class="Comment">//: ingredients right at call time, and stop incrementing refcounts inside</span> +<span class="Comment">//: next-ingredient</span> +<span class="Delimiter">:(before "End Populate Call Ingredient")</span> +increment_any_refcounts<span class="Delimiter">(</span>ingredient<span class="Delimiter">,</span> ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> +<span class="Delimiter">:(before "End Populate start-running Ingredient")</span> +increment_any_refcounts<span class="Delimiter">(</span>ingredient<span class="Delimiter">,</span> ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">));</span> +<span class="Delimiter">:(before "End should_update_refcounts_in_write_memory Special-cases For Primitives")</span> +<span class="Normal">if</span> <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>operation == NEXT_INGREDIENT || inst<span class="Delimiter">.</span>operation == NEXT_INGREDIENT_WITHOUT_TYPECHECKING<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>space_index<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">))</span> > <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>has_property<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">),</span> <span class="Constant">"raw"</span><span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> + <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario next_ingredient_never_leaks_refcounts)</span> +def create-scope n:address:number <span class="Delimiter">-></span> <span class="Normal">default</span>-space:address:array:location [ + <span class="Normal">default</span>-space<span class="Special"> <- </span><span class="Normal">new</span> location:type<span class="Delimiter">,</span> <span class="Constant">2</span> + load-ingredients +] +def use-scope [ + local-scope + <span class="Constant">0</span>:address:array:location/names:create-scope<span class="Special"> <- </span>next-ingredient + <span class="Normal">n</span>:address:number/space:<span class="Constant">1</span><span class="Special"> <- </span>next-ingredient <span class="Comment"># should decrement refcount</span> + *n/space:<span class="Constant">1</span><span class="Special"> <- </span>copy <span class="Constant">34</span> + <span class="Normal">n2</span>:number<span class="Special"> <- </span>add *n/space:<span class="Constant">1</span><span class="Delimiter">,</span> <span class="Constant">1</span> + reply n2 +] +def main [ + local-scope + <span class="Normal">n</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">12000</span>/unsafe <span class="Comment"># pretend allocation with a known address</span> + *n<span class="Special"> <- </span>copy <span class="Constant">23</span> + <span class="Normal">scope</span>:address:array:location<span class="Special"> <- </span>create-scope n + <span class="Normal">n2</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">13000</span>/unsafe + <span class="Normal">n3</span>:number<span class="Special"> <- </span>use-scope scope<span class="Delimiter">,</span> n2 +] +<span class="traceContains">+run: {n: ("address" "number"), "space": "1"} <- next-ingredient</span> +<span class="traceContains">+mem: decrementing refcount of 12000: 2 -> 1</span> +<span class="traceContains">+run: {n: ("address" "number"), "space": "1", "lookup": ()} <- copy {34: "literal"}</span> + +<span class="Comment">//: back to testing 'start-running'</span> + <span class="Delimiter">:(scenario start_running_returns_routine_id)</span> def f1 [ <span class="Constant">1</span>:number<span class="Special"> <- </span>start-running f2 @@ -340,6 +408,7 @@ def f1 [ <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>Routines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>state == COMPLETED<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Normal">if</span> <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>parent_index < <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Comment">// root thread</span> + <span class="Comment">// structured concurrency: <a href="http://250bpm.com/blog:71">http://250bpm.com/blog:71</a></span> <span class="Normal">if</span> <span class="Delimiter">(</span>has_completed_parent<span class="Delimiter">(</span>i<span class="Delimiter">))</span> <span class="Delimiter">{</span> Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>state = COMPLETED<span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -405,34 +474,6 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span <span class="SalientComment">//:: miscellaneous helpers</span> <span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> -RESTART<span class="Delimiter">,</span> -<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> -put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"restart"</span><span class="Delimiter">,</span> RESTART<span class="Delimiter">);</span> -<span class="Delimiter">:(before "End Primitive Recipe Checks")</span> -<span class="Normal">case</span> RESTART: <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'restart' requires exactly one ingredient, but got '"</span> << inst<span class="Delimiter">.</span>original_string << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"first ingredient of 'restart' should be a routine id generated by 'start-running', but got '"</span> << inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> -<span class="Delimiter">}</span> -<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> -<span class="Normal">case</span> RESTART: <span class="Delimiter">{</span> - <span class="Normal">int</span> id = ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> - <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>Routines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>id == id<span class="Delimiter">)</span> <span class="Delimiter">{</span> - Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>state = RUNNING<span class="Delimiter">;</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> - <span class="Delimiter">}</span> - <span class="Delimiter">}</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> -<span class="Delimiter">}</span> - -<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> STOP<span class="Delimiter">,</span> <span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"stop"</span><span class="Delimiter">,</span> STOP<span class="Delimiter">);</span> diff --git a/html/073wait.cc.html b/html/073wait.cc.html index dffb1cf5..49bdd7d3 100644 --- a/html/073wait.cc.html +++ b/html/073wait.cc.html @@ -361,6 +361,52 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span <span class="Delimiter">}</span> <span class="Identifier">return</span> <span class="Constant">0</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> + +<span class="Comment">//: helper for restarting blocking routines in tests</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +RESTART<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"restart"</span><span class="Delimiter">,</span> RESTART<span class="Delimiter">);</span> +<span class="Delimiter">:(before "End Primitive Recipe Checks")</span> +<span class="Normal">case</span> RESTART: <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'restart' requires exactly one ingredient, but got '"</span> << inst<span class="Delimiter">.</span>original_string << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"first ingredient of 'restart' should be a routine id generated by 'start-running', but got '"</span> << inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>original_string << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +<span class="Normal">case</span> RESTART: <span class="Delimiter">{</span> + <span class="Normal">int</span> id = ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> + <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> i = <span class="Constant">0</span><span class="Delimiter">;</span> i < SIZE<span class="Delimiter">(</span>Routines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>id == id<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>state == WAITING<span class="Delimiter">)</span> + Routines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)-></span>state = RUNNING<span class="Delimiter">;</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(scenario cannot_restart_completed_routine)</span> +<span class="Special">% Scheduling_interval = 1;</span> +def main [ + local-scope + <span class="Normal">r</span>:number/routine-id<span class="Special"> <- </span>start-running f + <span class="Normal">x</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Comment"># wait for f to be scheduled</span> + <span class="Comment"># r is COMPLETED by this point</span> + restart r <span class="Comment"># should have no effect</span> + <span class="Normal">x</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Comment"># give f time to be scheduled (though it shouldn't be)</span> +] +def f [ + <span class="Constant">1</span>:number/<span class="Special">raw <- </span>copy <span class="Constant">1</span> +] +<span class="Comment"># shouldn't crash</span> </pre> </body> </html> diff --git a/html/074deep_copy.cc.html b/html/074deep_copy.cc.html index 1a352a85..4a520023 100644 --- a/html/074deep_copy.cc.html +++ b/html/074deep_copy.cc.html @@ -248,7 +248,7 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span <span class="Comment">// allocate a tiny bit of temporary space for deep_copy()</span> trace<span class="Delimiter">(</span><span class="Constant">9991</span><span class="Delimiter">,</span> <span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"deep-copy: allocating space for temporary"</span> << end<span class="Delimiter">();</span> reagent tmp<span class="Delimiter">(</span><span class="Constant">"tmp:address:number"</span><span class="Delimiter">);</span> - tmp<span class="Delimiter">.</span>value = allocate<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> + tmp<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>allocate<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">));</span> products<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>deep_copy<span class="Delimiter">(</span>input<span class="Delimiter">,</span> tmp<span class="Delimiter">));</span> <span class="Comment">// reclaim Mu memory allocated for tmp</span> trace<span class="Delimiter">(</span><span class="Constant">9991</span><span class="Delimiter">,</span> <span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"deep-copy: reclaiming temporary"</span> << end<span class="Delimiter">();</span> @@ -295,10 +295,10 @@ vector<<span class="Normal">double</span>> deep_copy<span class="Delimiter <span class="Comment">// a temporary location to help copy the payload.</span> trace<span class="Delimiter">(</span><span class="Constant">9991</span><span class="Delimiter">,</span> <span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"deep-copy: writing temporary "</span> << tmp<span class="Delimiter">.</span>value << <span class="Constant">": "</span> << out << end<span class="Delimiter">();</span> put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> tmp<span class="Delimiter">.</span>value<span class="Delimiter">,</span> out<span class="Delimiter">);</span> - payload<span class="Delimiter">.</span>value = tmp<span class="Delimiter">.</span>value<span class="Delimiter">;</span> <span class="Comment">// now modified for output</span> + payload<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>tmp<span class="Delimiter">.</span>value<span class="Delimiter">);</span> <span class="Comment">// now modified for output</span> vector<<span class="Normal">double</span>> old_data = read_memory<span class="Delimiter">(</span>payload<span class="Delimiter">);</span> trace<span class="Delimiter">(</span><span class="Constant">9991</span><span class="Delimiter">,</span> <span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"deep-copy: really writing to "</span> << payload<span class="Delimiter">.</span>value << <span class="Constant">' '</span> << to_string<span class="Delimiter">(</span>payload<span class="Delimiter">)</span> << <span class="Constant">" (old value "</span> << to_string<span class="Delimiter">(</span>old_data<span class="Delimiter">)</span> << <span class="Constant">" new value "</span> << to_string<span class="Delimiter">(</span>data<span class="Delimiter">)</span> << <span class="Constant">")"</span> << end<span class="Delimiter">();</span> - write_memory<span class="Delimiter">(</span>payload<span class="Delimiter">,</span> data<span class="Delimiter">,</span> -<span class="Constant">1</span><span class="Delimiter">);</span> + write_memory<span class="Delimiter">(</span>payload<span class="Delimiter">,</span> data<span class="Delimiter">);</span> trace<span class="Delimiter">(</span><span class="Constant">9991</span><span class="Delimiter">,</span> <span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"deep-copy: output is "</span> << to_string<span class="Delimiter">(</span>data<span class="Delimiter">)</span> << end<span class="Delimiter">();</span> <span class="Identifier">return</span> out<span class="Delimiter">;</span> <span class="Delimiter">}</span> diff --git a/html/075channel.mu.html b/html/075channel.mu.html index 9583336a..8d87a38d 100644 --- a/html/075channel.mu.html +++ b/html/075channel.mu.html @@ -129,10 +129,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color *chan<span class="Special"> <- </span>put *chan, <span class="Constant">first-free:offset</span>, free ] -<span class="muRecipe">def</span> read in:address:source:_elem<span class="muRecipe"> -> </span>result:_elem, fail?:boolean, in:address:source:_elem [ +<span class="muRecipe">def</span> read in:address:source:_elem<span class="muRecipe"> -> </span>result:_elem, eof?:boolean, in:address:source:_elem [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> - fail?<span class="Special"> <- </span>copy <span class="Constant">0/false</span> <span class="Comment"># default status</span> + eof?<span class="Special"> <- </span>copy <span class="Constant">0/false</span> <span class="Comment"># default result</span> chan:address:channel:_elem<span class="Special"> <- </span>get *in, <span class="Constant">chan:offset</span> <span class="Delimiter">{</span> <span class="Comment"># block if chan is empty</span> diff --git a/html/082scenario_screen.cc.html b/html/082scenario_screen.cc.html index 8a204b48..fe7b980d 100644 --- a/html/082scenario_screen.cc.html +++ b/html/082scenario_screen.cc.html @@ -39,6 +39,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment">//: instructions in the scenario. 'screen-should-contain' can check unicode</span> <span class="Comment">//: characters in the fake screen</span> +<span class="Comment">//: first make sure we don't mangle these functions in other transforms</span> +<span class="Delimiter">:(before "End initialize_transform_rewrite_literal_string_to_text()")</span> +recipes_taking_literal_strings<span class="Delimiter">.</span>insert<span class="Delimiter">(</span><span class="Constant">"screen-should-contain"</span><span class="Delimiter">);</span> +recipes_taking_literal_strings<span class="Delimiter">.</span>insert<span class="Delimiter">(</span><span class="Constant">"screen-should-contain-in-color"</span><span class="Delimiter">);</span> + <span class="Delimiter">:(scenarios run_mu_scenario)</span> <span class="Delimiter">:(scenario screen_in_scenario)</span> scenario screen-in-scenario [ diff --git a/html/085scenario_console.cc.html b/html/085scenario_console.cc.html index d1b0cd33..bfa387e2 100644 --- a/html/085scenario_console.cc.html +++ b/html/085scenario_console.cc.html @@ -37,6 +37,10 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment">//: scenario. Like with the fake screen, 'assume-console' transparently</span> <span class="Comment">//: supports unicode.</span> +<span class="Comment">//: first make sure we don't mangle these functions in other transforms</span> +<span class="Delimiter">:(before "End initialize_transform_rewrite_literal_string_to_text()")</span> +recipes_taking_literal_strings<span class="Delimiter">.</span>insert<span class="Delimiter">(</span><span class="Constant">"assume-console"</span><span class="Delimiter">);</span> + <span class="Delimiter">:(scenarios run_mu_scenario)</span> <span class="Delimiter">:(scenario keyboard_in_scenario)</span> scenario keyboard-in-scenario [ diff --git a/html/087file.cc.html b/html/087file.cc.html index 71b7461f..7a0843f5 100644 --- a/html/087file.cc.html +++ b/html/087file.cc.html @@ -14,10 +14,12 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background- body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 12pt; font-size: 1em; } .Constant { color: #00a0a0; } +.Comment { color: #9090ff; } .Delimiter { color: #800080; } -.SalientComment { color: #00ffff; } +.cSpecial { color: #008000; } .Identifier { color: #fcb165; } .Normal { color: #eeeeee; background-color: #080808; padding-bottom: 1px; } +.PreProc { color: #800080; } --> </style> @@ -29,31 +31,187 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color </head> <body> <pre id='vimCodeElement'> -<span class="SalientComment">//:: Interacting with the file-system</span> +<span class="Comment">//: Interacting with the file system.</span> +<span class="Comment">//: '$open-file-for-reading' returns a FILE* as a number (ugh)</span> +<span class="Comment">//: '$read-from-file' accepts a number, interprets it as a FILE* (double ugh) and reads a character from it</span> +<span class="Comment">//: Similarly for writing files.</span> +<span class="Comment">//: These interfaces are ugly and tied to the current (Linux) host Mu happens</span> +<span class="Comment">//: to be implemented atop. Later layers will wrap them with better, more</span> +<span class="Comment">//: testable interfaces.</span> +<span class="Comment">//:</span> +<span class="Comment">//: Clearly we don't care about performance or any of that so far.</span> +<span class="Comment">//: todo: reading/writing binary files</span> <span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> -OPEN_FILE_FOR_READING<span class="Delimiter">,</span> +_OPEN_FILE_FOR_READING<span class="Delimiter">,</span> <span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> -put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"open-file-for-reading"</span><span class="Delimiter">,</span> OPEN_FILE_FOR_READING<span class="Delimiter">);</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"$open-file-for-reading"</span><span class="Delimiter">,</span> _OPEN_FILE_FOR_READING<span class="Delimiter">);</span> <span class="Delimiter">:(before "End Primitive Recipe Checks")</span> -<span class="Normal">case</span> OPEN_FILE_FOR_READING: <span class="Delimiter">{</span> +<span class="Normal">case</span> _OPEN_FILE_FOR_READING: <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'$open-file-for-reading' requires exactly one ingredient, but got '"</span> << inst<span class="Delimiter">.</span>original_string << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + string filename<span class="Delimiter">;</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"first ingredient of '$open-file-for-reading' should be a string, but got '"</span> << to_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">))</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> -<span class="Normal">case</span> OPEN_FILE_FOR_READING: <span class="Delimiter">{</span> +<span class="Normal">case</span> _OPEN_FILE_FOR_READING: <span class="Delimiter">{</span> + string filename = read_mu_string<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> + assert<span class="Delimiter">(</span><span class="Normal">sizeof</span><span class="Delimiter">(</span><span class="Normal">long</span> <span class="Normal">long</span> <span class="Normal">int</span><span class="Delimiter">)</span> >= <span class="Normal">sizeof</span><span class="Delimiter">(</span><span class="Normal">FILE</span>*<span class="Delimiter">));</span> + <span class="Normal">FILE</span>* f = fopen<span class="Delimiter">(</span>filename<span class="Delimiter">.</span>c_str<span class="Delimiter">(),</span> <span class="Constant">"r"</span><span class="Delimiter">);</span> + <span class="Normal">long</span> <span class="Normal">long</span> <span class="Normal">int</span> result = <span class="Normal">reinterpret_cast</span><<span class="Normal">long</span> <span class="Normal">long</span> <span class="Normal">int</span>><span class="Delimiter">(</span>f<span class="Delimiter">);</span> + products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> + products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Normal">static_cast</span><<span class="Normal">double</span>><span class="Delimiter">(</span>result<span class="Delimiter">));</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> -OPEN_FILE_FOR_WRITING<span class="Delimiter">,</span> +_OPEN_FILE_FOR_WRITING<span class="Delimiter">,</span> <span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> -put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"open-file-for-reading"</span><span class="Delimiter">,</span> OPEN_FILE_FOR_WRITING<span class="Delimiter">);</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"$open-file-for-writing"</span><span class="Delimiter">,</span> _OPEN_FILE_FOR_WRITING<span class="Delimiter">);</span> <span class="Delimiter">:(before "End Primitive Recipe Checks")</span> -<span class="Normal">case</span> OPEN_FILE_FOR_WRITING: <span class="Delimiter">{</span> +<span class="Normal">case</span> _OPEN_FILE_FOR_WRITING: <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'$open-file-for-writing' requires exactly one ingredient, but got '"</span> << inst<span class="Delimiter">.</span>original_string << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + string filename<span class="Delimiter">;</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"first ingredient of '$open-file-for-writing' should be a string, but got '"</span> << to_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">))</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> -<span class="Normal">case</span> OPEN_FILE_FOR_WRITING: <span class="Delimiter">{</span> +<span class="Normal">case</span> _OPEN_FILE_FOR_WRITING: <span class="Delimiter">{</span> + string filename = read_mu_string<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> + assert<span class="Delimiter">(</span><span class="Normal">sizeof</span><span class="Delimiter">(</span><span class="Normal">long</span> <span class="Normal">long</span> <span class="Normal">int</span><span class="Delimiter">)</span> >= <span class="Normal">sizeof</span><span class="Delimiter">(</span><span class="Normal">FILE</span>*<span class="Delimiter">));</span> + <span class="Normal">long</span> <span class="Normal">long</span> <span class="Normal">int</span> result = <span class="Normal">reinterpret_cast</span><<span class="Normal">long</span> <span class="Normal">long</span> <span class="Normal">int</span>><span class="Delimiter">(</span>fopen<span class="Delimiter">(</span>filename<span class="Delimiter">.</span>c_str<span class="Delimiter">(),</span> <span class="Constant">"w"</span><span class="Delimiter">));</span> + products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> + products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Normal">static_cast</span><<span class="Normal">double</span>><span class="Delimiter">(</span>result<span class="Delimiter">));</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +_READ_FROM_FILE<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"$read-from-file"</span><span class="Delimiter">,</span> _READ_FROM_FILE<span class="Delimiter">);</span> +<span class="Delimiter">:(before "End Primitive Recipe Checks")</span> +<span class="Normal">case</span> _READ_FROM_FILE: <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'$read-from-file' requires exactly one ingredient, but got '"</span> << inst<span class="Delimiter">.</span>original_string << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + string filename<span class="Delimiter">;</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"first ingredient of '$read-from-file' should be a number, but got '"</span> << to_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">))</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +<span class="Normal">case</span> _READ_FROM_FILE: <span class="Delimiter">{</span> + <span class="Normal">long</span> <span class="Normal">long</span> <span class="Normal">int</span> x = <span class="Normal">static_cast</span><<span class="Normal">long</span> <span class="Normal">long</span> <span class="Normal">int</span>><span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> + <span class="Normal">FILE</span>* f = <span class="Normal">reinterpret_cast</span><<span class="Normal">FILE</span>*><span class="Delimiter">(</span>x<span class="Delimiter">);</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>f == <span class="Constant">NULL</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> << <span class="Constant">"can't read from null file in '"</span> << to_string<span class="Delimiter">(</span>current_instruction<span class="Delimiter">())</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>feof<span class="Delimiter">(</span>f<span class="Delimiter">))</span> <span class="Delimiter">{</span> + products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>ferror<span class="Delimiter">(</span>f<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> << <span class="Constant">"file in invalid state in '"</span> << to_string<span class="Delimiter">(</span>current_instruction<span class="Delimiter">())</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Normal">char</span> c = getc<span class="Delimiter">(</span>f<span class="Delimiter">);</span> <span class="Comment">// todo: unicode</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>ferror<span class="Delimiter">(</span>f<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> << <span class="Constant">"couldn't read from file in '"</span> << to_string<span class="Delimiter">(</span>current_instruction<span class="Delimiter">())</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + raise << <span class="Constant">" errno: "</span> << errno << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>c<span class="Delimiter">);</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> +<span class="Delimiter">:(before "End Includes")</span> +<span class="PreProc">#include </span><span class="Constant"><cerrno></span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +_WRITE_TO_FILE<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"$write-to-file"</span><span class="Delimiter">,</span> _WRITE_TO_FILE<span class="Delimiter">);</span> +<span class="Delimiter">:(before "End Primitive Recipe Checks")</span> +<span class="Normal">case</span> _WRITE_TO_FILE: <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">2</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'$write-to-file' requires exactly two ingredients, but got '"</span> << inst<span class="Delimiter">.</span>original_string << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + string filename<span class="Delimiter">;</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"first ingredient of '$write-to-file' should be a number, but got '"</span> << to_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">))</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"second ingredient of '$write-to-file' should be a number, but got '"</span> << to_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">))</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +<span class="Normal">case</span> _WRITE_TO_FILE: <span class="Delimiter">{</span> + <span class="Normal">long</span> <span class="Normal">long</span> <span class="Normal">int</span> x = <span class="Normal">static_cast</span><<span class="Normal">long</span> <span class="Normal">long</span> <span class="Normal">int</span>><span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> + <span class="Normal">FILE</span>* f = <span class="Normal">reinterpret_cast</span><<span class="Normal">FILE</span>*><span class="Delimiter">(</span>x<span class="Delimiter">);</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>f == <span class="Constant">NULL</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> << <span class="Constant">"can't write to null file in '"</span> << to_string<span class="Delimiter">(</span>current_instruction<span class="Delimiter">())</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>feof<span class="Delimiter">(</span>f<span class="Delimiter">))</span> <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>ferror<span class="Delimiter">(</span>f<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> << <span class="Constant">"file in invalid state in '"</span> << to_string<span class="Delimiter">(</span>current_instruction<span class="Delimiter">())</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Normal">long</span> <span class="Normal">long</span> <span class="Normal">int</span> y = <span class="Normal">static_cast</span><<span class="Normal">long</span> <span class="Normal">long</span> <span class="Normal">int</span>><span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> + <span class="Normal">char</span> c = <span class="Normal">static_cast</span><<span class="Normal">char</span>><span class="Delimiter">(</span>y<span class="Delimiter">);</span> + putc<span class="Delimiter">(</span>c<span class="Delimiter">,</span> f<span class="Delimiter">);</span> <span class="Comment">// todo: unicode</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>ferror<span class="Delimiter">(</span>f<span class="Delimiter">))</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> << <span class="Constant">"couldn't write to file in '"</span> << to_string<span class="Delimiter">(</span>current_instruction<span class="Delimiter">())</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + raise << <span class="Constant">" errno: "</span> << errno << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +_CLOSE_FILE<span class="Delimiter">,</span> +<span class="Delimiter">:(before "End Primitive Recipe Numbers")</span> +put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"$close-file"</span><span class="Delimiter">,</span> _CLOSE_FILE<span class="Delimiter">);</span> +<span class="Delimiter">:(before "End Primitive Recipe Checks")</span> +<span class="Normal">case</span> _CLOSE_FILE: <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> != <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"'$close-file' requires exactly one ingredient, but got '"</span> << inst<span class="Delimiter">.</span>original_string << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + string filename<span class="Delimiter">;</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!is_mu_number<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>name<span class="Delimiter">)</span> << <span class="Constant">"first ingredient of '$close-file' should be a number, but got '"</span> << to_string<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">))</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> +<span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> +<span class="Normal">case</span> _CLOSE_FILE: <span class="Delimiter">{</span> + <span class="Normal">long</span> <span class="Normal">long</span> <span class="Normal">int</span> x = <span class="Normal">static_cast</span><<span class="Normal">long</span> <span class="Normal">long</span> <span class="Normal">int</span>><span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> + <span class="Normal">FILE</span>* f = <span class="Normal">reinterpret_cast</span><<span class="Normal">FILE</span>*><span class="Delimiter">(</span>x<span class="Delimiter">);</span> + fclose<span class="Delimiter">(</span>f<span class="Delimiter">);</span> + products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> + products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> <span class="Comment">// todo: ensure that caller always resets the ingredient</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> </pre> diff --git a/html/088file.mu.html b/html/088file.mu.html new file mode 100644 index 00000000..a8f2153c --- /dev/null +++ b/html/088file.mu.html @@ -0,0 +1,68 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<html> +<head> +<meta http-equiv="content-type" content="text/html; charset=UTF-8"> +<title>Mu - 088file.mu</title> +<meta name="Generator" content="Vim/7.4"> +<meta name="plugin-version" content="vim7.4_v2"> +<meta name="syntax" content="none"> +<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy="> +<meta name="colorscheme" content="minimal"> +<style type="text/css"> +<!-- +pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } +body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color: #080808; } +* { font-size: 12pt; font-size: 1em; } +.muRecipe { color: #ff8700; } +.muData { color: #ffff00; } +.Comment { color: #9090ff; } +.Delimiter { color: #800080; } +.Special { color: #c00000; } +.Constant { color: #00a0a0; } +.muControl { color: #c0a020; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment"># Wrappers around file-system primitives that take a 'filesystem' object and</span> +<span class="Comment"># are thus easier to test.</span> + +<span class="muData">container</span> filesystem [ + <span class="Delimiter">{</span>data: (address table (address array character) (address array character))<span class="Delimiter">}</span> +] + +<span class="muRecipe">def</span> start-reading fs:address:filesystem, filename:address:array:character<span class="muRecipe"> -> </span>contents:address:source:character [ + <span class="Constant">local-scope</span> + <span class="Constant">load-ingredients</span> + x:number/file<span class="Special"> <- </span>$open-file-for-reading filename + contents:address:source:character, sink:address:sink:character<span class="Special"> <- </span>new-channel <span class="Constant">30</span> + $print <span class="Constant">[sink: ]</span>, sink, <span class="Constant">10/newline</span> + chan:address:channel:character<span class="Special"> <- </span>get *sink, <span class="Constant">chan:offset</span> + $print <span class="Constant">[chan in start-reading: ]</span>, chan, <span class="Constant">10/newline</span> + start-running transmit x, sink +] + +<span class="muRecipe">def</span> transmit file:number, sink:address:sink:character<span class="muRecipe"> -> </span>file:number, sink:address:sink:character [ + <span class="Constant">local-scope</span> + <span class="Constant">load-ingredients</span> + <span class="Delimiter">{</span> + c:character<span class="Special"> <- </span>$read-from-file file + <span class="muControl">break-unless</span> c + sink<span class="Special"> <- </span>write sink, c + <span class="muControl">loop</span> + <span class="Delimiter">}</span> + $print <span class="Constant">[closing chan after reading file]</span>, <span class="Constant">10/newline</span> + sink<span class="Special"> <- </span>close sink + $print <span class="Constant">[returning from 'transmit']</span>, <span class="Constant">10/newline</span> +] +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/091run_sandboxed.cc.html b/html/091run_sandboxed.cc.html index 375b6beb..cd7cd455 100644 --- a/html/091run_sandboxed.cc.html +++ b/html/091run_sandboxed.cc.html @@ -387,7 +387,7 @@ def main [ string Most_recent_products<span class="Delimiter">;</span> <span class="Delimiter">:(before "End Setup")</span> Most_recent_products = <span class="Constant">""</span><span class="Delimiter">;</span> -<span class="Delimiter">:(before "End of Instruction")</span> +<span class="Delimiter">:(before "End Running One Instruction")</span> <span class="Normal">if</span> <span class="Delimiter">(</span>Track_most_recent_products<span class="Delimiter">)</span> <span class="Delimiter">{</span> track_most_recent_products<span class="Delimiter">(</span>current_instruction<span class="Delimiter">(),</span> products<span class="Delimiter">);</span> <span class="Delimiter">}</span> diff --git a/html/092persist.cc.html b/html/092persist.cc.html index 87682997..6c1e722c 100644 --- a/html/092persist.cc.html +++ b/html/092persist.cc.html @@ -82,18 +82,13 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span <span class="Delimiter">}</span> <span class="Delimiter">:(code)</span> +<span class="Comment">// <a href="http://cpp.indi.frih.net/blog/2014/09/how-to-read-an-entire-file-into-memory-in-cpp">http://cpp.indi.frih.net/blog/2014/09/how-to-read-an-entire-file-into-memory-in-cpp</a></span> string slurp<span class="Delimiter">(</span><span class="Normal">const</span> string& filename<span class="Delimiter">)</span> <span class="Delimiter">{</span> - ostringstream result<span class="Delimiter">;</span> ifstream fin<span class="Delimiter">(</span>filename<span class="Delimiter">.</span>c_str<span class="Delimiter">());</span> fin<span class="Delimiter">.</span>peek<span class="Delimiter">();</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!fin<span class="Delimiter">)</span> <span class="Identifier">return</span> result<span class="Delimiter">.</span>str<span class="Delimiter">();</span> <span class="Comment">// don't bother checking errno</span> - <span class="Normal">const</span> <span class="Normal">int</span> N = <span class="Constant">1024</span><span class="Delimiter">;</span> - <span class="Normal">char</span> buf[N]<span class="Delimiter">;</span> - <span class="Normal">while</span> <span class="Delimiter">(</span>has_data<span class="Delimiter">(</span>fin<span class="Delimiter">))</span> <span class="Delimiter">{</span> - bzero<span class="Delimiter">(</span>buf<span class="Delimiter">,</span> N<span class="Delimiter">);</span> - fin<span class="Delimiter">.</span>read<span class="Delimiter">(</span>buf<span class="Delimiter">,</span> N-<span class="Constant">1</span><span class="Delimiter">);</span> <span class="Comment">// leave at least one null</span> - result << buf<span class="Delimiter">;</span> - <span class="Delimiter">}</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!fin<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">""</span><span class="Delimiter">;</span> <span class="Comment">// don't bother checking errno</span> + ostringstream result<span class="Delimiter">;</span> + result << fin<span class="Delimiter">.</span>rdbuf<span class="Delimiter">();</span> fin<span class="Delimiter">.</span>close<span class="Delimiter">();</span> <span class="Identifier">return</span> result<span class="Delimiter">.</span>str<span class="Delimiter">();</span> <span class="Delimiter">}</span> diff --git a/html/filesystem.mu.html b/html/filesystem.mu.html new file mode 100644 index 00000000..17cecb3a --- /dev/null +++ b/html/filesystem.mu.html @@ -0,0 +1,52 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<html> +<head> +<meta http-equiv="content-type" content="text/html; charset=UTF-8"> +<title>Mu - filesystem.mu</title> +<meta name="Generator" content="Vim/7.4"> +<meta name="plugin-version" content="vim7.4_v2"> +<meta name="syntax" content="none"> +<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy="> +<meta name="colorscheme" content="minimal"> +<style type="text/css"> +<!-- +pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } +body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color: #080808; } +* { font-size: 12pt; font-size: 1em; } +.muRecipe { color: #ff8700; } +.Delimiter { color: #800080; } +.Comment { color: #9090ff; } +.Constant { color: #00a0a0; } +.Special { color: #c00000; } +.muControl { color: #c0a020; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="muRecipe">def</span> main [ + <span class="Constant">local-scope</span> + $print <span class="Constant">[file to read from: ]</span>, <span class="Constant">[/tmp/mu-fs]</span> + <span class="Comment"># initialize filesystem</span> + fs:address:filesystem<span class="Special"> <- </span>copy <span class="Constant">0/real-filesystem</span> + content-source:address:source:character<span class="Special"> <- </span>start-reading fs, <span class="Constant">[/tmp/mu-fs]</span> + <span class="Comment"># read from channel until exhausted and print out characters</span> + <span class="Delimiter">{</span> + c:character, done?:boolean, content-source<span class="Special"> <- </span>read content-source + <span class="muControl">break-if</span> done? + $print <span class="Constant">[Next: ]</span>, c, <span class="Constant">10/newline</span> + <span class="muControl">loop</span> + <span class="Delimiter">}</span> + $print <span class="Constant">[Done reading]</span>, <span class="Constant">10/newline</span> + <span class="Comment"># TODO: writing to file</span> +] +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/real-files.mu.html b/html/real-files.mu.html new file mode 100644 index 00000000..48cddbb8 --- /dev/null +++ b/html/real-files.mu.html @@ -0,0 +1,52 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +<html> +<head> +<meta http-equiv="content-type" content="text/html; charset=UTF-8"> +<title>Mu - real-files.mu</title> +<meta name="Generator" content="Vim/7.4"> +<meta name="plugin-version" content="vim7.4_v2"> +<meta name="syntax" content="none"> +<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy="> +<meta name="colorscheme" content="minimal"> +<style type="text/css"> +<!-- +pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; } +body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color: #080808; } +* { font-size: 12pt; font-size: 1em; } +.muRecipe { color: #ff8700; } +.Comment { color: #9090ff; } +.Constant { color: #00a0a0; } +.Special { color: #c00000; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment"># example program: read a character from one file and write it to another</span> +<span class="Comment"># BEWARE: this will modify your file system</span> +<span class="Comment"># before running it, put a character into /tmp/mu-x</span> +<span class="Comment"># after running it, check /tmp/mu-y</span> + +<span class="muRecipe">def</span> main [ + <span class="Constant">local-scope</span> + f:number/file<span class="Special"> <- </span>$open-file-for-reading <span class="Constant">[/tmp/mu-x]</span> + $print <span class="Constant">[file to read from: ]</span>, f, <span class="Constant">10/newline</span> + c:character<span class="Special"> <- </span>$read-from-file f + $print <span class="Constant">[copying ]</span>, c, <span class="Constant">10/newline</span> + f<span class="Special"> <- </span>$close-file f + $print <span class="Constant">[file after closing: ]</span>, f, <span class="Constant">10/newline</span> + f<span class="Special"> <- </span>$open-file-for-writing <span class="Constant">[/tmp/mu-y]</span> + $print <span class="Constant">[file to write to: ]</span>, f, <span class="Constant">10/newline</span> + $write-to-file f, c + f<span class="Special"> <- </span>$close-file f +] +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/screen.mu.html b/html/screen.mu.html index 0152db56..b178a778 100644 --- a/html/screen.mu.html +++ b/html/screen.mu.html @@ -29,10 +29,9 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <body> <pre id='vimCodeElement'> <span class="Comment"># example program: managing the display using 'screen' objects</span> -<span class="Comment">#</span> + <span class="Comment"># The zero screen below means 'use the real screen'. Tests can also use fake</span> <span class="Comment"># screens.</span> - <span class="muRecipe">def</span> main [ open-console <span class="Constant">10</span>:character<span class="Special"> <- </span>copy <span class="Constant">97/a</span> |