diff options
55 files changed, 1762 insertions, 520 deletions
diff --git a/html/000organization.cc.html b/html/000organization.cc.html index c90175d5..d34e80f2 100644 --- a/html/000organization.cc.html +++ b/html/000organization.cc.html @@ -145,7 +145,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment">//: our first directive; will move the include above the program</span> <span class="Delimiter">:(before "End Includes")</span> -<span class="PreProc">#include</span><span class="Constant"><stdlib.h></span> +<span class="PreProc">#include </span><span class="Constant"><stdlib.h></span> <span class="Comment">//: Without directives or with the :(code) directive, lines get added at the</span> <span class="Comment">//: end.</span> diff --git a/html/001help.cc.html b/html/001help.cc.html index c25cbf2f..d6b21301 100644 --- a/html/001help.cc.html +++ b/html/001help.cc.html @@ -21,6 +21,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color .Identifier { color: #fcb165; } .Normal { color: #eeeeee; background-color: #080808; padding-bottom: 1px; } .PreProc { color: #800080; } +.CommentedCode { color: #6c6c6c; } --> </style> @@ -129,10 +130,71 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment">//: up in than integer overflow.</span> <span class="Delimiter">:(before "End Includes")</span> <span class="PreProc">#define SIZE(X) (assert((X)</span><span class="Delimiter">.</span><span class="PreProc">size() < (</span><span class="Constant">1LL</span><span class="PreProc"><<(</span><span class="Normal">sizeof</span><span class="PreProc">(</span><span class="Normal">int</span><span class="PreProc">)*</span><span class="Constant">8</span><span class="PreProc">-</span><span class="Constant">2</span><span class="PreProc">)))</span><span class="Delimiter">,</span><span class="PreProc"> </span><span class="Normal">static_cast</span><span class="PreProc"><</span><span class="Normal">int</span><span class="PreProc">>((X)</span><span class="Delimiter">.</span><span class="PreProc">size()))</span> -<span class="Comment">//:</span> -<span class="Comment">//: 5. Integer overflow is still impossible to guard against. Maybe after</span> -<span class="Comment">//: reading <a href="http://www.cs.utah.edu/~regehr/papers/overflow12.pdf">http://www.cs.utah.edu/~regehr/papers/overflow12.pdf</a></span> -<span class="Comment">//:</span> + +<span class="Comment">//: 5. Integer overflow is guarded against at runtime using the -ftrapv flag</span> +<span class="Comment">//: to the compiler, supported by Clang (GCC version only works sometimes:</span> +<span class="Comment">//: <a href="http://stackoverflow.com/questions/20851061/how-to-make-gcc-ftrapv-work).">http://stackoverflow.com/questions/20851061/how-to-make-gcc-ftrapv-work).</a></span> +<span class="Delimiter">:(before "atexit(teardown)")</span> +initialize_signal_handlers<span class="Delimiter">();</span> <span class="Comment">// not always necessary, but doesn't hurt</span> +<span class="CommentedCode">//? cerr << INT_MAX+1 << '\n'; // test overflow</span> +<span class="CommentedCode">//? assert(false); // test SIGABRT</span> +<span class="Delimiter">:(code)</span> +<span class="Comment">// based on <a href="https://spin.atomicobject.com/2013/01/13/exceptions-stack-traces-c">https://spin.atomicobject.com/2013/01/13/exceptions-stack-traces-c</a></span> +<span class="Normal">void</span> initialize_signal_handlers<span class="Delimiter">()</span> <span class="Delimiter">{</span> + <span class="Normal">struct</span> sigaction action<span class="Delimiter">;</span> + bzero<span class="Delimiter">(</span>&action<span class="Delimiter">,</span> <span class="Normal">sizeof</span><span class="Delimiter">(</span>action<span class="Delimiter">));</span> + action<span class="Delimiter">.</span>sa_sigaction = dump_and_exit<span class="Delimiter">;</span> + sigemptyset<span class="Delimiter">(</span>&action<span class="Delimiter">.</span>sa_mask<span class="Delimiter">);</span> + sigaction<span class="Delimiter">(</span><span class="Constant">SIGABRT</span><span class="Delimiter">,</span> &action<span class="Delimiter">,</span> <span class="Constant">NULL</span><span class="Delimiter">);</span> <span class="Comment">// assert() failure or integer overflow on linux (with -ftrapv)</span> + sigaction<span class="Delimiter">(</span><span class="Constant">SIGILL</span><span class="Delimiter">,</span> &action<span class="Delimiter">,</span> <span class="Constant">NULL</span><span class="Delimiter">);</span> <span class="Comment">// integer overflow on OS X (with -ftrapv)</span> +<span class="Delimiter">}</span> +<span class="Normal">void</span> dump_and_exit<span class="Delimiter">(</span><span class="Normal">int</span> sig<span class="Delimiter">,</span> unused siginfo_t* dummy1<span class="Delimiter">,</span> unused <span class="Normal">void</span>* dummy2<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">switch</span> <span class="Delimiter">(</span>sig<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">case</span> <span class="Constant">SIGABRT</span>: +<span class="PreProc"> #ifndef __APPLE__</span> + cerr << <span class="Constant">"SIGABRT: might be an integer overflow if it wasn't an assert() failure</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">;</span> + _Exit<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> +<span class="PreProc"> #endif</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Normal">case</span> <span class="Constant">SIGILL</span>: +<span class="PreProc"> #ifdef __APPLE__</span> + cerr << <span class="Constant">"SIGILL: most likely caused by integer overflow</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">;</span> + _Exit<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span> +<span class="PreProc"> #endif</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Normal">default</span>: + <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> +<span class="Delimiter">:(before "End Includes")</span> +<span class="PreProc">#include </span><span class="Constant"><signal.h></span> + +<span class="Comment">//: For good measure we'll also enable SIGFPE.</span> +<span class="Delimiter">:(before "atexit(teardown)")</span> +feenableexcept<span class="Delimiter">(</span>FE_OVERFLOW | FE_UNDERFLOW<span class="Delimiter">);</span> +<span class="CommentedCode">//? assert(sizeof(int) == 4 && sizeof(float) == 4);</span> +<span class="CommentedCode">//? // | exp | mantissa</span> +<span class="CommentedCode">//? int smallest_subnormal = 0b00000000000000000000000000000001;</span> +<span class="CommentedCode">//? float smallest_subnormal_f = *reinterpret_cast<int*>(&smallest_subnormal);</span> +<span class="CommentedCode">//? cerr << "ε/2: " << smallest_subnormal_f/2 << " (underflow)\n"; // test SIGFPE</span> +<span class="Delimiter">:(before "End Includes")</span> +<span class="PreProc">#include </span><span class="Constant"><fenv.h></span> +<span class="Delimiter">:(code)</span> +<span class="PreProc">#ifdef __APPLE__</span> +<span class="Comment">// Public domain polyfill for feenableexcept on OS X</span> +<span class="Comment">// <a href="http://www-personal.umich.edu/~williams/archive/computation/fe-handling-example.c">http://www-personal.umich.edu/~williams/archive/computation/fe-handling-example.c</a></span> +<span class="Normal">inline</span> <span class="Normal">int</span> feenableexcept <span class="Delimiter">(</span><span class="Normal">unsigned</span> <span class="Normal">int</span> excepts<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">static</span> fenv_t fenv<span class="Delimiter">;</span> + <span class="Normal">unsigned</span> <span class="Normal">int</span> new_excepts = excepts & FE_ALL_EXCEPT<span class="Delimiter">;</span> + <span class="Normal">unsigned</span> <span class="Normal">int</span> old_excepts<span class="Delimiter">;</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>fegetenv<span class="Delimiter">(</span>&fenv<span class="Delimiter">))</span> <span class="Identifier">return</span> -<span class="Constant">1</span><span class="Delimiter">;</span> + old_excepts = fenv<span class="Delimiter">.</span>__control & FE_ALL_EXCEPT<span class="Delimiter">;</span> + fenv<span class="Delimiter">.</span>__control &= ~new_excepts<span class="Delimiter">;</span> + fenv<span class="Delimiter">.</span>__mxcsr &= ~<span class="Delimiter">(</span>new_excepts << <span class="Constant">7</span><span class="Delimiter">);</span> + <span class="Identifier">return</span> fesetenv<span class="Delimiter">(</span>&fenv<span class="Delimiter">)</span> ? -<span class="Constant">1</span> : old_excepts<span class="Delimiter">;</span> +<span class="Delimiter">}</span> +<span class="PreProc">#endif</span> + <span class="Comment">//: 6. Map's operator[] being non-const is fucking evil.</span> <span class="Delimiter">:(before "Globals")</span> <span class="Comment">// can't generate prototypes for these</span> <span class="Comment">// from <a href="http://stackoverflow.com/questions/152643/idiomatic-c-for-reading-from-a-const-map">http://stackoverflow.com/questions/152643/idiomatic-c-for-reading-from-a-const-map</a></span> @@ -158,29 +220,32 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">}</span> <span class="Comment">//: The contract: any container that relies on get_or_insert should never call</span> <span class="Comment">//: contains_key.</span> -<span class="Comment">//:</span> + <span class="Comment">//: 7. istreams are a royal pain in the arse. You have to be careful about</span> <span class="Comment">//: what subclass you try to putback into. You have to watch out for the pesky</span> <span class="Comment">//: failbit and badbit. Just avoid eof() and use this helper instead.</span> +<span class="Delimiter">:(code)</span> <span class="Normal">bool</span> has_data<span class="Delimiter">(</span>istream& in<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Identifier">return</span> in && !in<span class="Delimiter">.</span>eof<span class="Delimiter">();</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before "End Includes")</span> -<span class="PreProc">#include</span><span class="Constant"><assert.h></span> +<span class="PreProc">#include </span><span class="Constant"><assert.h></span> -<span class="PreProc">#include</span><span class="Constant"><iostream></span> +<span class="PreProc">#include </span><span class="Constant"><iostream></span> <span class="Normal">using</span> std::istream<span class="Delimiter">;</span> <span class="Normal">using</span> std::ostream<span class="Delimiter">;</span> <span class="Normal">using</span> std::iostream<span class="Delimiter">;</span> <span class="Normal">using</span> std::cin<span class="Delimiter">;</span> <span class="Normal">using</span> std::cout<span class="Delimiter">;</span> <span class="Normal">using</span> std::cerr<span class="Delimiter">;</span> -<span class="PreProc">#include</span><span class="Constant"><iomanip></span> +<span class="PreProc">#include </span><span class="Constant"><iomanip></span> -<span class="PreProc">#include</span><span class="Constant"><cstring></span> -<span class="PreProc">#include</span><span class="Constant"><string></span> +<span class="PreProc">#include </span><span class="Constant"><cstring></span> +<span class="PreProc">#include </span><span class="Constant"><string></span> <span class="Normal">using</span> std::string<span class="Delimiter">;</span> + +<span class="PreProc">#define unused __attribute__((unused))</span> </pre> </body> </html> diff --git a/html/002test.cc.html b/html/002test.cc.html index 6774e3ca..c01063f8 100644 --- a/html/002test.cc.html +++ b/html/002test.cc.html @@ -142,7 +142,7 @@ Passed = <span class="Constant">true</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before "End Includes")</span> -<span class="PreProc">#include</span><span class="Constant"><cstdlib></span> +<span class="PreProc">#include </span><span class="Constant"><cstdlib></span> </pre> </body> </html> diff --git a/html/003trace.cc.html b/html/003trace.cc.html index 71d2844d..13cba511 100644 --- a/html/003trace.cc.html +++ b/html/003trace.cc.html @@ -214,22 +214,19 @@ ostream& <span class="Normal">operator</span><<<span class="Delimiter" <span class="PreProc">#define DUMP(label) </span><span class="Normal">if</span><span class="PreProc"> (Trace_stream) cerr << Trace_stream</span><span class="Delimiter">-></span><span class="PreProc">readable_contents(label)</span><span class="Delimiter">;</span> -<span class="Comment">// All scenarios save their traces in the repo, just like code. This gives</span> -<span class="Comment">// future readers more meat when they try to make sense of a new project.</span> -<span class="Normal">static</span> string Trace_dir = <span class="Constant">".traces/"</span><span class="Delimiter">;</span> -string Trace_file<span class="Delimiter">;</span> +<span class="Normal">bool</span> Save_trace = <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Comment">// Trace_stream is a resource, lease_tracer uses RAII to manage it.</span> <span class="Normal">struct</span> lease_tracer <span class="Delimiter">{</span> lease_tracer<span class="Delimiter">()</span> <span class="Delimiter">{</span> Trace_stream = <span class="Normal">new</span> trace_stream<span class="Delimiter">;</span> <span class="Delimiter">}</span> ~lease_tracer<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="Delimiter">;</span> <span class="Comment">// in case tests close Trace_stream</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!Trace_file<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> - ofstream fout<span class="Delimiter">((</span>Trace_dir+Trace_file<span class="Delimiter">).</span>c_str<span class="Delimiter">());</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>Save_trace<span class="Delimiter">)</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> - <span class="Normal">delete</span> Trace_stream<span class="Delimiter">,</span> Trace_stream = <span class="Constant">NULL</span><span class="Delimiter">,</span> Trace_file = <span class="Constant">""</span><span class="Delimiter">;</span> + <span class="Normal">delete</span> Trace_stream<span class="Delimiter">,</span> Trace_stream = <span class="Constant">NULL</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">};</span> @@ -251,12 +248,8 @@ START_TRACING_UNTIL_END_OF_SCOPE string label<span class="Delimiter">,</span> contents<span class="Delimiter">;</span> split_label_contents<span class="Delimiter">(</span>expected_lines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>curr_expected_line<span class="Delimiter">),</span> &label<span class="Delimiter">,</span> &contents<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="Identifier">continue</span><span class="Delimiter">;</span> - - <span class="Normal">if</span> <span class="Delimiter">(</span>contents != trim<span class="Delimiter">(</span>p<span class="Delimiter">-></span>contents<span class="Delimiter">))</span> - <span class="Identifier">continue</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="Identifier">continue</span><span class="Delimiter">;</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>contents != trim<span class="Delimiter">(</span>p<span class="Delimiter">-></span>contents<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> ++curr_expected_line<span class="Delimiter">;</span> <span class="Normal">while</span> <span class="Delimiter">(</span>curr_expected_line < SIZE<span class="Delimiter">(</span>expected_lines<span class="Delimiter">)</span> && expected_lines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>curr_expected_line<span class="Delimiter">).</span>empty<span class="Delimiter">())</span> ++curr_expected_line<span class="Delimiter">;</span> @@ -265,8 +258,14 @@ START_TRACING_UNTIL_END_OF_SCOPE <span class="Delimiter">}</span> ++Num_failures<span class="Delimiter">;</span> - cerr << <span class="Constant">"</span><span class="cSpecial">\n</span><span class="Constant">F - "</span> << FUNCTION << <span class="Constant">"("</span> << <span class="Normal">FILE</span> << <span class="Constant">":"</span> << LINE << <span class="Constant">"): missing ["</span> << contents << <span class="Constant">"] in trace:</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">;</span> - DUMP<span class="Delimiter">(</span>label<span class="Delimiter">);</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>line_exists_anywhere<span class="Delimiter">(</span>label<span class="Delimiter">,</span> contents<span class="Delimiter">))</span> <span class="Delimiter">{</span> + cerr << <span class="Constant">"</span><span class="cSpecial">\n</span><span class="Constant">F - "</span> << FUNCTION << <span class="Constant">"("</span> << <span class="Normal">FILE</span> << <span class="Constant">":"</span> << LINE << <span class="Constant">"): line ["</span> << label << <span class="Constant">": "</span> << contents << <span class="Constant">"] out of order in trace:</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">;</span> + DUMP<span class="Delimiter">(</span><span class="Constant">""</span><span class="Delimiter">);</span> + <span class="Delimiter">}</span> + <span class="Normal">else</span> <span class="Delimiter">{</span> + cerr << <span class="Constant">"</span><span class="cSpecial">\n</span><span class="Constant">F - "</span> << FUNCTION << <span class="Constant">"("</span> << <span class="Normal">FILE</span> << <span class="Constant">":"</span> << LINE << <span class="Constant">"): missing ["</span> << contents << <span class="Constant">"] in trace:</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">;</span> + DUMP<span class="Delimiter">(</span>label<span class="Delimiter">);</span> + <span class="Delimiter">}</span> Passed = <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -284,6 +283,14 @@ START_TRACING_UNTIL_END_OF_SCOPE <span class="Delimiter">}</span> <span class="Delimiter">}</span> +<span class="Normal">bool</span> line_exists_anywhere<span class="Delimiter">(</span><span class="Normal">const</span> string& label<span class="Delimiter">,</span> <span class="Normal">const</span> string& contents<span class="Delimiter">)</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="Identifier">continue</span><span class="Delimiter">;</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>contents == trim<span class="Delimiter">(</span>p<span class="Delimiter">-></span>contents<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + ^L <span class="Normal">int</span> trace_count<span class="Delimiter">(</span>string label<span class="Delimiter">)</span> <span class="Delimiter">{</span> @@ -373,27 +380,25 @@ string trim<span class="Delimiter">(</span><span class="Normal">const</span> str <span class="Delimiter">}</span> <span class="Delimiter">:(before "End Includes")</span> -<span class="PreProc">#include</span><span class="Constant"><vector></span> +<span class="PreProc">#include </span><span class="Constant"><vector></span> <span class="Normal">using</span> std::vector<span class="Delimiter">;</span> -<span class="PreProc">#include</span><span class="Constant"><list></span> +<span class="PreProc">#include </span><span class="Constant"><list></span> <span class="Normal">using</span> std::list<span class="Delimiter">;</span> -<span class="PreProc">#include</span><span class="Constant"><map></span> +<span class="PreProc">#include </span><span class="Constant"><map></span> <span class="Normal">using</span> std::map<span class="Delimiter">;</span> -<span class="PreProc">#include</span><span class="Constant"><set></span> +<span class="PreProc">#include </span><span class="Constant"><set></span> <span class="Normal">using</span> std::set<span class="Delimiter">;</span> -<span class="PreProc">#include</span><span class="Constant"><algorithm></span> +<span class="PreProc">#include </span><span class="Constant"><algorithm></span> -<span class="PreProc">#include</span><span class="Constant"><sstream></span> +<span class="PreProc">#include </span><span class="Constant"><sstream></span> <span class="Normal">using</span> std::istringstream<span class="Delimiter">;</span> <span class="Normal">using</span> std::ostringstream<span class="Delimiter">;</span> -<span class="PreProc">#include</span><span class="Constant"><fstream></span> +<span class="PreProc">#include </span><span class="Constant"><fstream></span> <span class="Normal">using</span> std::ifstream<span class="Delimiter">;</span> <span class="Normal">using</span> std::ofstream<span class="Delimiter">;</span> -<span class="PreProc">#include</span><span class="Constant">"termbox/termbox.h"</span> - -<span class="PreProc">#define unused __attribute__((unused))</span> +<span class="PreProc">#include </span><span class="Constant">"termbox/termbox.h"</span> <span class="Delimiter">:(before "End Globals")</span> <span class="Comment">//: In future layers we'll use the depth field as follows:</span> diff --git a/html/010vm.cc.html b/html/010vm.cc.html index a2a4c926..508f7483 100644 --- a/html/010vm.cc.html +++ b/html/010vm.cc.html @@ -111,9 +111,11 @@ recipe_ordinal Next_recipe_ordinal = <span class="Constant">1</span><span class= ~type_tree<span class="Delimiter">();</span> type_tree<span class="Delimiter">(</span><span class="Normal">const</span> type_tree& old<span class="Delimiter">);</span> <span class="Comment">// simple: type ordinal</span> - <span class="Normal">explicit</span> type_tree<span class="Delimiter">(</span>string name<span class="Delimiter">,</span> type_ordinal v<span class="Delimiter">)</span> :name<span class="Delimiter">(</span>name<span class="Delimiter">),</span> value<span class="Delimiter">(</span>v<span class="Delimiter">),</span> left<span class="Delimiter">(</span><span class="Constant">NULL</span><span class="Delimiter">),</span> right<span class="Delimiter">(</span><span class="Constant">NULL</span><span class="Delimiter">)</span> <span class="Delimiter">{}</span> + <span class="Normal">explicit</span> type_tree<span class="Delimiter">(</span>string name<span class="Delimiter">);</span> + type_tree<span class="Delimiter">(</span>string name<span class="Delimiter">,</span> type_ordinal v<span class="Delimiter">)</span> :name<span class="Delimiter">(</span>name<span class="Delimiter">),</span> value<span class="Delimiter">(</span>v<span class="Delimiter">),</span> left<span class="Delimiter">(</span><span class="Constant">NULL</span><span class="Delimiter">),</span> right<span class="Delimiter">(</span><span class="Constant">NULL</span><span class="Delimiter">)</span> <span class="Delimiter">{}</span> <span class="Comment">// intermediate: list of type ordinals</span> type_tree<span class="Delimiter">(</span>string name<span class="Delimiter">,</span> type_ordinal v<span class="Delimiter">,</span> type_tree* r<span class="Delimiter">)</span> :name<span class="Delimiter">(</span>name<span class="Delimiter">),</span> value<span class="Delimiter">(</span>v<span class="Delimiter">),</span> left<span class="Delimiter">(</span><span class="Constant">NULL</span><span class="Delimiter">),</span> right<span class="Delimiter">(</span>r<span class="Delimiter">)</span> <span class="Delimiter">{}</span> + type_tree<span class="Delimiter">(</span>string name<span class="Delimiter">,</span> type_tree* r<span class="Delimiter">);</span> <span class="Comment">// advanced: tree containing type ordinals</span> type_tree<span class="Delimiter">(</span>type_tree* l<span class="Delimiter">,</span> type_tree* r<span class="Delimiter">)</span> :value<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">),</span> left<span class="Delimiter">(</span>l<span class="Delimiter">),</span> right<span class="Delimiter">(</span>r<span class="Delimiter">)</span> <span class="Delimiter">{}</span> <span class="Delimiter">};</span> @@ -133,6 +135,9 @@ recipe_ordinal Next_recipe_ordinal = <span class="Constant">1</span><span class= <span class="Delimiter">};</span> <span class="Comment">// End type_tree Definition</span> +<span class="Delimiter">:(code)</span> +type_tree::type_tree<span class="Delimiter">(</span>string name<span class="Delimiter">)</span> :name<span class="Delimiter">(</span>name<span class="Delimiter">),</span> value<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> name<span class="Delimiter">)),</span> left<span class="Delimiter">(</span><span class="Constant">NULL</span><span class="Delimiter">),</span> right<span class="Delimiter">(</span><span class="Constant">NULL</span><span class="Delimiter">)</span> <span class="Delimiter">{}</span> +type_tree::type_tree<span class="Delimiter">(</span>string name<span class="Delimiter">,</span> type_tree* r<span class="Delimiter">)</span> :name<span class="Delimiter">(</span>name<span class="Delimiter">),</span> value<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> name<span class="Delimiter">)),</span> left<span class="Delimiter">(</span><span class="Constant">NULL</span><span class="Delimiter">),</span> right<span class="Delimiter">(</span>r<span class="Delimiter">)</span> <span class="Delimiter">{}</span> <span class="Delimiter">:(before "End Globals")</span> <span class="Comment">// Locations refer to a common 'memory'. Each location can store a number.</span> @@ -305,9 +310,9 @@ reagent::reagent<span class="Delimiter">(</span><span class="Normal">const</span <span class="Normal">delete</span> type_names<span class="Delimiter">;</span> <span class="Comment">// special cases</span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_integer<span class="Delimiter">(</span>name<span class="Delimiter">)</span> && type == <span class="Constant">NULL</span><span class="Delimiter">)</span> - type = <span class="Normal">new</span> type_tree<span class="Delimiter">(</span><span class="Constant">"literal"</span><span class="Delimiter">,</span> get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"literal"</span><span class="Delimiter">));</span> + type = <span class="Normal">new</span> type_tree<span class="Delimiter">(</span><span class="Constant">"literal"</span><span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>name == <span class="Constant">"_"</span> && type == <span class="Constant">NULL</span><span class="Delimiter">)</span> - type = <span class="Normal">new</span> type_tree<span class="Delimiter">(</span><span class="Constant">"literal"</span><span class="Delimiter">,</span> get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"literal"</span><span class="Delimiter">));</span> + type = <span class="Normal">new</span> type_tree<span class="Delimiter">(</span><span class="Constant">"literal"</span><span class="Delimiter">);</span> <span class="Comment">// other properties</span> slurp_properties<span class="Delimiter">(</span>in<span class="Delimiter">,</span> properties<span class="Delimiter">);</span> <span class="Comment">// End Parsing reagent</span> @@ -463,8 +468,7 @@ string_tree* property<span class="Delimiter">(</span><span class="Normal">const< <span class="Delimiter">}</span> <span class="SalientComment">//:: Helpers for converting various values to string</span> -<span class="Comment">//: Use to_string() in trace(), and try to avoid relying on unstable codes that</span> -<span class="Comment">//: will perturb .traces/ from commit to commit.</span> +<span class="Comment">//: Use to_string() in trace(), and try to keep it stable from run to run.</span> <span class="Comment">//: Use debug_string() while debugging, and throw everything into it.</span> <span class="Comment">//: Use inspect() only for emitting a canonical format that can be parsed back</span> <span class="Comment">//: into the value.</span> @@ -705,9 +709,9 @@ string trim_floating_point<span class="Delimiter">(</span><span class="Normal">c <span class="Delimiter">}</span> <span class="Delimiter">:(before "End Includes")</span> -<span class="PreProc">#include</span><span class="Constant"><utility></span> +<span class="PreProc">#include </span><span class="Constant"><utility></span> <span class="Normal">using</span> std::pair<span class="Delimiter">;</span> -<span class="PreProc">#include</span><span class="Constant"><math.h></span> +<span class="PreProc">#include </span><span class="Constant"><math.h></span> </pre> </body> </html> diff --git a/html/011load.cc.html b/html/011load.cc.html index 09425a4a..8720745d 100644 --- a/html/011load.cc.html +++ b/html/011load.cc.html @@ -371,7 +371,6 @@ def main [ <span class="Comment">//: this test we can't represent with a scenario</span> <span class="Delimiter">:(code)</span> <span class="Normal">void</span> test_parse_comment_terminated_by_eof<span class="Delimiter">()</span> <span class="Delimiter">{</span> - Trace_file = <span class="Constant">"parse_comment_terminated_by_eof"</span><span class="Delimiter">;</span> load<span class="Delimiter">(</span><span class="Constant">"recipe main [</span><span class="cSpecial">\n</span><span class="Constant">"</span> <span class="Constant">" a:number <- copy 34</span><span class="cSpecial">\n</span><span class="Constant">"</span> <span class="Constant">"]</span><span class="cSpecial">\n</span><span class="Constant">"</span> diff --git a/html/014literal_string.cc.html b/html/014literal_string.cc.html index cee61889..80844f8d 100644 --- a/html/014literal_string.cc.html +++ b/html/014literal_string.cc.html @@ -140,7 +140,7 @@ string slurp_quoted<span class="Delimiter">(</span>istream& in<span class="D <span class="Delimiter">:(after "Parsing reagent(string s)")</span> <span class="Normal">if</span> <span class="Delimiter">(</span>s<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> == <span class="Constant">'['</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - assert<span class="Delimiter">(</span>*s<span class="Delimiter">.</span>rbegin<span class="Delimiter">()</span> == <span class="Constant">']'</span><span class="Delimiter">);</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>*s<span class="Delimiter">.</span>rbegin<span class="Delimiter">()</span> != <span class="Constant">']'</span><span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Comment">// unbalanced bracket; handled elsewhere</span> name = s<span class="Delimiter">;</span> <span class="Comment">// delete [] delimiters</span> name<span class="Delimiter">.</span>erase<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">);</span> @@ -229,6 +229,12 @@ def main [ copy [] ] <span class="traceContains">+parse: ingredient: {"": "literal-string"}</span> + +<span class="Delimiter">:(scenario multiple_unfinished_recipes)</span> +<span class="Special">% Hide_errors = true;</span> +recipe f1 [ +recipe f2 [ +<span class="traceContains">+error: unbalanced '['</span> </pre> </body> </html> diff --git a/html/020run.cc.html b/html/020run.cc.html index 65bc91ab..1a8359bd 100644 --- a/html/020run.cc.html +++ b/html/020run.cc.html @@ -172,7 +172,7 @@ map<string<span class="Delimiter">,</span> <span class="Normal">int</span>> <span class="Comment">//: Step 1: load all .mu files with numeric prefixes (in order)</span> <span class="Delimiter">:(before "End Load Recipes")</span> <span class="Comment">// Load .mu Core</span> -<span class="CommentedCode">//? Trace_file = "interactive";</span> +<span class="CommentedCode">//? Save_trace = true;</span> <span class="CommentedCode">//? START_TRACING_UNTIL_END_OF_SCOPE;</span> load_file_or_directory<span class="Delimiter">(</span><span class="Constant">"core.mu"</span><span class="Delimiter">);</span> <span class="CommentedCode">//? DUMP("");</span> @@ -196,6 +196,8 @@ load_file_or_directory<span class="Delimiter">(</span><span class="Constant">&qu <span class="Normal">if</span> <span class="Delimiter">(</span>Run_tests<span class="Delimiter">)</span> Recipe<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"main"</span><span class="Delimiter">));</span> <span class="Delimiter">}</span> transform_all<span class="Delimiter">();</span> +<span class="CommentedCode">//? DUMP("");</span> +<span class="CommentedCode">//? exit(0);</span> save_snapshots<span class="Delimiter">();</span> <span class="Comment">//: Step 3: if we aren't running tests, locate a recipe called 'main' and</span> @@ -204,7 +206,7 @@ save_snapshots<span class="Delimiter">();</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!Run_tests && contains_key<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"main"</span><span class="Delimiter">)</span> && contains_key<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"main"</span><span class="Delimiter">)))</span> <span class="Delimiter">{</span> <span class="Comment">// Running Main</span> setup<span class="Delimiter">();</span> -<span class="CommentedCode">//? Trace_file = "interactive";</span> +<span class="CommentedCode">//? Save_trace = true;</span> <span class="CommentedCode">//? START_TRACING_UNTIL_END_OF_SCOPE;</span> trace<span class="Delimiter">(</span><span class="Constant">9990</span><span class="Delimiter">,</span> <span class="Constant">"run"</span><span class="Delimiter">)</span> << <span class="Constant">"=== Starting to run"</span> << end<span class="Delimiter">();</span> assert<span class="Delimiter">(</span>Num_calls_to_transform_all == <span class="Constant">1</span><span class="Delimiter">);</span> @@ -237,8 +239,8 @@ save_snapshots<span class="Delimiter">();</span> <span class="Delimiter">:(code)</span> <span class="Normal">void</span> cleanup_main<span class="Delimiter">()</span> <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!Trace_file<span class="Delimiter">.</span>empty<span class="Delimiter">()</span> && Trace_stream<span class="Delimiter">)</span> <span class="Delimiter">{</span> - ofstream fout<span class="Delimiter">((</span>Trace_dir+Trace_file<span class="Delimiter">).</span>c_str<span class="Delimiter">());</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>Save_trace && Trace_stream<span class="Delimiter">)</span> <span class="Delimiter">{</span> + ofstream fout<span class="Delimiter">(</span><span class="Constant">"interactive"</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> @@ -281,8 +283,8 @@ atexit<span class="Delimiter">(</span>cleanup_main<span class="Delimiter">);</sp free<span class="Delimiter">(</span>files<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Delimiter">:(before "End Includes")</span> -<span class="PreProc">#include</span><span class="Constant"><dirent.h></span> -<span class="PreProc">#include</span><span class="Constant"><sys/stat.h></span> +<span class="PreProc">#include </span><span class="Constant"><dirent.h></span> +<span class="PreProc">#include </span><span class="Constant"><sys/stat.h></span> <span class="SalientComment">//:: Reading from memory, writing to memory.</span> @@ -328,18 +330,18 @@ vector<<span class="Normal">double</span>> read_memory<span class="Delimit <span class="Delimiter">:(code)</span> <span class="Normal">int</span> size_of<span class="Delimiter">(</span><span class="Normal">const</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>type == <span class="Constant">NULL</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">0</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">0</span><span class="Delimiter">;</span> <span class="Comment">// End size_of(reagent r) Cases</span> <span class="Identifier">return</span> size_of<span class="Delimiter">(</span>r<span class="Delimiter">.</span>type<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Normal">int</span> size_of<span class="Delimiter">(</span><span class="Normal">const</span> type_tree* type<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>type == <span class="Constant">NULL</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">0</span><span class="Delimiter">;</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!type<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">0</span><span class="Delimiter">;</span> <span class="Comment">// End size_of(type) Cases</span> <span class="Identifier">return</span> <span class="Constant">1</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Normal">bool</span> size_mismatch<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> - <span class="Normal">if</span> <span class="Delimiter">(</span>x<span class="Delimiter">.</span>type == <span class="Constant">NULL</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>!x<span class="Delimiter">.</span>type<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> <span class="Comment">// End size_mismatch(x) Cases</span> <span class="CommentedCode">//? if (size_of(x) != SIZE(data)) cerr << size_of(x) << " vs " << SIZE(data) << '\n';</span> <span class="Identifier">return</span> size_of<span class="Delimiter">(</span>x<span class="Delimiter">)</span> != SIZE<span class="Delimiter">(</span>data<span class="Delimiter">);</span> diff --git a/html/021check_instruction.cc.html b/html/021check_instruction.cc.html index 6a5db614..841c0cc9 100644 --- a/html/021check_instruction.cc.html +++ b/html/021check_instruction.cc.html @@ -56,7 +56,7 @@ Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</spa <span class="Comment">// Primitive Recipe Checks</span> <span class="Normal">case</span> COPY: <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> != SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">))</span> <span class="Delimiter">{</span> - raise << <span class="Constant">"ingredients and products should match in '"</span> << to_original_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<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">"ingredients and products should match in '"</span> << to_original_string<span class="Delimiter">(</span>inst<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">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>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> @@ -82,7 +82,7 @@ Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</spa def main [ <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">34</span><span class="Delimiter">,</span> <span class="Constant">35</span> ] -<span class="traceContains">+error: ingredients and products should match in '1:number <- copy 34, 35'</span> +<span class="traceContains">+error: main: ingredients and products should match in '1:number <- copy 34, 35'</span> <span class="Delimiter">:(scenario write_scalar_to_array_disallowed)</span> <span class="Special">% Hide_errors = true;</span> diff --git a/html/027call_ingredient.cc.html b/html/027call_ingredient.cc.html index 704fe99d..4757e0c2 100644 --- a/html/027call_ingredient.cc.html +++ b/html/027call_ingredient.cc.html @@ -206,7 +206,8 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span <span class="Comment">//: a particularly common array type is the string, or address:array:character</span> <span class="Delimiter">:(code)</span> -<span class="Normal">bool</span> is_mu_string<span class="Delimiter">(</span><span class="Normal">const</span> reagent& x<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="Normal">bool</span> is_mu_string<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="Delimiter">{</span> + <span class="Comment">// End Preprocess is_mu_string(reagent x)</span> <span class="Identifier">return</span> x<span class="Delimiter">.</span>type && x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value == get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"address"</span><span class="Delimiter">)</span> && x<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right diff --git a/html/029tools.cc.html b/html/029tools.cc.html index 3ce59059..f87390ff 100644 --- a/html/029tools.cc.html +++ b/html/029tools.cc.html @@ -215,8 +215,8 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span <span class="Delimiter">}</span> <span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> <span class="Normal">case</span> _SAVE_TRACE: <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!Trace_file<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span> - ofstream fout<span class="Delimiter">((</span>Trace_dir+Trace_file<span class="Delimiter">).</span>c_str<span class="Delimiter">());</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>Save_trace<span class="Delimiter">)</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> diff --git a/html/030container.cc.html b/html/030container.cc.html index 12193713..a7f5d552 100644 --- a/html/030container.cc.html +++ b/html/030container.cc.html @@ -128,14 +128,12 @@ def main [ ] <span class="traceContains">+mem: storing 0 in location 7</span> -<span class="Comment">//: Global data structure for container metadata.</span> <span class="Comment">//: Can't put this in type_info because later layers will add support for more</span> <span class="Comment">//: complex type trees where metadata depends on *combinations* of types.</span> - <span class="Delimiter">:(before "struct reagent")</span> <span class="Normal">struct</span> container_metadata <span class="Delimiter">{</span> <span class="Normal">int</span> size<span class="Delimiter">;</span> - vector<<span class="Normal">int</span>> offset<span class="Delimiter">;</span> + vector<<span class="Normal">int</span>> offset<span class="Delimiter">;</span> <span class="Comment">// not used by exclusive containers</span> <span class="Comment">// End container_metadata Fields</span> container_metadata<span class="Delimiter">()</span> :size<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Comment">// End container_metadata Constructor</span> @@ -365,6 +363,7 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span assert<span class="Delimiter">(</span>!get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> type<span class="Delimiter">-></span>value<span class="Delimiter">).</span>name<span class="Delimiter">.</span>empty<span class="Delimiter">());</span> <span class="Normal">const</span> type_info& info = get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> type<span class="Delimiter">-></span>value<span class="Delimiter">);</span> assert<span class="Delimiter">(</span>info<span class="Delimiter">.</span>kind == CONTAINER<span class="Delimiter">);</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>offset_value >= SIZE<span class="Delimiter">(</span>info<span class="Delimiter">.</span>elements<span class="Delimiter">))</span> <span class="Identifier">return</span> reagent<span class="Delimiter">();</span> <span class="Comment">// error handled elsewhere</span> reagent<span class="Comment">/*</span><span class="Comment">copy</span><span class="Comment">*/</span> element = info<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>at<span class="Delimiter">(</span>offset_value<span class="Delimiter">);</span> <span class="Comment">// End element_type Special-cases</span> <span class="Identifier">return</span> element<span class="Delimiter">;</span> @@ -588,7 +587,7 @@ Num_calls_to_transform_all_at_first_definition = -<span class="Constant">1</span put<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> name<span class="Delimiter">,</span> Next_type_ordinal++<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">"parse"</span><span class="Delimiter">)</span> << <span class="Constant">"type number: "</span> << get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> name<span class="Delimiter">)</span> << end<span class="Delimiter">();</span> - skip_bracket<span class="Delimiter">(</span>in<span class="Delimiter">,</span> <span class="Constant">"'container' must begin with '['"</span><span class="Delimiter">);</span> + skip_bracket<span class="Delimiter">(</span>in<span class="Delimiter">,</span> <span class="Constant">"'"</span>+command+<span class="Constant">"' must begin with '['"</span><span class="Delimiter">);</span> type_info& info = get_or_insert<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> name<span class="Delimiter">));</span> <span class="Normal">if</span> <span class="Delimiter">(</span>info<span class="Delimiter">.</span>Num_calls_to_transform_all_at_first_definition == -<span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Comment">// initial definition of this container</span> @@ -605,6 +604,15 @@ Num_calls_to_transform_all_at_first_definition = -<span class="Constant">1</span skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> string element = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>element == <span class="Constant">"]"</span><span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>in<span class="Delimiter">.</span>peek<span class="Delimiter">()</span> != <span class="cSpecial">'\n'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise << command << <span class="Constant">" '"</span> << name << <span class="Constant">"' contains multiple elements on a single line. Containers and exclusive containers must only contain elements, one to a line, no code.</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Comment">// skip rest of container declaration</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> + skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>next_word<span class="Delimiter">(</span>in<span class="Delimiter">)</span> == <span class="Constant">"]"</span><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> info<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>reagent<span class="Delimiter">(</span>element<span class="Delimiter">));</span> replace_unknown_types_with_unique_ordinals<span class="Delimiter">(</span>info<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>back<span class="Delimiter">().</span>type<span class="Delimiter">,</span> info<span class="Delimiter">);</span> trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">"parse"</span><span class="Delimiter">)</span> << <span class="Constant">" element: "</span> << to_string<span class="Delimiter">(</span>info<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>back<span class="Delimiter">())</span> << end<span class="Delimiter">();</span> @@ -637,6 +645,13 @@ Num_calls_to_transform_all_at_first_definition = -<span class="Constant">1</span raise << message << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> <span class="Delimiter">}</span> +<span class="Delimiter">:(scenario multi_word_line_in_container_declaration)</span> +<span class="Special">% Hide_errors = true;</span> +container foo [ + <span class="Normal">x</span>:number y:number +] +<span class="traceContains">+error: container 'foo' contains multiple elements on a single line. Containers and exclusive containers must only contain elements, one to a line, no code.</span> + <span class="Comment">//: ensure scenarios are consistent by always starting them at the same type</span> <span class="Comment">//: number.</span> <span class="Delimiter">:(before "End Setup")</span> <span class="Comment">//: for tests</span> diff --git a/html/031merge.cc.html b/html/031merge.cc.html index 12a4b2a5..34dc65a9 100644 --- a/html/031merge.cc.html +++ b/html/031merge.cc.html @@ -186,6 +186,7 @@ Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</spa <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> reagent& container = state<span class="Delimiter">.</span>data<span class="Delimiter">.</span>top<span class="Delimiter">().</span>container<span class="Delimiter">;</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!container<span class="Delimiter">.</span>type<span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Comment">// error handled elsewhere</span> type_info& container_info = get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> container<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value<span class="Delimiter">);</span> <span class="Normal">switch</span> <span class="Delimiter">(</span>container_info<span class="Delimiter">.</span>kind<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">case</span> CONTAINER: <span class="Delimiter">{</span> @@ -215,7 +216,7 @@ Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</spa <span class="Delimiter">}</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - <span class="Comment">// End valid_merge Cases</span> + <span class="Comment">// End check_merge_call Cases</span> <span class="Normal">default</span>: <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!types_coercible<span class="Delimiter">(</span>container<span class="Delimiter">,</span> ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>ingredient_index<span class="Delimiter">)))</span> <span class="Delimiter">{</span> raise << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"incorrect type of ingredient "</span> << ingredient_index << <span class="Constant">" in '"</span> << to_original_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> diff --git a/html/032array.cc.html b/html/032array.cc.html index 277398e6..fb9bb0d5 100644 --- a/html/032array.cc.html +++ b/html/032array.cc.html @@ -163,7 +163,7 @@ container foo [ <span class="Delimiter">:(before "End Load Container Element Definition")</span> <span class="Delimiter">{</span> <span class="Normal">const</span> type_tree* type = info<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>back<span class="Delimiter">().</span>type<span class="Delimiter">;</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>type<span class="Delimiter">-></span>name == <span class="Constant">"array"</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>type && type<span class="Delimiter">-></span>name == <span class="Constant">"array"</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!type<span class="Delimiter">-></span>right<span class="Delimiter">)</span> <span class="Delimiter">{</span> raise << <span class="Constant">"container '"</span> << name << <span class="Constant">"' doesn't specify type of array elements for '"</span> << info<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>back<span class="Delimiter">().</span>name << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> @@ -175,6 +175,17 @@ container foo [ <span class="Delimiter">}</span> <span class="Delimiter">}</span> +<span class="Delimiter">:(scenario code_inside_container)</span> +<span class="Special">% Hide_errors = true;</span> +container card [ + <span class="Normal">rank</span>:number<span class="Special"> <- </span>next-ingredient +] +recipe foo [ + <span class="Constant">1</span>:card<span class="Special"> <- </span>merge <span class="Constant">3</span> + <span class="Constant">2</span>:number<span class="Special"> <- </span>get <span class="Constant">1</span>:card rank:offset +] +<span class="Comment"># shouldn't die</span> + <span class="SalientComment">//:: To access elements of an array, use 'index'</span> <span class="Delimiter">:(scenario index)</span> @@ -245,7 +256,7 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span <span class="Comment">// Update INDEX index in Run</span> vector<<span class="Normal">double</span>> index_val<span class="Delimiter">(</span>read_memory<span class="Delimiter">(</span>index<span class="Delimiter">));</span> <span class="Normal">if</span> <span class="Delimiter">(</span>index_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> < <span class="Constant">0</span> || index_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> >= get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> base_address<span class="Delimiter">))</span> <span class="Delimiter">{</span> - raise << maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> << <span class="Constant">"invalid index "</span> << no_scientific<span class="Delimiter">(</span>index_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">))</span> << <span class="cSpecial">'\n'</span> << end<span class="Delimiter">();</span> + raise << maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> << <span class="Constant">"invalid index "</span> << no_scientific<span class="Delimiter">(</span>index_val<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">))</span> << <span class="Constant">" in '"</span> << to_original_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> type_tree* element_type = copy_array_element<span class="Delimiter">(</span>base<span class="Delimiter">.</span>type<span class="Delimiter">);</span> @@ -306,7 +317,7 @@ def main [ <span class="Constant">7</span>:number<span class="Special"> <- </span>copy <span class="Constant">16</span> index <span class="Constant">1</span>:array:number:<span class="Constant">3</span><span class="Delimiter">,</span> <span class="Constant">4</span> <span class="Comment"># less than size of array in locations, but larger than its length in elements</span> ] -<span class="traceContains">+error: main: invalid index 4</span> +<span class="traceContains">+error: main: invalid index 4 in 'index 1:array:number:3, 4'</span> <span class="Delimiter">:(scenario index_out_of_bounds_2)</span> <span class="Special">% Hide_errors = true;</span> @@ -320,7 +331,7 @@ def main [ <span class="Constant">7</span>:number<span class="Special"> <- </span>copy <span class="Constant">16</span> index <span class="Constant">1</span>:array:point<span class="Delimiter">,</span> -<span class="Constant">1</span> ] -<span class="traceContains">+error: main: invalid index -1</span> +<span class="traceContains">+error: main: invalid index -1 in 'index 1:array:point, -1'</span> <span class="Delimiter">:(scenario index_product_type_mismatch)</span> <span class="Special">% Hide_errors = true;</span> diff --git a/html/033exclusive_container.cc.html b/html/033exclusive_container.cc.html index 90f47d3a..70af4cac 100644 --- a/html/033exclusive_container.cc.html +++ b/html/033exclusive_container.cc.html @@ -304,18 +304,38 @@ container bar [ <span class="Normal">z</span>:number ] def main [ - local-scope <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> <span class="Constant">2</span>:foo<span class="Special"> <- </span>merge <span class="Constant">1</span>:number<span class="Delimiter">,</span> <span class="Constant">34</span> ] -<span class="traceContains">+error: main: ingredient 0 of 'merge' should be a literal, for the tag of exclusive-container 'foo'</span> +<span class="traceContains">+error: main: ingredient 0 of 'merge' should be a literal, for the tag of exclusive-container 'foo' in '2:foo <- merge 1:number, 34'</span> -<span class="Delimiter">:(before "End valid_merge Cases")</span> +<span class="Delimiter">:(scenario merge_handles_exclusive_container_inside_exclusive_container)</span> +exclusive-container foo [ + <span class="Normal">x</span>:number + <span class="Normal">y</span>:bar +] +exclusive-container bar [ + <span class="Normal">a</span>:number + <span class="Normal">b</span>:number +] +def main [ + <span class="Constant">1</span>:number<span class="Special"> <- </span>copy <span class="Constant">0</span> + <span class="Constant">2</span>:bar<span class="Special"> <- </span>merge <span class="Constant">0</span>/a<span class="Delimiter">,</span> <span class="Constant">34</span> + <span class="Constant">4</span>:foo<span class="Special"> <- </span>merge <span class="Constant">1</span>/y<span class="Delimiter">,</span> <span class="Constant">2</span>:bar +] +<span class="traceContains">+mem: storing 0 in location 5</span> +<span class="traceContains">+mem: storing 34 in location 6</span> +$error: <span class="Constant">0</span> + +<span class="Delimiter">:(before "End check_merge_call Cases")</span> <span class="Normal">case</span> EXCLUSIVE_CONTAINER: <span class="Delimiter">{</span> assert<span class="Delimiter">(</span>state<span class="Delimiter">.</span>data<span class="Delimiter">.</span>top<span class="Delimiter">().</span>container_element_index == <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">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"checking exclusive container "</span> << to_string<span class="Delimiter">(</span>container<span class="Delimiter">)</span> << <span class="Constant">" vs ingredient "</span> << ingredient_index << end<span class="Delimiter">();</span> + <span class="Comment">// easy case: exact match</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>types_strictly_match<span class="Delimiter">(</span>container<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>ingredient_index<span class="Delimiter">)))</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!is_literal<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>ingredient_index<span class="Delimiter">)))</span> <span class="Delimiter">{</span> - raise << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"ingredient "</span> << ingredient_index << <span class="Constant">" of 'merge' should be a literal, for the tag of exclusive-container '"</span> << container_info<span class="Delimiter">.</span>name << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + raise << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"ingredient "</span> << ingredient_index << <span class="Constant">" of 'merge' should be a literal, for the tag of exclusive-container '"</span> << container_info<span class="Delimiter">.</span>name << <span class="Constant">"' in '"</span> << to_original_string<span class="Delimiter">(</span>inst<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">return</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> reagent<span class="Comment">/*</span><span class="Comment">copy</span><span class="Comment">*/</span> ingredient = ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>ingredient_index<span class="Delimiter">);</span> <span class="Comment">// unnecessary copy just to keep this function from modifying caller</span> diff --git a/html/034address.cc.html b/html/034address.cc.html index c66b078c..f2ef1165 100644 --- a/html/034address.cc.html +++ b/html/034address.cc.html @@ -151,9 +151,6 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment">//:</span> <span class="Comment">//: This layer implements creating addresses using 'new'. The next few layers</span> <span class="Comment">//: will flesh out the rest of the life cycle.</span> -<span class="Comment">//:</span> -<span class="Comment">//: The tests in this layer use unsafe operations so as to stay decoupled from</span> -<span class="Comment">//: 'new'.</span> <span class="Comment">//: todo: give 'new' a custodian ingredient. Following malloc/free is a temporary hack.</span> @@ -310,33 +307,38 @@ put<span class="Delimiter">(</span>Recipe_ordinal<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">"array size is "</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> << end<span class="Delimiter">();</span> size = <span class="Comment">/*</span><span class="Comment">space for length</span><span class="Comment">*/</span><span class="Constant">1</span> + size*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="Delimiter">}</span> + <span class="Normal">int</span> result = allocate<span class="Delimiter">(</span>size<span class="Delimiter">);</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">)</span> > <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Comment">// initialize array length</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">"storing "</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="Constant">" in location "</span> << result+<span class="Comment">/*</span><span class="Comment">skip refcount</span><span class="Comment">*/</span><span class="Constant">1</span> << end<span class="Delimiter">();</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> result+<span class="Comment">/*</span><span class="Comment">skip refcount</span><span class="Comment">*/</span><span class="Constant">1</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="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">:(code)</span> +<span class="Normal">int</span> allocate<span class="Delimiter">(</span><span class="Normal">int</span> size<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Comment">// include space for refcount</span> size++<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">"allocating size "</span> << size << end<span class="Delimiter">();</span> <span class="CommentedCode">//? Total_alloc += size;</span> <span class="CommentedCode">//? Num_alloc++;</span> + <span class="Comment">// Allocate Special-cases</span> <span class="Comment">// compute the region of memory to return</span> <span class="Comment">// really crappy at the moment</span> ensure_space<span class="Delimiter">(</span>size<span class="Delimiter">);</span> <span class="Normal">const</span> <span class="Normal">int</span> result = Current_routine<span class="Delimiter">-></span>alloc<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">"new alloc: "</span> << result << end<span class="Delimiter">();</span> - <span class="Comment">// save result</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="Comment">// initialize allocated space</span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> address = result<span class="Delimiter">;</span> address < result+size<span class="Delimiter">;</span> ++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">"storing 0 in location "</span> << address << end<span class="Delimiter">();</span> put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> address<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">);</span> <span class="Delimiter">}</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">)</span> > <span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Comment">// initialize array length</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">"storing "</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="Constant">" in location "</span> << result+<span class="Comment">/*</span><span class="Comment">skip refcount</span><span class="Comment">*/</span><span class="Constant">1</span> << end<span class="Delimiter">();</span> - put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> result+<span class="Comment">/*</span><span class="Comment">skip refcount</span><span class="Comment">*/</span><span class="Constant">1</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="Delimiter">}</span> Current_routine<span class="Delimiter">-></span>alloc += size<span class="Delimiter">;</span> <span class="Comment">// no support yet for reclaiming memory between routines</span> assert<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-></span>alloc <= Current_routine<span class="Delimiter">-></span>alloc_max<span class="Delimiter">);</span> - <span class="Identifier">break</span><span class="Delimiter">;</span> + <span class="Identifier">return</span> result<span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Comment">//: statistics for debugging</span> diff --git a/html/035lookup.cc.html b/html/035lookup.cc.html index 1ad8c841..2f952cdd 100644 --- a/html/035lookup.cc.html +++ b/html/035lookup.cc.html @@ -297,14 +297,18 @@ def main [ <span class="traceContains">+mem: storing 15 in location 4</span> <span class="traceContains">+mem: storing 16 in location 5</span> -<span class="Delimiter">:(before "Update CREATE_ARRAY product in Check")</span> -<span class="Comment">// 'create-array' does not support indirection. Static arrays are meant to be</span> -<span class="Comment">// allocated on the 'stack'.</span> -assert<span class="Delimiter">(</span>!has_property<span class="Delimiter">(</span>product<span class="Delimiter">,</span> <span class="Constant">"lookup"</span><span class="Delimiter">));</span> -<span class="Delimiter">:(before "Update CREATE_ARRAY product in Run")</span> -<span class="Comment">// 'create-array' does not support indirection. Static arrays are meant to be</span> -<span class="Comment">// allocated on the 'stack'.</span> -assert<span class="Delimiter">(</span>!has_property<span class="Delimiter">(</span>product<span class="Delimiter">,</span> <span class="Constant">"lookup"</span><span class="Delimiter">));</span> +<span class="Delimiter">:(scenario create_array_indirect)</span> +def main [ + <span class="Constant">1000</span>:number/<span class="Special">raw <- </span>copy <span class="Constant">1</span> <span class="Comment"># pretend refcount</span> + <span class="Constant">1</span>:address:array:number:<span class="Constant">3</span><span class="Special"> <- </span>copy <span class="Constant">1000</span>/unsafe <span class="Comment"># pretend allocation</span> + <span class="Constant">1</span>:address:array:number:<span class="Constant">3</span>/lookup<span class="Special"> <- </span>create-array +] +<span class="traceContains">+mem: storing 3 in location 1001</span> + +<span class="Delimiter">:(after "Update CREATE_ARRAY product in Check")</span> +<span class="Normal">if</span> <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>product<span class="Delimiter">))</span> <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">:(after "Update CREATE_ARRAY product in Run")</span> +canonize<span class="Delimiter">(</span>product<span class="Delimiter">);</span> <span class="Delimiter">:(scenario index_indirect)</span> def main [ diff --git a/html/036refcount.cc.html b/html/036refcount.cc.html index e456934b..89e9d202 100644 --- a/html/036refcount.cc.html +++ b/html/036refcount.cc.html @@ -106,7 +106,7 @@ def main [ <span class="Normal">int</span> payload_size<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="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">"lookup"</span><span class="Delimiter">,</span> <span class="Constant">NULL</span><span class="Delimiter">));</span> lookup_memory_core<span class="Delimiter">(</span>x<span class="Delimiter">);</span> - <span class="Identifier">return</span> size_of<span class="Delimiter">(</span>x<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="Identifier">return</span> size_of<span class="Delimiter">(</span>x<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">:(scenario refcounts_reflexive)</span> @@ -257,12 +257,49 @@ def main [ <span class="Identifier">return</span> *<span class="Normal">this</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">};</span> -<span class="Delimiter">:(before "struct container_metadata ")</span> -<span class="Comment">// valid fields for containers: size, offset, address, maybe_address (if container directly or indirectly contains exclusive containers with addresses)</span> -<span class="Comment">// valid fields for exclusive containers: size, maybe_address</span> + +<span class="Comment">// For exclusive containers we might sometimes have an address at some offset</span> +<span class="Comment">// if some other offset has a specific tag. This struct encapsulates such</span> +<span class="Comment">// guards.</span> +<span class="Normal">struct</span> tag_condition_info <span class="Delimiter">{</span> + <span class="Normal">int</span> offset<span class="Delimiter">;</span> + <span class="Normal">int</span> tag<span class="Delimiter">;</span> + tag_condition_info<span class="Delimiter">(</span><span class="Normal">int</span> o<span class="Delimiter">,</span> <span class="Normal">int</span> t<span class="Delimiter">)</span> :offset<span class="Delimiter">(</span>o<span class="Delimiter">),</span> tag<span class="Delimiter">(</span>t<span class="Delimiter">)</span> <span class="Delimiter">{}</span> +<span class="Delimiter">};</span> + <span class="Delimiter">:(before "End container_metadata Fields")</span> -vector<address_element_info> address<span class="Delimiter">;</span> <span class="Comment">// list of offsets containing addresses, and the sizes of their corresponding payloads</span> -map<pair<<span class="Comment">/*</span><span class="Comment">offset</span><span class="Comment">*/</span><span class="Normal">int</span><span class="Delimiter">,</span> <span class="Comment">/*</span><span class="Comment">tag</span><span class="Comment">*/</span><span class="Normal">int</span>><span class="Delimiter">,</span> vector<address_element_info> > maybe_address<span class="Delimiter">;</span> +<span class="Comment">// a list of facts of the form:</span> +<span class="Comment">//</span> +<span class="Comment">// IF offset o1 has tag t2 AND offset o2 has tag t2 AND .., THEN</span> +<span class="Comment">// for all address_element_infos:</span> +<span class="Comment">// you need to update refcounts for the address at offset pointing to a payload of type payload_type (just in case we need to abandon something in the process)</span> +map<set<tag_condition_info><span class="Delimiter">,</span> set<address_element_info> > address<span class="Delimiter">;</span> +<span class="Delimiter">:(code)</span> +<span class="Normal">bool</span> <span class="Normal">operator</span><<span class="Delimiter">(</span><span class="Normal">const</span> set<tag_condition_info>& a<span class="Delimiter">,</span> <span class="Normal">const</span> set<tag_condition_info>& b<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>a<span class="Delimiter">.</span>size<span class="Delimiter">()</span> != b<span class="Delimiter">.</span>size<span class="Delimiter">())</span> <span class="Identifier">return</span> a<span class="Delimiter">.</span>size<span class="Delimiter">()</span> < b<span class="Delimiter">.</span>size<span class="Delimiter">();</span> + <span class="Normal">for</span> <span class="Delimiter">(</span>set<tag_condition_info>::const_iterator pa = a<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> pb = b<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> pa != a<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++pa<span class="Delimiter">,</span> ++pb<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>pa<span class="Delimiter">-></span>offset != pb<span class="Delimiter">-></span>offset<span class="Delimiter">)</span> <span class="Identifier">return</span> pa<span class="Delimiter">-></span>offset < pb<span class="Delimiter">-></span>offset<span class="Delimiter">;</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>pa<span class="Delimiter">-></span>tag != pb<span class="Delimiter">-></span>tag<span class="Delimiter">)</span> <span class="Identifier">return</span> pa<span class="Delimiter">-></span>tag < pb<span class="Delimiter">-></span>tag<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Comment">// equal</span> +<span class="Delimiter">}</span> +<span class="Normal">bool</span> <span class="Normal">operator</span><<span class="Delimiter">(</span><span class="Normal">const</span> tag_condition_info& a<span class="Delimiter">,</span> <span class="Normal">const</span> tag_condition_info& b<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>a<span class="Delimiter">.</span>offset != b<span class="Delimiter">.</span>offset<span class="Delimiter">)</span> <span class="Identifier">return</span> a<span class="Delimiter">.</span>offset < b<span class="Delimiter">.</span>offset<span class="Delimiter">;</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>a<span class="Delimiter">.</span>tag != b<span class="Delimiter">.</span>tag<span class="Delimiter">)</span> <span class="Identifier">return</span> a<span class="Delimiter">.</span>tag < b<span class="Delimiter">.</span>tag<span class="Delimiter">;</span> + <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Comment">// equal</span> +<span class="Delimiter">}</span> +<span class="Normal">bool</span> <span class="Normal">operator</span><<span class="Delimiter">(</span><span class="Normal">const</span> set<address_element_info>& a<span class="Delimiter">,</span> <span class="Normal">const</span> set<address_element_info>& b<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>a<span class="Delimiter">.</span>size<span class="Delimiter">()</span> != b<span class="Delimiter">.</span>size<span class="Delimiter">())</span> <span class="Identifier">return</span> a<span class="Delimiter">.</span>size<span class="Delimiter">()</span> < b<span class="Delimiter">.</span>size<span class="Delimiter">();</span> + <span class="Normal">for</span> <span class="Delimiter">(</span>set<address_element_info>::const_iterator pa = a<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> pb = b<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> pa != a<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++pa<span class="Delimiter">,</span> ++pb<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>pa<span class="Delimiter">-></span>offset != pb<span class="Delimiter">-></span>offset<span class="Delimiter">)</span> <span class="Identifier">return</span> pa<span class="Delimiter">-></span>offset < pb<span class="Delimiter">-></span>offset<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Comment">// equal</span> +<span class="Delimiter">}</span> +<span class="Normal">bool</span> <span class="Normal">operator</span><<span class="Delimiter">(</span><span class="Normal">const</span> address_element_info& a<span class="Delimiter">,</span> <span class="Normal">const</span> address_element_info& b<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>a<span class="Delimiter">.</span>offset != b<span class="Delimiter">.</span>offset<span class="Delimiter">)</span> <span class="Identifier">return</span> a<span class="Delimiter">.</span>offset < b<span class="Delimiter">.</span>offset<span class="Delimiter">;</span> + <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Comment">// equal</span> +<span class="Delimiter">}</span> + <span class="Comment">//: populate metadata.address in a separate transform, because it requires</span> <span class="Comment">//: already knowing the sizes of all types</span> @@ -298,66 +335,70 @@ Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</spa container_metadata& metadata = get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> type<span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!metadata<span class="Delimiter">.</span>address<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">return</span><span class="Delimiter">;</span> trace<span class="Delimiter">(</span><span class="Constant">9994</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"compute address offsets for container "</span> << info<span class="Delimiter">.</span>name << end<span class="Delimiter">();</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!append_addresses<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">,</span> type<span class="Delimiter">,</span> metadata<span class="Delimiter">.</span>address<span class="Delimiter">,</span> metadata<span class="Delimiter">))</span> - <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Comment">// error</span> + append_addresses<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">,</span> type<span class="Delimiter">,</span> metadata<span class="Delimiter">.</span>address<span class="Delimiter">,</span> set<tag_condition_info><span class="Delimiter">());</span> <span class="Delimiter">}</span> <span class="Normal">if</span> <span class="Delimiter">(</span>info<span class="Delimiter">.</span>kind == EXCLUSIVE_CONTAINER<span class="Delimiter">)</span> <span class="Delimiter">{</span> container_metadata& metadata = get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> type<span class="Delimiter">);</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!metadata<span class="Delimiter">.</span>maybe_address<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Identifier">return</span><span class="Delimiter">;</span> trace<span class="Delimiter">(</span><span class="Constant">9994</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"compute address offsets for exclusive container "</span> << info<span class="Delimiter">.</span>name << end<span class="Delimiter">();</span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> tag = <span class="Constant">0</span><span class="Delimiter">;</span> tag < SIZE<span class="Delimiter">(</span>info<span class="Delimiter">.</span>elements<span class="Delimiter">);</span> ++tag<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!append_addresses<span class="Delimiter">(</span><span class="Comment">/*</span><span class="Comment">skip tag offset</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">,</span> variant_type<span class="Delimiter">(</span>type<span class="Delimiter">,</span> tag<span class="Delimiter">).</span>type<span class="Delimiter">,</span> get_or_insert<span class="Delimiter">(</span>metadata<span class="Delimiter">.</span>maybe_address<span class="Delimiter">,</span> pair<<span class="Normal">int</span><span class="Delimiter">,</span> <span class="Normal">int</span>><span class="Delimiter">(</span><span class="Comment">/*</span><span class="Comment">tag offset</span><span class="Comment">*/</span><span class="Constant">0</span><span class="Delimiter">,</span> tag<span class="Delimiter">)),</span> metadata<span class="Delimiter">))</span> - <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Comment">// error</span> + set<tag_condition_info> key<span class="Delimiter">;</span> + key<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>tag_condition_info<span class="Delimiter">(</span><span class="Comment">/*</span><span class="Comment">tag is at offset</span><span class="Comment">*/</span><span class="Constant">0</span><span class="Delimiter">,</span> tag<span class="Delimiter">));</span> + append_addresses<span class="Delimiter">(</span><span class="Comment">/*</span><span class="Comment">skip tag offset</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">,</span> variant_type<span class="Delimiter">(</span>type<span class="Delimiter">,</span> tag<span class="Delimiter">).</span>type<span class="Delimiter">,</span> metadata<span class="Delimiter">.</span>address<span class="Delimiter">,</span> key<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> -<span class="Comment">// returns false on error (raised elsewhere)</span> -<span class="Comment">//: error status is used in later layers</span> -<span class="Normal">bool</span> append_addresses<span class="Delimiter">(</span><span class="Normal">int</span> base_offset<span class="Delimiter">,</span> <span class="Normal">const</span> type_tree* type<span class="Delimiter">,</span> vector<address_element_info>& out<span class="Delimiter">,</span> container_metadata& out_metadata<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="Normal">void</span> append_addresses<span class="Delimiter">(</span><span class="Normal">int</span> base_offset<span class="Delimiter">,</span> <span class="Normal">const</span> type_tree* type<span class="Delimiter">,</span> map<set<tag_condition_info><span class="Delimiter">,</span> set<address_element_info> >& out<span class="Delimiter">,</span> <span class="Normal">const</span> set<tag_condition_info>& key<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">const</span> type_info& info = get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> type<span class="Delimiter">-></span>value<span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>type<span class="Delimiter">-></span>name == <span class="Constant">"address"</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> assert<span class="Delimiter">(</span>type<span class="Delimiter">-></span>right && type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>name != <span class="Constant">"array"</span><span class="Delimiter">);</span> <span class="Comment">// array types can't be handled without a full reagent and its value</span> - out<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>address_element_info<span class="Delimiter">(</span>base_offset<span class="Delimiter">,</span> <span class="Normal">new</span> type_tree<span class="Delimiter">(</span>*type<span class="Delimiter">-></span>right<span class="Delimiter">)));</span> - <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> + get_or_insert<span class="Delimiter">(</span>out<span class="Delimiter">,</span> key<span class="Delimiter">).</span>insert<span class="Delimiter">(</span>address_element_info<span class="Delimiter">(</span>base_offset<span class="Delimiter">,</span> <span class="Normal">new</span> type_tree<span class="Delimiter">(</span>*type<span class="Delimiter">-></span>right<span class="Delimiter">)));</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>info<span class="Delimiter">.</span>kind == PRIMITIVE<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> - <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> curr_index = <span class="Constant">0</span><span class="Delimiter">,</span> curr_offset = base_offset<span class="Delimiter">;</span> curr_index < SIZE<span class="Delimiter">(</span>info<span class="Delimiter">.</span>elements<span class="Delimiter">);</span> ++curr_index<span class="Delimiter">)</span> <span class="Delimiter">{</span> - trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"checking container "</span> << type<span class="Delimiter">-></span>name << <span class="Constant">", element "</span> << curr_index << end<span class="Delimiter">();</span> - reagent<span class="Comment">/*</span><span class="Comment">copy</span><span class="Comment">*/</span> element = element_type<span class="Delimiter">(</span>type<span class="Delimiter">,</span> curr_index<span class="Delimiter">);</span> - <span class="Comment">// Compute Container Address Offset(element)</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> - trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"address at offset "</span> << curr_offset << end<span class="Delimiter">();</span> - out<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>address_element_info<span class="Delimiter">(</span>curr_offset<span class="Delimiter">,</span> <span class="Normal">new</span> type_tree<span class="Delimiter">(</span>*element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">)));</span> - ++curr_offset<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> <span class="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!append_addresses<span class="Delimiter">(</span>curr_offset<span class="Delimiter">,</span> element<span class="Delimiter">.</span>type<span class="Delimiter">,</span> out<span class="Delimiter">,</span> out_metadata<span class="Delimiter">))</span> - <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Comment">// error</span> - curr_offset += size_of<span class="Delimiter">(</span>element<span class="Delimiter">);</span> - <span class="Delimiter">}</span> - <span class="Normal">else</span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_exclusive_container<span class="Delimiter">(</span>element<span class="Delimiter">))</span> <span class="Delimiter">{</span> - <span class="Normal">const</span> type_info& element_info = get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value<span class="Delimiter">);</span> - <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> tag = <span class="Constant">0</span><span class="Delimiter">;</span> tag < SIZE<span class="Delimiter">(</span>element_info<span class="Delimiter">.</span>elements<span class="Delimiter">);</span> ++tag<span class="Delimiter">)</span> <span class="Delimiter">{</span> - vector<address_element_info>& tmp = get_or_insert<span class="Delimiter">(</span>out_metadata<span class="Delimiter">.</span>maybe_address<span class="Delimiter">,</span> pair<<span class="Normal">int</span><span class="Delimiter">,</span> <span class="Normal">int</span>><span class="Delimiter">(</span>curr_offset<span class="Delimiter">,</span> tag<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="Delimiter">{</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>!append_addresses<span class="Delimiter">(</span>curr_offset+<span class="Constant">1</span><span class="Delimiter">,</span> variant_type<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">,</span> tag<span class="Delimiter">).</span>type<span class="Delimiter">,</span> tmp<span class="Delimiter">,</span> out_metadata<span class="Delimiter">))</span> - <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Comment">// error</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>info<span class="Delimiter">.</span>kind == CONTAINER<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> curr_index = <span class="Constant">0</span><span class="Delimiter">,</span> curr_offset = base_offset<span class="Delimiter">;</span> curr_index < SIZE<span class="Delimiter">(</span>info<span class="Delimiter">.</span>elements<span class="Delimiter">);</span> ++curr_index<span class="Delimiter">)</span> <span class="Delimiter">{</span> + trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"checking container "</span> << type<span class="Delimiter">-></span>name << <span class="Constant">", element "</span> << curr_index << end<span class="Delimiter">();</span> + reagent<span class="Comment">/*</span><span class="Comment">copy</span><span class="Comment">*/</span> element = element_type<span class="Delimiter">(</span>type<span class="Delimiter">,</span> curr_index<span class="Delimiter">);</span> + <span class="Comment">// Compute Container Address Offset(element)</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> + trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"address at offset "</span> << curr_offset << end<span class="Delimiter">();</span> + get_or_insert<span class="Delimiter">(</span>out<span class="Delimiter">,</span> key<span class="Delimiter">).</span>insert<span class="Delimiter">(</span>address_element_info<span class="Delimiter">(</span>curr_offset<span class="Delimiter">,</span> <span class="Normal">new</span> type_tree<span class="Delimiter">(</span>*element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">)));</span> + ++curr_offset<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> <span class="Delimiter">{</span> + append_addresses<span class="Delimiter">(</span>curr_offset<span class="Delimiter">,</span> element<span class="Delimiter">.</span>type<span class="Delimiter">,</span> out<span class="Delimiter">,</span> key<span class="Delimiter">);</span> + curr_offset += size_of<span class="Delimiter">(</span>element<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + <span class="Normal">else</span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_exclusive_container<span class="Delimiter">(</span>element<span class="Delimiter">))</span> <span class="Delimiter">{</span> + <span class="Normal">const</span> type_info& element_info = get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> element<span class="Delimiter">.</span>type<span class="Delimiter">-></span>value<span class="Delimiter">);</span> + <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> tag = <span class="Constant">0</span><span class="Delimiter">;</span> tag < SIZE<span class="Delimiter">(</span>element_info<span class="Delimiter">.</span>elements<span class="Delimiter">);</span> ++tag<span class="Delimiter">)</span> <span class="Delimiter">{</span> + set<tag_condition_info> new_key = key<span class="Delimiter">;</span> + new_key<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>tag_condition_info<span class="Delimiter">(</span>curr_offset<span class="Delimiter">,</span> tag<span class="Delimiter">));</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>out<span class="Delimiter">,</span> new_key<span class="Delimiter">))</span> + append_addresses<span class="Delimiter">(</span>curr_offset+<span class="Comment">/*</span><span class="Comment">skip tag</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">,</span> variant_type<span class="Delimiter">(</span>element<span class="Delimiter">.</span>type<span class="Delimiter">,</span> tag<span class="Delimiter">).</span>type<span class="Delimiter">,</span> out<span class="Delimiter">,</span> new_key<span class="Delimiter">);</span> <span class="Delimiter">}</span> + curr_offset += size_of<span class="Delimiter">(</span>element<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + <span class="Normal">else</span> <span class="Delimiter">{</span> + <span class="Comment">// non-address primitive</span> + ++curr_offset<span class="Delimiter">;</span> <span class="Delimiter">}</span> - curr_offset += size_of<span class="Delimiter">(</span>element<span class="Delimiter">);</span> <span class="Delimiter">}</span> - <span class="Normal">else</span> <span class="Delimiter">{</span> - <span class="Comment">// non-address primitive</span> - ++curr_offset<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Normal">else</span> <span class="Normal">if</span> <span class="Delimiter">(</span>info<span class="Delimiter">.</span>kind == EXCLUSIVE_CONTAINER<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> tag = <span class="Constant">0</span><span class="Delimiter">;</span> tag < SIZE<span class="Delimiter">(</span>info<span class="Delimiter">.</span>elements<span class="Delimiter">);</span> ++tag<span class="Delimiter">)</span> <span class="Delimiter">{</span> + set<tag_condition_info> new_key = key<span class="Delimiter">;</span> + new_key<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>tag_condition_info<span class="Delimiter">(</span>base_offset<span class="Delimiter">,</span> tag<span class="Delimiter">));</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>out<span class="Delimiter">,</span> new_key<span class="Delimiter">))</span> + append_addresses<span class="Delimiter">(</span>base_offset+<span class="Comment">/*</span><span class="Comment">skip tag</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">,</span> variant_type<span class="Delimiter">(</span>type<span class="Delimiter">,</span> tag<span class="Delimiter">).</span>type<span class="Delimiter">,</span> out<span class="Delimiter">,</span> new_key<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> - <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Normal">int</span> payload_size<span class="Delimiter">(</span><span class="Normal">const</span> type_tree* type<span class="Delimiter">)</span> <span class="Delimiter">{</span> assert<span class="Delimiter">(</span>type<span class="Delimiter">-></span>name == <span class="Constant">"address"</span><span class="Delimiter">);</span> - <span class="Identifier">return</span> size_of<span class="Delimiter">(</span>type<span class="Delimiter">-></span>right<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> + assert<span class="Delimiter">(</span>type<span class="Delimiter">-></span>right<span class="Delimiter">-></span>name != <span class="Constant">"array"</span><span class="Delimiter">);</span> + <span class="Identifier">return</span> size_of<span class="Delimiter">(</span>type<span class="Delimiter">-></span>right<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="Comment">//: use metadata.address to update refcounts within containers, arrays and</span> @@ -384,17 +425,19 @@ Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</spa <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="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>metadata<span class="Delimiter">.</span>address<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">const</span> address_element_info& info = metadata<span class="Delimiter">.</span>address<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<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> + <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> <span class="Delimiter">}</span> - <span class="Normal">for</span> <span class="Delimiter">(</span>map<pair<<span class="Normal">int</span><span class="Delimiter">,</span> <span class="Normal">int</span>><span class="Delimiter">,</span> vector<address_element_info> >::const_iterator p = metadata<span class="Delimiter">.</span>maybe_address<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != metadata<span class="Delimiter">.</span>maybe_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>data<span class="Delimiter">.</span>at<span class="Delimiter">(</span>p<span class="Delimiter">-></span>first<span class="Delimiter">.</span>first<span class="Delimiter">)</span> != p<span class="Delimiter">-></span>first<span class="Delimiter">.</span>second<span class="Delimiter">)</span> <span class="Identifier">continue</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>p<span class="Delimiter">-></span>second<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Normal">const</span> address_element_info& info = p<span class="Delimiter">-></span>second<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<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> - <span class="Delimiter">}</span> +<span class="Delimiter">}</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> + <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> + <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(scenario refcounts_put_container)</span> @@ -553,11 +596,34 @@ def main [ <span class="traceContains">+run: {17: "foo"} <- copy {13: "foo"}</span> <span class="traceContains">+mem: incrementing refcount of 1000: 3 -> 4</span> +<span class="Delimiter">:(scenario refcounts_copy_exclusive_container_within_exclusive_container)</span> +exclusive-container foo [ + <span class="Normal">a</span>:number + <span class="Normal">b</span>:bar +] +exclusive-container bar [ + <span class="Normal">x</span>:number + <span class="Normal">y</span>:address:number +] +def main [ + <span class="Constant">1</span>:address:number<span class="Special"> <- </span><span class="Normal">new</span> number:type + <span class="Constant">10</span>:foo<span class="Special"> <- </span>merge <span class="Constant">1</span>/b<span class="Delimiter">,</span> <span class="Constant">1</span>/y<span class="Delimiter">,</span> <span class="Constant">1</span>:address:number + <span class="Constant">20</span>:foo<span class="Special"> <- </span>copy <span class="Constant">10</span>: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="Comment"># no change while merging items of other types</span> +<span class="traceContains">+run: {10: "foo"} <- merge {1: "literal", "b": ()}, {1: "literal", "y": ()}, {1: ("address" "number")}</span> +<span class="traceContains">+mem: incrementing refcount of 1000: 1 -> 2</span> +<span class="traceContains">+run: {20: "foo"} <- copy {10: "foo"}</span> +<span class="traceContains">+mem: incrementing refcount of 1000: 2 -> 3</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> <span class="Delimiter">}</span> <span class="Normal">bool</span> is_mu_container<span class="Delimiter">(</span><span class="Normal">const</span> type_tree* type<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">if</span> <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>type<span class="Delimiter">-></span>value == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> type_info& info = get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> type<span class="Delimiter">-></span>value<span class="Delimiter">);</span> <span class="Identifier">return</span> info<span class="Delimiter">.</span>kind == CONTAINER<span class="Delimiter">;</span> @@ -567,6 +633,7 @@ def main [ <span class="Identifier">return</span> is_mu_exclusive_container<span class="Delimiter">(</span>r<span class="Delimiter">.</span>type<span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Normal">bool</span> is_mu_exclusive_container<span class="Delimiter">(</span><span class="Normal">const</span> type_tree* type<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">if</span> <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>type<span class="Delimiter">-></span>value == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> type_info& info = get<span class="Delimiter">(</span>Type<span class="Delimiter">,</span> type<span class="Delimiter">-></span>value<span class="Delimiter">);</span> <span class="Identifier">return</span> info<span class="Delimiter">.</span>kind == EXCLUSIVE_CONTAINER<span class="Delimiter">;</span> diff --git a/html/037abandon.cc.html b/html/037abandon.cc.html index a6acff2f..661b2bb8 100644 --- a/html/037abandon.cc.html +++ b/html/037abandon.cc.html @@ -102,25 +102,20 @@ map<<span class="Normal">int</span><span class="Delimiter">,</span> <span cla put<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-></span>free_list<span class="Delimiter">,</span> payload_size<span class="Delimiter">,</span> address<span class="Delimiter">);</span> <span class="Delimiter">}</span> -<span class="Delimiter">:(before "ensure_space(size)" following "case ALLOCATE")</span> +<span class="Delimiter">:(after "Allocate Special-cases")</span> <span class="Normal">if</span> <span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-></span>free_list<span class="Delimiter">,</span> size<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">"abandon"</span><span class="Delimiter">)</span> << <span class="Constant">"picking up space from free-list of size "</span> << size << end<span class="Delimiter">();</span> <span class="Normal">int</span> result = get_or_insert<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-></span>free_list<span class="Delimiter">,</span> size<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">"new alloc from free list: "</span> << result << end<span class="Delimiter">();</span> put<span class="Delimiter">(</span>Current_routine<span class="Delimiter">-></span>free_list<span class="Delimiter">,</span> size<span class="Delimiter">,</span> get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> result<span class="Delimiter">));</span> - <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> curr = result+<span class="Constant">1</span><span class="Delimiter">;</span> curr < result+size<span class="Delimiter">;</span> ++curr<span class="Delimiter">)</span> <span class="Delimiter">{</span> + put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> result<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> curr = result<span class="Delimiter">;</span> curr < result+size<span class="Delimiter">;</span> ++curr<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> curr<span class="Delimiter">)</span> != <span class="Constant">0</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">"memory in free list was not zeroed out: "</span> << curr << <span class="Constant">'/'</span> << result << <span class="Constant">"; somebody wrote to us after free!!!</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="Comment">// always fatal</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">)</span> > <span class="Constant">1</span><span class="Delimiter">)</span> - put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> result+<span class="Comment">/*</span><span class="Comment">skip refcount</span><span class="Comment">*/</span><span class="Constant">1</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">else</span> - put<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> result<span class="Delimiter">,</span> <span class="Constant">0</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="Identifier">return</span> result<span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">:(scenario new_differing_size_no_reclaim)</span> diff --git a/html/038new_text.cc.html b/html/038new_text.cc.html index 179c33a0..35d3a2c9 100644 --- a/html/038new_text.cc.html +++ b/html/038new_text.cc.html @@ -120,6 +120,17 @@ def main [ ] <span class="traceContains">+app: abc foo</span> +<span class="Delimiter">:(scenario stash_string_as_array)</span> +def main [ + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span><span class="Normal">new</span> [abc] + stash *<span class="Constant">1</span>:address:array:character +] +<span class="traceContains">+app: 3 97 98 99</span> + +<span class="Comment">//: fixes way more than just stash</span> +<span class="Delimiter">:(before "End Preprocess is_mu_string(reagent x)")</span> +<span class="Normal">if</span> <span class="Delimiter">(</span>!canonize_type<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">false</span><span class="Delimiter">;</span> + <span class="Comment">//: Allocate more to routine when initializing a literal string</span> <span class="Delimiter">:(scenario new_string_overflow)</span> <span class="Special">% Initial_memory_per_routine = 2;</span> diff --git a/html/040brace.cc.html b/html/040brace.cc.html index 187db790..636f5d42 100644 --- a/html/040brace.cc.html +++ b/html/040brace.cc.html @@ -149,7 +149,7 @@ Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</spa <span class="Delimiter">}</span> <span class="Comment">// if implicit, compute target</span> reagent target<span class="Delimiter">;</span> - target<span class="Delimiter">.</span>type = <span class="Normal">new</span> type_tree<span class="Delimiter">(</span><span class="Constant">"offset"</span><span class="Delimiter">,</span> get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"offset"</span><span class="Delimiter">));</span> + target<span class="Delimiter">.</span>type = <span class="Normal">new</span> type_tree<span class="Delimiter">(</span><span class="Constant">"offset"</span><span class="Delimiter">);</span> target<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>open_braces<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> raise << <span class="Constant">"'"</span> << inst<span class="Delimiter">.</span>old_name << <span class="Constant">"' needs a '{' before</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> diff --git a/html/042name.cc.html b/html/042name.cc.html index 5b8dc773..996a039d 100644 --- a/html/042name.cc.html +++ b/html/042name.cc.html @@ -92,16 +92,12 @@ Name = Name_snapshot<span class="Delimiter">;</span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_integer<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>in<span class="Delimiter">).</span>name<span class="Delimiter">))</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!already_transformed<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>in<span class="Delimiter">),</span> names<span class="Delimiter">))</span> <span class="Delimiter">{</span> raise << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"use before set: '"</span> << inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>in<span class="Delimiter">).</span>name << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Normal">int</span> v = lookup_name<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>in<span class="Delimiter">),</span> r<span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>v >= <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>in<span class="Delimiter">).</span>set_value<span class="Delimiter">(</span>v<span class="Delimiter">);</span> - <span class="Comment">// HACK: belongs in a later layer, either in the scenario layer which</span> - <span class="Comment">// introduces the 'run' pseudo-instruction which is translated to</span> - <span class="Comment">// run_* recipes, or later when we start using screens and consoles in</span> - <span class="Comment">// scenarios.</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>is_special_name<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>in<span class="Delimiter">).</span>name<span class="Delimiter">)</span> && caller<span class="Delimiter">.</span>name<span class="Delimiter">.</span>substr<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">,</span> <span class="Constant">4</span><span class="Delimiter">)</span> == <span class="Constant">"run_"</span><span class="Delimiter">)</span> - inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>in<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> + <span class="Comment">// Done Placing Ingredient(inst, in, caller)</span> <span class="Delimiter">}</span> <span class="Normal">else</span> <span class="Delimiter">{</span> raise << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"can't find a place to store '"</span> << inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>in<span class="Delimiter">).</span>name << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> @@ -121,12 +117,7 @@ Name = Name_snapshot<span class="Delimiter">;</span> <span class="Normal">int</span> v = lookup_name<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>out<span class="Delimiter">),</span> r<span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>v >= <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>out<span class="Delimiter">).</span>set_value<span class="Delimiter">(</span>v<span class="Delimiter">);</span> - <span class="Comment">// HACK: belongs in a later layer, either in the scenario layer which</span> - <span class="Comment">// introduces the 'run' pseudo-instruction which is translated to</span> - <span class="Comment">// run_* recipes, or later when we start using screens and consoles in</span> - <span class="Comment">// scenarios.</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>is_special_name<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>out<span class="Delimiter">).</span>name<span class="Delimiter">)</span> && caller<span class="Delimiter">.</span>name<span class="Delimiter">.</span>substr<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">,</span> <span class="Constant">4</span><span class="Delimiter">)</span> == <span class="Constant">"run_"</span><span class="Delimiter">)</span> - inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>out<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> + <span class="Comment">// Done Placing Product(inst, out, caller)</span> <span class="Delimiter">}</span> <span class="Normal">else</span> <span class="Delimiter">{</span> raise << maybe<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"can't find a place to store '"</span> << inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>out<span class="Delimiter">).</span>name << <span class="Constant">"'</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> @@ -190,6 +181,7 @@ type_ordinal skip_addresses<span class="Delimiter">(</span>type_tree* type<span <span class="Identifier">return</span> !is_integer<span class="Delimiter">(</span>x<span class="Delimiter">.</span>name<span class="Delimiter">);</span> <span class="Delimiter">}</span> +<span class="Comment">// all names here should either be disqualified or also in bind_special_scenario_names</span> <span class="Normal">bool</span> is_special_name<span class="Delimiter">(</span><span class="Normal">const</span> string& s<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>s == <span class="Constant">"_"</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>s == <span class="Constant">"0"</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> diff --git a/html/050scenario.cc.html b/html/050scenario.cc.html index 3a26847d..e8a8d028 100644 --- a/html/050scenario.cc.html +++ b/html/050scenario.cc.html @@ -182,11 +182,11 @@ cerr << <span class="Constant">"</span><span class="cSpecial">\n</spa <span class="Normal">bool</span> not_already_inside_test = !Trace_stream<span class="Delimiter">;</span> <span class="CommentedCode">//? cerr << s.name << '\n';</span> <span class="Normal">if</span> <span class="Delimiter">(</span>not_already_inside_test<span class="Delimiter">)</span> <span class="Delimiter">{</span> - Trace_file = s<span class="Delimiter">.</span>name<span class="Delimiter">;</span> Trace_stream = <span class="Normal">new</span> trace_stream<span class="Delimiter">;</span> setup<span class="Delimiter">();</span> <span class="Delimiter">}</span> vector<recipe_ordinal> tmp = load<span class="Delimiter">(</span><span class="Constant">"recipe scenario_"</span>+s<span class="Delimiter">.</span>name+<span class="Constant">" [ "</span>+s<span class="Delimiter">.</span>to_run+<span class="Constant">" ]"</span><span class="Delimiter">);</span> + mark_autogenerated<span class="Delimiter">(</span>tmp<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> bind_special_scenario_names<span class="Delimiter">(</span>tmp<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> transform_all<span class="Delimiter">();</span> run<span class="Delimiter">(</span>tmp<span class="Delimiter">.</span>front<span class="Delimiter">());</span> @@ -197,16 +197,57 @@ cerr << <span class="Constant">"</span><span class="cSpecial">\n</spa <span class="Comment">// End Mu Test Teardown</span> <span class="Normal">if</span> <span class="Delimiter">(</span>not_already_inside_test && Trace_stream<span class="Delimiter">)</span> <span class="Delimiter">{</span> teardown<span class="Delimiter">();</span> - ofstream fout<span class="Delimiter">((</span>Trace_dir+Trace_file<span class="Delimiter">).</span>c_str<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="Normal">if</span> <span class="Delimiter">(</span>Save_trace<span class="Delimiter">)</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> <span class="Normal">delete</span> Trace_stream<span class="Delimiter">;</span> Trace_stream = <span class="Constant">NULL</span><span class="Delimiter">;</span> - Trace_file = <span class="Constant">""</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> Current_scenario = <span class="Constant">NULL</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> +<span class="Comment">//: Some variables for fake resources always get special /raw addresses in scenarios.</span> + +<span class="Comment">// Should contain everything passed by is_special_name but failed by is_disqualified.</span> +<span class="Normal">void</span> bind_special_scenario_names<span class="Delimiter">(</span>recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Comment">// Special Scenario Variable Names(r)</span> + <span class="Comment">// End Special Scenario Variable Names(r)</span> +<span class="Delimiter">}</span> +<span class="Delimiter">:(before "Done Placing Ingredient(inst, in, caller)")</span> +maybe_make_raw<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>in<span class="Delimiter">),</span> caller<span class="Delimiter">);</span> +<span class="Delimiter">:(before "Done Placing Product(inst, out, caller)")</span> +maybe_make_raw<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>out<span class="Delimiter">),</span> caller<span class="Delimiter">);</span> +<span class="Delimiter">:(code)</span> +<span class="Normal">void</span> maybe_make_raw<span class="Delimiter">(</span>reagent& r<span class="Delimiter">,</span> <span class="Normal">const</span> recipe& caller<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!is_special_name<span class="Delimiter">(</span>r<span class="Delimiter">.</span>name<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>starts_with<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">,</span> <span class="Constant">"scenario_"</span><span class="Delimiter">))</span> + r<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> + <span class="Comment">// End maybe_make_raw</span> +<span class="Delimiter">}</span> + +<span class="Comment">//: Test.</span> +<span class="Delimiter">:(before "End is_special_name Cases")</span> +<span class="Normal">if</span> <span class="Delimiter">(</span>s == <span class="Constant">"__maybe_make_raw_test__"</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> +<span class="Delimiter">:(before "End Special Scenario Variable Names(r)")</span> +<span class="Comment">//: ugly: we only need this for this one test, but need to define it for all time</span> +Name[r][<span class="Constant">"__maybe_make_raw_test__"</span>] = Reserved_for_tests-<span class="Constant">1</span><span class="Delimiter">;</span> +<span class="Delimiter">:(code)</span> +<span class="Normal">void</span> test_maybe_make_raw<span class="Delimiter">()</span> <span class="Delimiter">{</span> + <span class="Comment">// check that scenarios can use local-scope and special variables together</span> + vector<recipe_ordinal> tmp = load<span class="Delimiter">(</span> + <span class="Constant">"def scenario_foo [</span><span class="cSpecial">\n</span><span class="Constant">"</span> + <span class="Constant">" local-scope</span><span class="cSpecial">\n</span><span class="Constant">"</span> + <span class="Constant">" __maybe_make_raw_test__:number <- copy 34</span><span class="cSpecial">\n</span><span class="Constant">"</span> + <span class="Constant">"]</span><span class="cSpecial">\n</span><span class="Constant">"</span><span class="Delimiter">);</span> + mark_autogenerated<span class="Delimiter">(</span>tmp<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> + bind_special_scenario_names<span class="Delimiter">(</span>tmp<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> + transform_all<span class="Delimiter">();</span> + run<span class="Delimiter">(</span>tmp<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> + CHECK<span class="Delimiter">(</span>trace_count<span class="Delimiter">(</span><span class="Constant">"error"</span><span class="Delimiter">)</span> == <span class="Constant">0</span><span class="Delimiter">);</span> +<span class="Delimiter">}</span> + <span class="Comment">//: Watch out for redefinitions of scenario routines. We should never ever be</span> <span class="Comment">//: doing that, regardless of anything else.</span> <span class="Delimiter">:(scenarios run)</span> @@ -252,6 +293,7 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span ostringstream tmp<span class="Delimiter">;</span> tmp << <span class="Constant">"recipe run_"</span> << Next_recipe_ordinal << <span class="Constant">" [ "</span> << current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>name << <span class="Constant">" ]"</span><span class="Delimiter">;</span> vector<recipe_ordinal> tmp_recipe = load<span class="Delimiter">(</span>tmp<span class="Delimiter">.</span>str<span class="Delimiter">());</span> + mark_autogenerated<span class="Delimiter">(</span>tmp_recipe<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> bind_special_scenario_names<span class="Delimiter">(</span>tmp_recipe<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span> transform_all<span class="Delimiter">();</span> <span class="Normal">if</span> <span class="Delimiter">(</span>Trace_stream<span class="Delimiter">)</span> <span class="Delimiter">{</span> @@ -262,14 +304,9 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>push_front<span class="Delimiter">(</span>call<span class="Delimiter">(</span>tmp_recipe<span class="Delimiter">.</span>at<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">// not done with caller; don't increment current_step_index()</span> <span class="Delimiter">}</span> - -<span class="Comment">// Some variables for fake resources always get special addresses in</span> -<span class="Comment">// scenarios.</span> -<span class="Delimiter">:(code)</span> -<span class="Normal">void</span> bind_special_scenario_names<span class="Delimiter">(</span>recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span> - <span class="Comment">// Special Scenario Variable Names(r)</span> - <span class="Comment">// End Special Scenario Variable Names(r)</span> -<span class="Delimiter">}</span> +<span class="Delimiter">:(before "End maybe_make_raw")</span> +<span class="Normal">if</span> <span class="Delimiter">(</span>starts_with<span class="Delimiter">(</span>caller<span class="Delimiter">.</span>name<span class="Delimiter">,</span> <span class="Constant">"run_"</span><span class="Delimiter">))</span> + r<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> <span class="Delimiter">:(scenario run_multiple)</span> def main [ @@ -720,6 +757,31 @@ def main [ <span class="Delimiter">:(after "case _SYSTEM:")</span> <span class="Normal">if</span> <span class="Delimiter">(</span>Current_scenario<span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="SalientComment">//:: Warn if people use '_' manually in function names. They're reserved for internal use.</span> + +<span class="Delimiter">:(scenario recipe_name_with_underscore)</span> +<span class="Special">% Hide_errors = true;</span> +def foo_bar [ +] +<span class="traceContains">+error: foo_bar: don't create recipes with '_' in the name</span> + +<span class="Delimiter">:(before "End recipe Fields")</span> +<span class="Normal">bool</span> is_autogenerated<span class="Delimiter">;</span> +<span class="Delimiter">:(before "End recipe Constructor")</span> +is_autogenerated = <span class="Constant">false</span><span class="Delimiter">;</span> +<span class="Delimiter">:(code)</span> +<span class="Normal">void</span> mark_autogenerated<span class="Delimiter">(</span>recipe_ordinal r<span class="Delimiter">)</span> <span class="Delimiter">{</span> + get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> r<span class="Delimiter">).</span>is_autogenerated = <span class="Constant">true</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(after "void transform_all()")</span> + <span class="Normal">for</span> <span class="Delimiter">(</span>map<recipe_ordinal<span class="Delimiter">,</span> recipe>::iterator p = Recipe<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != Recipe<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">const</span> recipe& r = p<span class="Delimiter">-></span>second<span class="Delimiter">;</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>r<span class="Delimiter">.</span>name<span class="Delimiter">.</span>find<span class="Delimiter">(</span><span class="Constant">'_'</span><span class="Delimiter">)</span> == string::npos<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>r<span class="Delimiter">.</span>is_autogenerated<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span> <span class="Comment">// created by previous call to transform_all()</span> + raise << r<span class="Delimiter">.</span>name << <span class="Constant">": don't create recipes with '_' in the name</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + <span class="Delimiter">}</span> + <span class="SalientComment">//:: Helpers</span> <span class="Delimiter">:(code)</span> @@ -734,6 +796,10 @@ def main [ scenario s = parse_scenario<span class="Delimiter">(</span>in<span class="Delimiter">);</span> run_mu_scenario<span class="Delimiter">(</span>s<span class="Delimiter">);</span> <span class="Delimiter">}</span> + +<span class="Normal">bool</span> starts_with<span class="Delimiter">(</span><span class="Normal">const</span> string& s<span class="Delimiter">,</span> <span class="Normal">const</span> string& pat<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Identifier">return</span> s<span class="Delimiter">.</span>substr<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">,</span> pat<span class="Delimiter">.</span>size<span class="Delimiter">())</span> == pat<span class="Delimiter">;</span> +<span class="Delimiter">}</span> </pre> </body> </html> diff --git a/html/053recipe_header.cc.html b/html/053recipe_header.cc.html index 6b40e780..1a217076 100644 --- a/html/053recipe_header.cc.html +++ b/html/053recipe_header.cc.html @@ -193,6 +193,10 @@ def test [ curr<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> +<span class="Normal">if</span> <span class="Delimiter">(</span>curr<span class="Delimiter">.</span>name == <span class="Constant">"next-ingredient-without-typechecking"</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>result<span class="Delimiter">.</span>name<span class="Delimiter">)</span> << <span class="Constant">"never call 'next-ingredient-without-typechecking' directly</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + curr<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> +<span class="Delimiter">}</span> <span class="Comment">//: internal version of next-ingredient; don't call this directly</span> <span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> diff --git a/html/054static_dispatch.cc.html b/html/054static_dispatch.cc.html index 614ab74c..7e922bef 100644 --- a/html/054static_dispatch.cc.html +++ b/html/054static_dispatch.cc.html @@ -78,6 +78,7 @@ Recipe_variants = Recipe_variants_snapshot<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">"load"</span><span class="Delimiter">)</span> << <span class="Constant">"switching "</span> << result<span class="Delimiter">.</span>name << <span class="Constant">" to "</span> << new_name << end<span class="Delimiter">();</span> result<span class="Delimiter">.</span>name = new_name<span class="Delimiter">;</span> + result<span class="Delimiter">.</span>is_autogenerated = <span class="Constant">true</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> <span class="Normal">else</span> <span class="Delimiter">{</span> @@ -294,14 +295,14 @@ vector<recipe_ordinal> strictly_matching_variants_except_literal_zero_agai <span class="Normal">bool</span> all_header_reagents_strictly_match_except_literal_zero_against_address<span class="Delimiter">(</span><span class="Normal">const</span> instruction& inst<span class="Delimiter">,</span> <span class="Normal">const</span> recipe& variant<span class="Delimiter">)</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 < min<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">),</span> SIZE<span class="Delimiter">(</span>variant<span class="Delimiter">.</span>ingredients<span class="Delimiter">));</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!types_strictly_match_except_literal_zero_against_address<span class="Delimiter">(</span>variant<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> - trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"strict match failed: ingredient "</span> << i << end<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"match failed: ingredient "</span> << i << end<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">}</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 < min<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">),</span> SIZE<span class="Delimiter">(</span>variant<span class="Delimiter">.</span>products<span class="Delimiter">));</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_dummy<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="Normal">if</span> <span class="Delimiter">(</span>!types_strictly_match<span class="Delimiter">(</span>variant<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<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="Delimiter">{</span> - trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"strict match failed: product "</span> << i << end<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"match failed: product "</span> << i << end<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">}</span> @@ -329,14 +330,14 @@ vector<recipe_ordinal> strictly_matching_variants_except_literal_against_a <span class="Normal">bool</span> all_header_reagents_strictly_match_except_literal_against_address_or_boolean<span class="Delimiter">(</span><span class="Normal">const</span> instruction& inst<span class="Delimiter">,</span> <span class="Normal">const</span> recipe& variant<span class="Delimiter">)</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 < min<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">),</span> SIZE<span class="Delimiter">(</span>variant<span class="Delimiter">.</span>ingredients<span class="Delimiter">));</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!types_strictly_match_except_literal_against_address_or_boolean<span class="Delimiter">(</span>variant<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> - trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"strict match failed: ingredient "</span> << i << end<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"match failed: ingredient "</span> << i << end<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">}</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 < min<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>variant<span class="Delimiter">.</span>products<span class="Delimiter">),</span> 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="Normal">if</span> <span class="Delimiter">(</span>is_dummy<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="Normal">if</span> <span class="Delimiter">(</span>!types_strictly_match_except_literal_against_address_or_boolean<span class="Delimiter">(</span>variant<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<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="Delimiter">{</span> - trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"strict match failed: product "</span> << i << end<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"match failed: product "</span> << i << end<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">}</span> @@ -365,14 +366,14 @@ vector<recipe_ordinal> matching_variants<span class="Delimiter">(</span><s <span class="Normal">bool</span> all_header_reagents_match<span class="Delimiter">(</span><span class="Normal">const</span> instruction& inst<span class="Delimiter">,</span> <span class="Normal">const</span> recipe& variant<span class="Delimiter">)</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 < min<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">),</span> SIZE<span class="Delimiter">(</span>variant<span class="Delimiter">.</span>ingredients<span class="Delimiter">));</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!types_match<span class="Delimiter">(</span>variant<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)))</span> <span class="Delimiter">{</span> - trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"strict match failed: ingredient "</span> << i << end<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"match failed: ingredient "</span> << i << end<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">}</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 < min<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>variant<span class="Delimiter">.</span>products<span class="Delimiter">),</span> 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="Normal">if</span> <span class="Delimiter">(</span>is_dummy<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="Normal">if</span> <span class="Delimiter">(</span>!types_match<span class="Delimiter">(</span>variant<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<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="Delimiter">{</span> - trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"strict match failed: product "</span> << i << end<span class="Delimiter">();</span> + trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"match failed: product "</span> << i << end<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">}</span> diff --git a/html/055shape_shifting_container.cc.html b/html/055shape_shifting_container.cc.html index 7478d308..abce7ede 100644 --- a/html/055shape_shifting_container.cc.html +++ b/html/055shape_shifting_container.cc.html @@ -288,7 +288,7 @@ replace_type_ingredients<span class="Delimiter">(</span>element<span class="Deli replace_type_ingredients<span class="Delimiter">(</span>element<span class="Delimiter">,</span> type<span class="Delimiter">,</span> info<span class="Delimiter">);</span> <span class="Delimiter">:(before "Compute Container Address Offset(element)")</span> replace_type_ingredients<span class="Delimiter">(</span>element<span class="Delimiter">,</span> type<span class="Delimiter">,</span> info<span class="Delimiter">);</span> -<span class="Normal">if</span> <span class="Delimiter">(</span>contains_type_ingredient<span class="Delimiter">(</span>element<span class="Delimiter">))</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> <span class="Comment">// error raised elsewhere</span> +<span class="Normal">if</span> <span class="Delimiter">(</span>contains_type_ingredient<span class="Delimiter">(</span>element<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Comment">// error raised elsewhere</span> <span class="Delimiter">:(code)</span> <span class="Normal">void</span> replace_type_ingredients<span class="Delimiter">(</span>reagent& element<span class="Delimiter">,</span> <span class="Normal">const</span> type_tree* caller_type<span class="Delimiter">,</span> <span class="Normal">const</span> type_info& info<span class="Delimiter">)</span> <span class="Delimiter">{</span> @@ -542,7 +542,7 @@ assert<span class="Delimiter">(</span>!contains_type_ingredient<span class="Deli <span class="Normal">bool</span> has_nth_type<span class="Delimiter">(</span><span class="Normal">const</span> type_tree* base<span class="Delimiter">,</span> <span class="Normal">int</span> n<span class="Delimiter">)</span> <span class="Delimiter">{</span> assert<span class="Delimiter">(</span>n >= <span class="Constant">0</span><span class="Delimiter">);</span> - <span class="Normal">if</span> <span class="Delimiter">(</span>base == <span class="Constant">NULL</span><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>!base<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>n == <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="Identifier">return</span> has_nth_type<span class="Delimiter">(</span>base<span class="Delimiter">-></span>right<span class="Delimiter">,</span> n-<span class="Constant">1</span><span class="Delimiter">);</span> <span class="Delimiter">}</span> diff --git a/html/056shape_shifting_recipe.cc.html b/html/056shape_shifting_recipe.cc.html index 7e44abbd..be795d37 100644 --- a/html/056shape_shifting_recipe.cc.html +++ b/html/056shape_shifting_recipe.cc.html @@ -275,6 +275,7 @@ recipe_ordinal new_variant<span class="Delimiter">(</span>recipe_ordinal exempla assert<span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> new_recipe_ordinal<span class="Delimiter">));</span> recipe new_recipe = get<span class="Delimiter">(</span>Recipe<span class="Delimiter">,</span> exemplar<span class="Delimiter">);</span> new_recipe<span class="Delimiter">.</span>name = new_name<span class="Delimiter">;</span> + new_recipe<span class="Delimiter">.</span>is_autogenerated = <span class="Constant">true</span><span class="Delimiter">;</span> trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"switching "</span> << inst<span class="Delimiter">.</span>name << <span class="Constant">" to specialized "</span> << header_label<span class="Delimiter">(</span>new_recipe<span class="Delimiter">)</span> << end<span class="Delimiter">();</span> <span class="Comment">// Replace type ingredients with concrete types in new_recipe.</span> @@ -305,20 +306,20 @@ recipe_ordinal new_variant<span class="Delimiter">(</span>recipe_ordinal exempla trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">"compute type names: "</span> << variant<span class="Delimiter">.</span>name << end<span class="Delimiter">();</span> map<string<span class="Delimiter">,</span> type_tree*> type_names<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>variant<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> - save_or_deduce_type_name<span class="Delimiter">(</span>variant<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> type_names<span class="Delimiter">,</span> variant<span class="Delimiter">);</span> + save_or_deduce_type_name<span class="Delimiter">(</span>variant<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> type_names<span class="Delimiter">,</span> variant<span class="Delimiter">,</span> <span class="Constant">""</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>variant<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> - save_or_deduce_type_name<span class="Delimiter">(</span>variant<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> type_names<span class="Delimiter">,</span> variant<span class="Delimiter">);</span> + save_or_deduce_type_name<span class="Delimiter">(</span>variant<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> type_names<span class="Delimiter">,</span> variant<span class="Delimiter">,</span> <span class="Constant">""</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>variant<span class="Delimiter">.</span>steps<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span> instruction& inst = variant<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span> trace<span class="Delimiter">(</span><span class="Constant">9993</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">" instruction: "</span> << to_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> << end<span class="Delimiter">();</span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> in = <span class="Constant">0</span><span class="Delimiter">;</span> in < SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">);</span> ++in<span class="Delimiter">)</span> - save_or_deduce_type_name<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>in<span class="Delimiter">),</span> type_names<span class="Delimiter">,</span> variant<span class="Delimiter">);</span> + save_or_deduce_type_name<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span>in<span class="Delimiter">),</span> type_names<span class="Delimiter">,</span> variant<span class="Delimiter">,</span> <span class="Constant">" in '"</span> + to_original_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> + <span class="Constant">"'"</span><span class="Delimiter">);</span> <span class="Normal">for</span> <span class="Delimiter">(</span><span class="Normal">int</span> out = <span class="Constant">0</span><span class="Delimiter">;</span> out < SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">);</span> ++out<span class="Delimiter">)</span> - save_or_deduce_type_name<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>out<span class="Delimiter">),</span> type_names<span class="Delimiter">,</span> variant<span class="Delimiter">);</span> + save_or_deduce_type_name<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span>out<span class="Delimiter">),</span> type_names<span class="Delimiter">,</span> variant<span class="Delimiter">,</span> <span class="Constant">" in '"</span> + to_original_string<span class="Delimiter">(</span>inst<span class="Delimiter">)</span> + <span class="Constant">"'"</span><span class="Delimiter">);</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> -<span class="Normal">void</span> save_or_deduce_type_name<span class="Delimiter">(</span>reagent& x<span class="Delimiter">,</span> map<string<span class="Delimiter">,</span> type_tree*>& type<span class="Delimiter">,</span> <span class="Normal">const</span> recipe& variant<span class="Delimiter">)</span> <span class="Delimiter">{</span> +<span class="Normal">void</span> save_or_deduce_type_name<span class="Delimiter">(</span>reagent& x<span class="Delimiter">,</span> map<string<span class="Delimiter">,</span> type_tree*>& type<span class="Delimiter">,</span> <span class="Normal">const</span> recipe& variant<span class="Delimiter">,</span> <span class="Normal">const</span> string& context<span class="Delimiter">)</span> <span class="Delimiter">{</span> trace<span class="Delimiter">(</span><span class="Constant">9994</span><span class="Delimiter">,</span> <span class="Constant">"transform"</span><span class="Delimiter">)</span> << <span class="Constant">" checking "</span> << to_string<span class="Delimiter">(</span>x<span class="Delimiter">)</span> << <span class="Constant">": "</span> << names_to_string<span class="Delimiter">(</span>x<span class="Delimiter">.</span>type<span class="Delimiter">)</span> << end<span class="Delimiter">();</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!x<span class="Delimiter">.</span>type && contains_key<span class="Delimiter">(</span>type<span class="Delimiter">,</span> x<span class="Delimiter">.</span>name<span class="Delimiter">))</span> <span class="Delimiter">{</span> x<span class="Delimiter">.</span>type = <span class="Normal">new</span> type_tree<span class="Delimiter">(</span>*get<span class="Delimiter">(</span>type<span class="Delimiter">,</span> x<span class="Delimiter">.</span>name<span class="Delimiter">));</span> @@ -326,7 +327,7 @@ recipe_ordinal new_variant<span class="Delimiter">(</span>recipe_ordinal exempla <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Delimiter">}</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 << maybe<span class="Delimiter">(</span>variant<span class="Delimiter">.</span>original_name<span class="Delimiter">)</span> << <span class="Constant">"unknown type for '"</span> << x<span class="Delimiter">.</span>original_string << <span class="Constant">"' (check the name for typos)</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> + raise << maybe<span class="Delimiter">(</span>variant<span class="Delimiter">.</span>original_name<span class="Delimiter">)</span> << <span class="Constant">"unknown type for '"</span> << x<span class="Delimiter">.</span>original_string << <span class="Constant">"'"</span> << context << <span class="Constant">" (check the name for typos)</span><span class="cSpecial">\n</span><span class="Constant">"</span> << end<span class="Delimiter">();</span> <span class="Identifier">return</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> <span class="Normal">if</span> <span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>type<span class="Delimiter">,</span> x<span class="Delimiter">.</span>name<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span> @@ -721,8 +722,6 @@ $error: <span class="Constant">0</span> <span class="Delimiter">:(code)</span> <span class="Comment">// this one needs a little more fine-grained control</span> <span class="Normal">void</span> test_shape_shifting_new_ingredient_does_not_pollute_global_namespace<span class="Delimiter">()</span> <span class="Delimiter">{</span> - Trace_file = <span class="Constant">"shape_shifting_new_ingredient_does_not_pollute_global_namespace"</span><span class="Delimiter">;</span> - <span class="Comment">// if you specialize a shape-shifting recipe that allocates a type-ingredient..</span> transform<span class="Delimiter">(</span><span class="Constant">"def barz x:_elem [</span><span class="cSpecial">\n</span><span class="Constant">"</span> <span class="Constant">" local-scope</span><span class="cSpecial">\n</span><span class="Constant">"</span> @@ -927,7 +926,7 @@ def foo a:d1:_elem <span class="Delimiter">-></span> b:number [ container d1:_elem [ <span class="Normal">x</span>:_elem ] -<span class="traceContains">+error: foo: unknown type for 'e' (check the name for typos)</span> +<span class="traceContains">+error: foo: unknown type for 'e' in 'copy e' (check the name for typos)</span> <span class="traceContains">+error: specializing foo: missing type for 'e'</span> <span class="Comment"># and it doesn't crash</span> @@ -946,7 +945,7 @@ def foo a:d1:_elem <span class="Delimiter">-></span> b:number [ container d1:_elem [ <span class="Normal">x</span>:_elem ] -<span class="traceContains">+error: foo: unknown type for 'e' (check the name for typos)</span> +<span class="traceContains">+error: foo: unknown type for 'e' in 'get e, x:offset' (check the name for typos)</span> <span class="traceContains">+error: specializing foo: missing type for 'e'</span> <span class="Comment"># and it doesn't crash</span> diff --git a/html/069rewrite_literal_string.cc.html b/html/060rewrite_literal_string.cc.html index e9ec3837..6596dd01 100644 --- a/html/069rewrite_literal_string.cc.html +++ b/html/060rewrite_literal_string.cc.html @@ -2,7 +2,7 @@ <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> -<title>Mu - 069rewrite_literal_string.cc</title> +<title>Mu - 060rewrite_literal_string.cc</title> <meta name="Generator" content="Vim/7.4"> <meta name="plugin-version" content="vim7.4_v2"> <meta name="syntax" content="cpp"> diff --git a/html/070text.mu.html b/html/061text.mu.html index 7b1c40d7..84c7c349 100644 --- a/html/070text.mu.html +++ b/html/061text.mu.html @@ -2,7 +2,7 @@ <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> -<title>Mu - 070text.mu</title> +<title>Mu - 061text.mu</title> <meta name="Generator" content="Vim/7.4"> <meta name="plugin-version" content="vim7.4_v2"> <meta name="syntax" content="none"> diff --git a/html/071rewrite_stash.cc.html b/html/062rewrite_stash.cc.html index fda0846d..a5a67068 100644 --- a/html/071rewrite_stash.cc.html +++ b/html/062rewrite_stash.cc.html @@ -2,7 +2,7 @@ <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> -<title>Mu - 071rewrite_stash.cc</title> +<title>Mu - 062rewrite_stash.cc</title> <meta name="Generator" content="Vim/7.4"> <meta name="plugin-version" content="vim7.4_v2"> <meta name="syntax" content="cpp"> diff --git a/html/073array.mu.html b/html/063array.mu.html index 6766426d..75ed8c88 100644 --- a/html/073array.mu.html +++ b/html/063array.mu.html @@ -2,7 +2,7 @@ <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> -<title>Mu - 073array.mu</title> +<title>Mu - 063array.mu</title> <meta name="Generator" content="Vim/7.4"> <meta name="plugin-version" content="vim7.4_v2"> <meta name="syntax" content="none"> diff --git a/html/064list.mu.html b/html/064list.mu.html new file mode 100644 index 00000000..3b81c73b --- /dev/null +++ b/html/064list.mu.html @@ -0,0 +1,349 @@ +<!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 - 064list.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; } +.muScenario { color: #00af00; } +.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="Comment"># A list links up multiple objects together to make them easier to manage.</span> +<span class="Comment">#</span> +<span class="Comment"># The objects must be of the same type. If you want to store multiple types in</span> +<span class="Comment"># a single list, use an exclusive-container.</span> + +<span class="muData">container</span> list:_elem [ + value:_elem + next:address:list:_elem +] + +<span class="muRecipe">def</span> push x:_elem, in:address:list:_elem<span class="muRecipe"> -> </span>result:address:list:_elem [ + <span class="Constant">local-scope</span> + <span class="Constant">load-ingredients</span> + result<span class="Special"> <- </span>new <span class="Delimiter">{</span>(list _elem): type<span class="Delimiter">}</span> + *result<span class="Special"> <- </span>merge x, in +] + +<span class="muRecipe">def</span> first in:address:list:_elem<span class="muRecipe"> -> </span>result:_elem [ + <span class="Constant">local-scope</span> + <span class="Constant">load-ingredients</span> + result<span class="Special"> <- </span>get *in, <span class="Constant">value:offset</span> +] + +<span class="muRecipe">def</span> rest in:address:list:_elem<span class="muRecipe"> -> </span>result:address:list:_elem/contained-in:in [ + <span class="Constant">local-scope</span> + <span class="Constant">load-ingredients</span> + result<span class="Special"> <- </span>get *in, <span class="Constant">next:offset</span> +] + +<span class="muScenario">scenario</span> list-handling [ + run [ + <span class="Constant">local-scope</span> + x:address:list:number<span class="Special"> <- </span>push <span class="Constant">3</span>, <span class="Constant">0</span> + x<span class="Special"> <- </span>push <span class="Constant">4</span>, x + x<span class="Special"> <- </span>push <span class="Constant">5</span>, x + <span class="Constant">10</span>:number/<span class="Special">raw <- </span>first x + x<span class="Special"> <- </span>rest x + <span class="Constant">11</span>:number/<span class="Special">raw <- </span>first x + x<span class="Special"> <- </span>rest x + <span class="Constant">12</span>:number/<span class="Special">raw <- </span>first x + <span class="Constant">20</span>:address:list:number/<span class="Special">raw <- </span>rest x + ] + memory-should-contain [ + <span class="Constant">10</span><span class="Special"> <- </span><span class="Constant">5</span> + <span class="Constant">11</span><span class="Special"> <- </span><span class="Constant">4</span> + <span class="Constant">12</span><span class="Special"> <- </span><span class="Constant">3</span> + <span class="Constant">20</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># nothing left</span> + ] +] + +<span class="muRecipe">def</span> length l:address:list:_elem<span class="muRecipe"> -> </span>result:number [ + <span class="Constant">local-scope</span> + <span class="Constant">load-ingredients</span> + <span class="muControl">return-unless</span> l, <span class="Constant">0</span> + rest:address:list:_elem<span class="Special"> <- </span>rest l + length-of-rest:number<span class="Special"> <- </span>length rest + result<span class="Special"> <- </span>add length-of-rest, <span class="Constant">1</span> +] + +<span class="Comment"># insert 'x' after 'in'</span> +<span class="muRecipe">def</span> insert x:_elem, in:address:list:_elem<span class="muRecipe"> -> </span>in:address:list:_elem [ + <span class="Constant">local-scope</span> + <span class="Constant">load-ingredients</span> + new-node:address:list:_elem<span class="Special"> <- </span>new <span class="Delimiter">{</span>(list _elem): type<span class="Delimiter">}</span> + *new-node<span class="Special"> <- </span>put *new-node, <span class="Constant">value:offset</span>, x + next-node:address:list:_elem<span class="Special"> <- </span>get *in, <span class="Constant">next:offset</span> + *in<span class="Special"> <- </span>put *in, <span class="Constant">next:offset</span>, new-node + *new-node<span class="Special"> <- </span>put *new-node, <span class="Constant">next:offset</span>, next-node +] + +<span class="muScenario">scenario</span> inserting-into-list [ + run [ + <span class="Constant">local-scope</span> + list:address:list:character<span class="Special"> <- </span>push <span class="Constant">3</span>, <span class="Constant">0</span> + list<span class="Special"> <- </span>push <span class="Constant">4</span>, list + list<span class="Special"> <- </span>push <span class="Constant">5</span>, list + list2:address:list:character<span class="Special"> <- </span>rest list <span class="Comment"># inside list</span> + list2<span class="Special"> <- </span>insert <span class="Constant">6</span>, list2 + <span class="Comment"># check structure</span> + list2<span class="Special"> <- </span>copy list + <span class="Constant">10</span>:character/<span class="Special">raw <- </span>first list2 + list2<span class="Special"> <- </span>rest list2 + <span class="Constant">11</span>:character/<span class="Special">raw <- </span>first list2 + list2<span class="Special"> <- </span>rest list2 + <span class="Constant">12</span>:character/<span class="Special">raw <- </span>first list2 + list2<span class="Special"> <- </span>rest list2 + <span class="Constant">13</span>:character/<span class="Special">raw <- </span>first list2 + ] + memory-should-contain [ + <span class="Constant">10</span><span class="Special"> <- </span><span class="Constant">5</span> <span class="Comment"># scanning next</span> + <span class="Constant">11</span><span class="Special"> <- </span><span class="Constant">4</span> + <span class="Constant">12</span><span class="Special"> <- </span><span class="Constant">6</span> <span class="Comment"># inserted element</span> + <span class="Constant">13</span><span class="Special"> <- </span><span class="Constant">3</span> + ] +] + +<span class="muScenario">scenario</span> inserting-at-end-of-list [ + run [ + <span class="Constant">local-scope</span> + list:address:list:character<span class="Special"> <- </span>push <span class="Constant">3</span>, <span class="Constant">0</span> + list<span class="Special"> <- </span>push <span class="Constant">4</span>, list + list<span class="Special"> <- </span>push <span class="Constant">5</span>, list + list2:address:list:character<span class="Special"> <- </span>rest list <span class="Comment"># inside list</span> + list2<span class="Special"> <- </span>rest list2 <span class="Comment"># now at end of list</span> + list2<span class="Special"> <- </span>insert <span class="Constant">6</span>, list2 + <span class="Comment"># check structure like before</span> + list2<span class="Special"> <- </span>copy list + <span class="Constant">10</span>:character/<span class="Special">raw <- </span>first list2 + list2<span class="Special"> <- </span>rest list2 + <span class="Constant">11</span>:character/<span class="Special">raw <- </span>first list2 + list2<span class="Special"> <- </span>rest list2 + <span class="Constant">12</span>:character/<span class="Special">raw <- </span>first list2 + list2<span class="Special"> <- </span>rest list2 + <span class="Constant">13</span>:character/<span class="Special">raw <- </span>first list2 + ] + memory-should-contain [ + <span class="Constant">10</span><span class="Special"> <- </span><span class="Constant">5</span> <span class="Comment"># scanning next</span> + <span class="Constant">11</span><span class="Special"> <- </span><span class="Constant">4</span> + <span class="Constant">12</span><span class="Special"> <- </span><span class="Constant">3</span> + <span class="Constant">13</span><span class="Special"> <- </span><span class="Constant">6</span> <span class="Comment"># inserted element</span> + ] +] + +<span class="muScenario">scenario</span> inserting-after-start-of-list [ + run [ + <span class="Constant">local-scope</span> + list:address:list:character<span class="Special"> <- </span>push <span class="Constant">3</span>, <span class="Constant">0</span> + list<span class="Special"> <- </span>push <span class="Constant">4</span>, list + list<span class="Special"> <- </span>push <span class="Constant">5</span>, list + list<span class="Special"> <- </span>insert <span class="Constant">6</span>, list + <span class="Comment"># check structure like before</span> + list2:address:list:character<span class="Special"> <- </span>copy list + <span class="Constant">10</span>:character/<span class="Special">raw <- </span>first list2 + list2<span class="Special"> <- </span>rest list2 + <span class="Constant">11</span>:character/<span class="Special">raw <- </span>first list2 + list2<span class="Special"> <- </span>rest list2 + <span class="Constant">12</span>:character/<span class="Special">raw <- </span>first list2 + list2<span class="Special"> <- </span>rest list2 + <span class="Constant">13</span>:character/<span class="Special">raw <- </span>first list2 + ] + memory-should-contain [ + <span class="Constant">10</span><span class="Special"> <- </span><span class="Constant">5</span> <span class="Comment"># scanning next</span> + <span class="Constant">11</span><span class="Special"> <- </span><span class="Constant">6</span> <span class="Comment"># inserted element</span> + <span class="Constant">12</span><span class="Special"> <- </span><span class="Constant">4</span> + <span class="Constant">13</span><span class="Special"> <- </span><span class="Constant">3</span> + ] +] + +<span class="Comment"># remove 'x' from its surrounding list 'in'</span> +<span class="Comment">#</span> +<span class="Comment"># Returns null if and only if list is empty. Beware: in that case any other</span> +<span class="Comment"># pointers to the head are now invalid.</span> +<span class="muRecipe">def</span> remove x:address:list:_elem/contained-in:in, in:address:list:_elem<span class="muRecipe"> -> </span>in:address:list:_elem [ + <span class="Constant">local-scope</span> + <span class="Constant">load-ingredients</span> + <span class="Comment"># if 'x' is null, return</span> + <span class="muControl">return-unless</span> x + next-node:address:list:_elem<span class="Special"> <- </span>rest x + <span class="Comment"># clear next pointer of 'x'</span> + *x<span class="Special"> <- </span>put *x, <span class="Constant">next:offset</span>, <span class="Constant">0</span> + <span class="Comment"># if 'x' is at the head of 'in', return the new head</span> + at-head?:boolean<span class="Special"> <- </span>equal x, in + <span class="muControl">return-if</span> at-head?, next-node + <span class="Comment"># compute prev-node</span> + prev-node:address:list:_elem<span class="Special"> <- </span>copy in + curr:address:list:_elem<span class="Special"> <- </span>rest prev-node + <span class="Delimiter">{</span> + <span class="muControl">return-unless</span> curr + found?:boolean<span class="Special"> <- </span>equal curr, x + <span class="muControl">break-if</span> found? + prev-node<span class="Special"> <- </span>copy curr + curr<span class="Special"> <- </span>rest curr + <span class="Delimiter">}</span> + <span class="Comment"># set its next pointer to skip 'x'</span> + *prev-node<span class="Special"> <- </span>put *prev-node, <span class="Constant">next:offset</span>, next-node +] + +<span class="muScenario">scenario</span> removing-from-list [ + run [ + <span class="Constant">local-scope</span> + list:address:list:character<span class="Special"> <- </span>push <span class="Constant">3</span>, <span class="Constant">0</span> + list<span class="Special"> <- </span>push <span class="Constant">4</span>, list + list<span class="Special"> <- </span>push <span class="Constant">5</span>, list + list2:address:list:character<span class="Special"> <- </span>rest list <span class="Comment"># second element</span> + list<span class="Special"> <- </span>remove list2, list + <span class="Constant">10</span>:boolean/<span class="Special">raw <- </span>equal list2, <span class="Constant">0</span> + <span class="Comment"># check structure like before</span> + list2<span class="Special"> <- </span>copy list + <span class="Constant">11</span>:character/<span class="Special">raw <- </span>first list2 + list2<span class="Special"> <- </span>rest list2 + <span class="Constant">12</span>:character/<span class="Special">raw <- </span>first list2 + <span class="Constant">20</span>:address:list:character/<span class="Special">raw <- </span>rest list2 + ] + memory-should-contain [ + <span class="Constant">10</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># remove returned non-null</span> + <span class="Constant">11</span><span class="Special"> <- </span><span class="Constant">5</span> <span class="Comment"># scanning next, skipping deleted element</span> + <span class="Constant">12</span><span class="Special"> <- </span><span class="Constant">3</span> + <span class="Constant">20</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># no more elements</span> + ] +] + +<span class="muScenario">scenario</span> removing-from-start-of-list [ + run [ + <span class="Constant">local-scope</span> + list:address:list:character<span class="Special"> <- </span>push <span class="Constant">3</span>, <span class="Constant">0</span> + list<span class="Special"> <- </span>push <span class="Constant">4</span>, list + list<span class="Special"> <- </span>push <span class="Constant">5</span>, list + list<span class="Special"> <- </span>remove list, list + <span class="Comment"># check structure like before</span> + list2:address:list:character<span class="Special"> <- </span>copy list + <span class="Constant">10</span>:character/<span class="Special">raw <- </span>first list2 + list2<span class="Special"> <- </span>rest list2 + <span class="Constant">11</span>:character/<span class="Special">raw <- </span>first list2 + <span class="Constant">20</span>:address:list:character/<span class="Special">raw <- </span>rest list2 + ] + memory-should-contain [ + <span class="Constant">10</span><span class="Special"> <- </span><span class="Constant">4</span> <span class="Comment"># scanning next, skipping deleted element</span> + <span class="Constant">11</span><span class="Special"> <- </span><span class="Constant">3</span> + <span class="Constant">20</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># no more elements</span> + ] +] + +<span class="muScenario">scenario</span> removing-from-end-of-list [ + run [ + <span class="Constant">local-scope</span> + list:address:list:character<span class="Special"> <- </span>push <span class="Constant">3</span>, <span class="Constant">0</span> + list<span class="Special"> <- </span>push <span class="Constant">4</span>, list + list<span class="Special"> <- </span>push <span class="Constant">5</span>, list + <span class="Comment"># delete last element</span> + list2:address:list:character<span class="Special"> <- </span>rest list + list2<span class="Special"> <- </span>rest list2 + list<span class="Special"> <- </span>remove list2, list + <span class="Constant">10</span>:boolean/<span class="Special">raw <- </span>equal list2, <span class="Constant">0</span> + <span class="Comment"># check structure like before</span> + list2<span class="Special"> <- </span>copy list + <span class="Constant">11</span>:character/<span class="Special">raw <- </span>first list2 + list2<span class="Special"> <- </span>rest list2 + <span class="Constant">12</span>:character/<span class="Special">raw <- </span>first list2 + <span class="Constant">20</span>:address:list:character/<span class="Special">raw <- </span>rest list2 + ] + memory-should-contain [ + <span class="Constant">10</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># remove returned non-null</span> + <span class="Constant">11</span><span class="Special"> <- </span><span class="Constant">5</span> <span class="Comment"># scanning next, skipping deleted element</span> + <span class="Constant">12</span><span class="Special"> <- </span><span class="Constant">4</span> + <span class="Constant">20</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># no more elements</span> + ] +] + +<span class="muScenario">scenario</span> removing-from-singleton-list [ + run [ + <span class="Constant">local-scope</span> + list:address:list:character<span class="Special"> <- </span>push <span class="Constant">3</span>, <span class="Constant">0</span> + list<span class="Special"> <- </span>remove list, list + <span class="Constant">1</span>:number/<span class="Special">raw <- </span>copy list + ] + memory-should-contain [ + <span class="Constant">1</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># back to an empty list</span> + ] +] + +<span class="muRecipe">def</span> to-text in:address:list:_elem<span class="muRecipe"> -> </span>result:address:array:character [ + <span class="Constant">local-scope</span> + <span class="Constant">load-ingredients</span> + buf:address:buffer<span class="Special"> <- </span>new-buffer <span class="Constant">80</span> + buf<span class="Special"> <- </span>to-buffer in, buf + result<span class="Special"> <- </span>buffer-to-array buf +] + +<span class="Comment"># variant of 'to-text' which stops printing after a few elements (and so is robust to cycles)</span> +<span class="muRecipe">def</span> to-text-line in:address:list:_elem<span class="muRecipe"> -> </span>result:address:array:character [ + <span class="Constant">local-scope</span> + <span class="Constant">load-ingredients</span> + buf:address:buffer<span class="Special"> <- </span>new-buffer <span class="Constant">80</span> + buf<span class="Special"> <- </span>to-buffer in, buf, <span class="Constant">6</span> <span class="Comment"># max elements to display</span> + result<span class="Special"> <- </span>buffer-to-array buf +] + +<span class="muRecipe">def</span> to-buffer in:address:list:_elem, buf:address:buffer<span class="muRecipe"> -> </span>buf:address:buffer [ + <span class="Constant">local-scope</span> + <span class="Constant">load-ingredients</span> + <span class="Delimiter">{</span> + <span class="muControl">break-if</span> in + buf<span class="Special"> <- </span>append buf, <span class="Constant">48/0</span> + <span class="muControl">return</span> + <span class="Delimiter">}</span> + <span class="Comment"># append in.value to buf</span> + val:_elem<span class="Special"> <- </span>get *in, <span class="Constant">value:offset</span> + buf<span class="Special"> <- </span>append buf, val + <span class="Comment"># now prepare next</span> + next:address:list:_elem<span class="Special"> <- </span>rest in + nextn:number<span class="Special"> <- </span>copy next + <span class="muControl">return-unless</span> next + buf<span class="Special"> <- </span>append buf, <span class="Constant">[ -> ]</span> + <span class="Comment"># and recurse</span> + remaining:number, optional-ingredient-found?:boolean<span class="Special"> <- </span><span class="Constant">next-ingredient</span> + <span class="Delimiter">{</span> + <span class="muControl">break-if</span> optional-ingredient-found? + <span class="Comment"># unlimited recursion</span> + buf<span class="Special"> <- </span>to-buffer next, buf + <span class="muControl">return</span> + <span class="Delimiter">}</span> + <span class="Delimiter">{</span> + <span class="muControl">break-unless</span> remaining + <span class="Comment"># limited recursion</span> + remaining<span class="Special"> <- </span>subtract remaining, <span class="Constant">1</span> + buf<span class="Special"> <- </span>to-buffer next, buf, remaining + <span class="muControl">return</span> + <span class="Delimiter">}</span> + <span class="Comment"># past recursion depth; insert ellipses and stop</span> + append buf, <span class="Constant">[...]</span> +] +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/075random.cc.html b/html/065random.cc.html index 7dbb066d..b9fa34be 100644 --- a/html/075random.cc.html +++ b/html/065random.cc.html @@ -2,7 +2,7 @@ <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> -<title>Mu - 075random.cc</title> +<title>Mu - 065random.cc</title> <meta name="Generator" content="Vim/7.4"> <meta name="plugin-version" content="vim7.4_v2"> <meta name="syntax" content="cpp"> @@ -94,7 +94,7 @@ def main [ <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> +<span class="PreProc">#include </span><span class="Constant"><math.h></span> </pre> </body> </html> diff --git a/html/076duplex_list.mu.html b/html/066duplex_list.mu.html index aa5cff43..4fc7cb86 100644 --- a/html/076duplex_list.mu.html +++ b/html/066duplex_list.mu.html @@ -2,7 +2,7 @@ <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> -<title>Mu - 076duplex_list.mu</title> +<title>Mu - 066duplex_list.mu</title> <meta name="Generator" content="Vim/7.4"> <meta name="plugin-version" content="vim7.4_v2"> <meta name="syntax" content="none"> @@ -77,6 +77,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> duplex-list-handling [ run [ + <span class="Constant">local-scope</span> <span class="Comment"># reserve locations 0-9 to check for missing null check</span> <span class="Constant">10</span>:number/<span class="Special">raw <- </span>copy <span class="Constant">34</span> <span class="Constant">11</span>:number/<span class="Special">raw <- </span>copy <span class="Constant">35</span> @@ -133,6 +134,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> inserting-into-duplex-list [ run [ + <span class="Constant">local-scope</span> list:address:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">3</span>, <span class="Constant">0</span> list<span class="Special"> <- </span>push <span class="Constant">4</span>, list list<span class="Special"> <- </span>push <span class="Constant">5</span>, list @@ -169,6 +171,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> inserting-at-end-of-duplex-list [ run [ + <span class="Constant">local-scope</span> list:address:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">3</span>, <span class="Constant">0</span> list<span class="Special"> <- </span>push <span class="Constant">4</span>, list list<span class="Special"> <- </span>push <span class="Constant">5</span>, list @@ -206,6 +209,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> inserting-after-start-of-duplex-list [ run [ + <span class="Constant">local-scope</span> list:address:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">3</span>, <span class="Constant">0</span> list<span class="Special"> <- </span>push <span class="Constant">4</span>, list list<span class="Special"> <- </span>push <span class="Constant">5</span>, list @@ -271,6 +275,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> removing-from-duplex-list [ run [ + <span class="Constant">local-scope</span> list:address:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">3</span>, <span class="Constant">0</span> list<span class="Special"> <- </span>push <span class="Constant">4</span>, list list<span class="Special"> <- </span>push <span class="Constant">5</span>, list @@ -299,6 +304,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> removing-from-start-of-duplex-list [ run [ + <span class="Constant">local-scope</span> list:address:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">3</span>, <span class="Constant">0</span> list<span class="Special"> <- </span>push <span class="Constant">4</span>, list list<span class="Special"> <- </span>push <span class="Constant">5</span>, list @@ -324,6 +330,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muScenario">scenario</span> removing-from-end-of-duplex-list [ run [ + <span class="Constant">local-scope</span> list:address:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">3</span>, <span class="Constant">0</span> list<span class="Special"> <- </span>push <span class="Constant">4</span>, list list<span class="Special"> <- </span>push <span class="Constant">5</span>, list @@ -352,7 +359,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] ] -<span class="muScenario">scenario</span> removing-from-singleton-list [ +<span class="muScenario">scenario</span> removing-from-singleton-duplex-list [ run [ <span class="Constant">local-scope</span> list:address:duplex-list:character<span class="Special"> <- </span>push <span class="Constant">3</span>, <span class="Constant">0</span> diff --git a/html/077stream.mu.html b/html/067stream.mu.html index 9fcfa379..6bafe8b4 100644 --- a/html/077stream.mu.html +++ b/html/067stream.mu.html @@ -2,7 +2,7 @@ <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> -<title>Mu - 077stream.mu</title> +<title>Mu - 067stream.mu</title> <meta name="Generator" content="Vim/7.4"> <meta name="plugin-version" content="vim7.4_v2"> <meta name="syntax" content="none"> diff --git a/html/078hash.cc.html b/html/068hash.cc.html index aa8c8724..b2e810df 100644 --- a/html/078hash.cc.html +++ b/html/068hash.cc.html @@ -2,7 +2,7 @@ <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> -<title>Mu - 078hash.cc</title> +<title>Mu - 068hash.cc</title> <meta name="Generator" content="Vim/7.4"> <meta name="plugin-version" content="vim7.4_v2"> <meta name="syntax" content="cpp"> @@ -57,7 +57,7 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span <span class="Delimiter">}</span> <span class="Delimiter">:(before "End Primitive Recipe Implementations")</span> <span class="Normal">case</span> HASH: <span class="Delimiter">{</span> - reagent<span class="Comment">/*</span><span class="Comment">copy</span><span class="Comment">*/</span> input = current_instruction<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="Normal">const</span> reagent& input = current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</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>hash<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">,</span> input<span class="Delimiter">));</span> <span class="Identifier">break</span><span class="Delimiter">;</span> @@ -66,7 +66,7 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span <span class="Comment">//: in all the code below, the intermediate results of hashing are threaded through 'h'</span> <span class="Delimiter">:(code)</span> -<span class="Normal">size_t</span> hash<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">size_t</span> hash<span class="Delimiter">(</span><span class="Normal">size_t</span> h<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> canonize<span class="Delimiter">(</span>r<span class="Delimiter">);</span> <span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_string<span class="Delimiter">(</span>r<span class="Delimiter">))</span> <span class="Comment">// optimization</span> <span class="Identifier">return</span> hash_mu_string<span class="Delimiter">(</span>h<span class="Delimiter">,</span> r<span class="Delimiter">);</span> diff --git a/html/079table.mu.html b/html/069table.mu.html index 547a9c2f..45ec2f16 100644 --- a/html/079table.mu.html +++ b/html/069table.mu.html @@ -2,7 +2,7 @@ <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> -<title>Mu - 079table.mu</title> +<title>Mu - 069table.mu</title> <meta name="Generator" content="Vim/7.4"> <meta name="plugin-version" content="vim7.4_v2"> <meta name="syntax" content="none"> diff --git a/html/060recipe.cc.html b/html/070recipe.cc.html index 6c6778b0..d1901cfb 100644 --- a/html/060recipe.cc.html +++ b/html/070recipe.cc.html @@ -2,7 +2,7 @@ <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> -<title>Mu - 060recipe.cc</title> +<title>Mu - 070recipe.cc</title> <meta name="Generator" content="Vim/7.4"> <meta name="plugin-version" content="vim7.4_v2"> <meta name="syntax" content="cpp"> @@ -70,7 +70,7 @@ get_or_insert<span class="Delimiter">(</span>Type<span class="Delimiter">,</span <span class="Delimiter">:(before "End Null-type is_disqualified Exceptions")</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!x<span class="Delimiter">.</span>type && contains_key<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> x<span class="Delimiter">.</span>name<span class="Delimiter">))</span> <span class="Delimiter">{</span> - x<span class="Delimiter">.</span>type = <span class="Normal">new</span> type_tree<span class="Delimiter">(</span><span class="Constant">"recipe-literal"</span><span class="Delimiter">,</span> get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"recipe-literal"</span><span class="Delimiter">));</span> + x<span class="Delimiter">.</span>type = <span class="Normal">new</span> type_tree<span class="Delimiter">(</span><span class="Constant">"recipe-literal"</span><span class="Delimiter">);</span> x<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> x<span class="Delimiter">.</span>name<span class="Delimiter">));</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -99,6 +99,10 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span trace<span class="Delimiter">(</span><span class="Constant">"trace"</span><span class="Delimiter">)</span> << <span class="Constant">"indirect 'call': incrementing callstack depth to "</span> << Trace_stream<span class="Delimiter">-></span>callstack_depth << end<span class="Delimiter">();</span> assert<span class="Delimiter">(</span>Trace_stream<span class="Delimiter">-></span>callstack_depth < <span class="Constant">9000</span><span class="Delimiter">);</span> <span class="Comment">// 9998-101 plus cushion</span> <span class="Delimiter">}</span> + <span class="Normal">if</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="Delimiter">{</span> + raise << maybe<span class="Delimiter">(</span>current_recipe_name<span class="Delimiter">())</span> << <span class="Constant">"tried to call empty recipe in '"</span> << to_string<span class="Delimiter">(</span>current_instruction<span class="Delimiter">())</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">const</span> instruction& caller_instruction = current_instruction<span class="Delimiter">();</span> Current_routine<span class="Delimiter">-></span>calls<span class="Delimiter">.</span>push_front<span class="Delimiter">(</span>call<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> ingredients<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>begin<span class="Delimiter">());</span> <span class="Comment">// drop the callee</span> @@ -171,13 +175,21 @@ recipe from_reagent<span class="Delimiter">(</span><span class="Normal">const</s curr = curr<span class="Delimiter">-></span>right<span class="Delimiter">;</span> <span class="Comment">// skip delimiter</span> <span class="Identifier">break</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> - result_header<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span><span class="Constant">"recipe:"</span>+curr<span class="Delimiter">-></span>name<span class="Delimiter">);</span> + result_header<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>next_recipe_reagent<span class="Delimiter">(</span>curr<span class="Delimiter">));</span> <span class="Delimiter">}</span> <span class="Normal">for</span> <span class="Delimiter">(;</span> curr<span class="Delimiter">;</span> curr=curr<span class="Delimiter">-></span>right<span class="Delimiter">)</span> - result_header<span class="Delimiter">.</span>products<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span><span class="Constant">"recipe:"</span>+curr<span class="Delimiter">-></span>name<span class="Delimiter">);</span> + result_header<span class="Delimiter">.</span>products<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>next_recipe_reagent<span class="Delimiter">(</span>curr<span class="Delimiter">));</span> <span class="Identifier">return</span> result_header<span class="Delimiter">;</span> <span class="Delimiter">}</span> +reagent next_recipe_reagent<span class="Delimiter">(</span><span class="Normal">const</span> type_tree* curr<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!curr<span class="Delimiter">-></span>left<span class="Delimiter">)</span> <span class="Identifier">return</span> reagent<span class="Delimiter">(</span><span class="Constant">"recipe:"</span>+curr<span class="Delimiter">-></span>name<span class="Delimiter">);</span> + reagent result<span class="Delimiter">;</span> + result<span class="Delimiter">.</span>name = <span class="Constant">"recipe"</span><span class="Delimiter">;</span> + result<span class="Delimiter">.</span>type = <span class="Normal">new</span> type_tree<span class="Delimiter">(</span>*curr<span class="Delimiter">-></span>left<span class="Delimiter">);</span> + <span class="Identifier">return</span> result<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + <span class="Normal">bool</span> is_mu_recipe<span class="Delimiter">(</span><span class="Normal">const</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>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>r<span class="Delimiter">.</span>type<span class="Delimiter">-></span>name == <span class="Constant">"recipe"</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> @@ -231,6 +243,19 @@ def f x:boolean <span class="Delimiter">-></span> y:boolean [ <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span> <span class="Delimiter">}</span> +<span class="Delimiter">:(scenario call_variable_compound_ingredient)</span> +def main [ + <span class="Delimiter">{</span><span class="Constant">1</span>: <span class="Delimiter">(</span>recipe <span class="Delimiter">(</span>address number<span class="Delimiter">)</span> <span class="Delimiter">-></span> number<span class="Delimiter">)}</span><span class="Special"> <- </span>copy f + <span class="Constant">2</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">0</span> + <span class="Constant">3</span>:number<span class="Special"> <- </span>call <span class="Delimiter">{</span><span class="Constant">1</span>: <span class="Delimiter">(</span>recipe <span class="Delimiter">(</span>address number<span class="Delimiter">)</span> <span class="Delimiter">-></span> number<span class="Delimiter">)},</span> <span class="Constant">2</span>:address:number +] +def f x:address:number <span class="Delimiter">-></span> y:number [ + local-scope + load-ingredients + y<span class="Special"> <- </span>copy x +] +$error: <span class="Constant">0</span> + <span class="Comment">//: make sure we don't accidentally break on a function literal</span> <span class="Delimiter">:(scenario jump_forbidden_on_recipe_literals)</span> <span class="Special">% Hide_errors = true;</span> diff --git a/html/061scheduler.cc.html b/html/071scheduler.cc.html index f5c231de..4f556a1e 100644 --- a/html/061scheduler.cc.html +++ b/html/071scheduler.cc.html @@ -2,7 +2,7 @@ <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> -<title>Mu - 061scheduler.cc</title> +<title>Mu - 071scheduler.cc</title> <meta name="Generator" content="Vim/7.4"> <meta name="plugin-version" content="vim7.4_v2"> <meta name="syntax" content="cpp"> diff --git a/html/062wait.cc.html b/html/072wait.cc.html index 2f1f08b2..b07d3272 100644 --- a/html/062wait.cc.html +++ b/html/072wait.cc.html @@ -2,7 +2,7 @@ <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> -<title>Mu - 062wait.cc</title> +<title>Mu - 072wait.cc</title> <meta name="Generator" content="Vim/7.4"> <meta name="plugin-version" content="vim7.4_v2"> <meta name="syntax" content="cpp"> diff --git a/html/073deep_copy.cc.html b/html/073deep_copy.cc.html new file mode 100644 index 00000000..9dcb057a --- /dev/null +++ b/html/073deep_copy.cc.html @@ -0,0 +1,425 @@ +<!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 - 073deep_copy.cc</title> +<meta name="Generator" content="Vim/7.4"> +<meta name="plugin-version" content="vim7.4_v2"> +<meta name="syntax" content="cpp"> +<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; } +.Constant { color: #00a0a0; } +.cSpecial { color: #008000; } +.traceContains { color: #008000; } +.Comment { color: #9090ff; } +.Delimiter { color: #800080; } +.Special { color: #c00000; } +.Identifier { color: #fcb165; } +.Normal { color: #eeeeee; background-color: #080808; padding-bottom: 1px; } +--> +</style> + +<script type='text/javascript'> +<!-- + +--> +</script> +</head> +<body> +<pre id='vimCodeElement'> +<span class="Comment">// To recursively copy containers and any addresses they contain, use</span> +<span class="Comment">// 'deep-copy'.</span> +<span class="Comment">//</span> +<span class="Comment">// Invariant: After a deep-copy its ingredient and result will point to no</span> +<span class="Comment">// common addresses.</span> +<span class="Comment">// Implications: Refcounts of all data pointed to by the original ingredient</span> +<span class="Comment">// will remain unchanged. Refcounts of all data pointed to by the (newly</span> +<span class="Comment">// created) result will be 1, in the absence of cycles.</span> +<span class="Comment">//</span> +<span class="Comment">// We do handle cycles in the ingredient, however. All cycles are translated</span> +<span class="Comment">// to new cycles in the product.</span> + +<span class="Delimiter">:(scenario deep_copy_number)</span> +def main [ + local-scope + <span class="Normal">x</span>:number<span class="Special"> <- </span>copy <span class="Constant">34</span> + <span class="Normal">y</span>:number<span class="Special"> <- </span>deep-copy x + <span class="Constant">10</span>:boolean/<span class="Special">raw <- </span>equal x<span class="Delimiter">,</span> y +] +<span class="Comment"># non-address primitives are identical</span> +<span class="traceContains">+mem: storing 1 in location 10</span> + +<span class="Delimiter">:(scenario deep_copy_container_without_address)</span> +container foo [ + <span class="Normal">x</span>:number + <span class="Normal">y</span>:number +] +def main [ + local-scope + <span class="Normal">a</span>:foo<span class="Special"> <- </span>merge <span class="Constant">34</span><span class="Delimiter">,</span> <span class="Constant">35</span> + <span class="Normal">b</span>:foo<span class="Special"> <- </span>deep-copy a + <span class="Constant">10</span>:boolean/<span class="Special">raw <- </span>equal a<span class="Delimiter">,</span> b +] +<span class="Comment"># containers are identical as long as they don't contain addresses</span> +<span class="traceContains">+mem: storing 1 in location 10</span> + +<span class="Delimiter">:(scenario deep_copy_address)</span> +<span class="Special">% Memory_allocated_until = 200;</span> +def main [ + <span class="Comment"># avoid all memory allocations except the implicit ones inside deep-copy, so</span> + <span class="Comment"># that the result is deterministic</span> + <span class="Constant">1</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">100</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>:address:number<span class="Special"> <- </span>deep-copy <span class="Constant">1</span>:address:number + <span class="Constant">10</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">1</span>:address:number<span class="Delimiter">,</span> <span class="Constant">2</span>:address:number + <span class="Constant">11</span>:boolean<span class="Special"> <- </span>equal *<span class="Constant">1</span>:address:number<span class="Delimiter">,</span> *<span class="Constant">2</span>:address:number + <span class="Constant">2</span>:address:number<span class="Special"> <- </span>copy <span class="Constant">0</span> +] +<span class="Comment"># the result of deep-copy is a new address</span> +<span class="traceContains">+mem: storing 0 in location 10</span> +<span class="Comment"># however, the contents are identical</span> +<span class="traceContains">+mem: storing 1 in location 11</span> +<span class="Comment"># the result of deep-copy gets a refcount of 1</span> +<span class="Comment"># (its address 202 = 200 base + 2 for temporary space inside deep-copy)</span> +<span class="traceContains">+run: {2: ("address" "number")} <- copy {0: "literal"}</span> +<span class="traceContains">+mem: decrementing refcount of 202: 1 -> 0</span> +<span class="traceContains">+abandon: saving 202 in free-list of size 2</span> + +<span class="Delimiter">:(scenario deep_copy_address_to_container)</span> +<span class="Special">% Memory_allocated_until = 200;</span> +def main [ + <span class="Comment"># avoid all memory allocations except the implicit ones inside deep-copy, so</span> + <span class="Comment"># that the result is deterministic</span> + <span class="Constant">1</span>:address:point<span class="Special"> <- </span>copy <span class="Constant">100</span>/unsafe <span class="Comment"># pretend allocation</span> + *<span class="Constant">1</span>:address:point<span class="Special"> <- </span>merge <span class="Constant">34</span><span class="Delimiter">,</span> <span class="Constant">35</span> + <span class="Constant">2</span>:address:point<span class="Special"> <- </span>deep-copy <span class="Constant">1</span>:address:point + <span class="Constant">10</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">1</span>:address:point<span class="Delimiter">,</span> <span class="Constant">2</span>:address:point + <span class="Constant">11</span>:boolean<span class="Special"> <- </span>equal *<span class="Constant">1</span>:address:point<span class="Delimiter">,</span> *<span class="Constant">2</span>:address:point +] +<span class="Comment"># the result of deep-copy is a new address</span> +<span class="traceContains">+mem: storing 0 in location 10</span> +<span class="Comment"># however, the contents are identical</span> +<span class="traceContains">+mem: storing 1 in location 11</span> + +<span class="Delimiter">:(scenario deep_copy_address_to_address)</span> +<span class="Special">% Memory_allocated_until = 200;</span> +def main [ + <span class="Comment"># avoid all memory allocations except the implicit ones inside deep-copy, so</span> + <span class="Comment"># that the result is deterministic</span> + <span class="Constant">1</span>:address:address:number<span class="Special"> <- </span>copy <span class="Constant">100</span>/unsafe <span class="Comment"># pretend allocation</span> + *<span class="Constant">1</span>:address:address:number<span class="Special"> <- </span>copy <span class="Constant">150</span>/unsafe + **<span class="Constant">1</span>:address:address:number<span class="Special"> <- </span>copy <span class="Constant">34</span> + <span class="Constant">2</span>:address:address:number<span class="Special"> <- </span>deep-copy <span class="Constant">1</span>:address:address:number + <span class="Constant">10</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">1</span>:address:address:number<span class="Delimiter">,</span> <span class="Constant">2</span>:address:address:number + <span class="Constant">11</span>:boolean<span class="Special"> <- </span>equal *<span class="Constant">1</span>:address:address:number<span class="Delimiter">,</span> *<span class="Constant">2</span>:address:address:number + <span class="Constant">12</span>:boolean<span class="Special"> <- </span>equal **<span class="Constant">1</span>:address:address:number<span class="Delimiter">,</span> **<span class="Constant">2</span>:address:address:number +] +<span class="Comment"># the result of deep-copy is a new address</span> +<span class="traceContains">+mem: storing 0 in location 10</span> +<span class="Comment"># any addresses in it or pointed to it are also new</span> +<span class="traceContains">+mem: storing 0 in location 11</span> +<span class="Comment"># however, the non-address contents are identical</span> +<span class="traceContains">+mem: storing 1 in location 12</span> + +<span class="Delimiter">:(scenario deep_copy_array)</span> +<span class="Special">% Memory_allocated_until = 200;</span> +def main [ + <span class="Comment"># avoid all memory allocations except the implicit ones inside deep-copy, so</span> + <span class="Comment"># that the result is deterministic</span> + <span class="Constant">100</span>:number<span class="Special"> <- </span>copy <span class="Constant">1</span> <span class="Comment"># pretend refcount</span> + <span class="Constant">101</span>:number<span class="Special"> <- </span>copy <span class="Constant">3</span> <span class="Comment"># pretend array length</span> + <span class="Constant">1</span>:address:array:number<span class="Special"> <- </span>copy <span class="Constant">100</span>/unsafe <span class="Comment"># pretend allocation</span> + put-index *<span class="Constant">1</span>:address:array:number<span class="Delimiter">,</span> <span class="Constant">0</span><span class="Delimiter">,</span> <span class="Constant">34</span> + put-index *<span class="Constant">1</span>:address:array:number<span class="Delimiter">,</span> <span class="Constant">1</span><span class="Delimiter">,</span> <span class="Constant">35</span> + put-index *<span class="Constant">1</span>:address:array:number<span class="Delimiter">,</span> <span class="Constant">2</span><span class="Delimiter">,</span> <span class="Constant">36</span> + stash [old:]<span class="Delimiter">,</span> *<span class="Constant">1</span>:address:array:number + <span class="Constant">2</span>:address:array:number<span class="Special"> <- </span>deep-copy <span class="Constant">1</span>:address:array:number + stash <span class="Constant">2</span>:address:array:number + stash [<span class="Normal">new</span>:]<span class="Delimiter">,</span> *<span class="Constant">2</span>:address:array:number + <span class="Constant">10</span>:boolean<span class="Special"> <- </span>equal <span class="Constant">1</span>:address:array:number<span class="Delimiter">,</span> <span class="Constant">2</span>:address:array:number + <span class="Constant">11</span>:boolean<span class="Special"> <- </span>equal *<span class="Constant">1</span>:address:array:number<span class="Delimiter">,</span> *<span class="Constant">2</span>:address:array:number +] +<span class="traceContains">+app: old: 3 34 35 36</span> +<span class="traceContains">+app: new: 3 34 35 36</span> +<span class="Comment"># the result of deep-copy is a new address</span> +<span class="traceContains">+mem: storing 0 in location 10</span> +<span class="Comment"># however, the contents are identical</span> +<span class="traceContains">+mem: storing 1 in location 11</span> + +<span class="Delimiter">:(scenario deep_copy_container_with_address)</span> +container foo [ + <span class="Normal">x</span>:number + <span class="Normal">y</span>:address:number +] +def main [ + local-scope + <span class="Normal">y0</span>:address:number<span class="Special"> <- </span><span class="Normal">new</span> number:type + *y0<span class="Special"> <- </span>copy <span class="Constant">35</span> + <span class="Normal">a</span>:foo<span class="Special"> <- </span>merge <span class="Constant">34</span><span class="Delimiter">,</span> y0 + <span class="Normal">b</span>:foo<span class="Special"> <- </span>deep-copy a + <span class="Constant">10</span>:boolean/<span class="Special">raw <- </span>equal a<span class="Delimiter">,</span> b + <span class="Normal">y1</span>:address:number<span class="Special"> <- </span>get b<span class="Delimiter">,</span> y:offset + <span class="Constant">11</span>:boolean/<span class="Special">raw <- </span>equal y0<span class="Delimiter">,</span> y1 + <span class="Constant">12</span>:number/<span class="Special">raw <- </span>copy *y1 +] +<span class="Comment"># containers containing addresses are not identical to their deep copies</span> +<span class="traceContains">+mem: storing 0 in location 10</span> +<span class="Comment"># the addresses they contain are not identical either</span> +<span class="traceContains">+mem: storing 0 in location 11</span> +<span class="traceContains">+mem: storing 35 in location 12</span> + +<span class="Delimiter">:(scenario deep_copy_exclusive_container_with_address)</span> +exclusive-container foo [ + <span class="Normal">x</span>:number + <span class="Normal">y</span>:address:number +] +def main [ + local-scope + <span class="Normal">y0</span>:address:number<span class="Special"> <- </span><span class="Normal">new</span> number:type + *y0<span class="Special"> <- </span>copy <span class="Constant">34</span> + <span class="Normal">a</span>:foo<span class="Special"> <- </span>merge <span class="Constant">1</span>/y<span class="Delimiter">,</span> y0 + <span class="Normal">b</span>:foo<span class="Special"> <- </span>deep-copy a + <span class="Constant">10</span>:boolean/<span class="Special">raw <- </span>equal a<span class="Delimiter">,</span> b + <span class="Normal">y1</span>:address:number<span class="Delimiter">,</span> z:boolean<span class="Special"> <- </span>maybe-convert b<span class="Delimiter">,</span> y:variant + <span class="Constant">11</span>:boolean/<span class="Special">raw <- </span>equal y0<span class="Delimiter">,</span> y1 + <span class="Constant">12</span>:number/<span class="Special">raw <- </span>copy *y1 +] +<span class="Comment"># exclusive containers containing addresses are not identical to their deep copies</span> +<span class="traceContains">+mem: storing 0 in location 10</span> +<span class="Comment"># the addresses they contain are not identical either</span> +<span class="traceContains">+mem: storing 0 in location 11</span> +<span class="traceContains">+mem: storing 34 in location 12</span> + +<span class="Delimiter">:(scenario deep_copy_exclusive_container_with_container_with_address)</span> +exclusive-container foo [ + <span class="Normal">x</span>:number + <span class="Normal">y</span>:bar <span class="Comment"># inline</span> +] +container bar [ + <span class="Normal">x</span>:address:number +] +def main [ + local-scope + <span class="Normal">y0</span>:address:number<span class="Special"> <- </span><span class="Normal">new</span> number:type + *y0<span class="Special"> <- </span>copy <span class="Constant">34</span> + <span class="Normal">a</span>:bar<span class="Special"> <- </span>merge y0 + <span class="Normal">b</span>:foo<span class="Special"> <- </span>merge <span class="Constant">1</span>/y<span class="Delimiter">,</span> a + <span class="Normal">c</span>:foo<span class="Special"> <- </span>deep-copy b + <span class="Constant">10</span>:boolean/<span class="Special">raw <- </span>equal b<span class="Delimiter">,</span> c + <span class="Normal">d</span>:bar<span class="Delimiter">,</span> z:boolean<span class="Special"> <- </span>maybe-convert c<span class="Delimiter">,</span> y:variant + <span class="Normal">y1</span>:address:number<span class="Special"> <- </span>get d<span class="Delimiter">,</span> x:offset + <span class="Constant">11</span>:boolean/<span class="Special">raw <- </span>equal y0<span class="Delimiter">,</span> y1 + <span class="Constant">12</span>:number/<span class="Special">raw <- </span>copy *y1 +] +<span class="Comment"># exclusive containers containing addresses are not identical to their deep copies</span> +<span class="traceContains">+mem: storing 0 in location 10</span> +<span class="Comment"># sub-containers containing addresses are not identical either</span> +<span class="traceContains">+mem: storing 0 in location 11</span> +<span class="traceContains">+mem: storing 34 in location 12</span> + +<span class="Delimiter">:(before "End Primitive Recipe Declarations")</span> +DEEP_COPY<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">"deep-copy"</span><span class="Delimiter">,</span> DEEP_COPY<span class="Delimiter">);</span> +<span class="Delimiter">:(before "End Primitive Recipe Checks")</span> +<span class="Normal">case</span> DEEP_COPY: <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">"'deep-copy' takes exactly one ingredient rather than '"</span> << to_original_string<span class="Delimiter">(</span>inst<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>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">"'deep-copy' takes exactly one ingredient rather than '"</span> << to_original_string<span class="Delimiter">(</span>inst<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>!types_strictly_match<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> 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">"'deep-copy' requires its ingredient and product to be the same type, but got '"</span> << to_original_string<span class="Delimiter">(</span>inst<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> DEEP_COPY: <span class="Delimiter">{</span> + <span class="Normal">const</span> reagent& input = current_instruction<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="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> + 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> + abandon<span class="Delimiter">(</span>tmp<span class="Delimiter">.</span>value<span class="Delimiter">,</span> tmp<span class="Delimiter">.</span>type<span class="Delimiter">-></span>right<span class="Delimiter">,</span> payload_size<span class="Delimiter">(</span>tmp<span class="Delimiter">));</span> + <span class="Comment">// reclaim host memory allocated for tmp.type when tmp goes out of scope</span> + <span class="Identifier">break</span><span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Delimiter">:(code)</span> +vector<<span class="Normal">double</span>> deep_copy<span class="Delimiter">(</span><span class="Normal">const</span> reagent& in<span class="Delimiter">,</span> <span class="Normal">const</span> reagent& tmp<span class="Delimiter">)</span> <span class="Delimiter">{</span> + map<<span class="Normal">int</span><span class="Delimiter">,</span> <span class="Normal">int</span>> addresses_copied<span class="Delimiter">;</span> + <span class="Identifier">return</span> deep_copy<span class="Delimiter">(</span>in<span class="Delimiter">,</span> addresses_copied<span class="Delimiter">,</span> tmp<span class="Delimiter">);</span> +<span class="Delimiter">}</span> + +vector<<span class="Normal">double</span>> deep_copy<span class="Delimiter">(</span>reagent<span class="Comment">/*</span><span class="Comment">copy</span><span class="Comment">*/</span> in<span class="Delimiter">,</span> map<<span class="Normal">int</span><span class="Delimiter">,</span> <span class="Normal">int</span>>& addresses_copied<span class="Delimiter">,</span> <span class="Normal">const</span> reagent& tmp<span class="Delimiter">)</span> <span class="Delimiter">{</span> + canonize<span class="Delimiter">(</span>in<span class="Delimiter">);</span> + vector<<span class="Normal">double</span>> result<span class="Delimiter">;</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>is_mu_address<span class="Delimiter">(</span>in<span class="Delimiter">))</span> + result<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>deep_copy_address<span class="Delimiter">(</span>in<span class="Delimiter">,</span> addresses_copied<span class="Delimiter">,</span> tmp<span class="Delimiter">));</span> + <span class="Normal">else</span> + deep_copy<span class="Delimiter">(</span>in<span class="Delimiter">,</span> addresses_copied<span class="Delimiter">,</span> tmp<span class="Delimiter">,</span> result<span class="Delimiter">);</span> + <span class="Identifier">return</span> result<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Comment">// deep-copy an address and return a new address</span> +<span class="Normal">int</span> deep_copy_address<span class="Delimiter">(</span><span class="Normal">const</span> reagent& canonized_in<span class="Delimiter">,</span> map<<span class="Normal">int</span><span class="Delimiter">,</span> <span class="Normal">int</span>>& addresses_copied<span class="Delimiter">,</span> <span class="Normal">const</span> reagent& tmp<span class="Delimiter">)</span> <span class="Delimiter">{</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>canonized_in<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> + <span class="Normal">int</span> in_address = payload_address<span class="Delimiter">(</span>canonized_in<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: copying address "</span> << in_address << end<span class="Delimiter">();</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>contains_key<span class="Delimiter">(</span>addresses_copied<span class="Delimiter">,</span> in_address<span class="Delimiter">))</span> <span class="Delimiter">{</span> + <span class="Normal">int</span> out = get<span class="Delimiter">(</span>addresses_copied<span class="Delimiter">,</span> in_address<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: copy already exists: "</span> << out << end<span class="Delimiter">();</span> + <span class="Identifier">return</span> out<span class="Delimiter">;</span> + <span class="Delimiter">}</span> + <span class="Normal">int</span> out = allocate<span class="Delimiter">(</span>payload_size<span class="Delimiter">(</span>canonized_in<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: new address is "</span> << out << end<span class="Delimiter">();</span> + put<span class="Delimiter">(</span>addresses_copied<span class="Delimiter">,</span> in_address<span class="Delimiter">,</span> out<span class="Delimiter">);</span> + reagent<span class="Comment">/*</span><span class="Comment">copy</span><span class="Comment">*/</span> payload = canonized_in<span class="Delimiter">;</span> + payload<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">"lookup"</span><span class="Delimiter">,</span> <span class="Constant">NULL</span><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">"recursing on payload "</span> << payload<span class="Delimiter">.</span>value << <span class="Constant">' '</span> << to_string<span class="Delimiter">(</span>payload<span class="Delimiter">)</span> << end<span class="Delimiter">();</span> + vector<<span class="Normal">double</span>> data = deep_copy<span class="Delimiter">(</span>payload<span class="Delimiter">,</span> addresses_copied<span class="Delimiter">,</span> tmp<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: writing result "</span> << out << <span class="Constant">": "</span> << to_string<span class="Delimiter">(</span>data<span class="Delimiter">)</span> << end<span class="Delimiter">();</span> + <span class="Comment">// HACK: write_memory interface isn't ideal for this situation; we need</span> + <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> + 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> + 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> + +<span class="Comment">// deep-copy a non-address and return a vector of locations</span> +<span class="Normal">void</span> deep_copy<span class="Delimiter">(</span><span class="Normal">const</span> reagent& canonized_in<span class="Delimiter">,</span> map<<span class="Normal">int</span><span class="Delimiter">,</span> <span class="Normal">int</span>>& addresses_copied<span class="Delimiter">,</span> <span class="Normal">const</span> reagent& tmp<span class="Delimiter">,</span> vector<<span class="Normal">double</span>>& out<span class="Delimiter">)</span> <span class="Delimiter">{</span> + assert<span class="Delimiter">(</span>!is_mu_address<span class="Delimiter">(</span>canonized_in<span class="Delimiter">));</span> + vector<<span class="Normal">double</span>> data = read_memory<span class="Delimiter">(</span>canonized_in<span class="Delimiter">);</span> + out<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>out<span class="Delimiter">.</span>end<span class="Delimiter">(),</span> data<span class="Delimiter">.</span>begin<span class="Delimiter">(),</span> data<span class="Delimiter">.</span>end<span class="Delimiter">());</span> + <span class="Normal">if</span> <span class="Delimiter">(</span>!contains_key<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> canonized_in<span class="Delimiter">.</span>type<span class="Delimiter">))</span> <span class="Identifier">return</span><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: scanning for addresses in "</span> << to_string<span class="Delimiter">(</span>data<span class="Delimiter">)</span> << end<span class="Delimiter">();</span> + <span class="Normal">const</span> container_metadata& metadata = get<span class="Delimiter">(</span>Container_metadata<span class="Delimiter">,</span> canonized_in<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> <span class="Delimiter">{</span> + <span class="Comment">// construct a fake reagent that reads directly from the appropriate</span> + <span class="Comment">// field of the container</span> + reagent curr<span class="Delimiter">;</span> + curr<span class="Delimiter">.</span>type = <span class="Normal">new</span> type_tree<span class="Delimiter">(</span><span class="Constant">"address"</span><span class="Delimiter">,</span> <span class="Normal">new</span> type_tree<span class="Delimiter">(</span>*info<span class="Delimiter">-></span>payload_type<span class="Delimiter">));</span> + curr<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>canonized_in<span class="Delimiter">.</span>value + info<span class="Delimiter">-></span>offset<span class="Delimiter">);</span> + curr<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> + 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: copying address "</span> << curr<span class="Delimiter">.</span>value << end<span class="Delimiter">();</span> + out<span class="Delimiter">.</span>at<span class="Delimiter">(</span>info<span class="Delimiter">-></span>offset<span class="Delimiter">)</span> = deep_copy_address<span class="Delimiter">(</span>curr<span class="Delimiter">,</span> addresses_copied<span class="Delimiter">,</span> tmp<span class="Delimiter">);</span> + <span class="Delimiter">}</span> + <span class="Delimiter">}</span> +<span class="Delimiter">}</span> + +<span class="Normal">int</span> payload_address<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="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">"lookup"</span><span class="Delimiter">,</span> <span class="Constant">NULL</span><span class="Delimiter">));</span> + canonize<span class="Delimiter">(</span>x<span class="Delimiter">);</span> + <span class="Identifier">return</span> x<span class="Delimiter">.</span>value<span class="Delimiter">;</span> +<span class="Delimiter">}</span> + +<span class="Comment">//: moar tests, just because I can't believe it all works</span> + +<span class="Delimiter">:(scenario deep_copy_stress_test_1)</span> +container foo1 [ + <span class="Normal">p</span>:address:number +] +container foo2 [ + <span class="Normal">p</span>:address:foo1 +] +exclusive-container foo3 [ + <span class="Normal">p</span>:address:foo1 + <span class="Normal">q</span>:address:foo2 +] +def main [ + local-scope + <span class="Normal">x</span>:address:number<span class="Special"> <- </span><span class="Normal">new</span> number:type + *x<span class="Special"> <- </span>copy <span class="Constant">34</span> + <span class="Normal">a</span>:address:foo1<span class="Special"> <- </span><span class="Normal">new</span> foo1:type + *a<span class="Special"> <- </span>merge x + <span class="Normal">b</span>:address:foo2<span class="Special"> <- </span><span class="Normal">new</span> foo2:type + *b<span class="Special"> <- </span>merge a + <span class="Normal">c</span>:foo3<span class="Special"> <- </span>merge <span class="Constant">1</span>/q<span class="Delimiter">,</span> b + <span class="Normal">d</span>:foo3<span class="Special"> <- </span>deep-copy c + <span class="Normal">e</span>:address:foo2<span class="Delimiter">,</span> z:boolean<span class="Special"> <- </span>maybe-convert d<span class="Delimiter">,</span> q:variant + <span class="Normal">f</span>:address:foo1<span class="Special"> <- </span>get *e<span class="Delimiter">,</span> p:offset + <span class="Normal">g</span>:address:number<span class="Special"> <- </span>get *f<span class="Delimiter">,</span> p:offset + <span class="Constant">1</span>:number/<span class="Special">raw <- </span>copy *g +] +<span class="traceContains">+mem: storing 34 in location 1</span> + +<span class="Delimiter">:(scenario deep_copy_stress_test_2)</span> +container foo1 [ + <span class="Normal">p</span>:address:number +] +container foo2 [ + <span class="Normal">p</span>:address:foo1 +] +exclusive-container foo3 [ + <span class="Normal">p</span>:address:foo1 + <span class="Normal">q</span>:address:foo2 +] +container foo4 [ + <span class="Normal">p</span>:number + <span class="Normal">q</span>:address:foo3 +] +def main [ + local-scope + <span class="Normal">x</span>:address:number<span class="Special"> <- </span><span class="Normal">new</span> number:type + *x<span class="Special"> <- </span>copy <span class="Constant">34</span> + <span class="Normal">a</span>:address:foo1<span class="Special"> <- </span><span class="Normal">new</span> foo1:type + *a<span class="Special"> <- </span>merge x + <span class="Normal">b</span>:address:foo2<span class="Special"> <- </span><span class="Normal">new</span> foo2:type + *b<span class="Special"> <- </span>merge a + <span class="Normal">c</span>:address:foo3<span class="Special"> <- </span><span class="Normal">new</span> foo3:type + *c<span class="Special"> <- </span>merge <span class="Constant">1</span>/q<span class="Delimiter">,</span> b + <span class="Normal">d</span>:foo4<span class="Special"> <- </span>merge <span class="Constant">35</span><span class="Delimiter">,</span> c + <span class="Normal">e</span>:foo4<span class="Special"> <- </span>deep-copy d + <span class="Normal">f</span>:address:foo3<span class="Special"> <- </span>get e<span class="Delimiter">,</span> q:offset + <span class="Normal">g</span>:address:foo2<span class="Delimiter">,</span> z:boolean<span class="Special"> <- </span>maybe-convert *f<span class="Delimiter">,</span> q:variant + <span class="Normal">h</span>:address:foo1<span class="Special"> <- </span>get *g<span class="Delimiter">,</span> p:offset + <span class="Normal">y</span>:address:number<span class="Special"> <- </span>get *h<span class="Delimiter">,</span> p:offset + <span class="Constant">1</span>:number/<span class="Special">raw <- </span>copy *y +] +<span class="traceContains">+mem: storing 34 in location 1</span> + +<span class="Delimiter">:(scenario deep_copy_cycles)</span> +container foo [ + <span class="Normal">p</span>:number + <span class="Normal">q</span>:address:foo +] +def main [ + local-scope + <span class="Normal">x</span>:address:foo<span class="Special"> <- </span><span class="Normal">new</span> foo:type + *x<span class="Special"> <- </span>put *x<span class="Delimiter">,</span> p:offset<span class="Delimiter">,</span> <span class="Constant">34</span> + *x<span class="Special"> <- </span>put *x<span class="Delimiter">,</span> q:offset<span class="Delimiter">,</span> x <span class="Comment"># create a cycle</span> + <span class="Normal">y</span>:address:foo<span class="Special"> <- </span>deep-copy x + <span class="Constant">1</span>:number/<span class="Special">raw <- </span>get *y<span class="Delimiter">,</span> p:offset + <span class="Normal">y2</span>:address:foo<span class="Special"> <- </span>get *y<span class="Delimiter">,</span> q:offset + stash y [vs] y2 + <span class="Constant">2</span>:boolean/<span class="Special">raw <- </span>equal y<span class="Delimiter">,</span> y2 <span class="Comment"># is it still a cycle?</span> + <span class="Constant">3</span>:boolean/<span class="Special">raw <- </span>equal x<span class="Delimiter">,</span> y <span class="Comment"># is it the same cycle?</span> +] +<span class="traceContains">+mem: storing 34 in location 1</span> +<span class="Comment"># deep copy also contains a cycle</span> +<span class="traceContains">+mem: storing 1 in location 2</span> +<span class="Comment"># but it's a completely different (disjoint) cycle</span> +<span class="traceContains">+mem: storing 0 in location 3</span> +</pre> +</body> +</html> +<!-- vim: set foldmethod=manual : --> diff --git a/html/072channel.mu.html b/html/074channel.mu.html index dd3923a5..e2214f12 100644 --- a/html/072channel.mu.html +++ b/html/074channel.mu.html @@ -2,7 +2,7 @@ <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> -<title>Mu - 072channel.mu</title> +<title>Mu - 074channel.mu</title> <meta name="Generator" content="Vim/7.4"> <meta name="plugin-version" content="vim7.4_v2"> <meta name="syntax" content="none"> @@ -36,12 +36,17 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment"># Mu synchronizes using channels rather than locks, like Erlang and Go.</span> <span class="Comment">#</span> <span class="Comment"># The two ends of a channel will usually belong to different routines, but</span> -<span class="Comment"># each end should only be used by a single one. Don't try to read from or</span> -<span class="Comment"># write to it from multiple routines at once.</span> +<span class="Comment"># each end should (currently) only be used by a single one. Don't try to read</span> +<span class="Comment"># from or write to it from multiple routines at once.</span> <span class="Comment">#</span> -<span class="Comment"># The key property of channels is that writing to a full channel or reading</span> -<span class="Comment"># from an empty one will put the current routine in 'waiting' state until the</span> -<span class="Comment"># operation can be completed.</span> +<span class="Comment"># Key properties of channels:</span> +<span class="Comment">#</span> +<span class="Comment"># a) Writing to a full channel or reading from an empty one will put the</span> +<span class="Comment"># current routine in 'waiting' state until the operation can be completed.</span> +<span class="Comment">#</span> +<span class="Comment"># b) Writing to a channel implicitly performs a deep copy, to prevent</span> +<span class="Comment"># addresses from being shared between routines, thereby causing race</span> +<span class="Comment"># conditions.</span> <span class="muScenario">scenario</span> channel [ run [ @@ -106,10 +111,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color full-address:location<span class="Special"> <- </span>get-location *chan, <span class="Constant">first-full:offset</span> wait-for-location full-address <span class="Delimiter">}</span> - <span class="Comment"># store val</span> + <span class="Comment"># store a deep copy of val</span> circular-buffer:address:array:_elem<span class="Special"> <- </span>get *chan, <span class="Constant">data:offset</span> free:number<span class="Special"> <- </span>get *chan, <span class="Constant">first-free:offset</span> - *circular-buffer<span class="Special"> <- </span>put-index *circular-buffer, free, val + val-copy:_elem<span class="Special"> <- </span>deep-copy val <span class="Comment"># on this instruction rests all Mu's concurrency-safety</span> + *circular-buffer<span class="Special"> <- </span>put-index *circular-buffer, free, val-copy <span class="Comment"># mark its slot as filled</span> free<span class="Special"> <- </span>add free, <span class="Constant">1</span> <span class="Delimiter">{</span> @@ -307,7 +313,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] <span class="Comment"># a channel can be closed from either the source or the sink</span> -<span class="Comment"># both threads can modify it, but they can only set it, so this is a benign race</span> +<span class="Comment"># both routines can modify the 'closed?' bit, but they can only ever set it, so this is a benign race</span> <span class="muRecipe">def</span> close x:address:source:_elem<span class="muRecipe"> -> </span>x:address:source:_elem [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> diff --git a/html/074list.mu.html b/html/074list.mu.html deleted file mode 100644 index 5154783c..00000000 --- a/html/074list.mu.html +++ /dev/null @@ -1,148 +0,0 @@ -<!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 - 074list.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; } -.muScenario { color: #00af00; } -.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="Comment"># A list links up multiple objects together to make them easier to manage.</span> -<span class="Comment">#</span> -<span class="Comment"># The objects must be of the same type. If you want to store multiple types in</span> -<span class="Comment"># a single list, use an exclusive-container.</span> - -<span class="muData">container</span> list:_elem [ - value:_elem - next:address:list:_elem -] - -<span class="muRecipe">def</span> push x:_elem, in:address:list:_elem<span class="muRecipe"> -> </span>result:address:list:_elem [ - <span class="Constant">local-scope</span> - <span class="Constant">load-ingredients</span> - result<span class="Special"> <- </span>new <span class="Delimiter">{</span>(list _elem): type<span class="Delimiter">}</span> - *result<span class="Special"> <- </span>merge x, in -] - -<span class="muRecipe">def</span> first in:address:list:_elem<span class="muRecipe"> -> </span>result:_elem [ - <span class="Constant">local-scope</span> - <span class="Constant">load-ingredients</span> - result<span class="Special"> <- </span>get *in, <span class="Constant">value:offset</span> -] - -<span class="muRecipe">def</span> rest in:address:list:_elem<span class="muRecipe"> -> </span>result:address:list:_elem/contained-in:in [ - <span class="Constant">local-scope</span> - <span class="Constant">load-ingredients</span> - result<span class="Special"> <- </span>get *in, <span class="Constant">next:offset</span> -] - -<span class="muScenario">scenario</span> list-handling [ - run [ - <span class="Constant">local-scope</span> - x:address:list:number<span class="Special"> <- </span>push <span class="Constant">3</span>, <span class="Constant">0</span> - x<span class="Special"> <- </span>push <span class="Constant">4</span>, x - x<span class="Special"> <- </span>push <span class="Constant">5</span>, x - <span class="Constant">10</span>:number/<span class="Special">raw <- </span>first x - x<span class="Special"> <- </span>rest x - <span class="Constant">11</span>:number/<span class="Special">raw <- </span>first x - x<span class="Special"> <- </span>rest x - <span class="Constant">12</span>:number/<span class="Special">raw <- </span>first x - <span class="Constant">20</span>:address:list:number/<span class="Special">raw <- </span>rest x - ] - memory-should-contain [ - <span class="Constant">10</span><span class="Special"> <- </span><span class="Constant">5</span> - <span class="Constant">11</span><span class="Special"> <- </span><span class="Constant">4</span> - <span class="Constant">12</span><span class="Special"> <- </span><span class="Constant">3</span> - <span class="Constant">20</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># nothing left</span> - ] -] - -<span class="muRecipe">def</span> length l:address:list:_elem<span class="muRecipe"> -> </span>result:number [ - <span class="Constant">local-scope</span> - <span class="Constant">load-ingredients</span> - <span class="muControl">return-unless</span> l, <span class="Constant">0</span> - rest:address:list:_elem<span class="Special"> <- </span>rest l - length-of-rest:number<span class="Special"> <- </span>length rest - result<span class="Special"> <- </span>add length-of-rest, <span class="Constant">1</span> -] - -<span class="muRecipe">def</span> to-text in:address:list:_elem<span class="muRecipe"> -> </span>result:address:array:character [ - <span class="Constant">local-scope</span> - <span class="Constant">load-ingredients</span> - buf:address:buffer<span class="Special"> <- </span>new-buffer <span class="Constant">80</span> - buf<span class="Special"> <- </span>to-buffer in, buf - result<span class="Special"> <- </span>buffer-to-array buf -] - -<span class="Comment"># variant of 'to-text' which stops printing after a few elements (and so is robust to cycles)</span> -<span class="muRecipe">def</span> to-text-line in:address:list:_elem<span class="muRecipe"> -> </span>result:address:array:character [ - <span class="Constant">local-scope</span> - <span class="Constant">load-ingredients</span> - buf:address:buffer<span class="Special"> <- </span>new-buffer <span class="Constant">80</span> - buf<span class="Special"> <- </span>to-buffer in, buf, <span class="Constant">6</span> <span class="Comment"># max elements to display</span> - result<span class="Special"> <- </span>buffer-to-array buf -] - -<span class="muRecipe">def</span> to-buffer in:address:list:_elem, buf:address:buffer<span class="muRecipe"> -> </span>buf:address:buffer [ - <span class="Constant">local-scope</span> - <span class="Constant">load-ingredients</span> - <span class="Delimiter">{</span> - <span class="muControl">break-if</span> in - buf<span class="Special"> <- </span>append buf, <span class="Constant">48/0</span> - <span class="muControl">return</span> - <span class="Delimiter">}</span> - <span class="Comment"># append in.value to buf</span> - val:_elem<span class="Special"> <- </span>get *in, <span class="Constant">value:offset</span> - buf<span class="Special"> <- </span>append buf, val - <span class="Comment"># now prepare next</span> - next:address:list:_elem<span class="Special"> <- </span>rest in - nextn:number<span class="Special"> <- </span>copy next - <span class="muControl">return-unless</span> next - buf<span class="Special"> <- </span>append buf, <span class="Constant">[ -> ]</span> - <span class="Comment"># and recurse</span> - remaining:number, optional-ingredient-found?:boolean<span class="Special"> <- </span><span class="Constant">next-ingredient</span> - <span class="Delimiter">{</span> - <span class="muControl">break-if</span> optional-ingredient-found? - <span class="Comment"># unlimited recursion</span> - buf<span class="Special"> <- </span>to-buffer next, buf - <span class="muControl">return</span> - <span class="Delimiter">}</span> - <span class="Delimiter">{</span> - <span class="muControl">break-unless</span> remaining - <span class="Comment"># limited recursion</span> - remaining<span class="Special"> <- </span>subtract remaining, <span class="Constant">1</span> - buf<span class="Special"> <- </span>to-buffer next, buf, remaining - <span class="muControl">return</span> - <span class="Delimiter">}</span> - <span class="Comment"># past recursion depth; insert ellipses and stop</span> - append buf, <span class="Constant">[...]</span> -] -</pre> -</body> -</html> -<!-- vim: set foldmethod=manual : --> diff --git a/html/082scenario_screen.cc.html b/html/082scenario_screen.cc.html index 6f14b589..090a0daa 100644 --- a/html/082scenario_screen.cc.html +++ b/html/082scenario_screen.cc.html @@ -184,7 +184,7 @@ Name[r][<span class="Constant">"screen"</span>] = SCREEN<span class="D <span class="Normal">if</span> <span class="Delimiter">(</span>curr<span class="Delimiter">.</span>name == <span class="Constant">"assume-screen"</span><span class="Delimiter">)</span> <span class="Delimiter">{</span> curr<span class="Delimiter">.</span>name = <span class="Constant">"new-fake-screen"</span><span class="Delimiter">;</span> assert<span class="Delimiter">(</span>curr<span class="Delimiter">.</span>products<span class="Delimiter">.</span>empty<span class="Delimiter">());</span> - curr<span class="Delimiter">.</span>products<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>reagent<span class="Delimiter">(</span><span class="Constant">"screen:address:screen"</span><span class="Delimiter">));</span> + curr<span class="Delimiter">.</span>products<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>reagent<span class="Delimiter">(</span><span class="Constant">"screen:address:screen/raw"</span><span class="Delimiter">));</span> <span class="Comment">// only allowed in scenario blocks</span> curr<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>set_value<span class="Delimiter">(</span>SCREEN<span class="Delimiter">);</span> <span class="Delimiter">}</span> @@ -238,7 +238,6 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span <span class="Delimiter">:(code)</span> <span class="Normal">void</span> check_screen<span class="Delimiter">(</span><span class="Normal">const</span> string& expected_contents<span class="Delimiter">,</span> <span class="Normal">const</span> <span class="Normal">int</span> color<span class="Delimiter">)</span> <span class="Delimiter">{</span> - assert<span class="Delimiter">(</span>!current_call<span class="Delimiter">().</span>default_space<span class="Delimiter">);</span> <span class="Comment">// not supported</span> <span class="Normal">int</span> screen_location = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> SCREEN<span class="Delimiter">)</span>+<span class="Comment">/*</span><span class="Comment">skip refcount</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">;</span> <span class="Normal">int</span> data_offset = find_element_name<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"screen"</span><span class="Delimiter">),</span> <span class="Constant">"data"</span><span class="Delimiter">,</span> <span class="Constant">""</span><span class="Delimiter">);</span> assert<span class="Delimiter">(</span>data_offset >= <span class="Constant">0</span><span class="Delimiter">);</span> @@ -374,7 +373,6 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span <span class="Delimiter">:(code)</span> <span class="Normal">void</span> dump_screen<span class="Delimiter">()</span> <span class="Delimiter">{</span> - assert<span class="Delimiter">(</span>!current_call<span class="Delimiter">().</span>default_space<span class="Delimiter">);</span> <span class="Comment">// not supported</span> <span class="Normal">int</span> screen_location = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> SCREEN<span class="Delimiter">)</span> + <span class="Comment">/*</span><span class="Comment">skip refcount</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">;</span> <span class="Normal">int</span> width_offset = find_element_name<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"screen"</span><span class="Delimiter">),</span> <span class="Constant">"num-columns"</span><span class="Delimiter">,</span> <span class="Constant">""</span><span class="Delimiter">);</span> <span class="Normal">int</span> screen_width = get_or_insert<span class="Delimiter">(</span>Memory<span class="Delimiter">,</span> screen_location+width_offset<span class="Delimiter">);</span> diff --git a/html/085scenario_console.cc.html b/html/085scenario_console.cc.html index 2db2a1f1..d1b0cd33 100644 --- a/html/085scenario_console.cc.html +++ b/html/085scenario_console.cc.html @@ -314,7 +314,7 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span <span class="Comment">// memoize result if already computed</span> <span class="Normal">static</span> <span class="Normal">int</span> result = <span class="Constant">0</span><span class="Delimiter">;</span> <span class="Normal">if</span> <span class="Delimiter">(</span>result<span class="Delimiter">)</span> <span class="Identifier">return</span> result<span class="Delimiter">;</span> - type_tree* type = <span class="Normal">new</span> type_tree<span class="Delimiter">(</span><span class="Constant">"event"</span><span class="Delimiter">,</span> get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"event"</span><span class="Delimiter">));</span> + type_tree* type = <span class="Normal">new</span> type_tree<span class="Delimiter">(</span><span class="Constant">"event"</span><span class="Delimiter">);</span> result = size_of<span class="Delimiter">(</span>type<span class="Delimiter">);</span> <span class="Normal">delete</span> type<span class="Delimiter">;</span> <span class="Identifier">return</span> result<span class="Delimiter">;</span> @@ -325,7 +325,7 @@ put<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span <span class="Normal">static</span> <span class="Normal">int</span> result = <span class="Constant">0</span><span class="Delimiter">;</span> <span class="Normal">if</span> <span class="Delimiter">(</span>result<span class="Delimiter">)</span> <span class="Identifier">return</span> result<span class="Delimiter">;</span> assert<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"console"</span><span class="Delimiter">));</span> - type_tree* type = <span class="Normal">new</span> type_tree<span class="Delimiter">(</span><span class="Constant">"console"</span><span class="Delimiter">,</span> get<span class="Delimiter">(</span>Type_ordinal<span class="Delimiter">,</span> <span class="Constant">"console"</span><span class="Delimiter">));</span> + type_tree* type = <span class="Normal">new</span> type_tree<span class="Delimiter">(</span><span class="Constant">"console"</span><span class="Delimiter">);</span> result = size_of<span class="Delimiter">(</span>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="Normal">delete</span> type<span class="Delimiter">;</span> <span class="Identifier">return</span> result<span class="Delimiter">;</span> diff --git a/html/091run_interactive.cc.html b/html/091run_interactive.cc.html index b3093619..6bd254b0 100644 --- a/html/091run_interactive.cc.html +++ b/html/091run_interactive.cc.html @@ -157,8 +157,6 @@ map<string<span class="Delimiter">,</span> vector<recipe_ordinal> > <span class="Normal">if</span> <span class="Delimiter">(</span>should_stash_snapshots<span class="Delimiter">)</span> stash_snapshots<span class="Delimiter">();</span> Save_trace_stream = Trace_stream<span class="Delimiter">;</span> - Save_trace_file = Trace_file<span class="Delimiter">;</span> - Trace_file = <span class="Constant">""</span><span class="Delimiter">;</span> Trace_stream = <span class="Normal">new</span> trace_stream<span class="Delimiter">;</span> Trace_stream<span class="Delimiter">-></span>collect_depth = App_depth<span class="Delimiter">;</span> <span class="Delimiter">}</span> @@ -169,7 +167,6 @@ map<string<span class="Delimiter">,</span> vector<recipe_ordinal> > <span class="Normal">delete</span> Trace_stream<span class="Delimiter">;</span> Trace_stream = Save_trace_stream<span class="Delimiter">;</span> Save_trace_stream = <span class="Constant">NULL</span><span class="Delimiter">;</span> - Trace_file = Save_trace_file<span class="Delimiter">;</span> Save_trace_file<span class="Delimiter">.</span>clear<span class="Delimiter">();</span> Recipe<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>get<span class="Delimiter">(</span>Recipe_ordinal<span class="Delimiter">,</span> <span class="Constant">"interactive"</span><span class="Delimiter">));</span> <span class="Comment">// keep past sandboxes from inserting errors</span> <span class="Normal">if</span> <span class="Delimiter">(</span>!Recipe_snapshot_stash<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> diff --git a/html/edit/002-typing.mu.html b/html/edit/002-typing.mu.html index 7375cd90..69e1b614 100644 --- a/html/edit/002-typing.mu.html +++ b/html/edit/002-typing.mu.html @@ -726,12 +726,40 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muRecipe">after</span> <span class="Constant"><insert-character-special-case></span> [ <span class="Comment"># if the line wraps at the cursor, move cursor to start of next row</span> <span class="Delimiter">{</span> - <span class="Comment"># if we're at the column just before the wrap indicator</span> - wrap-column:number<span class="Special"> <- </span>subtract right, <span class="Constant">1</span> + <span class="Comment"># if either:</span> + <span class="Comment"># a) we're at the end of the line and at the column of the wrap indicator, or</span> + <span class="Comment"># b) we're not at end of line and just before the column of the wrap indicator</span> + wrap-column:number<span class="Special"> <- </span>copy right + before-wrap-column:number<span class="Special"> <- </span>subtract wrap-column, <span class="Constant">1</span> at-wrap?:boolean<span class="Special"> <- </span>greater-or-equal cursor-column, wrap-column - <span class="muControl">break-unless</span> at-wrap? - cursor-column<span class="Special"> <- </span>subtract cursor-column, wrap-column - cursor-column<span class="Special"> <- </span>add cursor-column, left + just-before-wrap?:boolean<span class="Special"> <- </span>greater-or-equal cursor-column, before-wrap-column + next:address:duplex-list:character<span class="Special"> <- </span>next before-cursor + <span class="Comment"># at end of line? next == 0 || next.value == 10/newline</span> + at-end-of-line?:boolean<span class="Special"> <- </span>equal next, <span class="Constant">0</span> + <span class="Delimiter">{</span> + <span class="muControl">break-if</span> at-end-of-line? + next-character:character<span class="Special"> <- </span>get *next, <span class="Constant">value:offset</span> + at-end-of-line?<span class="Special"> <- </span>equal next-character, <span class="Constant">10/newline</span> + <span class="Delimiter">}</span> + <span class="Comment"># break unless ((eol? and at-wrap?) or (~eol? and just-before-wrap?))</span> + move-cursor-to-next-line?:boolean<span class="Special"> <- </span>copy <span class="Constant">0/false</span> + <span class="Delimiter">{</span> + <span class="muControl">break-if</span> at-end-of-line? + move-cursor-to-next-line?<span class="Special"> <- </span>copy just-before-wrap? + <span class="Comment"># if we're moving the cursor because it's in the middle of a wrapping</span> + <span class="Comment"># line, adjust it to left-most column</span> + potential-new-cursor-column:number<span class="Special"> <- </span>copy left + <span class="Delimiter">}</span> + <span class="Delimiter">{</span> + <span class="muControl">break-unless</span> at-end-of-line? + move-cursor-to-next-line?<span class="Special"> <- </span>copy at-wrap? + <span class="Comment"># if we're moving the cursor because it's at the end of a wrapping line,</span> + <span class="Comment"># adjust it to one past the left-most column to make room for the</span> + <span class="Comment"># newly-inserted wrap-indicator</span> + potential-new-cursor-column:number<span class="Special"> <- </span>add left, <span class="Constant">1/make-room-for-wrap-indicator</span> + <span class="Delimiter">}</span> + <span class="muControl">break-unless</span> move-cursor-to-next-line? + cursor-column<span class="Special"> <- </span>copy potential-new-cursor-column *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-column:offset</span>, cursor-column cursor-row<span class="Special"> <- </span>add cursor-row, <span class="Constant">1</span> *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-row:offset</span>, cursor-row @@ -746,12 +774,12 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">}</span> ] -<span class="muScenario">scenario</span> editor-wraps-cursor-after-inserting-characters [ +<span class="muScenario">scenario</span> editor-wraps-cursor-after-inserting-characters-in-middle-of-line [ assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcde]</span> <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> assume-console [ - left-click <span class="Constant">1</span>, <span class="Constant">4</span> <span class="Comment"># line is full; no wrap icon yet</span> + left-click <span class="Constant">1</span>, <span class="Constant">3</span> <span class="Comment"># right before the wrap icon</span> type <span class="Constant">[f]</span> ] run [ @@ -761,40 +789,43 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] screen-should-contain [ <span class="Constant"> . .</span> - <span class="Constant"> .abcd↩ .</span> - <span class="Constant"> .fe .</span> + <span class="Constant"> .abcf↩ .</span> + <span class="Constant"> .de .</span> <span class="Constant"> .┈┈┈┈┈ .</span> <span class="Constant"> . .</span> ] memory-should-contain [ <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">2</span> <span class="Comment"># cursor row</span> - <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">1</span> <span class="Comment"># cursor column</span> + <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># cursor column</span> ] ] -<span class="muScenario">scenario</span> editor-wraps-cursor-after-inserting-characters-2 [ +<span class="muScenario">scenario</span> editor-wraps-cursor-after-inserting-characters-at-end-of-line [ + <span class="Constant">local-scope</span> assume-screen <span class="Constant">10/width</span>, <span class="Constant">5/height</span> - <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abcde]</span> - <span class="Constant">2</span>:address:editor-data<span class="Special"> <- </span>new-editor <span class="Constant">1</span>:address:array:character, screen:address:screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + <span class="Comment"># create an editor containing two lines</span> + contents:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> +<span class="Constant">xyz]</span> + <span class="Constant">1</span>:address:editor-data/<span class="Special">raw <- </span>new-editor contents, screen, <span class="Constant">0/left</span>, <span class="Constant">5/right</span> + screen-should-contain [ + <span class="Constant"> . .</span> + <span class="Constant"> .abc .</span> + <span class="Constant"> .xyz .</span> + <span class="Constant"> . .</span> + ] assume-console [ - left-click <span class="Constant">1</span>, <span class="Constant">3</span> <span class="Comment"># right before the wrap icon</span> - type <span class="Constant">[f]</span> + left-click <span class="Constant">1</span>, <span class="Constant">4</span> <span class="Comment"># at end of first line</span> + type <span class="Constant">[de]</span> <span class="Comment"># trigger wrap</span> ] run [ - editor-event-loop screen:address:screen, console:address:console, <span class="Constant">2</span>:address:editor-data - <span class="Constant">3</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-row:offset</span> - <span class="Constant">4</span>:number<span class="Special"> <- </span>get *<span class="Constant">2</span>:address:editor-data, <span class="Constant">cursor-column:offset</span> + editor-event-loop screen:address:screen, console:address:console, <span class="Constant">1</span>:address:editor-data/<span class="Special">raw</span> ] screen-should-contain [ <span class="Constant"> . .</span> - <span class="Constant"> .abcf↩ .</span> - <span class="Constant"> .de .</span> + <span class="Constant"> .abcd↩ .</span> + <span class="Constant"> .e .</span> + <span class="Constant"> .xyz .</span> <span class="Constant"> .┈┈┈┈┈ .</span> - <span class="Constant"> . .</span> - ] - memory-should-contain [ - <span class="Constant">3</span><span class="Special"> <- </span><span class="Constant">2</span> <span class="Comment"># cursor row</span> - <span class="Constant">4</span><span class="Special"> <- </span><span class="Constant">0</span> <span class="Comment"># cursor column</span> ] ] diff --git a/html/edit/004-programming-environment.mu.html b/html/edit/004-programming-environment.mu.html index 6ae14e6c..a640fa59 100644 --- a/html/edit/004-programming-environment.mu.html +++ b/html/edit/004-programming-environment.mu.html @@ -21,6 +21,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color .Comment { color: #9090ff; } .Constant { color: #00a0a0; } .SalientComment { color: #00ffff; } +.CommentedCode { color: #6c6c6c; } .muControl { color: #c0a020; } --> </style> @@ -45,7 +46,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color initial-sandbox:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> hide-screen <span class="Constant">0/screen</span> env:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment <span class="Constant">0/screen</span>, initial-recipe, initial-sandbox - render-all <span class="Constant">0/screen</span>, env + render-all <span class="Constant">0/screen</span>, env, render event-loop <span class="Constant">0/screen</span>, <span class="Constant">0/console</span>, env <span class="Comment"># never gets here</span> ] @@ -146,7 +147,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">{</span> <span class="muControl">break-if</span> more-events? env, screen<span class="Special"> <- </span>resize screen, env - screen<span class="Special"> <- </span>render-all screen, env + screen<span class="Special"> <- </span>render-all screen, env, render-without-moving-cursor render-all-on-no-more-events?<span class="Special"> <- </span>copy <span class="Constant">0/false</span> <span class="Comment"># full render done</span> <span class="Delimiter">}</span> <span class="muControl">loop</span> <span class="Constant">+next-event:label</span> @@ -171,14 +172,14 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">{</span> <span class="muControl">break-unless</span> render-all-on-no-more-events? <span class="Comment"># no more events, and we have to force render</span> - screen<span class="Special"> <- </span>render-all screen, env + screen<span class="Special"> <- </span>render-all screen, env, render render-all-on-no-more-events?<span class="Special"> <- </span>copy <span class="Constant">0/false</span> <span class="muControl">jump</span> <span class="Constant">+finish-event:label</span> <span class="Delimiter">}</span> <span class="Comment"># no more events, no force render</span> <span class="Delimiter">{</span> <span class="muControl">break-unless</span> render? - screen<span class="Special"> <- </span>render-recipes screen, env + screen<span class="Special"> <- </span>render-recipes screen, env, render <span class="muControl">jump</span> <span class="Constant">+finish-event:label</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> @@ -199,14 +200,14 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">{</span> <span class="muControl">break-unless</span> render-all-on-no-more-events? <span class="Comment"># no more events, and we have to force render</span> - screen<span class="Special"> <- </span>render-all screen, env + screen<span class="Special"> <- </span>render-all screen, env, render render-all-on-no-more-events?<span class="Special"> <- </span>copy <span class="Constant">0/false</span> <span class="muControl">jump</span> <span class="Constant">+finish-event:label</span> <span class="Delimiter">}</span> <span class="Comment"># no more events, no force render</span> <span class="Delimiter">{</span> <span class="muControl">break-unless</span> render? - screen<span class="Special"> <- </span>render-sandbox-side screen, env + screen<span class="Special"> <- </span>render-sandbox-side screen, env, render <span class="muControl">jump</span> <span class="Constant">+finish-event:label</span> <span class="Delimiter">}</span> <span class="Delimiter">}</span> @@ -243,6 +244,90 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color *current-sandbox<span class="Special"> <- </span>put *current-sandbox, <span class="Constant">cursor-column:offset</span>, left ] +<span class="Comment"># Variant of 'render' that updates cursor-row and cursor-column based on</span> +<span class="Comment"># before-cursor (rather than the other way around). If before-cursor moves</span> +<span class="Comment"># off-screen, it resets cursor-row and cursor-column.</span> +<span class="muRecipe">def</span> render-without-moving-cursor screen:address:screen, editor:address:editor-data<span class="muRecipe"> -> </span>last-row:number, last-column:number, screen:address:screen, editor:address:editor-data [ + <span class="Constant">local-scope</span> + <span class="Constant">load-ingredients</span> + <span class="muControl">return-unless</span> editor, <span class="Constant">1/top</span>, <span class="Constant">0/left</span>, screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span> + left:number<span class="Special"> <- </span>get *editor, <span class="Constant">left:offset</span> + screen-height:number<span class="Special"> <- </span>screen-height screen + right:number<span class="Special"> <- </span>get *editor, <span class="Constant">right:offset</span> + curr:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + prev:address:duplex-list:character<span class="Special"> <- </span>copy curr <span class="Comment"># just in case curr becomes null and we can't compute prev</span> + curr<span class="Special"> <- </span>next curr +<span class="Constant"> +render-loop-initialization</span> + color:number<span class="Special"> <- </span>copy <span class="Constant">7/white</span> + row:number<span class="Special"> <- </span>copy <span class="Constant">1/top</span> + column:number<span class="Special"> <- </span>copy left + <span class="Comment"># save before-cursor</span> + old-before-cursor:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">before-cursor:offset</span> + <span class="Comment"># initialze cursor-row/cursor-column/before-cursor to the top of the screen</span> + <span class="Comment"># by default</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-row:offset</span>, row + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-column:offset</span>, column + top-of-screen:address:duplex-list:character<span class="Special"> <- </span>get *editor, <span class="Constant">top-of-screen:offset</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">before-cursor:offset</span>, top-of-screen + screen<span class="Special"> <- </span>move-cursor screen, row, column + <span class="Delimiter">{</span> +<span class="Constant"> +next-character</span> + <span class="muControl">break-unless</span> curr + off-screen?:boolean<span class="Special"> <- </span>greater-or-equal row, screen-height + <span class="muControl">break-if</span> off-screen? + <span class="Comment"># if we find old-before-cursor still on the new resized screen, update</span> + <span class="Comment"># editor-data.cursor-row and editor-data.cursor-column based on</span> + <span class="Comment"># old-before-cursor</span> + <span class="Delimiter">{</span> + at-cursor?:boolean<span class="Special"> <- </span>equal old-before-cursor, prev + <span class="muControl">break-unless</span> at-cursor? + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-row:offset</span>, row + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">cursor-column:offset</span>, column + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">before-cursor:offset</span>, old-before-cursor + <span class="Delimiter">}</span> + c:character<span class="Special"> <- </span>get *curr, <span class="Constant">value:offset</span> +<span class="Constant"> <character-c-received></span> + <span class="Delimiter">{</span> + <span class="Comment"># newline? move to left rather than 0</span> + newline?:boolean<span class="Special"> <- </span>equal c, <span class="Constant">10/newline</span> + <span class="muControl">break-unless</span> newline? + <span class="Comment"># clear rest of line in this window</span> + clear-line-until screen, right + <span class="Comment"># skip to next line</span> + row<span class="Special"> <- </span>add row, <span class="Constant">1</span> + column<span class="Special"> <- </span>copy left + screen<span class="Special"> <- </span>move-cursor screen, row, column + curr<span class="Special"> <- </span>next curr + prev<span class="Special"> <- </span>next prev + <span class="muControl">loop</span> <span class="Constant">+next-character:label</span> + <span class="Delimiter">}</span> + <span class="Delimiter">{</span> + <span class="Comment"># at right? wrap. even if there's only one more letter left; we need</span> + <span class="Comment"># room for clicking on the cursor after it.</span> + at-right?:boolean<span class="Special"> <- </span>equal column, right + <span class="muControl">break-unless</span> at-right? + <span class="Comment"># print wrap icon</span> + wrap-icon:character<span class="Special"> <- </span>copy <span class="Constant">8617/loop-back-to-left</span> + print screen, wrap-icon, <span class="Constant">245/grey</span> + column<span class="Special"> <- </span>copy left + row<span class="Special"> <- </span>add row, <span class="Constant">1</span> + screen<span class="Special"> <- </span>move-cursor screen, row, column + <span class="Comment"># don't increment curr</span> + <span class="muControl">loop</span> <span class="Constant">+next-character:label</span> + <span class="Delimiter">}</span> + print screen, c, color + curr<span class="Special"> <- </span>next curr + prev<span class="Special"> <- </span>next prev + column<span class="Special"> <- </span>add column, <span class="Constant">1</span> + <span class="muControl">loop</span> + <span class="Delimiter">}</span> + <span class="Comment"># save first character off-screen</span> + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">bottom-of-screen:offset</span>, curr + *editor<span class="Special"> <- </span>put *editor, <span class="Constant">bottom:offset</span>, row + <span class="muControl">return</span> row, column, screen/same-as-ingredient:<span class="Constant">0</span>, editor/same-as-ingredient:<span class="Constant">1</span> +] + + <span class="muScenario">scenario</span> point-at-multiple-editors [ trace-until <span class="Constant">100/app</span> <span class="Comment"># trace too long</span> assume-screen <span class="Constant">30/width</span>, <span class="Constant">5/height</span> @@ -276,7 +361,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[def]</span> <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character - render-all screen, <span class="Constant">3</span>:address:programming-environment-data + render-all screen, <span class="Constant">3</span>:address:programming-environment-data, render <span class="Comment"># type one letter in each of them</span> assume-console [ left-click <span class="Constant">1</span>, <span class="Constant">1</span> @@ -321,7 +406,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[def]</span> <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character - render-all screen, <span class="Constant">3</span>:address:programming-environment-data + render-all screen, <span class="Constant">3</span>:address:programming-environment-data, render ] <span class="Comment"># divider isn't messed up</span> screen-should-contain [ @@ -339,7 +424,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc]</span> <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[def]</span> <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character - render-all screen, <span class="Constant">3</span>:address:programming-environment-data + render-all screen, <span class="Constant">3</span>:address:programming-environment-data, render <span class="Comment"># initialize programming environment and highlight cursor</span> assume-console <span class="Constant">[]</span> run [ @@ -373,14 +458,14 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] <span class="muScenario">scenario</span> backspace-in-sandbox-editor-joins-lines [ - trace-until <span class="Constant">100/app</span> <span class="Comment"># trace too long</span> +<span class="CommentedCode">#? trace-until 100/app # trace too long</span> assume-screen <span class="Constant">30/width</span>, <span class="Constant">5/height</span> <span class="Comment"># initialize sandbox side with two lines</span> <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[abc</span> <span class="Constant">def]</span> <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character - render-all screen, <span class="Constant">3</span>:address:programming-environment-data + render-all screen, <span class="Constant">3</span>:address:programming-environment-data, render screen-should-contain [ <span class="Constant"> . run (F4) .</span> <span class="Constant"> . ┊abc .</span> @@ -407,7 +492,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] ] -<span class="muRecipe">def</span> render-all screen:address:screen, env:address:programming-environment-data<span class="muRecipe"> -> </span>screen:address:screen, env:address:programming-environment-data [ +<span class="muRecipe">def</span> render-all screen:address:screen, env:address:programming-environment-data, <span class="Delimiter">{</span>render-editor: (<span class="muRecipe">recipe</span> (address screen) (address editor-data)<span class="muRecipe"> -> </span>number number (address screen) (address editor-data))<span class="Delimiter">}</span><span class="muRecipe"> -> </span>screen:address:screen, env:address:programming-environment-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> trace <span class="Constant">10</span>, <span class="Constant">[app]</span>, <span class="Constant">[render all]</span> @@ -427,8 +512,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color height:number<span class="Special"> <- </span>screen-height screen draw-vertical screen, divider, <span class="Constant">1/top</span>, height, <span class="Constant">9482/vertical-dotted</span> <span class="Comment">#</span> - screen<span class="Special"> <- </span>render-recipes screen, env - screen<span class="Special"> <- </span>render-sandbox-side screen, env + screen<span class="Special"> <- </span>render-recipes screen, env, render-editor + screen<span class="Special"> <- </span>render-sandbox-side screen, env, render-editor <span class="Constant"> <render-components-end></span> <span class="Comment">#</span> recipes:address:editor-data<span class="Special"> <- </span>get *env, <span class="Constant">recipes:offset</span> @@ -439,7 +524,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color show-screen screen ] -<span class="muRecipe">def</span> render-recipes screen:address:screen, env:address:programming-environment-data<span class="muRecipe"> -> </span>screen:address:screen, env:address:programming-environment-data [ +<span class="muRecipe">def</span> render-recipes screen:address:screen, env:address:programming-environment-data, <span class="Delimiter">{</span>render-editor: (<span class="muRecipe">recipe</span> (address screen) (address editor-data)<span class="muRecipe"> -> </span>number number (address screen) (address editor-data))<span class="Delimiter">}</span><span class="muRecipe"> -> </span>screen:address:screen, env:address:programming-environment-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> trace <span class="Constant">11</span>, <span class="Constant">[app]</span>, <span class="Constant">[render recipes]</span> @@ -447,7 +532,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment"># render recipes</span> left:number<span class="Special"> <- </span>get *recipes, <span class="Constant">left:offset</span> right:number<span class="Special"> <- </span>get *recipes, <span class="Constant">right:offset</span> - row:number, column:number, screen<span class="Special"> <- </span>render screen, recipes + row:number, column:number, screen<span class="Special"> <- </span>call render-editor, screen, recipes clear-line-until screen, right row<span class="Special"> <- </span>add row, <span class="Constant">1</span> <span class="Constant"> <render-recipe-components-end></span> @@ -458,13 +543,13 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] <span class="Comment"># replaced in a later layer</span> -<span class="muRecipe">def</span> render-sandbox-side screen:address:screen, env:address:programming-environment-data<span class="muRecipe"> -> </span>screen:address:screen, env:address:programming-environment-data [ +<span class="muRecipe">def</span> render-sandbox-side screen:address:screen, env:address:programming-environment-data, <span class="Delimiter">{</span>render-editor: (<span class="muRecipe">recipe</span> (address screen) (address editor-data)<span class="muRecipe"> -> </span>number number (address screen) (address editor-data))<span class="Delimiter">}</span><span class="muRecipe"> -> </span>screen:address:screen, env:address:programming-environment-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> current-sandbox:address:editor-data<span class="Special"> <- </span>get *env, <span class="Constant">current-sandbox:offset</span> left:number<span class="Special"> <- </span>get *current-sandbox, <span class="Constant">left:offset</span> right:number<span class="Special"> <- </span>get *current-sandbox, <span class="Constant">right:offset</span> - row:number, column:number, screen, current-sandbox<span class="Special"> <- </span>render screen, current-sandbox + row:number, column:number, screen, current-sandbox<span class="Special"> <- </span>call render-editor, screen, current-sandbox clear-line-until screen, right row<span class="Special"> <- </span>add row, <span class="Constant">1</span> <span class="Comment"># draw solid line after code (you'll see why in later layers)</span> @@ -490,68 +575,6 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color screen<span class="Special"> <- </span>move-cursor screen, cursor-row, cursor-column ] -<span class="Comment"># print a text 's' to 'editor' in 'color' starting at 'row'</span> -<span class="Comment"># clear rest of last line, move cursor to next line</span> -<span class="muRecipe">def</span> render screen:address:screen, s:address:array:character, left:number, right:number, color:number, row:number<span class="muRecipe"> -> </span>row:number, screen:address:screen [ - <span class="Constant">local-scope</span> - <span class="Constant">load-ingredients</span> - <span class="muControl">return-unless</span> s - column:number<span class="Special"> <- </span>copy left - screen<span class="Special"> <- </span>move-cursor screen, row, column - screen-height:number<span class="Special"> <- </span>screen-height screen - i:number<span class="Special"> <- </span>copy <span class="Constant">0</span> - len:number<span class="Special"> <- </span>length *s - <span class="Delimiter">{</span> -<span class="Constant"> +next-character</span> - done?:boolean<span class="Special"> <- </span>greater-or-equal i, len - <span class="muControl">break-if</span> done? - done?<span class="Special"> <- </span>greater-or-equal row, screen-height - <span class="muControl">break-if</span> done? - c:character<span class="Special"> <- </span>index *s, i - <span class="Delimiter">{</span> - <span class="Comment"># at right? wrap.</span> - at-right?:boolean<span class="Special"> <- </span>equal column, right - <span class="muControl">break-unless</span> at-right? - <span class="Comment"># print wrap icon</span> - wrap-icon:character<span class="Special"> <- </span>copy <span class="Constant">8617/loop-back-to-left</span> - print screen, wrap-icon, <span class="Constant">245/grey</span> - column<span class="Special"> <- </span>copy left - row<span class="Special"> <- </span>add row, <span class="Constant">1</span> - screen<span class="Special"> <- </span>move-cursor screen, row, column - <span class="muControl">loop</span> <span class="Constant">+next-character:label</span> <span class="Comment"># retry i</span> - <span class="Delimiter">}</span> - i<span class="Special"> <- </span>add i, <span class="Constant">1</span> - <span class="Delimiter">{</span> - <span class="Comment"># newline? move to left rather than 0</span> - newline?:boolean<span class="Special"> <- </span>equal c, <span class="Constant">10/newline</span> - <span class="muControl">break-unless</span> newline? - <span class="Comment"># clear rest of line in this window</span> - <span class="Delimiter">{</span> - done?:boolean<span class="Special"> <- </span>greater-than column, right - <span class="muControl">break-if</span> done? - space:character<span class="Special"> <- </span>copy <span class="Constant">32/space</span> - print screen, space - column<span class="Special"> <- </span>add column, <span class="Constant">1</span> - <span class="muControl">loop</span> - <span class="Delimiter">}</span> - row<span class="Special"> <- </span>add row, <span class="Constant">1</span> - column<span class="Special"> <- </span>copy left - screen<span class="Special"> <- </span>move-cursor screen, row, column - <span class="muControl">loop</span> <span class="Constant">+next-character:label</span> - <span class="Delimiter">}</span> - print screen, c, color - column<span class="Special"> <- </span>add column, <span class="Constant">1</span> - <span class="muControl">loop</span> - <span class="Delimiter">}</span> - was-at-left?:boolean<span class="Special"> <- </span>equal column, left - clear-line-until screen, right - <span class="Delimiter">{</span> - <span class="muControl">break-if</span> was-at-left? - row<span class="Special"> <- </span>add row, <span class="Constant">1</span> - <span class="Delimiter">}</span> - move-cursor screen, row, left -] - <span class="Comment"># like 'render' for texts, but with colorization for comments like in the editor</span> <span class="muRecipe">def</span> render-code screen:address:screen, s:address:array:character, left:number, right:number, row:number<span class="muRecipe"> -> </span>row:number, screen:address:screen [ <span class="Constant">local-scope</span> @@ -621,7 +644,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">{</span> redraw-screen?:boolean<span class="Special"> <- </span>equal c, <span class="Constant">12/ctrl-l</span> <span class="muControl">break-unless</span> redraw-screen? - screen<span class="Special"> <- </span>render-all screen, env:address:programming-environment-data + screen<span class="Special"> <- </span>render-all screen, env:address:programming-environment-data, render sync-screen screen <span class="muControl">loop</span> <span class="Constant">+next-event:label</span> <span class="Delimiter">}</span> diff --git a/html/edit/005-sandbox.mu.html b/html/edit/005-sandbox.mu.html index e3523d27..a4aa964c 100644 --- a/html/edit/005-sandbox.mu.html +++ b/html/edit/005-sandbox.mu.html @@ -50,7 +50,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color hide-screen <span class="Constant">0/screen</span> env:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment <span class="Constant">0/screen</span>, initial-recipe, initial-sandbox env<span class="Special"> <- </span>restore-sandboxes env - render-all <span class="Constant">0/screen</span>, env + render-all <span class="Constant">0/screen</span>, env, render event-loop <span class="Constant">0/screen</span>, <span class="Constant">0/console</span>, env <span class="Comment"># never gets here</span> ] @@ -167,7 +167,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color screen<span class="Special"> <- </span>update-status screen, <span class="Constant">[running... ]</span>, <span class="Constant">245/grey</span> error?:boolean, env, screen<span class="Special"> <- </span>run-sandboxes env, screen <span class="Comment"># F4 might update warnings and results on both sides</span> - screen<span class="Special"> <- </span>render-all screen, env + screen<span class="Special"> <- </span>render-all screen, env, render <span class="Delimiter">{</span> <span class="muControl">break-if</span> error? screen<span class="Special"> <- </span>update-status screen, <span class="Constant">[ ]</span>, <span class="Constant">245/grey</span> @@ -269,7 +269,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">}</span> ] -<span class="muRecipe">def!</span> render-sandbox-side screen:address:screen, env:address:programming-environment-data<span class="muRecipe"> -> </span>screen:address:screen, env:address:programming-environment-data [ +<span class="muRecipe">def!</span> render-sandbox-side screen:address:screen, env:address:programming-environment-data, <span class="Delimiter">{</span>render-editor: (<span class="muRecipe">recipe</span> (address screen) (address editor-data)<span class="muRecipe"> -> </span>number number (address screen) (address editor-data))<span class="Delimiter">}</span><span class="muRecipe"> -> </span>screen:address:screen, env:address:programming-environment-data [ <span class="Constant">local-scope</span> <span class="Constant">load-ingredients</span> trace <span class="Constant">11</span>, <span class="Constant">[app]</span>, <span class="Constant">[render sandbox side]</span> @@ -282,7 +282,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">{</span> render-current-sandbox?:boolean<span class="Special"> <- </span>equal render-from, <span class="Constant">-1</span> <span class="muControl">break-unless</span> render-current-sandbox? - row, column, screen, current-sandbox<span class="Special"> <- </span>render screen, current-sandbox + row, column, screen, current-sandbox<span class="Special"> <- </span>call render-editor, screen, current-sandbox clear-screen-from screen, row, column, left, right row<span class="Special"> <- </span>add row, <span class="Constant">1</span> <span class="Delimiter">}</span> @@ -327,7 +327,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">{</span> <span class="muControl">break-unless</span> empty-screen? <span class="Constant"> <render-sandbox-response></span> - row, screen<span class="Special"> <- </span>render screen, sandbox-response, left, right, <span class="Constant">245/grey</span>, row + row, screen<span class="Special"> <- </span>render-text screen, sandbox-response, left, right, <span class="Constant">245/grey</span>, row <span class="Delimiter">}</span> <span class="Constant"> +render-sandbox-end</span> at-bottom?:boolean<span class="Special"> <- </span>greater-or-equal row, screen-height @@ -388,6 +388,68 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color copy-button-right:number<span class="Special"> <- </span>subtract delete-button-left, <span class="Constant">1</span> ] +<span class="Comment"># print a text 's' to 'editor' in 'color' starting at 'row'</span> +<span class="Comment"># clear rest of last line, move cursor to next line</span> +<span class="muRecipe">def</span> render-text screen:address:screen, s:address:array:character, left:number, right:number, color:number, row:number<span class="muRecipe"> -> </span>row:number, screen:address:screen [ + <span class="Constant">local-scope</span> + <span class="Constant">load-ingredients</span> + <span class="muControl">return-unless</span> s + column:number<span class="Special"> <- </span>copy left + screen<span class="Special"> <- </span>move-cursor screen, row, column + screen-height:number<span class="Special"> <- </span>screen-height screen + i:number<span class="Special"> <- </span>copy <span class="Constant">0</span> + len:number<span class="Special"> <- </span>length *s + <span class="Delimiter">{</span> +<span class="Constant"> +next-character</span> + done?:boolean<span class="Special"> <- </span>greater-or-equal i, len + <span class="muControl">break-if</span> done? + done?<span class="Special"> <- </span>greater-or-equal row, screen-height + <span class="muControl">break-if</span> done? + c:character<span class="Special"> <- </span>index *s, i + <span class="Delimiter">{</span> + <span class="Comment"># at right? wrap.</span> + at-right?:boolean<span class="Special"> <- </span>equal column, right + <span class="muControl">break-unless</span> at-right? + <span class="Comment"># print wrap icon</span> + wrap-icon:character<span class="Special"> <- </span>copy <span class="Constant">8617/loop-back-to-left</span> + print screen, wrap-icon, <span class="Constant">245/grey</span> + column<span class="Special"> <- </span>copy left + row<span class="Special"> <- </span>add row, <span class="Constant">1</span> + screen<span class="Special"> <- </span>move-cursor screen, row, column + <span class="muControl">loop</span> <span class="Constant">+next-character:label</span> <span class="Comment"># retry i</span> + <span class="Delimiter">}</span> + i<span class="Special"> <- </span>add i, <span class="Constant">1</span> + <span class="Delimiter">{</span> + <span class="Comment"># newline? move to left rather than 0</span> + newline?:boolean<span class="Special"> <- </span>equal c, <span class="Constant">10/newline</span> + <span class="muControl">break-unless</span> newline? + <span class="Comment"># clear rest of line in this window</span> + <span class="Delimiter">{</span> + done?:boolean<span class="Special"> <- </span>greater-than column, right + <span class="muControl">break-if</span> done? + space:character<span class="Special"> <- </span>copy <span class="Constant">32/space</span> + print screen, space + column<span class="Special"> <- </span>add column, <span class="Constant">1</span> + <span class="muControl">loop</span> + <span class="Delimiter">}</span> + row<span class="Special"> <- </span>add row, <span class="Constant">1</span> + column<span class="Special"> <- </span>copy left + screen<span class="Special"> <- </span>move-cursor screen, row, column + <span class="muControl">loop</span> <span class="Constant">+next-character:label</span> + <span class="Delimiter">}</span> + print screen, c, color + column<span class="Special"> <- </span>add column, <span class="Constant">1</span> + <span class="muControl">loop</span> + <span class="Delimiter">}</span> + was-at-left?:boolean<span class="Special"> <- </span>equal column, left + clear-line-until screen, right + <span class="Delimiter">{</span> + <span class="muControl">break-if</span> was-at-left? + row<span class="Special"> <- </span>add row, <span class="Constant">1</span> + <span class="Delimiter">}</span> + move-cursor screen, row, left +] + <span class="Comment"># assumes programming environment has no sandboxes; restores them from previous session</span> <span class="muRecipe">def</span> restore-sandboxes env:address:programming-environment-data<span class="muRecipe"> -> </span>env:address:programming-environment-data [ <span class="Constant">local-scope</span> @@ -428,7 +490,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Constant">load-ingredients</span> <span class="muControl">return-unless</span> sandbox-screen <span class="Comment"># print 'screen:'</span> - row<span class="Special"> <- </span>render screen, <span class="Constant">[screen:]</span>, left, right, <span class="Constant">245/grey</span>, row + row<span class="Special"> <- </span>render-text screen, <span class="Constant">[screen:]</span>, left, right, <span class="Constant">245/grey</span>, row screen<span class="Special"> <- </span>move-cursor screen, row, left <span class="Comment"># start printing sandbox-screen</span> column:number<span class="Special"> <- </span>copy left @@ -611,6 +673,160 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] ] +<span class="Comment"># keep the bottom of recipes from scrolling off the screen</span> + +<span class="muScenario">scenario</span> scrolling-down-past-bottom-of-recipe-editor [ + <span class="Constant">local-scope</span> + trace-until <span class="Constant">100/app</span> + assume-screen <span class="Constant">100/width</span>, <span class="Constant">10/height</span> + env:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">[]</span>, <span class="Constant">[]</span> + render-all screen, env, render + assume-console [ + press enter + press down-arrow + ] + event-loop screen, console:address:console, env + <span class="Comment"># no scroll</span> + screen-should-contain [ + <span class="Constant"> . run (F4) .</span> + <span class="Constant"> . ┊ .</span> + <span class="Constant"> . ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> + <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊ .</span> + <span class="Constant"> . ┊ .</span> + ] +] + +<span class="muScenario">scenario</span> cursor-down-in-recipe-editor [ + <span class="Constant">local-scope</span> + trace-until <span class="Constant">100/app</span> + assume-screen <span class="Constant">100/width</span>, <span class="Constant">10/height</span> + env:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">[]</span>, <span class="Constant">[]</span> + render-all screen, env, render + assume-console [ + press enter + press up-arrow + press down-arrow <span class="Comment"># while cursor isn't at bottom</span> + ] + event-loop screen, console:address:console, env + cursor:character<span class="Special"> <- </span>copy <span class="Constant">9251/␣</span> + print screen:address:screen, cursor + <span class="Comment"># cursor moves back to bottom</span> + screen-should-contain [ + <span class="Constant"> . run (F4) .</span> + <span class="Constant"> . ┊ .</span> + <span class="Constant"> .␣ ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> + <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊ .</span> + <span class="Constant"> . ┊ .</span> + ] +] + +<span class="Comment"># we'll not use the recipe-editor's 'bottom' element directly, because later</span> +<span class="Comment"># layers will add other stuff to the left side below the editor (error messages)</span> + +<span class="muData">container</span> programming-environment-data [ + recipe-bottom:number +] + +<span class="muRecipe">after</span> <span class="Constant"><render-recipe-components-end></span> [ + *env<span class="Special"> <- </span>put *env, <span class="Constant">recipe-bottom:offset</span>, row +] + +<span class="muRecipe">after</span> <span class="Constant"><global-keypress></span> [ + <span class="Delimiter">{</span> + <span class="muControl">break-if</span> sandbox-in-focus? + down-arrow?:boolean<span class="Special"> <- </span>equal k, <span class="Constant">65516/down-arrow</span> + <span class="muControl">break-unless</span> down-arrow? + recipe-editor:address:editor-data<span class="Special"> <- </span>get *env, <span class="Constant">recipes:offset</span> + recipe-cursor-row:number<span class="Special"> <- </span>get *recipe-editor, <span class="Constant">cursor-row:offset</span> + recipe-editor-bottom:number<span class="Special"> <- </span>get *recipe-editor, <span class="Constant">bottom:offset</span> + at-bottom-of-editor?:boolean<span class="Special"> <- </span>greater-or-equal recipe-cursor-row, recipe-editor-bottom + <span class="muControl">break-unless</span> at-bottom-of-editor? + more-to-scroll?:boolean<span class="Special"> <- </span>more-to-scroll? env, screen + <span class="muControl">break-if</span> more-to-scroll? + <span class="muControl">loop</span> <span class="Constant">+next-event:label</span> + <span class="Delimiter">}</span> + <span class="Delimiter">{</span> + <span class="muControl">break-if</span> sandbox-in-focus? + page-down?:boolean<span class="Special"> <- </span>equal k, <span class="Constant">65518/page-down</span> + <span class="muControl">break-unless</span> page-down? + more-to-scroll?:boolean<span class="Special"> <- </span>more-to-scroll? env, screen + <span class="muControl">break-if</span> more-to-scroll? + <span class="muControl">loop</span> <span class="Constant">+next-event:label</span> + <span class="Delimiter">}</span> +] + +<span class="muRecipe">after</span> <span class="Constant"><global-type></span> [ + <span class="Delimiter">{</span> + <span class="muControl">break-if</span> sandbox-in-focus? + page-down?:boolean<span class="Special"> <- </span>equal k, <span class="Constant">6/ctrl-f</span> + <span class="muControl">break-unless</span> page-down? + more-to-scroll?:boolean<span class="Special"> <- </span>more-to-scroll? env, screen + <span class="muControl">break-if</span> more-to-scroll? + <span class="muControl">loop</span> <span class="Constant">+next-event:label</span> + <span class="Delimiter">}</span> +] + +<span class="muRecipe">def</span> more-to-scroll? env:address:programming-environment-data, screen:address:screen<span class="muRecipe"> -> </span>result:boolean [ + <span class="Constant">local-scope</span> + <span class="Constant">load-ingredients</span> + recipe-bottom:number<span class="Special"> <- </span>get *env, <span class="Constant">recipe-bottom:offset</span> + height:number<span class="Special"> <- </span>screen-height screen + result<span class="Special"> <- </span>greater-or-equal recipe-bottom, height +] + +<span class="muScenario">scenario</span> scrolling-down-past-bottom-of-recipe-editor-2 [ + <span class="Constant">local-scope</span> + trace-until <span class="Constant">100/app</span> + assume-screen <span class="Constant">100/width</span>, <span class="Constant">10/height</span> + env:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">[]</span>, <span class="Constant">[]</span> + render-all screen, env, render + assume-console [ + <span class="Comment"># add a line</span> + press enter + <span class="Comment"># cursor back to top line</span> + press up-arrow + <span class="Comment"># try to scroll</span> + press page-down <span class="Comment"># or ctrl-f</span> + ] + event-loop screen, console:address:console, env + <span class="Comment"># no scroll, and cursor remains at top line</span> + screen-should-contain [ + <span class="Constant"> . run (F4) .</span> + <span class="Constant"> . ┊ .</span> + <span class="Constant"> . ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> + <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊ .</span> + <span class="Constant"> . ┊ .</span> + ] +] + +<span class="muScenario">scenario</span> scrolling-down-past-bottom-of-recipe-editor-3 [ + <span class="Constant">local-scope</span> + trace-until <span class="Constant">100/app</span> + assume-screen <span class="Constant">100/width</span>, <span class="Constant">10/height</span> + env:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">[]</span>, <span class="Constant">[ab</span> +<span class="Constant">cd]</span> + render-all screen, env, render + assume-console [ + <span class="Comment"># add a line</span> + press enter + <span class="Comment"># switch to sandbox</span> + press ctrl-n + <span class="Comment"># move cursor</span> + press down-arrow + ] + event-loop screen, console:address:console, env + cursor:character<span class="Special"> <- </span>copy <span class="Constant">9251/␣</span> + print screen:address:screen, cursor + <span class="Comment"># no scroll on recipe side, cursor moves on sandbox side</span> + screen-should-contain [ + <span class="Constant"> . run (F4) .</span> + <span class="Constant"> . ┊ab .</span> + <span class="Constant"> . ┊␣d .</span> +<span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> + <span class="Constant"> . ┊ .</span> + ] +] + <span class="Comment"># scrolling through sandboxes</span> <span class="muScenario">scenario</span> scrolling-down-past-bottom-of-sandbox-editor [ @@ -620,7 +836,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[add 2, 2]</span> <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character - render-all screen, <span class="Constant">3</span>:address:programming-environment-data + render-all screen, <span class="Constant">3</span>:address:programming-environment-data, render assume-console [ <span class="Comment"># create a sandbox</span> press F4 @@ -690,7 +906,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color *env<span class="Special"> <- </span>put *env, <span class="Constant">render-from:offset</span>, render-from <span class="Delimiter">}</span> hide-screen screen - screen<span class="Special"> <- </span>render-sandbox-side screen, env + screen<span class="Special"> <- </span>render-sandbox-side screen, env, render show-screen screen <span class="muControl">jump</span> <span class="Constant">+finish-event:label</span> <span class="Delimiter">}</span> @@ -721,7 +937,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color render-from<span class="Special"> <- </span>subtract render-from, <span class="Constant">1</span> *env<span class="Special"> <- </span>put *env, <span class="Constant">render-from:offset</span>, render-from hide-screen screen - screen<span class="Special"> <- </span>render-sandbox-side screen, env + screen<span class="Special"> <- </span>render-sandbox-side screen, env, render show-screen screen <span class="muControl">jump</span> <span class="Constant">+finish-event:label</span> <span class="Delimiter">}</span> @@ -755,14 +971,14 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment"># create a sandbox</span> <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[add 2, 2]</span> <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character - render-all screen, <span class="Constant">3</span>:address:programming-environment-data + render-all screen, <span class="Constant">3</span>:address:programming-environment-data, render assume-console [ press F4 ] event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data <span class="Comment"># hit 'down' in recipe editor</span> assume-console [ - press down-arrow + press page-down ] run [ event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data @@ -772,8 +988,8 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Comment"># cursor moves down on recipe side</span> screen-should-contain [ <span class="Constant"> . run (F4) .</span> - <span class="Constant"> . ┊ .</span> - <span class="Constant"> .␣ ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> + <span class="Constant"> .␣ ┊ .</span> + <span class="Constant"> . ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> <span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊0 edit copy delete .</span> <span class="Constant"> . ┊add 2, 2 .</span> ] @@ -786,7 +1002,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character - render-all screen, <span class="Constant">3</span>:address:programming-environment-data + render-all screen, <span class="Constant">3</span>:address:programming-environment-data, render <span class="Comment"># create 2 sandboxes</span> assume-console [ press ctrl-n @@ -938,7 +1154,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character - render-all screen, <span class="Constant">3</span>:address:programming-environment-data + render-all screen, <span class="Constant">3</span>:address:programming-environment-data, render <span class="Comment"># create a sandbox</span> assume-console [ press ctrl-n diff --git a/html/edit/006-sandbox-copy.mu.html b/html/edit/006-sandbox-copy.mu.html index c201b609..ccf5d361 100644 --- a/html/edit/006-sandbox-copy.mu.html +++ b/html/edit/006-sandbox-copy.mu.html @@ -167,7 +167,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color copy?, env<span class="Special"> <- </span>try-copy-sandbox click-row, env <span class="muControl">break-unless</span> copy? hide-screen screen - screen<span class="Special"> <- </span>render-sandbox-side screen, env + screen<span class="Special"> <- </span>render-sandbox-side screen, env, render screen<span class="Special"> <- </span>update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env show-screen screen <span class="muControl">loop</span> <span class="Constant">+next-event:label</span> @@ -215,6 +215,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Constant">load-ingredients</span> curr-sandbox:address:sandbox-data<span class="Special"> <- </span>get *env, <span class="Constant">sandbox:offset</span> <span class="Delimiter">{</span> + <span class="muControl">break-unless</span> curr-sandbox start:number<span class="Special"> <- </span>get *curr-sandbox, <span class="Constant">starting-row-on-screen:offset</span> found?:boolean<span class="Special"> <- </span>equal click-row, start <span class="muControl">return-if</span> found?, curr-sandbox diff --git a/html/edit/007-sandbox-delete.mu.html b/html/edit/007-sandbox-delete.mu.html index 137a7887..f9f26d6f 100644 --- a/html/edit/007-sandbox-delete.mu.html +++ b/html/edit/007-sandbox-delete.mu.html @@ -106,7 +106,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color delete?, env<span class="Special"> <- </span>try-delete-sandbox click-row, env <span class="muControl">break-unless</span> delete? hide-screen screen - screen<span class="Special"> <- </span>render-sandbox-side screen, env + screen<span class="Special"> <- </span>render-sandbox-side screen, env, render screen<span class="Special"> <- </span>update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env show-screen screen <span class="muControl">loop</span> <span class="Constant">+next-event:label</span> @@ -188,7 +188,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character - render-all screen, <span class="Constant">3</span>:address:programming-environment-data + render-all screen, <span class="Constant">3</span>:address:programming-environment-data, render <span class="Comment"># create 2 sandboxes and scroll to second</span> assume-console [ press ctrl-n @@ -234,7 +234,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character - render-all screen, <span class="Constant">3</span>:address:programming-environment-data + render-all screen, <span class="Constant">3</span>:address:programming-environment-data, render <span class="Comment"># create 2 sandboxes and scroll to second</span> assume-console [ press ctrl-n @@ -280,7 +280,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character - render-all screen, <span class="Constant">3</span>:address:programming-environment-data + render-all screen, <span class="Constant">3</span>:address:programming-environment-data, render <span class="Comment"># create 2 sandboxes and scroll to second</span> assume-console [ press ctrl-n @@ -328,7 +328,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character - render-all screen, <span class="Constant">3</span>:address:programming-environment-data + render-all screen, <span class="Constant">3</span>:address:programming-environment-data, render <span class="Comment"># create 2 sandboxes</span> assume-console [ press ctrl-n diff --git a/html/edit/008-sandbox-edit.mu.html b/html/edit/008-sandbox-edit.mu.html index 80712819..e79738c5 100644 --- a/html/edit/008-sandbox-edit.mu.html +++ b/html/edit/008-sandbox-edit.mu.html @@ -162,7 +162,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color edit?, env<span class="Special"> <- </span>try-edit-sandbox click-row, env <span class="muControl">break-unless</span> edit? hide-screen screen - screen<span class="Special"> <- </span>render-sandbox-side screen, env + screen<span class="Special"> <- </span>render-sandbox-side screen, env, render screen<span class="Special"> <- </span>update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env show-screen screen <span class="muControl">loop</span> <span class="Constant">+next-event:label</span> @@ -258,7 +258,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character - render-all screen, <span class="Constant">3</span>:address:programming-environment-data + render-all screen, <span class="Constant">3</span>:address:programming-environment-data, render <span class="Comment"># create 2 sandboxes and scroll to second</span> assume-console [ press ctrl-n @@ -306,7 +306,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character - render-all screen, <span class="Constant">3</span>:address:programming-environment-data + render-all screen, <span class="Constant">3</span>:address:programming-environment-data, render <span class="Comment"># create 2 sandboxes</span> assume-console [ press ctrl-n diff --git a/html/edit/009-sandbox-test.mu.html b/html/edit/009-sandbox-test.mu.html index 5d7e782a..eeb61f7f 100644 --- a/html/edit/009-sandbox-test.mu.html +++ b/html/edit/009-sandbox-test.mu.html @@ -165,7 +165,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color sandbox<span class="Special"> <- </span>toggle-expected-response sandbox save-sandboxes env hide-screen screen - screen<span class="Special"> <- </span>render-sandbox-side screen, env, <span class="Constant">1/clear</span> + screen<span class="Special"> <- </span>render-sandbox-side screen, env, render screen<span class="Special"> <- </span>update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env <span class="Comment"># no change in cursor</span> show-screen screen @@ -226,11 +226,11 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color response-is-expected?:boolean<span class="Special"> <- </span>equal expected-response, sandbox-response <span class="Delimiter">{</span> <span class="muControl">break-if</span> response-is-expected?:boolean - row, screen<span class="Special"> <- </span>render screen, sandbox-response, left, right, <span class="Constant">1/red</span>, row + row, screen<span class="Special"> <- </span>render-text screen, sandbox-response, left, right, <span class="Constant">1/red</span>, row <span class="Delimiter">}</span> <span class="Delimiter">{</span> <span class="muControl">break-unless</span> response-is-expected?:boolean - row, screen<span class="Special"> <- </span>render screen, sandbox-response, left, right, <span class="Constant">2/green</span>, row + row, screen<span class="Special"> <- </span>render-text screen, sandbox-response, left, right, <span class="Constant">2/green</span>, row <span class="Delimiter">}</span> <span class="muControl">jump</span> <span class="Constant">+render-sandbox-end:label</span> <span class="Delimiter">}</span> diff --git a/html/edit/010-sandbox-trace.mu.html b/html/edit/010-sandbox-trace.mu.html index 282d2463..b791d18b 100644 --- a/html/edit/010-sandbox-trace.mu.html +++ b/html/edit/010-sandbox-trace.mu.html @@ -156,6 +156,48 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color ] ] +<span class="muScenario">scenario</span> clicking-on-app-trace-does-nothing [ + trace-until <span class="Constant">100/app</span> <span class="Comment"># trace too long</span> + assume-screen <span class="Constant">100/width</span>, <span class="Constant">10/height</span> + <span class="Constant">1</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[]</span> + <span class="Comment"># create and expand the trace</span> + <span class="Constant">2</span>:address:array:character<span class="Special"> <- </span>new <span class="Constant">[stash 123456789]</span> + assume-console [ + press F4 + left-click <span class="Constant">4</span>, <span class="Constant">51</span> + ] + <span class="Constant">3</span>:address:programming-environment-data<span class="Special"> <- </span>new-programming-environment screen:address:screen, <span class="Constant">1</span>:address:array:character, <span class="Constant">2</span>:address:array:character + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data + screen-should-contain [ + <span class="Constant"> . run (F4) .</span> + <span class="Constant"> . ┊ .</span> +<span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> + <span class="Constant"> . ┊0 edit copy delete .</span> + <span class="Constant"> . ┊stash 123456789 .</span> + <span class="Constant"> . ┊123456789 .</span> + <span class="Constant"> . ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> + <span class="Constant"> . ┊ .</span> + ] + <span class="Comment"># click on the stash under the edit-button region (or any of the other buttons, really)</span> + assume-console [ + left-click <span class="Constant">5</span>, <span class="Constant">57</span> + ] + run [ + event-loop screen:address:screen, console:address:console, <span class="Constant">3</span>:address:programming-environment-data + ] + <span class="Comment"># no change; doesn't die</span> + screen-should-contain [ + <span class="Constant"> . run (F4) .</span> + <span class="Constant"> . ┊ .</span> +<span class="Constant"> .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> + <span class="Constant"> . ┊0 edit copy delete .</span> + <span class="Constant"> . ┊stash 123456789 .</span> + <span class="Constant"> . ┊123456789 .</span> + <span class="Constant"> . ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━.</span> + <span class="Constant"> . ┊ .</span> + ] +] + <span class="muData">container</span> sandbox-data [ trace:address:array:character display-trace?:boolean @@ -194,7 +236,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color x<span class="Special"> <- </span>not x *sandbox<span class="Special"> <- </span>put *sandbox, <span class="Constant">display-trace?:offset</span>, x hide-screen screen - screen<span class="Special"> <- </span>render-sandbox-side screen, env, <span class="Constant">1/clear</span> + screen<span class="Special"> <- </span>render-sandbox-side screen, env, render screen<span class="Special"> <- </span>update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env <span class="Comment"># no change in cursor</span> show-screen screen @@ -240,7 +282,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="muControl">break-unless</span> display-trace? sandbox-trace:address:array:character<span class="Special"> <- </span>get *sandbox, <span class="Constant">trace:offset</span> <span class="muControl">break-unless</span> sandbox-trace <span class="Comment"># nothing to print; move on</span> - row, screen<span class="Special"> <- </span>render screen, sandbox-trace, left, right, <span class="Constant">245/grey</span>, row + row, screen<span class="Special"> <- </span>render-text screen, sandbox-trace, left, right, <span class="Constant">245/grey</span>, row <span class="Delimiter">}</span> <span class="Constant"> <render-sandbox-trace-done></span> ] diff --git a/html/edit/011-errors.mu.html b/html/edit/011-errors.mu.html index 9689ea9f..6bf5c452 100644 --- a/html/edit/011-errors.mu.html +++ b/html/edit/011-errors.mu.html @@ -71,7 +71,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color <span class="Delimiter">{</span> recipe-errors:address:array:character<span class="Special"> <- </span>get *env, <span class="Constant">recipe-errors:offset</span> <span class="muControl">break-unless</span> recipe-errors - row, screen<span class="Special"> <- </span>render screen, recipe-errors, left, right, <span class="Constant">1/red</span>, row + row, screen<span class="Special"> <- </span>render-text screen, recipe-errors, left, right, <span class="Constant">1/red</span>, row <span class="Delimiter">}</span> ] @@ -143,7 +143,7 @@ body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color sandbox-errors:address:array:character<span class="Special"> <- </span>get *sandbox, <span class="Constant">errors:offset</span> <span class="muControl">break-unless</span> sandbox-errors *sandbox<span class="Special"> <- </span>put *sandbox, <span class="Constant">response-starting-row-on-screen:offset</span>, <span class="Constant">0</span> <span class="Comment"># no response</span> - row, screen<span class="Special"> <- </span>render screen, sandbox-errors, left, right, <span class="Constant">1/red</span>, row + row, screen<span class="Special"> <- </span>render-text screen, sandbox-errors, left, right, <span class="Constant">1/red</span>, row <span class="Comment"># don't try to print anything more for this sandbox</span> <span class="muControl">jump</span> <span class="Constant">+render-sandbox-end:label</span> <span class="Delimiter">}</span> |